From b3d63c259b319f3ce737e7e64a59b1484826f734 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Tue, 30 Apr 2019 07:23:34 +0000 Subject: [PATCH] redefined qse_awk_mmgr(), qse_awk_getcmgr(), qse_setcmgr() by exposing the mmgr/cmgr fields via qse_awk_alt_t. implemented comparison operations for the fun value. changed behavior of some comparison operations that would otherwise result in a runtime error --- qse/cmd/awk/awk.c | 5 +- qse/include/qse/awk/awk.h | 33 ++- qse/lib/awk/awk-prv.h | 4 +- qse/lib/awk/awk.c | 19 +- qse/lib/awk/fnc.c | 10 +- qse/lib/awk/misc.c | 20 +- qse/lib/awk/parse.c | 24 +- qse/lib/awk/run.c | 464 +++++++++++++++++++++++++++----------- qse/lib/awk/tree.h | 2 +- qse/lib/awk/val.c | 48 ++-- 10 files changed, 424 insertions(+), 205 deletions(-) diff --git a/qse/cmd/awk/awk.c b/qse/cmd/awk/awk.c index 413818d8..201c145e 100644 --- a/qse/cmd/awk/awk.c +++ b/qse/cmd/awk/awk.c @@ -219,14 +219,13 @@ static qse_htb_walk_t print_awk_value ( return QSE_HTB_WALK_FORWARD; } -static qse_htb_walk_t set_global ( - qse_htb_t* map, qse_htb_pair_t* pair, void* arg) +static qse_htb_walk_t set_global (qse_htb_t* map, qse_htb_pair_t* pair, void* arg) { qse_awk_val_t* v; qse_awk_rtx_t* rtx = (qse_awk_rtx_t*)arg; struct gvmv_t* gvmv = (struct gvmv_t*)QSE_HTB_VPTR(pair); - v = qse_awk_rtx_makenstrvalwithxstr (rtx, &gvmv->str); + v = qse_awk_rtx_makenstrvalwithxstr(rtx, &gvmv->str); if (v == QSE_NULL) return QSE_HTB_WALK_STOP; qse_awk_rtx_refupval (rtx, v); diff --git a/qse/include/qse/awk/awk.h b/qse/include/qse/awk/awk.h index e486fb31..8465208a 100644 --- a/qse/include/qse/awk/awk.h +++ b/qse/include/qse/awk/awk.h @@ -91,6 +91,17 @@ typedef qse_flt_t qse_awk_flt_t; */ typedef struct qse_awk_t qse_awk_t; +#define QSE_AWK_HDR \ + qse_mmgr_t* mmgr; \ + qse_cmgr_t* cmgr + +typedef struct qse_awk_alt_t qse_awk_alt_t; +struct qse_awk_alt_t +{ + /* ensure that qse_awk_alt_t matches the beginning part of qse_awk_t */ + QSE_AWK_HDR; +}; + /** \struct qse_awk_rtx_t * The #qse_awk_rtx_t type defines a runtime context. A runtime context * maintains runtime state for a running script. You can create multiple @@ -1401,7 +1412,7 @@ typedef enum qse_awk_gbl_id_t qse_awk_gbl_id_t; */ enum qse_awk_val_type_t { - /* the values between QSE_AWK_VAL_NIL and QSE_AWK_VAL_MAP inclusive + /* the values between QSE_AWK_VAL_NIL and QSE_AWK_VAL_FUN inclusive * must be synchronized with an internal table of the __cmp_val * function in run.c and the __val_type_name in val.c */ QSE_AWK_VAL_NIL = 0, /**< nil */ @@ -1409,11 +1420,11 @@ enum qse_awk_val_type_t QSE_AWK_VAL_FLT = 2, /**< floating-pointer number */ QSE_AWK_VAL_STR = 3, /**< string */ QSE_AWK_VAL_MBS = 4, /**< byte array */ - QSE_AWK_VAL_MAP = 5, /**< map */ + QSE_AWK_VAL_FUN = 5, /**< function pointer */ + QSE_AWK_VAL_MAP = 6, /**< map */ - QSE_AWK_VAL_REX = 6, /**< regular expression */ - QSE_AWK_VAL_REF = 7, /**< reference to other types */ - QSE_AWK_VAL_FUN = 8 + QSE_AWK_VAL_REX = 7, /**< regular expression */ + QSE_AWK_VAL_REF = 8 /**< reference to other types */ }; typedef enum qse_awk_val_type_t qse_awk_val_type_t; @@ -1525,9 +1536,15 @@ QSE_EXPORT void qse_awk_close ( * The qse_awk_getmmgr() function gets the memory manager used in * qse_awk_open(). */ -QSE_EXPORT qse_mmgr_t* qse_awk_getmmgr ( - qse_awk_t* awk -); +#if defined(MOO_HAVE_INLINE) + static MOO_INLINE qse_mmgr_t* qse_awk_getmmgr (qse_awk_t* awk) { return awk->mmgr; } + static MOO_INLINE qse_cmgr_t* qse_awk_getcmgr (qse_awk_t* awk) { return awk->cmgr; } + static MOO_INLINE void qse_setcmgr (qse_awk_t* awk, qse_awk_cmgr_t* cmgr) { awk->cmgr = cmgr; } +#else +# define qse_awk_getmmgr(awk) (((qse_awk_alt_t*)(awk))->mmgr) +# define qse_awk_getcmgr(awk) (((qse_awk_alt_t*)(awk))->cmgr) +# define qse_awk_setcmgr(awk,mgr) (((qse_awk_alt_t*)(awk))->cmgr = (mgr)) +#endif /** * The qse_awk_getxtn() function gets the poniter to the beginning diff --git a/qse/lib/awk/awk-prv.h b/qse/lib/awk/awk-prv.h index 852fcc13..6d6371ef 100644 --- a/qse/lib/awk/awk-prv.h +++ b/qse/lib/awk/awk-prv.h @@ -166,8 +166,8 @@ struct qse_awk_tok_t struct qse_awk_t { - qse_mmgr_t* mmgr; - qse_cmgr_t* cmgr; + /* exposed fields via qse_awk_alt_t */ + QSE_AWK_HDR; /* primitive functions */ qse_awk_prm_t prm; diff --git a/qse/lib/awk/awk.c b/qse/lib/awk/awk.c index 69ee42d2..01fd01af 100644 --- a/qse/lib/awk/awk.c +++ b/qse/lib/awk/awk.c @@ -348,9 +348,9 @@ void qse_awk_clear (qse_awk_t* awk) awk->parse.depth.expr = 0; awk->parse.depth.incl = 0; - /* clear parse trees */ + /* clear parse trees */ /*awk->tree.ngbls_base = 0; - awk->tree.ngbls = 0; */ + awk->tree.ngbls = 0; */ awk->tree.ngbls = awk->tree.ngbls_base; awk->tree.cur_fun.ptr = QSE_NULL; @@ -362,7 +362,7 @@ void qse_awk_clear (qse_awk_t* awk) /*QSE_ASSERT (awk->tree.begin->next == QSE_NULL);*/ qse_awk_clrpt (awk, awk->tree.begin); awk->tree.begin = QSE_NULL; - awk->tree.begin_tail = QSE_NULL; + awk->tree.begin_tail = QSE_NULL; } if (awk->tree.end != QSE_NULL) @@ -370,7 +370,7 @@ void qse_awk_clear (qse_awk_t* awk) /*QSE_ASSERT (awk->tree.end->next == QSE_NULL);*/ qse_awk_clrpt (awk, awk->tree.end); awk->tree.end = QSE_NULL; - awk->tree.end_tail = QSE_NULL; + awk->tree.end_tail = QSE_NULL; } while (awk->tree.chain != QSE_NULL) @@ -395,11 +395,6 @@ void qse_awk_clear (qse_awk_t* awk) */ } -qse_mmgr_t* qse_awk_getmmgr (qse_awk_t* awk) -{ - return awk->mmgr; -} - void* qse_awk_getxtn (qse_awk_t* awk) { return QSE_XTN (awk); @@ -419,13 +414,13 @@ static int dup_str_opt (qse_awk_t* awk, const void* value, qse_cstr_t* tmp) { if (value) { - tmp->ptr = qse_strdup (value, awk->mmgr); - if (tmp->ptr == QSE_NULL) + tmp->ptr = qse_strdup(value, awk->mmgr); + if (!tmp->ptr) { qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL); return -1; } - tmp->len = qse_strlen (tmp->ptr); + tmp->len = qse_strlen(tmp->ptr); } else { diff --git a/qse/lib/awk/fnc.c b/qse/lib/awk/fnc.c index 2f994c07..0c30916f 100644 --- a/qse/lib/awk/fnc.c +++ b/qse/lib/awk/fnc.c @@ -594,7 +594,7 @@ int qse_awk_fnc_length (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) default: /* convert to string and get length */ - str = qse_awk_rtx_valtostrdup (rtx, v, &len); + str = qse_awk_rtx_valtostrdup(rtx, v, &len); if (str == QSE_NULL) return -1; QSE_AWK_FREE (rtx->awk, str); } @@ -1517,7 +1517,6 @@ 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; - qse_awk_int_t lv; qse_awk_val_t* r; int n; @@ -1527,12 +1526,7 @@ static int fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) a0 = qse_awk_rtx_getarg(rtx, 0); - n = qse_awk_rtx_valtoint(rtx, a0, &lv); - if (n <= -1) return -1; - - r = qse_awk_rtx_makeintval(rtx, lv); - if (r == QSE_NULL) return -1; - + r = qse_awk_rtx_makeintval(rtx, QSE_AWK_RTX_GETVALTYPE(rtx, a0) == QSE_AWK_VAL_NIL); qse_awk_rtx_setretval (rtx, r); return 0; } diff --git a/qse/lib/awk/misc.c b/qse/lib/awk/misc.c index 139e8655..d669fb99 100644 --- a/qse/lib/awk/misc.c +++ b/qse/lib/awk/misc.c @@ -36,14 +36,14 @@ void* qse_awk_allocmem (qse_awk_t* awk, qse_size_t size) { - void* ptr = QSE_AWK_ALLOC (awk, size); + void* ptr = QSE_AWK_ALLOC(awk, size); if (ptr == QSE_NULL) qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL); return ptr; } void* qse_awk_callocmem (qse_awk_t* awk, qse_size_t size) { - void* ptr = QSE_AWK_ALLOC (awk, size); + void* ptr = QSE_AWK_ALLOC(awk, size); if (ptr) QSE_MEMSET (ptr, 0, size); else qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL); return ptr; @@ -51,8 +51,8 @@ void* qse_awk_callocmem (qse_awk_t* awk, qse_size_t size) void* qse_awk_reallocmem (qse_awk_t* awk, void* ptr, qse_size_t size) { - void* nptr = QSE_AWK_REALLOC (awk, ptr, size); - if (nptr == QSE_NULL) qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL); + void* nptr = QSE_AWK_REALLOC(awk, ptr, size); + if (!nptr) qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL); return nptr; } @@ -63,22 +63,22 @@ void qse_awk_freemem (qse_awk_t* awk, void* ptr) qse_char_t* qse_awk_strdup (qse_awk_t* awk, const qse_char_t* s) { - qse_char_t* ptr = QSE_AWK_STRDUP (awk, s); - if (ptr == QSE_NULL) qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL); + qse_char_t* ptr = QSE_AWK_STRDUP(awk, s); + if (!ptr) qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL); return ptr; } qse_char_t* qse_awk_strxdup (qse_awk_t* awk, const qse_char_t* s, qse_size_t l) { - qse_char_t* ptr = QSE_AWK_STRXDUP (awk, s, l); - if (ptr == QSE_NULL) qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL); + qse_char_t* ptr = QSE_AWK_STRXDUP(awk, s, l); + if (!ptr) qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL); return ptr; } qse_char_t* qse_awk_cstrdup (qse_awk_t* awk, const qse_cstr_t* s) { - qse_char_t* ptr = qse_cstrdup (s, awk->mmgr); - if (ptr == QSE_NULL) qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL); + qse_char_t* ptr = qse_cstrdup(s, awk->mmgr); + if (!ptr) qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL); return ptr; } diff --git a/qse/lib/awk/parse.c b/qse/lib/awk/parse.c index 1a4dfae6..d974eaf9 100644 --- a/qse/lib/awk/parse.c +++ b/qse/lib/awk/parse.c @@ -4252,8 +4252,10 @@ static qse_awk_nde_t* parse_increment (qse_awk_t* awk, const qse_awk_loc_t* xloc #define FNTYPE_FNC 1 #define FNTYPE_FUN 2 -static QSE_INLINE int isfunname (qse_awk_t* awk, const qse_cstr_t* name) +static QSE_INLINE int isfunname (qse_awk_t* awk, const qse_cstr_t* name, qse_awk_fun_t** fun) { + qse_htb_pair_t* pair; + /* check if it is an awk function being processed currently */ if (awk->tree.cur_fun.ptr) { @@ -4265,14 +4267,20 @@ static QSE_INLINE int isfunname (qse_awk_t* awk, const qse_cstr_t* name) } /* check the funtion name in the function table */ - if (qse_htb_search(awk->tree.funs, name->ptr, name->len) != QSE_NULL) + pair = qse_htb_search(awk->tree.funs, name->ptr, name->len); + if (pair) { /* one of the functions defined previously */ + if (fun) + { + *fun = (qse_awk_fun_t*)QSE_HTB_VPTR(pair); + QSE_ASSERT (*fun != QSE_NULL); + } return FNTYPE_FUN; } /* check if it is a function not resolved so far */ - if (qse_htb_search(awk->parse.funs, name->ptr, name->len) != QSE_NULL) + if (qse_htb_search(awk->parse.funs, name->ptr, name->len)) { /* one of the function calls not resolved so far. */ return FNTYPE_FUN; @@ -4289,7 +4297,7 @@ static QSE_INLINE int isfnname (qse_awk_t* awk, const qse_cstr_t* name) return FNTYPE_FNC; } - return isfunname(awk, name); + return isfunname(awk, name, QSE_NULL); } static qse_awk_nde_t* parse_primary_int (qse_awk_t* awk, const qse_awk_loc_t* xloc) @@ -4981,7 +4989,7 @@ oops: } #if defined(ENABLE_FEATURE_FUN_AS_VALUE) -static qse_awk_nde_t* parse_fun_as_value (qse_awk_t* awk, const qse_cstr_t* name, const qse_awk_loc_t* xloc) +static qse_awk_nde_t* parse_fun_as_value (qse_awk_t* awk, const qse_cstr_t* name, const qse_awk_loc_t* xloc, qse_awk_fun_t* funptr) { qse_awk_nde_fun_t* nde; @@ -4997,6 +5005,7 @@ static qse_awk_nde_t* parse_fun_as_value (qse_awk_t* awk, const qse_cstr_t* nam nde->loc = *xloc; nde->name.ptr = name->ptr; nde->name.len = name->len; + nde->funptr = funptr; return (qse_awk_nde_t*)nde; @@ -5067,8 +5076,9 @@ static qse_awk_nde_t* parse_primary_ident_noseg (qse_awk_t* awk, const qse_awk_l else { int fntype; + qse_awk_fun_t* funptr = QSE_NULL; - fntype = isfunname(awk, name); + fntype = isfunname(awk, name, &funptr); if (fntype) { @@ -5084,7 +5094,7 @@ static qse_awk_nde_t* parse_primary_ident_noseg (qse_awk_t* awk, const qse_awk_l { /* function name appeared without () */ #if defined(ENABLE_FEATURE_FUN_AS_VALUE) - nde = parse_fun_as_value(awk, name, xloc); + nde = parse_fun_as_value(awk, name, xloc, funptr); #else SETERR_ARG_LOC (awk, QSE_AWK_EFUNRED, name->ptr, name->len, xloc); #endif diff --git a/qse/lib/awk/run.c b/qse/lib/awk/run.c index b4a59a56..0e61efc8 100644 --- a/qse/lib/awk/run.c +++ b/qse/lib/awk/run.c @@ -4188,46 +4188,106 @@ static qse_awk_val_t* eval_binop_band ( return qse_awk_rtx_makeintval (rtx, l1 & l2); } -static QSE_INLINE int __cmp_nil_nil (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +/* -------------------------------------------------------------------- */ + +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 +}; +typedef enum cmp_op_t cmp_op_t; + +static QSE_INLINE cmp_op_t inverse_cmp_op (cmp_op_t op) +{ + static cmp_op_t inverse_cmp_op_tab[] = + { + CMP_OP_NE, + CMP_OP_EQ, + CMP_OP_LT, + CMP_OP_LE, + CMP_OP_GT, + CMP_OP_GE + }; + return inverse_cmp_op_tab[op]; +} + +static QSE_INLINE int __cmp_ensure_not_equal (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. + * this function return a number that ensures to make NE to true and + * all other operations false */ + + switch (op_hint) + { + case CMP_OP_EQ: + case CMP_OP_NE: + return 1; /* not equal */ + + case CMP_OP_GT: + case CMP_OP_LT: + return 0; /* make GT or LT to be false by claiming equal */ + + case CMP_OP_GE: + return -1; /* make GE false by claiming less */ + case CMP_OP_LE: + return 1; /* make LE false by claiming greater */ + } +} + +/* -------------------------------------------------------------------- */ +static QSE_INLINE int __cmp_nil_nil (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { return 0; } -static QSE_INLINE int __cmp_nil_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +static QSE_INLINE int __cmp_nil_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { qse_awk_int_t v = QSE_AWK_RTX_GETINTFROMVAL (rtx, right); return (v < 0)? 1: ((v > 0)? -1: 0); } -static QSE_INLINE int __cmp_nil_flt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +static QSE_INLINE int __cmp_nil_flt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { if (((qse_awk_val_flt_t*)right)->val < 0) return 1; if (((qse_awk_val_flt_t*)right)->val > 0) return -1; return 0; } -static QSE_INLINE int __cmp_nil_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +static QSE_INLINE int __cmp_nil_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { return (((qse_awk_val_str_t*)right)->val.len == 0)? 0: -1; } -static QSE_INLINE int __cmp_nil_bytearr (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +static QSE_INLINE int __cmp_nil_mbs (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { return (((qse_awk_val_mbs_t*)right)->val.len == 0)? 0: -1; } -static QSE_INLINE int __cmp_nil_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +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); +} + +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) { return (QSE_HTB_SIZE(((qse_awk_val_map_t*)right)->map) == 0)? 0: -1; } -static QSE_INLINE int __cmp_int_nil (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +/* -------------------------------------------------------------------- */ + +static QSE_INLINE int __cmp_int_nil (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { qse_awk_int_t v = QSE_AWK_RTX_GETINTFROMVAL(rtx, left); return (v > 0)? 1: ((v < 0)? -1: 0); } -static QSE_INLINE int __cmp_int_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +static QSE_INLINE int __cmp_int_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { qse_awk_int_t v1 = QSE_AWK_RTX_GETINTFROMVAL(rtx, left); @@ -4236,7 +4296,7 @@ static QSE_INLINE int __cmp_int_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qs } static QSE_INLINE int __cmp_int_flt ( - qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) + qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { qse_awk_int_t v1 = QSE_AWK_RTX_GETINTFROMVAL (rtx, left); if (v1 > ((qse_awk_val_flt_t*)right)->val) return 1; @@ -4244,9 +4304,10 @@ static QSE_INLINE int __cmp_int_flt ( return 0; } -static QSE_INLINE int __cmp_int_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +static QSE_INLINE int __cmp_int_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { - qse_awk_rtx_valtostr_out_t out; + qse_char_t* str0; + qse_size_t len0; int n; /* SCO CC doesn't seem to handle right->nstr > 0 properly */ @@ -4263,7 +4324,7 @@ static QSE_INLINE int __cmp_int_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qs &ll, &rr ); - v1 = QSE_AWK_RTX_GETINTFROMVAL (rtx, left); + v1 = QSE_AWK_RTX_GETINTFROMVAL(rtx, left); if (n == 0) { /* a numeric integral string */ @@ -4276,40 +4337,76 @@ static QSE_INLINE int __cmp_int_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qs } } - out.type = QSE_AWK_RTX_VALTOSTR_CPLDUP; - if (qse_awk_rtx_valtostr(rtx, left, &out) <= -1) return CMP_ERROR; + str0 = qse_awk_rtx_valtostrdup(rtx, left, &len0); + if (!str0) return CMP_ERROR; if (rtx->gbl.ignorecase) { - n = qse_strxncasecmp( - out.u.cpldup.ptr, - out.u.cpldup.len, - ((qse_awk_val_str_t*)right)->val.ptr, - ((qse_awk_val_str_t*)right)->val.len - ); + n = qse_strxncasecmp(str0, len0, ((qse_awk_val_str_t*)right)->val.ptr, ((qse_awk_val_str_t*)right)->val.len); } else { - n = qse_strxncmp( - out.u.cpldup.ptr, - out.u.cpldup.len, - ((qse_awk_val_str_t*)right)->val.ptr, - ((qse_awk_val_str_t*)right)->val.len - ); + n = qse_strxncmp(str0, len0, ((qse_awk_val_str_t*)right)->val.ptr, ((qse_awk_val_str_t*)right)->val.len); } - QSE_AWK_FREE (rtx->awk, out.u.cpldup.ptr); + qse_awk_rtx_freemem (rtx, str0); return n; } -static QSE_INLINE int __cmp_int_bytearr (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +static QSE_INLINE int __cmp_int_mbs (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { - /* can't compare an integer with a byte array */ - SETERR_COD (rtx, QSE_AWK_EOPERAND); - return CMP_ERROR; + qse_mchar_t* str0; + qse_size_t len0; + int n; + + if (rtx->awk->opt.trait & QSE_AWK_NCMPONSTR || right->nstr /*> 0*/) + { + qse_awk_int_t ll, v1; + qse_awk_flt_t rr; + + n = qse_awk_rtx_mbstonum ( + rtx, + QSE_AWK_RTX_STRTONUM_MAKE_OPTION(1, 0), + ((qse_awk_val_mbs_t*)right)->val.ptr, + ((qse_awk_val_mbs_t*)right)->val.len, + &ll, &rr + ); + + v1 = QSE_AWK_RTX_GETINTFROMVAL(rtx, left); + if (n == 0) + { + /* a numeric integral string */ + return (v1 > ll)? 1: ((v1 < ll)? -1: 0); + } + else if (n > 0) + { + /* a numeric floating-point string */ + return (v1 > rr)? 1: ((v1 < rr)? -1: 0); + } + } + + str0 = qse_awk_rtx_valtombsdup(rtx, left, &len0); + if (!str0) return QSE_NULL; + + if (rtx->gbl.ignorecase) + { + n = qse_mbsxncasecmp(str0, len0, ((qse_awk_val_mbs_t*)right)->val.ptr, ((qse_awk_val_mbs_t*)right)->val.len); + } + else + { + n = qse_mbsxncmp(str0, len0, ((qse_awk_val_mbs_t*)right)->val.ptr, ((qse_awk_val_mbs_t*)right)->val.len); + } + + qse_awk_rtx_freemem (rtx, str0); + return n; } -static QSE_INLINE int __cmp_int_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +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); +} + +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) { /* compare an integer and the size of a map */ qse_awk_int_t v1 = QSE_AWK_RTX_GETINTFROMVAL(rtx, left); @@ -4319,14 +4416,16 @@ static QSE_INLINE int __cmp_int_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qs return 0; } -static QSE_INLINE int __cmp_flt_nil (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +/* -------------------------------------------------------------------- */ + +static QSE_INLINE int __cmp_flt_nil (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { if (((qse_awk_val_flt_t*)left)->val > 0) return 1; if (((qse_awk_val_flt_t*)left)->val < 0) return -1; return 0; } -static int __cmp_flt_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +static QSE_INLINE int __cmp_flt_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { qse_awk_int_t v2 = QSE_AWK_RTX_GETINTFROMVAL (rtx, right); if (((qse_awk_val_flt_t*)left)->val > v2) return 1; @@ -4334,7 +4433,7 @@ static int __cmp_flt_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t return 0; } -static int __cmp_flt_flt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +static QSE_INLINE int __cmp_flt_flt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { if (((qse_awk_val_flt_t*)left)->val > ((qse_awk_val_flt_t*)right)->val) return 1; @@ -4343,9 +4442,10 @@ static int __cmp_flt_flt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t return 0; } -static int __cmp_flt_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +static QSE_INLINE int __cmp_flt_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { - qse_awk_rtx_valtostr_out_t out; + qse_char_t* str0; + qse_size_t len0; int n; /* SCO CC doesn't seem to handle right->nstr > 0 properly */ @@ -4354,54 +4454,71 @@ static int __cmp_flt_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t const qse_char_t* end; qse_awk_flt_t rr; - rr = qse_awk_strxtoflt ( - rtx->awk, - ((qse_awk_val_str_t*)right)->val.ptr, - ((qse_awk_val_str_t*)right)->val.len, - &end - ); - if (end == ((qse_awk_val_str_t*)right)->val.ptr + - ((qse_awk_val_str_t*)right)->val.len) + rr = qse_awk_strxtoflt(rtx->awk, ((qse_awk_val_str_t*)right)->val.ptr, ((qse_awk_val_str_t*)right)->val.len, &end); + if (end == ((qse_awk_val_str_t*)right)->val.ptr + ((qse_awk_val_str_t*)right)->val.len) { return (((qse_awk_val_flt_t*)left)->val > rr)? 1: (((qse_awk_val_flt_t*)left)->val < rr)? -1: 0; } } - out.type = QSE_AWK_RTX_VALTOSTR_CPLDUP; - if (qse_awk_rtx_valtostr(rtx, left, &out) <= -1) return CMP_ERROR; + str0 = qse_awk_rtx_valtostrdup(rtx, left, &len0); + if (!str0) return CMP_ERROR; if (rtx->gbl.ignorecase) { - n = qse_strxncasecmp ( - out.u.cpldup.ptr, - out.u.cpldup.len, - ((qse_awk_val_str_t*)right)->val.ptr, - ((qse_awk_val_str_t*)right)->val.len - ); + n = qse_strxncasecmp(str0, len0, ((qse_awk_val_str_t*)right)->val.ptr, ((qse_awk_val_str_t*)right)->val.len); } else { - n = qse_strxncmp ( - out.u.cpldup.ptr, - out.u.cpldup.len, - ((qse_awk_val_str_t*)right)->val.ptr, - ((qse_awk_val_str_t*)right)->val.len - ); + n = qse_strxncmp(str0, len0, ((qse_awk_val_str_t*)right)->val.ptr, ((qse_awk_val_str_t*)right)->val.len); } - QSE_AWK_FREE (rtx->awk, out.u.cpldup.ptr); + qse_awk_rtx_freemem (rtx, str0); return n; } -static int __cmp_flt_bytearr (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +static QSE_INLINE int __cmp_flt_mbs (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { - /* can't compare a float with a byte array */ - SETERR_COD (rtx, QSE_AWK_EOPERAND); - return CMP_ERROR; + qse_mchar_t* str0; + qse_size_t len0; + int n; + + if (rtx->awk->opt.trait & QSE_AWK_NCMPONSTR || right->nstr /*> 0*/) + { + const qse_mchar_t* end; + qse_awk_flt_t rr; + + rr = qse_awk_mbsxtoflt(rtx->awk, ((qse_awk_val_mbs_t*)right)->val.ptr, ((qse_awk_val_mbs_t*)right)->val.len, &end); + if (end == ((qse_awk_val_mbs_t*)right)->val.ptr + ((qse_awk_val_mbs_t*)right)->val.len) + { + return (((qse_awk_val_flt_t*)left)->val > rr)? 1: + (((qse_awk_val_flt_t*)left)->val < rr)? -1: 0; + } + } + + str0 = qse_awk_rtx_valtombsdup(rtx, left, &len0); + if (!str0) return CMP_ERROR; + + if (rtx->gbl.ignorecase) + { + n = qse_mbsxncasecmp(str0, len0, ((qse_awk_val_mbs_t*)right)->val.ptr, ((qse_awk_val_mbs_t*)right)->val.len); + } + else + { + n = qse_mbsxncmp(str0, len0, ((qse_awk_val_mbs_t*)right)->val.ptr, ((qse_awk_val_mbs_t*)right)->val.len); + } + + qse_awk_rtx_freemem (rtx, str0); + return n; } -static QSE_INLINE int __cmp_flt_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +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); +} + +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) { /* compare a float with the size of a map */ qse_awk_int_t v2 = QSE_HTB_SIZE(((qse_awk_val_map_t*)right)->map); @@ -4410,22 +4527,30 @@ static QSE_INLINE int __cmp_flt_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qs return 0; } -static QSE_INLINE int __cmp_str_nil (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +/* -------------------------------------------------------------------- */ + +static QSE_INLINE int __cmp_str_nil (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { return (((qse_awk_val_str_t*)left)->val.len == 0)? 0: 1; } -static QSE_INLINE int __cmp_str_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +static QSE_INLINE int __cmp_str_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { - return -__cmp_int_str(rtx, right, left); + int n; + n = __cmp_int_str(rtx, right, left, inverse_cmp_op(op_hint)); + if (n == CMP_ERROR) return CMP_ERROR; + return -n; } -static QSE_INLINE int __cmp_str_flt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +static QSE_INLINE int __cmp_str_flt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { - return -__cmp_flt_str (rtx, right, left); + int n; + n = __cmp_flt_str(rtx, right, left, inverse_cmp_op(op_hint)); + if (n == CMP_ERROR) return CMP_ERROR; + return -n; } -static QSE_INLINE int __cmp_str_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +static QSE_INLINE int __cmp_str_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { qse_awk_val_str_t* ls, * rs; @@ -4498,7 +4623,7 @@ static QSE_INLINE int __cmp_str_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qs } } -static QSE_INLINE int __cmp_str_bytearr (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +static QSE_INLINE int __cmp_str_mbs (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { qse_awk_val_str_t* ls = (qse_awk_val_str_t*)left; qse_awk_val_mbs_t* rs = (qse_awk_val_mbs_t*)right; @@ -4526,34 +4651,48 @@ static QSE_INLINE int __cmp_str_bytearr (qse_awk_rtx_t* rtx, qse_awk_val_t* left #endif } -static QSE_INLINE int __cmp_str_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +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) { - /* can't compare a map with a string */ - SETERR_COD (rtx, QSE_AWK_EOPERAND); - return CMP_ERROR; + return __cmp_ensure_not_equal(op_hint); } -static QSE_INLINE int __cmp_bytearr_nil (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +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); +} + +/* -------------------------------------------------------------------- */ + +static QSE_INLINE int __cmp_mbs_nil (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { return (((qse_awk_val_mbs_t*)left)->val.len == 0)? 0: 1; } -static QSE_INLINE int __cmp_bytearr_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +static QSE_INLINE int __cmp_mbs_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { - return -__cmp_int_bytearr(rtx, right, left); + int n; + n = __cmp_int_mbs(rtx, right, left, inverse_cmp_op(op_hint)); + if (n == CMP_ERROR) return CMP_ERROR; + return -n; } -static QSE_INLINE int __cmp_bytearr_flt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +static QSE_INLINE int __cmp_mbs_flt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { - return -__cmp_flt_bytearr(rtx, right, left); + int n; + n = __cmp_flt_mbs(rtx, right, left, inverse_cmp_op(op_hint)); + if (n == CMP_ERROR) return CMP_ERROR; + return -n; } -static QSE_INLINE int __cmp_bytearr_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +static QSE_INLINE int __cmp_mbs_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { - return -__cmp_str_bytearr(rtx, right, left); + int n; + n = __cmp_str_mbs(rtx, right, left, inverse_cmp_op(op_hint)); + if (n == CMP_ERROR) return CMP_ERROR; + return -n; } -static QSE_INLINE int __cmp_bytearr_bytearr (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +static QSE_INLINE int __cmp_mbs_mbs (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) { qse_awk_val_mbs_t* ls = (qse_awk_val_mbs_t*)left; qse_awk_val_mbs_t* rs = (qse_awk_val_mbs_t*)right; @@ -4563,66 +4702,119 @@ static QSE_INLINE int __cmp_bytearr_bytearr (qse_awk_rtx_t* rtx, qse_awk_val_t* return qse_mbsxncmp(ls->val.ptr, ls->val.len, rs->val.ptr, rs->val.len); } -static QSE_INLINE int __cmp_bytearr_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +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) { - /* can't compare a byte array with a map */ - SETERR_COD (rtx, QSE_AWK_EOPERAND); - return CMP_ERROR; + return __cmp_ensure_not_equal(op_hint); } - -static QSE_INLINE int __cmp_map_nil (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +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_nil_map (rtx, right, left); + return __cmp_ensure_not_equal(op_hint); } -static QSE_INLINE int __cmp_map_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +/* -------------------------------------------------------------------- */ + +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_int_map (rtx, right, left); + return __cmp_ensure_not_equal(op_hint); } -static QSE_INLINE int __cmp_map_flt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +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_flt_map (rtx, right, left); + return __cmp_ensure_not_equal(op_hint); } -static QSE_INLINE int __cmp_map_str (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +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) { - /* can't compare a map with a string */ - SETERR_COD (rtx, QSE_AWK_EOPERAND); - return CMP_ERROR; + return __cmp_ensure_not_equal(op_hint); } -static QSE_INLINE int __cmp_map_bytearr (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +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) { - /* can't compare a map with a byte array */ - SETERR_COD (rtx, QSE_AWK_EOPERAND); - return CMP_ERROR; + return __cmp_ensure_not_equal(op_hint); } -static QSE_INLINE int __cmp_map_map (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) +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); +} + +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); +} + +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); +} + +/* -------------------------------------------------------------------- */ + +static QSE_INLINE int __cmp_map_nil (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) +{ + int n; + n = __cmp_nil_map(rtx, right, left, inverse_cmp_op(op_hint)); + if (n == CMP_ERROR) return CMP_ERROR; + return -n; +} + +static QSE_INLINE int __cmp_map_int (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) +{ + int n; + n = __cmp_int_map(rtx, right, left, inverse_cmp_op(op_hint)); + if (n == CMP_ERROR) return CMP_ERROR; + return -n; +} + +static QSE_INLINE int __cmp_map_flt (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right, cmp_op_t op_hint) +{ + int n; + n = __cmp_flt_map(rtx, right, left, inverse_cmp_op(op_hint)); + if (n == CMP_ERROR) return CMP_ERROR; + return -n; +} + +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); +} + +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); +} + +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); +} + +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) { /* can't compare a map with a map */ SETERR_COD (rtx, QSE_AWK_EOPERAND); return CMP_ERROR; } +/* -------------------------------------------------------------------- */ -static int __cmp_val( - qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) + +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) { qse_awk_val_type_t lvtype, rvtype; - typedef int (*cmp_val_t) (qse_awk_rtx_t*, qse_awk_val_t*, qse_awk_val_t*); + typedef int (*cmp_val_t) (qse_awk_rtx_t*, qse_awk_val_t*, qse_awk_val_t*, cmp_op_t op_hint); static cmp_val_t func[] = { /* this table must be synchronized with * the QSE_AWK_VAL_XXX values in awk.h */ - __cmp_nil_nil, __cmp_nil_int, __cmp_nil_flt, __cmp_nil_str, __cmp_nil_bytearr, __cmp_nil_map, - __cmp_int_nil, __cmp_int_int, __cmp_int_flt, __cmp_int_str, __cmp_int_bytearr, __cmp_int_map, - __cmp_flt_nil, __cmp_flt_int, __cmp_flt_flt, __cmp_flt_str, __cmp_flt_bytearr, __cmp_flt_map, - __cmp_str_nil, __cmp_str_int, __cmp_str_flt, __cmp_str_str, __cmp_str_bytearr, __cmp_str_map, - __cmp_bytearr_nil, __cmp_bytearr_int, __cmp_bytearr_flt, __cmp_bytearr_str, __cmp_bytearr_bytearr, __cmp_bytearr_map, - __cmp_map_nil, __cmp_map_int, __cmp_map_flt, __cmp_map_str, __cmp_map_bytearr, __cmp_map_map + __cmp_nil_nil, __cmp_nil_int, __cmp_nil_flt, __cmp_nil_str, __cmp_nil_mbs, __cmp_nil_fun, __cmp_nil_map, + __cmp_int_nil, __cmp_int_int, __cmp_int_flt, __cmp_int_str, __cmp_int_mbs, __cmp_int_fun, __cmp_int_map, + __cmp_flt_nil, __cmp_flt_int, __cmp_flt_flt, __cmp_flt_str, __cmp_flt_mbs, __cmp_flt_fun, __cmp_flt_map, + __cmp_str_nil, __cmp_str_int, __cmp_str_flt, __cmp_str_str, __cmp_str_mbs, __cmp_str_fun, __cmp_str_map, + __cmp_mbs_nil, __cmp_mbs_int, __cmp_mbs_flt, __cmp_mbs_str, __cmp_mbs_mbs, __cmp_mbs_fun, __cmp_mbs_map, + __cmp_fun_nil, __cmp_fun_int, __cmp_fun_flt, __cmp_fun_str, __cmp_fun_mbs, __cmp_fun_fun, __cmp_fun_map, + __cmp_map_nil, __cmp_map_int, __cmp_map_flt, __cmp_map_str, __cmp_map_mbs, __cmp_map_fun, __cmp_map_map }; lvtype = QSE_AWK_RTX_GETVALTYPE(rtx, left); @@ -4639,14 +4831,20 @@ static int __cmp_val( QSE_ASSERT (rvtype >= QSE_AWK_VAL_NIL && rvtype <= QSE_AWK_VAL_MAP); /* mapping fomula and table layout assume: - * QSE_AWK_VAL_NIL = 0 - * QSE_AWK_VAL_INT = 1 - * QSE_AWK_VAL_FLT = 2 - * QSE_AWK_VAL_STR = 3 - * QSE_AWK_VAL_MBS = 4 - * QSE_AWK_VAL_MAP = 5 + * QSE_AWK_VAL_NIL = 0 + * QSE_AWK_VAL_INT = 1 + * QSE_AWK_VAL_FLT = 2 + * QSE_AWK_VAL_STR = 3 + * QSE_AWK_VAL_MBS = 4 + * QSE_AWK_VAL_FUN = 5 + * QSE_AWK_VAL_MAP = 6 + * + * op_hint indicate the operation in progress when this function is called. + * this hint doesn't require the comparison function to compare using this + * 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 * 6 + rvtype](rtx, left, right); + return func[lvtype * 7 + rvtype](rtx, left, right, op_hint); } static int teq_val (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) @@ -4693,6 +4891,10 @@ static int teq_val (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* righ ((qse_awk_val_mbs_t*)right)->val.len) == 0; break; + case QSE_AWK_VAL_FUN: + n = ((qse_awk_val_fun_t*)left)->fun == ((qse_awk_val_fun_t*)right)->fun; + break; + default: /* map-x and map-y are always different regardless of * their contents. however, if they are pointing to the @@ -4709,52 +4911,52 @@ static int teq_val (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* righ static qse_awk_val_t* eval_binop_teq (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) { - return teq_val (rtx, left, right)? QSE_AWK_VAL_ONE: QSE_AWK_VAL_ZERO; + return teq_val(rtx, left, right)? QSE_AWK_VAL_ONE: QSE_AWK_VAL_ZERO; } static qse_awk_val_t* eval_binop_tne (qse_awk_rtx_t* rtx, qse_awk_val_t* left, qse_awk_val_t* right) { - return teq_val (rtx, left, right)? QSE_AWK_VAL_ZERO: QSE_AWK_VAL_ONE; + return teq_val(rtx, left, right)? QSE_AWK_VAL_ZERO: QSE_AWK_VAL_ONE; } 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); + int n = __cmp_val(rtx, left, right, CMP_OP_EQ); if (n == CMP_ERROR) 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); + int n = __cmp_val(rtx, left, right, CMP_OP_NE); if (n == CMP_ERROR) 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); + int n = __cmp_val(rtx, left, right, CMP_OP_GT); if (n == CMP_ERROR) 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); + int n = __cmp_val(rtx, left, right, CMP_OP_GE); if (n == CMP_ERROR) 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); + int n = __cmp_val(rtx, left, right, CMP_OP_LT); if (n == CMP_ERROR) 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); + int n = __cmp_val(rtx, left, right, CMP_OP_LE); if (n == CMP_ERROR) return QSE_NULL; return (n <= 0)? QSE_AWK_VAL_ONE: QSE_AWK_VAL_ZERO; } @@ -6267,11 +6469,13 @@ static qse_awk_val_t* eval_fun (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde) { qse_awk_val_t* val; qse_awk_fun_t* fun; - qse_htb_pair_t* pair; + - fun = ((qse_awk_nde_fun_t*)nde)->ptr; + fun = ((qse_awk_nde_fun_t*)nde)->funptr; if (!fun) { + qse_htb_pair_t* pair; + /* TODO: support bultin functions?, support module functions? */ pair = qse_htb_search(rtx->awk->tree.funs, ((qse_awk_nde_fun_t*)nde)->name.ptr, ((qse_awk_nde_fun_t*)nde)->name.len); if (!pair) diff --git a/qse/lib/awk/tree.h b/qse/lib/awk/tree.h index 7c2de98a..885f3ebb 100644 --- a/qse/lib/awk/tree.h +++ b/qse/lib/awk/tree.h @@ -179,7 +179,7 @@ struct qse_awk_nde_fun_t { QSE_AWK_NDE_HDR; qse_cstr_t name; /* function name */ - qse_awk_fun_t* ptr; /* QSE_NULL or actual pointer */ + qse_awk_fun_t* funptr; /* QSE_NULL or actual pointer */ }; /* QSE_AWK_NDE_NAMED, QSE_AWK_NDE_GBL, diff --git a/qse/lib/awk/val.c b/qse/lib/awk/val.c index 8b6596a3..a42f099c 100644 --- a/qse/lib/awk/val.c +++ b/qse/lib/awk/val.c @@ -759,10 +759,10 @@ const qse_char_t* qse_awk_rtx_getvaltypename(qse_awk_rtx_t* rtx, qse_awk_val_t* QSE_T("flt"), QSE_T("str"), QSE_T("mbs"), + QSE_T("fun"), QSE_T("map"), QSE_T("rex"), - QSE_T("ref"), - QSE_T("fun") + QSE_T("ref") }; return __val_type_name[QSE_AWK_RTX_GETVALTYPE(rtx, val)]; @@ -854,6 +854,10 @@ void qse_awk_rtx_freeval (qse_awk_rtx_t* rtx, qse_awk_val_t* val, int cache) break; } + case QSE_AWK_VAL_FUN: + QSE_AWK_FREE (rtx->awk, val); + break; + case QSE_AWK_VAL_MAP: { qse_htb_fini (((qse_awk_val_map_t*)val)->map); @@ -871,10 +875,6 @@ void qse_awk_rtx_freeval (qse_awk_rtx_t* rtx, qse_awk_val_t* val, int cache) break; } - case QSE_AWK_VAL_FUN: - QSE_AWK_FREE (rtx->awk, val); - break; - } } } @@ -1007,14 +1007,14 @@ int qse_awk_rtx_valtobool (qse_awk_rtx_t* rtx, const qse_awk_val_t* val) return ((qse_awk_val_mbs_t*)val)->val.len > 0; case QSE_AWK_VAL_REX: /* TODO: is this correct? */ return ((qse_awk_val_rex_t*)val)->str.len > 0; + case QSE_AWK_VAL_FUN: + /* return always true */ + return 1; case QSE_AWK_VAL_MAP: /* true if the map size is greater than 0. false if not */ return QSE_HTB_SIZE(((qse_awk_val_map_t*)val)->map) > 0; case QSE_AWK_VAL_REF: return val_ref_to_bool (rtx, (qse_awk_val_ref_t*)val); - case QSE_AWK_VAL_FUN: - /* return always true */ - return 1; } QSE_ASSERTX ( @@ -1506,6 +1506,11 @@ int qse_awk_rtx_valtostr (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_awk_rt #endif } + case QSE_AWK_VAL_FUN: + { + return str_to_str(rtx, ((qse_awk_val_fun_t*)v)->fun->name.ptr, ((qse_awk_val_fun_t*)v)->fun->name.len, out); + } + case QSE_AWK_VAL_MAP: { if (rtx->awk->opt.trait & QSE_AWK_FLEXMAP) @@ -1519,11 +1524,6 @@ int qse_awk_rtx_valtostr (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_awk_rt { return val_ref_to_str(rtx, (qse_awk_val_ref_t*)v, out); } - - case QSE_AWK_VAL_FUN: - { - return str_to_str(rtx, ((qse_awk_val_fun_t*)v)->fun->name.ptr, ((qse_awk_val_fun_t*)v)->fun->name.len, out); - } } @@ -1809,6 +1809,12 @@ int qse_awk_rtx_valtonum (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_awk_in ); } + case QSE_AWK_VAL_FUN: + { + /* unable to convert a function to a number */ + break; + } + case QSE_AWK_VAL_MAP: { if (rtx->awk->opt.trait & QSE_AWK_FLEXMAP) @@ -1823,12 +1829,6 @@ int qse_awk_rtx_valtonum (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_awk_in { return val_ref_to_num(rtx, (qse_awk_val_ref_t*)v, l, r); } - - case QSE_AWK_VAL_FUN: - { - /* unable to convert a function to a number */ - break; - } } #ifdef DEBUG_VAL @@ -2153,6 +2153,10 @@ void qse_awk_dprintval (qse_awk_rtx_t* run, qse_awk_val_t* val) qse_errputstrf (QSE_T("/%s/"), ((qse_awk_val_rex_t*)val)->ptr); break; + case QSE_AWK_VAL_FUN: + qse_errputstrf (QSE_T("%.*s"), (int)((qse_awk_val_fun_t*)val)->fun->name.len, ((qse_awk_val_fun_t*)val)->fun->name.ptr); + break; + case QSE_AWK_VAL_MAP: qse_errputstrf (QSE_T("MAP[")); qse_htb_walk (((qse_awk_val_map_t*)val)->map, print_pair, run); @@ -2165,10 +2169,6 @@ void qse_awk_dprintval (qse_awk_rtx_t* run, qse_awk_val_t* val) qse_errputstrf (QSE_T("]")); break; - case QSE_AWK_VAL_FUN: - qse_errputstrf (QSE_T("%.*s"), (int)((qse_awk_val_fun_t*)val)->fun->name.len, ((qse_awk_val_fun_t*)val)->fun->name.ptr); - break; - default: qse_errputstrf (QSE_T("**** INTERNAL ERROR - INVALID VALUE TYPE ****\n")); }