added qse_awk_rtx_getrefvaltype()/qse_awk_rtx_getrefval()
finished asort() in awk added qse_sortx()
This commit is contained in:
parent
c3e30eaae4
commit
2ac2ad8200
@ -2958,6 +2958,21 @@ QSE_EXPORT qse_awk_int_t qse_awk_rtx_hashval (
|
||||
qse_awk_val_t* v
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* The qse_awk_rtx_getrefvaltype() function returns the type of the value
|
||||
* that the given reference points to.
|
||||
*/
|
||||
QSE_EXPORT qse_awk_val_type_t qse_awk_rtx_getrefvaltype (
|
||||
qse_awk_rtx_t* rtx,
|
||||
qse_awk_val_ref_t* ref
|
||||
);
|
||||
|
||||
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_getrefval (
|
||||
qse_awk_rtx_t* rtx,
|
||||
qse_awk_val_ref_t* ref
|
||||
);
|
||||
|
||||
/**
|
||||
* The qse_awk_rtx_setrefval() function changes the value
|
||||
* of a variable referenced in \a ref.
|
||||
|
@ -55,10 +55,23 @@ typedef int (*qse_search_comper_t) (
|
||||
void* ctx
|
||||
);
|
||||
|
||||
/**
|
||||
* The qse_search_comperx_t type defines a search callback function.
|
||||
* It should return 0 on success and -1 on failure. the comparsion
|
||||
* result must be put back into the variable pointed to by \a cv.
|
||||
*/
|
||||
typedef int (*qse_search_comperx_t) (
|
||||
const void* ptr1,
|
||||
const void* ptr2,
|
||||
void* ctx,
|
||||
int * cv
|
||||
);
|
||||
|
||||
/**
|
||||
* The qse_sort_comper_t type defines a sort callback function.
|
||||
*/
|
||||
typedef qse_search_comper_t qse_sort_comper_t;
|
||||
typedef qse_search_comperx_t qse_sort_comperx_t;
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
@ -134,6 +147,14 @@ QSE_EXPORT void qse_qsort (
|
||||
void* ctx
|
||||
);
|
||||
|
||||
QSE_EXPORT int qse_qsortx (
|
||||
void* base,
|
||||
qse_size_t nmemb,
|
||||
qse_size_t size,
|
||||
qse_sort_comperx_t comper,
|
||||
void* ctx
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* The qse_rand31() function implements Park-Miller's minimal standard
|
||||
|
@ -45,7 +45,7 @@ static int fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi);
|
||||
*
|
||||
* - v: value. pass it after normal evaluation.
|
||||
* - r: pass a variable by reference
|
||||
* - x: regular expression as it it. not evaluated as /rex/ ~ $0.
|
||||
* - x: regular expression as it is. not evaluated as /rex/ ~ $0.
|
||||
*
|
||||
* If the first character of the specifer is 'R', all
|
||||
* parameters are passed by reference regarless of the remaining
|
||||
@ -67,30 +67,30 @@ static qse_awk_fnc_t sysfnctab[] =
|
||||
{ {QSE_T("typename"), 8}, 0, { {1, 1, QSE_NULL}, fnc_typename, 0 }, QSE_NULL},
|
||||
|
||||
/* array sort */
|
||||
{ {QSE_T("asort"), 5}, 0, { {1, 3, QSE_NULL}, fnc_asort, 0 }, QSE_NULL},
|
||||
{ {QSE_T("asort"), 5}, 0, { {1, 3, QSE_T("rrv")}, fnc_asort, 0 }, QSE_NULL},
|
||||
|
||||
/* string functions */
|
||||
{ {QSE_T("gsub"), 4}, 0, { {2, 3, QSE_T("xvr")}, qse_awk_fnc_gsub, 0 }, QSE_NULL},
|
||||
{ {QSE_T("index"), 5}, 0, { {2, 3, QSE_NULL}, qse_awk_fnc_index, 0 }, QSE_NULL},
|
||||
{ {QSE_T("length"), 6}, 1, { {0, 1, QSE_NULL}, qse_awk_fnc_length, 0 }, QSE_NULL},
|
||||
{ {QSE_T("match"), 5}, 0, { {2, 4, QSE_T("vxvr")}, qse_awk_fnc_match, 0 }, QSE_NULL},
|
||||
{ {QSE_T("split"), 5}, 0, { {2, 3, QSE_T("vrx")}, qse_awk_fnc_split, 0 }, QSE_NULL},
|
||||
{ {QSE_T("sprintf"), 7}, 0, { {1, A_MAX, QSE_NULL}, qse_awk_fnc_sprintf, 0 }, QSE_NULL},
|
||||
{ {QSE_T("sub"), 3}, 0, { {2, 3, QSE_T("xvr")}, qse_awk_fnc_sub, 0 }, QSE_NULL},
|
||||
{ {QSE_T("substr"), 6}, 0, { {2, 3, QSE_NULL}, qse_awk_fnc_substr, 0 }, QSE_NULL},
|
||||
{ {QSE_T("tolower"), 7}, 0, { {1, 1, QSE_NULL}, qse_awk_fnc_tolower, 0 }, QSE_NULL},
|
||||
{ {QSE_T("toupper"), 7}, 0, { {1, 1, QSE_NULL}, qse_awk_fnc_toupper, 0 }, QSE_NULL},
|
||||
{ {QSE_T("gsub"), 4}, 0, { {2, 3, QSE_T("xvr")}, qse_awk_fnc_gsub, 0 }, QSE_NULL},
|
||||
{ {QSE_T("index"), 5}, 0, { {2, 3, QSE_NULL}, qse_awk_fnc_index, 0 }, QSE_NULL},
|
||||
{ {QSE_T("length"), 6}, 1, { {0, 1, QSE_NULL}, qse_awk_fnc_length, 0 }, QSE_NULL},
|
||||
{ {QSE_T("match"), 5}, 0, { {2, 4, QSE_T("vxvr")}, qse_awk_fnc_match, 0 }, QSE_NULL},
|
||||
{ {QSE_T("split"), 5}, 0, { {2, 3, QSE_T("vrx")}, qse_awk_fnc_split, 0 }, QSE_NULL},
|
||||
{ {QSE_T("sprintf"), 7}, 0, { {1, A_MAX, QSE_NULL}, qse_awk_fnc_sprintf, 0 }, QSE_NULL},
|
||||
{ {QSE_T("sub"), 3}, 0, { {2, 3, QSE_T("xvr")}, qse_awk_fnc_sub, 0 }, QSE_NULL},
|
||||
{ {QSE_T("substr"), 6}, 0, { {2, 3, QSE_NULL}, qse_awk_fnc_substr, 0 }, QSE_NULL},
|
||||
{ {QSE_T("tolower"), 7}, 0, { {1, 1, QSE_NULL}, qse_awk_fnc_tolower, 0 }, QSE_NULL},
|
||||
{ {QSE_T("toupper"), 7}, 0, { {1, 1, QSE_NULL}, qse_awk_fnc_toupper, 0 }, QSE_NULL},
|
||||
|
||||
/* math functions */
|
||||
{ {QSE_T("sin"), 3}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL},
|
||||
{ {QSE_T("cos"), 3}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL},
|
||||
{ {QSE_T("tan"), 3}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL},
|
||||
{ {QSE_T("atan"), 4}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL},
|
||||
{ {QSE_T("atan2"), 5}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL},
|
||||
{ {QSE_T("log"), 3}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL},
|
||||
{ {QSE_T("log10"), 5}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL},
|
||||
{ {QSE_T("exp"), 3}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL},
|
||||
{ {QSE_T("sqrt"), 4}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL},
|
||||
{ {QSE_T("sin"), 3}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL},
|
||||
{ {QSE_T("cos"), 3}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL},
|
||||
{ {QSE_T("tan"), 3}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL},
|
||||
{ {QSE_T("atan"), 4}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL},
|
||||
{ {QSE_T("atan2"), 5}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL},
|
||||
{ {QSE_T("log"), 3}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL},
|
||||
{ {QSE_T("log10"), 5}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL},
|
||||
{ {QSE_T("exp"), 3}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL},
|
||||
{ {QSE_T("sqrt"), 4}, 0, { {A_MAX, 0, QSE_T("math") }, QSE_NULL, 0 }, QSE_NULL},
|
||||
|
||||
/* time functions */
|
||||
{ {QSE_T("mktime"), 6}, 0, { {A_MAX, 0, QSE_T("sys") }, QSE_NULL, 0 }, QSE_NULL},
|
||||
@ -704,7 +704,6 @@ int qse_awk_fnc_split (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
||||
a2 = (nargs >= 3)? qse_awk_rtx_getarg (rtx, 2): QSE_NULL;
|
||||
|
||||
a1_vtype = QSE_AWK_RTX_GETVALTYPE (rtx, a1);
|
||||
|
||||
QSE_ASSERT (a1_vtype == QSE_AWK_VAL_REF);
|
||||
|
||||
str.ptr = qse_awk_rtx_getvalstr(rtx, a0, &str.len);
|
||||
@ -714,7 +713,7 @@ int qse_awk_fnc_split (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
||||
{
|
||||
/* get the value from FS */
|
||||
t1 = qse_awk_rtx_getgbl(rtx, QSE_AWK_GBL_FS);
|
||||
t1_vtype = QSE_AWK_RTX_GETVALTYPE (rtx, t1);
|
||||
t1_vtype = QSE_AWK_RTX_GETVALTYPE(rtx, t1);
|
||||
if (t1_vtype == QSE_AWK_VAL_NIL)
|
||||
{
|
||||
fs.ptr = QSE_T(" ");
|
||||
@ -727,7 +726,7 @@ int qse_awk_fnc_split (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
||||
}
|
||||
else
|
||||
{
|
||||
fs.ptr = qse_awk_rtx_valtostrdup (rtx, t1, &fs.len);
|
||||
fs.ptr = qse_awk_rtx_valtostrdup(rtx, t1, &fs.len);
|
||||
if (fs.ptr == QSE_NULL) goto oops;
|
||||
fs_free = (qse_char_t*)fs.ptr;
|
||||
}
|
||||
@ -801,15 +800,11 @@ int qse_awk_fnc_split (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
||||
|
||||
if (fs.len <= 1)
|
||||
{
|
||||
p = qse_awk_rtx_strxntok (rtx,
|
||||
p, str.len, fs.ptr, fs.len, &tok);
|
||||
p = qse_awk_rtx_strxntok(rtx, p, str.len, fs.ptr, fs.len, &tok);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = qse_awk_rtx_strxntokbyrex (
|
||||
rtx, str.ptr, org_len, p, str.len,
|
||||
fs_rex, &tok, &errnum
|
||||
);
|
||||
p = qse_awk_rtx_strxntokbyrex(rtx, str.ptr, org_len, p, str.len, fs_rex, &tok, &errnum);
|
||||
if (p == QSE_NULL && errnum != QSE_AWK_ENOERR)
|
||||
{
|
||||
qse_awk_rtx_seterrnum (rtx, errnum, QSE_NULL);
|
||||
@ -821,7 +816,7 @@ int qse_awk_fnc_split (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
||||
{
|
||||
/* no field at all*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QSE_ASSERT ((tok.ptr != QSE_NULL && tok.len > 0) || tok.len == 0);
|
||||
|
||||
@ -848,13 +843,13 @@ int qse_awk_fnc_split (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
||||
/*if (str_free) QSE_AWK_FREE (rtx->awk, str_free);*/
|
||||
qse_awk_rtx_freevalstr (rtx, a0, str.ptr);
|
||||
|
||||
if (fs_free) QSE_AWK_FREE (rtx->awk, fs_free);
|
||||
if (fs_free) qse_awk_rtx_freemem (rtx, fs_free);
|
||||
|
||||
if (fs_rex_free)
|
||||
{
|
||||
if (rtx->gbl.ignorecase)
|
||||
qse_awk_freerex (rtx->awk, QSE_NULL, fs_rex_free);
|
||||
else
|
||||
else
|
||||
qse_awk_freerex (rtx->awk, fs_rex_free, QSE_NULL);
|
||||
}
|
||||
|
||||
@ -870,13 +865,13 @@ oops:
|
||||
/*if (str_free) QSE_AWK_FREE (rtx->awk, str_free);*/
|
||||
if (str.ptr) qse_awk_rtx_freevalstr (rtx, a0, str.ptr);
|
||||
|
||||
if (fs_free) QSE_AWK_FREE (rtx->awk, fs_free);
|
||||
if (fs_free) qse_awk_rtx_freemem (rtx, fs_free);
|
||||
|
||||
if (fs_rex_free)
|
||||
{
|
||||
if (rtx->gbl.ignorecase)
|
||||
qse_awk_freerex (rtx->awk, QSE_NULL, fs_rex_free);
|
||||
else
|
||||
else
|
||||
qse_awk_freerex (rtx->awk, fs_rex_free, QSE_NULL);
|
||||
}
|
||||
return -1;
|
||||
@ -1531,31 +1526,58 @@ static int fnc_ismap (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static QSE_INLINE int asort_compare (const void* x1, const void* x2, void* ctx)
|
||||
static QSE_INLINE int asort_compare (const void* x1, const void* x2, void* ctx, int* cv)
|
||||
{
|
||||
int n;
|
||||
if (qse_awk_rtx_cmpval((qse_awk_rtx_t*)ctx, (qse_awk_val_t*)x1, (qse_awk_val_t*)x2, &n) <= -1) return -1;
|
||||
return n;
|
||||
if (qse_awk_rtx_cmpval((qse_awk_rtx_t*)ctx, *(qse_awk_val_t**)x1, *(qse_awk_val_t**)x2, &n) <= -1) return -1;
|
||||
*cv = n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct cud_t
|
||||
{
|
||||
qse_awk_rtx_t* rtx;
|
||||
qse_awk_fun_t* fun;
|
||||
};
|
||||
|
||||
static QSE_INLINE int asort_compare_ud (const void* x1, const void* x2, void* ctx, int* cv)
|
||||
{
|
||||
struct cud_t* cud = (struct cud_t*)ctx;
|
||||
qse_awk_val_t* r, * args[2];
|
||||
qse_awk_int_t rv;
|
||||
|
||||
args[0] = *(qse_awk_val_t**)x1;
|
||||
args[1] = *(qse_awk_val_t**)x2;
|
||||
r = qse_awk_rtx_callfun(cud->rtx, cud->fun, args, 2);
|
||||
if (!r) return -1;
|
||||
if (qse_awk_rtx_valtoint(cud->rtx, r, &rv) <= -1) return -1;
|
||||
*cv = rv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
||||
{
|
||||
qse_size_t nargs;
|
||||
qse_awk_val_t* a0, * a2;
|
||||
qse_awk_val_t* a0, * a0_val, * a1, * a2;
|
||||
qse_awk_val_type_t a0_type, v_type;
|
||||
qse_awk_val_t* r, * rmap;
|
||||
qse_awk_int_t rv = 0; /* as if no element in the map */
|
||||
qse_awk_val_map_itr_t itr;
|
||||
qse_awk_fun_t* fun;
|
||||
qse_awk_fun_t* fun = QSE_NULL;
|
||||
qse_size_t msz, i;
|
||||
qse_awk_val_t** va;
|
||||
int x;
|
||||
|
||||
nargs = qse_awk_rtx_getnargs(rtx);
|
||||
|
||||
a0 = qse_awk_rtx_getarg(rtx, 0);
|
||||
|
||||
if (QSE_AWK_RTX_GETVALTYPE(rtx, a0) != QSE_AWK_VAL_MAP)
|
||||
a0_type = QSE_AWK_RTX_GETVALTYPE(rtx, a0);
|
||||
QSE_ASSERT (a0_type == QSE_AWK_VAL_REF);
|
||||
|
||||
v_type = qse_awk_rtx_getrefvaltype(rtx, (qse_awk_val_ref_t*)a0);
|
||||
if (v_type != QSE_AWK_VAL_MAP)
|
||||
{
|
||||
if (QSE_AWK_RTX_GETVALTYPE(rtx, a0) == QSE_AWK_VAL_NIL)
|
||||
if (v_type == QSE_AWK_VAL_NIL)
|
||||
{
|
||||
/* treat it as an empty value */
|
||||
goto done;
|
||||
@ -1565,30 +1587,43 @@ static int fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
||||
return -1;
|
||||
}
|
||||
|
||||
a0_val = qse_awk_rtx_getrefval(rtx, (qse_awk_val_ref_t*)a0);
|
||||
QSE_ASSERT (QSE_AWK_RTX_GETVALTYPE(rtx, a0_val) == QSE_AWK_VAL_MAP);
|
||||
|
||||
if (nargs >= 2)
|
||||
{
|
||||
a2 = qse_awk_rtx_getarg(rtx, 2);
|
||||
if (QSE_AWK_RTX_GETVALTYPE(rtx, a2) != QSE_AWK_VAL_FUN)
|
||||
a1 = qse_awk_rtx_getarg(rtx, 1); /* destination map */
|
||||
|
||||
if (nargs >= 3)
|
||||
{
|
||||
qse_awk_rtx_seterrnum (rtx, QSE_AWK_EINVAL, QSE_NULL);
|
||||
return -1;
|
||||
}
|
||||
a2 = qse_awk_rtx_getarg(rtx, 2);
|
||||
if (QSE_AWK_RTX_GETVALTYPE(rtx, a2) != QSE_AWK_VAL_FUN)
|
||||
{
|
||||
qse_awk_rtx_seterrnum (rtx, QSE_AWK_EINVAL, QSE_NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fun = ((qse_awk_val_fun_t*)a2)->fun;
|
||||
if (fun->nargs < 2)
|
||||
{
|
||||
/* the comparison accepts less than 2 arguments */
|
||||
qse_awk_rtx_seterrnum (rtx, QSE_AWK_EINVAL, QSE_NULL);
|
||||
return -1;
|
||||
fun = ((qse_awk_val_fun_t*)a2)->fun;
|
||||
if (fun->nargs < 2)
|
||||
{
|
||||
/* the comparison accepts less than 2 arguments */
|
||||
qse_awk_rtx_seterrnum (rtx, QSE_AWK_EINVAL, QSE_NULL);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
a1 = a0; /* let a0 be the destination. a0 is both source and destination */
|
||||
}
|
||||
|
||||
if (!qse_awk_rtx_getfirstmapvalitr(rtx, a0, &itr)) goto done; /* map empty */
|
||||
|
||||
msz = qse_htb_getsize(((qse_awk_val_map_t*)a0)->map);
|
||||
if (!qse_awk_rtx_getfirstmapvalitr(rtx, a0_val, &itr)) goto done; /* map empty */
|
||||
|
||||
msz = qse_htb_getsize(((qse_awk_val_map_t*)a0_val)->map);
|
||||
QSE_ASSERT (msz > 0);
|
||||
|
||||
va = (qse_awk_val_t**)qse_awk_rtx_allocmem(rtx, msz * QSE_SIZEOF(qse_awk_val_t*));
|
||||
va = (qse_awk_val_t**)qse_awk_rtx_allocmem(rtx, msz * QSE_SIZEOF(*va));
|
||||
if (!va) return -1;
|
||||
|
||||
i = 0;
|
||||
@ -1596,9 +1631,25 @@ static int fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
||||
{
|
||||
va[i++] = (qse_awk_val_t*)QSE_AWK_VAL_MAP_ITR_VAL(&itr);
|
||||
}
|
||||
while (qse_awk_rtx_getnextmapvalitr(rtx, a0, &itr));
|
||||
while (qse_awk_rtx_getnextmapvalitr(rtx, a0_val, &itr));
|
||||
|
||||
qse_qsort (va, msz, QSE_SIZEOF(*va), asort_compare, rtx);
|
||||
if (fun)
|
||||
{
|
||||
struct cud_t cud;
|
||||
cud.rtx = rtx;
|
||||
cud.fun = fun;
|
||||
x = qse_qsortx(va, msz, QSE_SIZEOF(*va), asort_compare_ud, &cud);
|
||||
}
|
||||
else
|
||||
{
|
||||
x = qse_qsortx(va, msz, QSE_SIZEOF(*va), asort_compare, rtx);
|
||||
}
|
||||
|
||||
if (x <= -1)
|
||||
{
|
||||
qse_awk_rtx_freemem (rtx, va);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rmap = qse_awk_rtx_makemapval(rtx);
|
||||
if (!rmap)
|
||||
@ -1622,7 +1673,7 @@ static int fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
||||
QSE_NULL
|
||||
);
|
||||
|
||||
if (qse_awk_rtx_setmapvalfld (rtx, rmap, ridx, ridx_len, va[i]) == QSE_NULL)
|
||||
if (qse_awk_rtx_setmapvalfld(rtx, rmap, ridx, ridx_len, va[i]) == QSE_NULL)
|
||||
{
|
||||
qse_awk_rtx_freeval (rtx, rmap, 0);
|
||||
qse_awk_rtx_freemem (rtx, va);
|
||||
@ -1630,30 +1681,13 @@ static int fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
#if 0
|
||||
/* TODO: complete this function */
|
||||
r = qse_awk_rtx_callfun(rtx, fun, valargs, nargs);
|
||||
if (qse_awk_rtx_valtoint(rtx, r, &rv) <= -1) return -1;
|
||||
|
||||
if (rv > 0)
|
||||
{
|
||||
}
|
||||
else if (rv < 0)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
rv = msz;
|
||||
qse_awk_rtx_freemem (rtx, va);
|
||||
/* TODO: set the resulting map back to a0.
|
||||
* or to a1 if a1 is given */
|
||||
qse_awk_rtx_setretval (rtx, rmap);
|
||||
return 0;
|
||||
|
||||
qse_awk_rtx_refupval (rtx, rmap);
|
||||
x = qse_awk_rtx_setrefval (rtx, (qse_awk_val_ref_t*)a1, rmap);
|
||||
qse_awk_rtx_refdownval (rtx, rmap);
|
||||
if (x <= -1) return -1;
|
||||
|
||||
done:
|
||||
r = qse_awk_rtx_makeintval(rtx, rv);
|
||||
|
@ -1650,7 +1650,7 @@ qse_awk_val_t* qse_awk_rtx_callfun (
|
||||
}
|
||||
else
|
||||
{
|
||||
/* thr return value captured in termination by exit()
|
||||
/* the return value captured in termination by exit()
|
||||
* is reference-counted up in capture_retval_on_exit().
|
||||
* let's do the same thing for the return value normally
|
||||
* returned. */
|
||||
@ -5996,7 +5996,7 @@ static qse_awk_val_t* __eval_call (
|
||||
}
|
||||
|
||||
/* push all arguments onto the stack */
|
||||
nargs = argpusher (run, call, apdata);
|
||||
nargs = argpusher(run, call, apdata);
|
||||
if (nargs == (qse_size_t)-1)
|
||||
{
|
||||
UNWIND_RTX_STACK_BASE (run);
|
||||
@ -6049,7 +6049,7 @@ static qse_awk_val_t* __eval_call (
|
||||
{
|
||||
run->errinf.num = QSE_AWK_ENOERR;
|
||||
|
||||
n = call->u.fnc.spec.impl (run, &call->u.fnc.info);
|
||||
n = call->u.fnc.spec.impl(run, &call->u.fnc.info);
|
||||
|
||||
if (n <= -1)
|
||||
{
|
||||
|
@ -1911,6 +1911,69 @@ qse_awk_int_t qse_awk_rtx_hashval (qse_awk_rtx_t* rtx, qse_awk_val_t* v)
|
||||
return hv & ~(((qse_awk_uint_t)1) << ((QSE_SIZEOF(qse_awk_uint_t) * 8) - 1));
|
||||
}
|
||||
|
||||
qse_awk_val_type_t qse_awk_rtx_getrefvaltype (qse_awk_rtx_t* rtx, qse_awk_val_ref_t* ref)
|
||||
{
|
||||
/* return the type of the value that the reference points to */
|
||||
switch (ref->id)
|
||||
{
|
||||
case QSE_AWK_VAL_REF_POS:
|
||||
{
|
||||
return QSE_AWK_VAL_STR;
|
||||
}
|
||||
case QSE_AWK_VAL_REF_GBL:
|
||||
{
|
||||
qse_size_t idx;
|
||||
qse_awk_val_t* v;
|
||||
idx = (qse_size_t)ref->adr;
|
||||
v = RTX_STACK_GBL(rtx, idx);
|
||||
return QSE_AWK_RTX_GETVALTYPE(rtx, v);
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
qse_awk_val_t** xref = (qse_awk_val_t**)ref->adr;
|
||||
qse_awk_val_t* v;
|
||||
|
||||
/* A reference value is not able to point to another
|
||||
* refernce value for the way values are represented
|
||||
* in QSEAWK */
|
||||
v = *xref;
|
||||
QSE_ASSERT (QSE_AWK_RTX_GETVALTYPE(rtx, v) != QSE_AWK_VAL_REF);
|
||||
return QSE_AWK_RTX_GETVALTYPE(rtx, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qse_awk_val_t* qse_awk_rtx_getrefval (qse_awk_rtx_t* rtx, qse_awk_val_ref_t* ref)
|
||||
{
|
||||
switch (ref->id)
|
||||
{
|
||||
case QSE_AWK_VAL_REF_POS:
|
||||
{
|
||||
/* a positional doesn't contain a value. you should use qse_awk_rtx_valtoXXX()
|
||||
* like qse_awk_rtx_valtostr(), qse_Awk_rtx_valtoint() */
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
case QSE_AWK_VAL_REF_GBL:
|
||||
{
|
||||
qse_size_t idx;
|
||||
idx = (qse_size_t)ref->adr;
|
||||
return RTX_STACK_GBL(rtx, idx);
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
qse_awk_val_t** xref = (qse_awk_val_t**)ref->adr;
|
||||
/* A reference value is not able to point to another
|
||||
* refernce value for the way values are represented
|
||||
* in QSEAWK */
|
||||
QSE_ASSERT (QSE_AWK_RTX_GETVALTYPE (rtx, *xref)!= QSE_AWK_VAL_REF);
|
||||
return *xref;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int qse_awk_rtx_setrefval (qse_awk_rtx_t* rtx, qse_awk_val_ref_t* ref, qse_awk_val_t* val)
|
||||
{
|
||||
qse_awk_val_type_t vtype = QSE_AWK_RTX_GETVALTYPE (rtx, val);
|
||||
@ -2001,7 +2064,7 @@ int qse_awk_rtx_setrefval (qse_awk_rtx_t* rtx, qse_awk_val_ref_t* ref, qse_awk_v
|
||||
qse_awk_val_type_t rref_vtype;
|
||||
|
||||
rref = (qse_awk_val_t**)ref->adr; /* old value pointer */
|
||||
rref_vtype = QSE_AWK_RTX_GETVALTYPE (rtx, *rref); /* old value type */
|
||||
rref_vtype = QSE_AWK_RTX_GETVALTYPE(rtx, *rref); /* old value type */
|
||||
if (vtype == QSE_AWK_VAL_MAP)
|
||||
{
|
||||
/* new value: map, old value: nil or map => ok */
|
||||
|
@ -64,8 +64,8 @@
|
||||
/*
|
||||
* Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
|
||||
*/
|
||||
#define swapcode(TYPE,parmi,parmj,n) { \
|
||||
qse_size_t i = (n) / sizeof (TYPE); \
|
||||
#define swapcode(TYPE,parmi,parmj,n) do { \
|
||||
qse_size_t i = (n) / QSE_SIZEOF (TYPE); \
|
||||
register TYPE *pi = (TYPE*)(parmi); \
|
||||
register TYPE *pj = (TYPE*)(parmj); \
|
||||
do { \
|
||||
@ -73,29 +73,38 @@
|
||||
*pi++ = *pj; \
|
||||
*pj++ = t; \
|
||||
} while (--i > 0); \
|
||||
}
|
||||
} while(0)
|
||||
|
||||
#define SWAPINIT(a,size) \
|
||||
swaptype = ((qse_byte_t*)a-(qse_byte_t*)0)%sizeof(long) || \
|
||||
size % sizeof(long) ? 2 : size == sizeof(long)? 0 : 1;
|
||||
|
||||
static QSE_INLINE void swapfunc (
|
||||
qse_byte_t* a, qse_byte_t* b, int n, int swaptype)
|
||||
{
|
||||
if (swaptype <= 1)
|
||||
swapcode(long, a, b, n)
|
||||
else
|
||||
swapcode(qse_byte_t, a, b, n)
|
||||
}
|
||||
#define get_swaptype(a, elemsize) (((qse_byte_t*)(a) - (qse_byte_t*)0) % QSE_SIZEOF(long) || elemsize % QSE_SIZEOF(long)? 2 : elemsize == QSE_SIZEOF(long)? 0 : 1)
|
||||
|
||||
#define swap(a, b) \
|
||||
if (swaptype == 0) { \
|
||||
long t = *(long*)(a); \
|
||||
*(long*)(a) = *(long*)(b); \
|
||||
*(long*)(b) = t; \
|
||||
} else swapfunc(a, b, size, swaptype)
|
||||
|
||||
#define vecswap(a,b,n) if ((n) > 0) swapfunc(a, b, n, swaptype)
|
||||
#define swap(a, b, elemsize) do { \
|
||||
switch (swaptype) \
|
||||
{ \
|
||||
case 0: \
|
||||
{ \
|
||||
long t = *(long*)(a); \
|
||||
*(long*)(a) = *(long*)(b); \
|
||||
*(long*)(b) = t; \
|
||||
break; \
|
||||
} \
|
||||
case 1: \
|
||||
swapcode(long, a, b, elemsize); \
|
||||
break; \
|
||||
default: \
|
||||
swapcode(qse_byte_t, a, b, elemsize); \
|
||||
break; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define vecswap(a,b,n) do { \
|
||||
if ((n) > 0) \
|
||||
{ \
|
||||
if (swaptype <= 1) swapcode(long, a, b, n); \
|
||||
else swapcode(qse_byte_t, a, b, n); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
static QSE_INLINE qse_byte_t* med3 (qse_byte_t* a, qse_byte_t* b, qse_byte_t* c, qse_sort_comper_t comper, void* ctx)
|
||||
{
|
||||
@ -111,26 +120,48 @@ static QSE_INLINE qse_byte_t* med3 (qse_byte_t* a, qse_byte_t* b, qse_byte_t* c,
|
||||
}
|
||||
}
|
||||
|
||||
static QSE_INLINE qse_byte_t* med3x (qse_byte_t* a, qse_byte_t* b, qse_byte_t* c, qse_sort_comperx_t comper, void* ctx)
|
||||
{
|
||||
int n;
|
||||
|
||||
if (comper(a, b, ctx, &n) <= -1) return QSE_NULL;
|
||||
if (n < 0)
|
||||
{
|
||||
if (comper(b, c, ctx, &n) <= -1) return QSE_NULL;
|
||||
if (n < 0) return b;
|
||||
|
||||
if (comper(a, c, ctx, &n) <= -1) return QSE_NULL;
|
||||
return (n < 0)? c: a;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (comper(b, c, ctx, &n) <= -1) return QSE_NULL;
|
||||
if (n > 0) return b;
|
||||
if (comper(a, c, ctx, &n) <= -1) return QSE_NULL;
|
||||
return (n > 0)? c: a;
|
||||
}
|
||||
}
|
||||
|
||||
void qse_qsort (void* base, qse_size_t nmemb, qse_size_t size, qse_sort_comper_t comper, void* ctx)
|
||||
{
|
||||
qse_byte_t*pa, *pb, *pc, *pd, *pl, *pm, *pn;
|
||||
qse_byte_t* pa, * pb, * pc, * pd, * pl, * pm, * pn;
|
||||
int swaptype, swap_cnt;
|
||||
long r;
|
||||
qse_size_t d;
|
||||
register qse_byte_t*a = (qse_byte_t*)base;
|
||||
register qse_byte_t* a = (qse_byte_t*)base;
|
||||
|
||||
loop:
|
||||
SWAPINIT(a, size);
|
||||
swaptype = get_swaptype(a, size);
|
||||
|
||||
swap_cnt = 0;
|
||||
if (nmemb < 7)
|
||||
{
|
||||
for (pm = (qse_byte_t*)a + size;
|
||||
pm < (qse_byte_t*) a + nmemb * size; pm += size)
|
||||
qse_byte_t* end = (qse_byte_t*)a + (nmemb * size);
|
||||
for (pm = (qse_byte_t*)a + size; pm < end; pm += size)
|
||||
{
|
||||
for (pl = pm; pl > (qse_byte_t*)a && comper(pl - size, pl, ctx) > 0; pl -= size)
|
||||
{
|
||||
swap(pl, pl - size);
|
||||
swap(pl, pl - size, size);
|
||||
}
|
||||
}
|
||||
return;
|
||||
@ -149,7 +180,7 @@ loop:
|
||||
}
|
||||
pm = med3(pl, pm, pn, comper, ctx);
|
||||
}
|
||||
swap(a, pm);
|
||||
swap(a, pm, size);
|
||||
pa = pb = (qse_byte_t*)a + size;
|
||||
|
||||
pc = pd = (qse_byte_t*)a + (nmemb - 1) * size;
|
||||
@ -160,7 +191,7 @@ loop:
|
||||
if (r == 0)
|
||||
{
|
||||
swap_cnt = 1;
|
||||
swap(pa, pb);
|
||||
swap(pa, pb, size);
|
||||
pa += size;
|
||||
}
|
||||
pb += size;
|
||||
@ -170,13 +201,13 @@ loop:
|
||||
if (r == 0)
|
||||
{
|
||||
swap_cnt = 1;
|
||||
swap(pc, pd);
|
||||
swap(pc, pd, size);
|
||||
pd -= size;
|
||||
}
|
||||
pc -= size;
|
||||
}
|
||||
if (pb > pc) break;
|
||||
swap (pb, pc);
|
||||
swap (pb, pc, size);
|
||||
swap_cnt = 1;
|
||||
pb += size;
|
||||
pc -= size;
|
||||
@ -188,10 +219,9 @@ loop:
|
||||
for (pm = (qse_byte_t*)a + size;
|
||||
pm < (qse_byte_t*)a + nmemb * size; pm += size)
|
||||
{
|
||||
for (pl = pm; pl > (qse_byte_t*)a &&
|
||||
comper(pl - size, pl, ctx) > 0; pl -= size)
|
||||
for (pl = pm; pl > (qse_byte_t*)a && comper(pl - size, pl, ctx) > 0; pl -= size)
|
||||
{
|
||||
swap(pl, pl - size);
|
||||
swap(pl, pl - size, size);
|
||||
}
|
||||
}
|
||||
return;
|
||||
@ -215,6 +245,134 @@ loop:
|
||||
/* qsort(pn - r, r / size, size, comper);*/
|
||||
}
|
||||
|
||||
int qse_qsortx (void* base, qse_size_t nmemb, qse_size_t size, qse_sort_comperx_t comper, void* ctx)
|
||||
{
|
||||
qse_byte_t* pa, * pb, * pc, * pd, * pl, * pm, * pn;
|
||||
int swaptype, swap_cnt;
|
||||
long r;
|
||||
int n;
|
||||
qse_size_t d;
|
||||
register qse_byte_t* a = (qse_byte_t*)base;
|
||||
|
||||
loop:
|
||||
swaptype = get_swaptype(a, size);
|
||||
|
||||
swap_cnt = 0;
|
||||
if (nmemb < 7)
|
||||
{
|
||||
qse_byte_t* end = (qse_byte_t*)a + (nmemb * size);
|
||||
for (pm = (qse_byte_t*)a + size; pm < end; pm += size)
|
||||
{
|
||||
pl = pm;
|
||||
while (pl > (qse_byte_t*)a)
|
||||
{
|
||||
qse_byte_t* pl2 = pl - size;
|
||||
if (comper(pl2, pl, ctx, &n) <= -1) return -1;
|
||||
if (n <= 0) break;
|
||||
swap (pl, pl2, size);
|
||||
pl = pl2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
pm = (qse_byte_t*)a + (nmemb / 2) * size;
|
||||
if (nmemb > 7)
|
||||
{
|
||||
pl = (qse_byte_t*)a;
|
||||
pn = (qse_byte_t*)a + (nmemb - 1) * size;
|
||||
if (nmemb > 40)
|
||||
{
|
||||
d = (nmemb / 8) * size;
|
||||
pl = med3x(pl, pl + d, pl + 2 * d, comper, ctx);
|
||||
if (!pl) return -1;
|
||||
pm = med3x(pm - d, pm, pm + d, comper, ctx);
|
||||
if (!pm) return -1;
|
||||
pn = med3x(pn - 2 * d, pn - d, pn, comper, ctx);
|
||||
if (!pn) return -1;
|
||||
}
|
||||
pm = med3x(pl, pm, pn, comper, ctx);
|
||||
if (!pm) return -1;
|
||||
}
|
||||
swap(a, pm, size);
|
||||
pa = pb = (qse_byte_t*)a + size;
|
||||
|
||||
pc = pd = (qse_byte_t*)a + (nmemb - 1) * size;
|
||||
for (;;)
|
||||
{
|
||||
while (pb <= pc)
|
||||
{
|
||||
if (comper(pb, a, ctx, &n) <= -1) return -1;
|
||||
if (n > 0) break;
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
swap_cnt = 1;
|
||||
swap(pa, pb, size);
|
||||
pa += size;
|
||||
}
|
||||
pb += size;
|
||||
}
|
||||
while (pb <= pc)
|
||||
{
|
||||
if (comper(pc, a, ctx, &n) <= -1) return -1;
|
||||
if (n < 0) break;
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
swap_cnt = 1;
|
||||
swap(pc, pd, size);
|
||||
pd -= size;
|
||||
}
|
||||
pc -= size;
|
||||
}
|
||||
if (pb > pc) break;
|
||||
swap (pb, pc, size);
|
||||
swap_cnt = 1;
|
||||
pb += size;
|
||||
pc -= size;
|
||||
}
|
||||
|
||||
if (swap_cnt == 0)
|
||||
{
|
||||
/* switch to insertion sort */
|
||||
qse_byte_t* end = (qse_byte_t*)a + (nmemb * size);
|
||||
for (pm = (qse_byte_t*)a + size; pm < end; pm += size)
|
||||
{
|
||||
pl = pm;
|
||||
while (pl > (qse_byte_t*)a)
|
||||
{
|
||||
if (comper(pl - size, pl, ctx, &n) <= -1) return -1;
|
||||
if (n <= 0) break;
|
||||
swap(pl, pl - size, size);
|
||||
pl = pl - size;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
pn = (qse_byte_t*)a + nmemb * size;
|
||||
r = qsort_min(pa - (qse_byte_t*)a, pb - pa);
|
||||
vecswap (a, pb - r, r);
|
||||
r = qsort_min (pd - pc, pn - pd - size);
|
||||
vecswap (pb, pn - r, r);
|
||||
|
||||
if ((r = pb - pa) > size)
|
||||
{
|
||||
if (qse_qsortx(a, r / size, size, comper, ctx) <= -1) return -1;
|
||||
}
|
||||
|
||||
if ((r = pd - pc) > size)
|
||||
{
|
||||
/* Iterate rather than recurse to save stack space */
|
||||
a = pn - r;
|
||||
nmemb = r / size;
|
||||
goto loop;
|
||||
}
|
||||
/* qsortx(pn - r, r / size, size, comper);*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user