diff --git a/qse/lib/awk/fnc.c b/qse/lib/awk/fnc.c index a2aaade2..6614c06b 100644 --- a/qse/lib/awk/fnc.c +++ b/qse/lib/awk/fnc.c @@ -25,7 +25,9 @@ */ #include "awk-prv.h" - +#include +#include + static int fnc_close (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi); static int fnc_fflush (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi); static int fnc_int (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi); @@ -1529,16 +1531,23 @@ 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) +{ + 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; +} + 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* r; + 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_size_t msz, i; - const qse_awk_val_t** va; + qse_awk_val_t** va; nargs = qse_awk_rtx_getnargs(rtx); @@ -1579,16 +1588,48 @@ static int fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) msz = qse_htb_getsize(((qse_awk_val_map_t*)a0)->map); QSE_ASSERT (msz > 0); - va = (const 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(qse_awk_val_t*)); if (!va) return -1; i = 0; do { - va[i++] = QSE_AWK_VAL_MAP_ITR_VAL(&itr); + va[i++] = (qse_awk_val_t*)QSE_AWK_VAL_MAP_ITR_VAL(&itr); } while (qse_awk_rtx_getnextmapvalitr(rtx, a0, &itr)); + qse_qsort (va, msz, QSE_SIZEOF(*va), asort_compare, rtx); + + rmap = qse_awk_rtx_makemapval(rtx); + if (!rmap) + { + qse_awk_rtx_freemem (rtx, va); + return -1; + } + + for (i = 0; i < msz; i++) + { + qse_char_t ridx[128]; + qse_size_t ridx_len; + + ridx_len = qse_fmtuintmax ( + ridx, + QSE_COUNTOF(ridx), + i, + 10 | QSE_FMTINTMAX_NOTRUNC | QSE_FMTINTMAX_NONULL, + -1, + QSE_T('\0'), + 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); + return -1; + } + } + { #if 0 /* TODO: complete this function */ @@ -1609,6 +1650,10 @@ static int fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) 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; done: r = qse_awk_rtx_makeintval(rtx, rv); diff --git a/qse/lib/awk/run.c b/qse/lib/awk/run.c index 0e61efc8..0a784489 100644 --- a/qse/lib/awk/run.c +++ b/qse/lib/awk/run.c @@ -1023,8 +1023,8 @@ static int init_rtx (qse_awk_rtx_t* rtx, qse_awk_t* awk, qse_awk_rio_t* rio) if (qse_str_init(&rtx->format.out, MMGR(rtx), 256) <= -1) goto oops_3; if (qse_str_init(&rtx->format.fmt, MMGR(rtx), 256) <= -1) goto oops_4; - if (qse_str_init(&rtx->formatmbs.out, MMGR(rtx), 256) <= -1) goto oops_5; - if (qse_str_init(&rtx->formatmbs.fmt, MMGR(rtx), 256) <= -1) goto oops_6; + if (qse_mbs_init(&rtx->formatmbs.out, MMGR(rtx), 256) <= -1) goto oops_5; + if (qse_mbs_init(&rtx->formatmbs.fmt, MMGR(rtx), 256) <= -1) goto oops_6; rtx->named = qse_htb_open(MMGR(rtx), QSE_SIZEOF(rtx), 1024, 70, QSE_SIZEOF(qse_char_t), 1); if (!rtx->named) goto oops_7; @@ -1073,9 +1073,9 @@ oops_9: oops_8: qse_htb_close (rtx->named); oops_7: - qse_str_fini (&rtx->formatmbs.fmt); + qse_mbs_fini (&rtx->formatmbs.fmt); oops_6: - qse_str_fini (&rtx->formatmbs.out); + qse_mbs_fini (&rtx->formatmbs.out); oops_5: qse_str_fini (&rtx->format.fmt); oops_4: @@ -1158,8 +1158,8 @@ static void fini_rtx (qse_awk_rtx_t* rtx, int fini_globals) QSE_AWK_FREE (rtx->awk, rtx->formatmbs.tmp.ptr); rtx->formatmbs.tmp.ptr = QSE_NULL; rtx->formatmbs.tmp.len = 0; - qse_str_fini (&rtx->formatmbs.fmt); - qse_str_fini (&rtx->formatmbs.out); + qse_mbs_fini (&rtx->formatmbs.fmt); + qse_mbs_fini (&rtx->formatmbs.out); QSE_AWK_FREE (rtx->awk, rtx->format.tmp.ptr); rtx->format.tmp.ptr = QSE_NULL; @@ -4192,12 +4192,13 @@ static qse_awk_val_t* eval_binop_band ( enum cmp_op_t { - CMP_OP_EQ = 0, - CMP_OP_NE = 1, - CMP_OP_GT = 2, - CMP_OP_GE = 3, - CMP_OP_LT = 4, - CMP_OP_LE = 5 + CMP_OP_NONE = 0, + CMP_OP_EQ = 1, + CMP_OP_NE = 2, + CMP_OP_GT = 3, + CMP_OP_GE = 4, + CMP_OP_LT = 5, + CMP_OP_LE = 6 }; typedef enum cmp_op_t cmp_op_t; @@ -4205,6 +4206,7 @@ static QSE_INLINE cmp_op_t inverse_cmp_op (cmp_op_t op) { static cmp_op_t inverse_cmp_op_tab[] = { + CMP_OP_NONE, CMP_OP_NE, CMP_OP_EQ, CMP_OP_LT, @@ -4215,7 +4217,7 @@ static QSE_INLINE cmp_op_t inverse_cmp_op (cmp_op_t op) return inverse_cmp_op_tab[op]; } -static QSE_INLINE int __cmp_ensure_not_equal (cmp_op_t op_hint) +static QSE_INLINE int __cmp_ensure_not_equal (qse_awk_rtx_t* rtx, cmp_op_t op_hint) { /* checking equality is mostly obvious. however, it is not possible * to test if one is less/greater than the other for some operands. @@ -4236,6 +4238,10 @@ static QSE_INLINE int __cmp_ensure_not_equal (cmp_op_t op_hint) return -1; /* make GE false by claiming less */ case CMP_OP_LE: return 1; /* make LE false by claiming greater */ + + default: + SETERR_COD (rtx, QSE_AWK_EOPERAND); + return -1; } } @@ -4271,7 +4277,7 @@ static QSE_INLINE int __cmp_nil_mbs (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qs static QSE_INLINE int __cmp_nil_fun (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { /* != -> true, all others -> false */ - return __cmp_ensure_not_equal(op_hint); + return __cmp_ensure_not_equal(rtx, op_hint); } static QSE_INLINE int __cmp_nil_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) @@ -4403,7 +4409,7 @@ static QSE_INLINE int __cmp_int_mbs (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qs static QSE_INLINE int __cmp_int_fun (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { - return __cmp_ensure_not_equal(op_hint); + return __cmp_ensure_not_equal(rtx, op_hint); } static QSE_INLINE int __cmp_int_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) @@ -4515,7 +4521,7 @@ static QSE_INLINE int __cmp_flt_mbs (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qs static QSE_INLINE int __cmp_flt_fun (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { - return __cmp_ensure_not_equal(op_hint); + return __cmp_ensure_not_equal(rtx, op_hint); } static QSE_INLINE int __cmp_flt_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) @@ -4653,12 +4659,12 @@ static QSE_INLINE int __cmp_str_mbs (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qs static QSE_INLINE int __cmp_str_fun (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { - return __cmp_ensure_not_equal(op_hint); + return __cmp_ensure_not_equal(rtx, op_hint); } static QSE_INLINE int __cmp_str_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { - return __cmp_ensure_not_equal(op_hint); + return __cmp_ensure_not_equal(rtx, op_hint); } /* -------------------------------------------------------------------- */ @@ -4704,49 +4710,49 @@ static QSE_INLINE int __cmp_mbs_mbs (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qs static QSE_INLINE int __cmp_mbs_fun (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { - return __cmp_ensure_not_equal(op_hint); + return __cmp_ensure_not_equal(rtx, op_hint); } static QSE_INLINE int __cmp_mbs_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { - return __cmp_ensure_not_equal(op_hint); + return __cmp_ensure_not_equal(rtx, op_hint); } /* -------------------------------------------------------------------- */ static QSE_INLINE int __cmp_fun_nil (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { - return __cmp_ensure_not_equal(op_hint); + return __cmp_ensure_not_equal(rtx, op_hint); } static QSE_INLINE int __cmp_fun_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { - return __cmp_ensure_not_equal(op_hint); + return __cmp_ensure_not_equal(rtx, op_hint); } static QSE_INLINE int __cmp_fun_flt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { - return __cmp_ensure_not_equal(op_hint); + return __cmp_ensure_not_equal(rtx, op_hint); } static QSE_INLINE int __cmp_fun_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { - return __cmp_ensure_not_equal(op_hint); + return __cmp_ensure_not_equal(rtx, op_hint); } static QSE_INLINE int __cmp_fun_mbs (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { - return __cmp_ensure_not_equal(op_hint); + return __cmp_ensure_not_equal(rtx, op_hint); } static QSE_INLINE int __cmp_fun_fun (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { - return (((qse_awk_val_fun_t*)left)->fun == ((qse_awk_val_fun_t*)right)->fun)? 0: __cmp_ensure_not_equal(op_hint); + return (((qse_awk_val_fun_t*)left)->fun == ((qse_awk_val_fun_t*)right)->fun)? 0: __cmp_ensure_not_equal(rtx, op_hint); } static QSE_INLINE int __cmp_fun_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { - return __cmp_ensure_not_equal(op_hint); + return __cmp_ensure_not_equal(rtx, op_hint); } /* -------------------------------------------------------------------- */ @@ -4777,17 +4783,17 @@ static QSE_INLINE int __cmp_map_flt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qs static QSE_INLINE int __cmp_map_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { - return __cmp_ensure_not_equal(op_hint); + return __cmp_ensure_not_equal(rtx, op_hint); } static QSE_INLINE int __cmp_map_mbs (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { - return __cmp_ensure_not_equal(op_hint); + return __cmp_ensure_not_equal(rtx, op_hint); } static QSE_INLINE int __cmp_map_fun (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { - return __cmp_ensure_not_equal(op_hint); + return __cmp_ensure_not_equal(rtx, op_hint); } static QSE_INLINE int __cmp_map_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) @@ -4799,8 +4805,9 @@ static QSE_INLINE int __cmp_map_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qs /* -------------------------------------------------------------------- */ -static QSE_INLINE int __cmp_val(qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) +static QSE_INLINE int __cmp_val (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint, int* ret) { + int n; qse_awk_val_type_t lvtype, rvtype; typedef int (*cmp_val_t) (qse_awk_rtx_t*, qse_awk_val_t*, qse_awk_val_t*, cmp_op_t op_hint); @@ -4824,7 +4831,7 @@ static QSE_INLINE int __cmp_val(qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk { /* a map can't be compared againt other values */ SETERR_COD (rtx, QSE_AWK_EOPERAND); - return CMP_ERROR; + return -1; } QSE_ASSERT (lvtype >= QSE_AWK_VAL_NIL && lvtype <= QSE_AWK_VAL_MAP); @@ -4844,7 +4851,16 @@ static QSE_INLINE int __cmp_val(qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk * operation. the comparision function should return 0 if equal, -1 if less, * 1 if greater, CMP_ERROR upon error regardless of this hint. */ - return func[lvtype * 7 + rvtype](rtx, left, right, op_hint); + n = func[lvtype * 7 + rvtype](rtx, left, right, op_hint); + if (n == CMP_ERROR) return -1; + + *ret = n; + return 0; +} + +int qse_awk_rtx_cmpval (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, int* ret) +{ + return __cmp_val(rtx, left, right, CMP_OP_NONE, ret); } static int teq_val (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) @@ -4921,43 +4937,43 @@ static qse_awk_val_t* eval_binop_tne (qse_awk_rtx_t* rtx, qse_awk_val_t* left, q static qse_awk_val_t* eval_binop_eq (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) { - int n = __cmp_val(rtx, left, right, CMP_OP_EQ); - if (n == CMP_ERROR) return QSE_NULL; + int n; + if (__cmp_val(rtx, left, right, CMP_OP_EQ, &n) <= -1) return QSE_NULL; return (n == 0)? QSE_AWK_VAL_ONE: QSE_AWK_VAL_ZERO; } static qse_awk_val_t* eval_binop_ne (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) { - int n = __cmp_val(rtx, left, right, CMP_OP_NE); - if (n == CMP_ERROR) return QSE_NULL; + int n; + if (__cmp_val(rtx, left, right, CMP_OP_NE, &n) <= -1) return QSE_NULL; return (n != 0)? QSE_AWK_VAL_ONE: QSE_AWK_VAL_ZERO; } static qse_awk_val_t* eval_binop_gt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) { - int n = __cmp_val(rtx, left, right, CMP_OP_GT); - if (n == CMP_ERROR) return QSE_NULL; + int n; + if (__cmp_val(rtx, left, right, CMP_OP_GT, &n) <= -1) return QSE_NULL; return (n > 0)? QSE_AWK_VAL_ONE: QSE_AWK_VAL_ZERO; } static qse_awk_val_t* eval_binop_ge (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) { - int n = __cmp_val(rtx, left, right, CMP_OP_GE); - if (n == CMP_ERROR) return QSE_NULL; + int n; + if (__cmp_val(rtx, left, right, CMP_OP_GE, &n) <= -1) return QSE_NULL; return (n >= 0)? QSE_AWK_VAL_ONE: QSE_AWK_VAL_ZERO; } static qse_awk_val_t* eval_binop_lt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) { - int n = __cmp_val(rtx, left, right, CMP_OP_LT); - if (n == CMP_ERROR) return QSE_NULL; + int n; + if (__cmp_val(rtx, left, right, CMP_OP_LT, &n) <= -1) return QSE_NULL; return (n < 0)? QSE_AWK_VAL_ONE: QSE_AWK_VAL_ZERO; } static qse_awk_val_t* eval_binop_le (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) { - int n = __cmp_val(rtx, left, right, CMP_OP_LE); - if (n == CMP_ERROR) return QSE_NULL; + int n; + if (__cmp_val(rtx, left, right, CMP_OP_LE, &n) <= -1) return QSE_NULL; return (n <= 0)? QSE_AWK_VAL_ONE: QSE_AWK_VAL_ZERO; } diff --git a/qse/lib/awk/run.h b/qse/lib/awk/run.h index daa31952..d46df676 100644 --- a/qse/lib/awk/run.h +++ b/qse/lib/awk/run.h @@ -133,6 +133,13 @@ qse_mchar_t* qse_awk_rtx_formatmbs ( qse_size_t* len ); +int qse_awk_rtx_cmpval ( + qse_awk_rtx_t* rtx, + qse_awk_val_t* left, + qse_awk_val_t* right, + int* ret +); + #if defined(__cplusplus) } #endif diff --git a/qse/lib/cmn/alg-sort.c b/qse/lib/cmn/alg-sort.c index 4a38bcf3..de3193d1 100644 --- a/qse/lib/cmn/alg-sort.c +++ b/qse/lib/cmn/alg-sort.c @@ -97,9 +97,7 @@ static QSE_INLINE void swapfunc ( #define vecswap(a,b,n) if ((n) > 0) swapfunc(a, b, n, swaptype) -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) +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) { if (comper(a, b, ctx) < 0) { @@ -113,9 +111,7 @@ static QSE_INLINE qse_byte_t* med3 ( } } -void qse_qsort ( - void* base, qse_size_t nmemb, qse_size_t size, - qse_sort_comper_t comper, void* ctx) +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; int swaptype, swap_cnt; @@ -132,8 +128,7 @@ 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); }