From 23d316a65971d32e1c4f21d9e1e4f35a1c3fd35f Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Tue, 16 Apr 2013 10:09:24 +0000 Subject: [PATCH] enhanced qse_awk_rtx_setrefval() to handle references properly enhanced qse_awk_rtx_valtostr() and qse_awk_rtx_valtonum() to handle references more correctly. changed some awk error codes. --- qse/cmd/awk/awk.c | 2 +- qse/include/qse/awk/awk.h | 11 +- qse/lib/awk/awk.h | 8 + qse/lib/awk/err.c | 11 +- qse/lib/awk/fnc.c | 110 ++------- qse/lib/awk/mod-dir.c | 23 +- qse/lib/awk/mod-sys.c | 11 +- qse/lib/awk/mod-uci.c | 19 +- qse/lib/awk/run.c | 504 +++++++++++++++++++++----------------- qse/lib/awk/std.c | 18 +- qse/lib/awk/val.c | 301 ++++++++++++++--------- 11 files changed, 550 insertions(+), 468 deletions(-) diff --git a/qse/cmd/awk/awk.c b/qse/cmd/awk/awk.c index 166de327..7847c0be 100644 --- a/qse/cmd/awk/awk.c +++ b/qse/cmd/awk/awk.c @@ -250,7 +250,7 @@ static qse_htb_walk_t print_awk_value ( str = qse_awk_rtx_valtostrdup (rtx, QSE_HTB_VPTR(pair), &len); if (str == QSE_NULL) { - if (qse_awk_rtx_geterrnum(rtx) == QSE_AWK_EVALTYPE) + if (qse_awk_rtx_geterrnum(rtx) == QSE_AWK_EVALTOSTR) { dprint (QSE_T("%.*s = [not printable]\n"), (int)QSE_HTB_KLEN(pair), QSE_HTB_KPTR(pair)); diff --git a/qse/include/qse/awk/awk.h b/qse/include/qse/awk/awk.h index 3e0ef1c0..15591537 100644 --- a/qse/include/qse/awk/awk.h +++ b/qse/include/qse/awk/awk.h @@ -949,7 +949,9 @@ typedef void (*qse_awk_rtx_ecb_stmt_t) ( /** * The qse_awk_rtx_ecb_gblset_t type defines the callback function - * executed when a global variable is set with a value. + * executed when a global variable is set with a value. It is not + * called when a global variable is changed implicitly. For example, + * it is not called when FNR is updated for each record read. */ typedef void (*qse_awk_rtx_ecb_gblset_t) ( qse_awk_rtx_t* rtx, /**< runtime context */ @@ -1239,9 +1241,12 @@ enum qse_awk_errnum_t QSE_AWK_EMAPNA, /**< map cannot be assigned to variable */ QSE_AWK_EMAPNRA, /**< map '${0}' cannot be reassigned */ QSE_AWK_EMAPUR, /**< map unreturnable */ - QSE_AWK_EMAPPH, /**< map prohibited */ + QSE_AWK_EMAPTOSCALAR, /**< cannot change a map to a scalar value */ QSE_AWK_ESCALARTOMAP, /**< cannot change a scalar value to a map */ - QSE_AWK_EVALTYPE, /**< invalid value type */ + QSE_AWK_EVALTOSTR, /**< invalid value to convert to a string */ + QSE_AWK_EVALTONUM, /**< invalid value to convert to a number */ + QSE_AWK_EVALTOCHR, /**< invalid value to convert to a character */ + QSE_AWK_EHASHVAL, /**< invalid value to hash */ QSE_AWK_ERNEXTBEG, /**< 'next' called from BEGIN block */ QSE_AWK_ERNEXTEND, /**< 'next' called from END block */ QSE_AWK_ERNEXTFBEG, /**< 'nextfile' called from BEGIN block */ diff --git a/qse/lib/awk/awk.h b/qse/lib/awk/awk.h index 5998a291..eab86edf 100644 --- a/qse/lib/awk/awk.h +++ b/qse/lib/awk/awk.h @@ -241,6 +241,14 @@ struct qse_awk_chain_t qse_awk_chain_t* next; }; +#define RTX_STACK_AT(rtx,n) ((rtx)->stack[(rtx)->stack_base+(n)]) +#define RTX_STACK_NARGS(rtx) (RTX_STACK_AT(rtx,3)) +#define RTX_STACK_ARG(rtx,n) RTX_STACK_AT(rtx,3+1+(n)) +#define RTX_STACK_LCL(rtx,n) RTX_STACK_AT(rtx,3+(qse_size_t)RTX_STACK_NARGS(rtx)+1+(n)) +#define RTX_STACK_RETVAL(rtx) RTX_STACK_AT(rtx,2) +#define RTX_STACK_GBL(rtx,n) ((rtx)->stack[(n)]) +#define RTX_STACK_RETVAL_GBL(rtx) ((rtx)->stack[(rtx)->awk->tree.ngbls+2]) + struct qse_awk_rtx_t { int id; diff --git a/qse/lib/awk/err.c b/qse/lib/awk/err.c index a188527c..330d6967 100644 --- a/qse/lib/awk/err.c +++ b/qse/lib/awk/err.c @@ -118,14 +118,17 @@ const qse_char_t* qse_awk_dflerrstr (const qse_awk_t* awk, qse_awk_errnum_t errn QSE_T("right-hand side of the 'in' operator not a map"), QSE_T("right-hand side of the 'in' operator not a map nor nil"), QSE_T("value not referenceable"), - QSE_T("indexed value cannot be a map"), - QSE_T("positional value cannot be a map"), + QSE_T("indexed variable cannot be assigned a map"), + QSE_T("positional cannot be assigned a map"), QSE_T("map cannot be assigned to variable"), QSE_T("map '${0}' cannot be reassigned"), QSE_T("map cannot be returned"), - QSE_T("map prohibited"), + QSE_T("cannot change a map to a scalar value"), QSE_T("cannot change a scalar value to a map"), - QSE_T("invalid value type"), + QSE_T("invalid value to convert to a string"), + QSE_T("invalid value to convert to a number"), + QSE_T("invalid value to a character"), + QSE_T("invalid value for hashing"), QSE_T("'next' called from BEGIN block"), QSE_T("'next' called from END block"), QSE_T("'nextfile' called from BEGIN block"), diff --git a/qse/lib/awk/fnc.c b/qse/lib/awk/fnc.c index f86f6dc3..ffb60fed 100644 --- a/qse/lib/awk/fnc.c +++ b/qse/lib/awk/fnc.c @@ -627,7 +627,7 @@ static int fnc_substr (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) static int fnc_split (qse_awk_rtx_t* run, const qse_awk_fnc_info_t* fi) { qse_size_t nargs; - qse_awk_val_t* a0, * a1, * a2, * t1, * t2, ** a1_ref; + qse_awk_val_t* a0, * a1, * a2, * t1, * t2; qse_cstr_t str, fs; qse_char_t* str_free = QSE_NULL, * fs_free = QSE_NULL; @@ -640,6 +640,7 @@ static int fnc_split (qse_awk_rtx_t* run, const qse_awk_fnc_info_t* fi) qse_long_t nflds; qse_awk_errnum_t errnum; + int x; nargs = qse_awk_rtx_getnargs (run); QSE_ASSERT (nargs >= 2 && nargs <= 3); @@ -650,33 +651,6 @@ static int fnc_split (qse_awk_rtx_t* run, const qse_awk_fnc_info_t* fi) QSE_ASSERT (a1->type == QSE_AWK_VAL_REF); - if (((qse_awk_val_ref_t*)a1)->id >= QSE_AWK_VAL_REF_NAMEDIDX && - ((qse_awk_val_ref_t*)a1)->id <= QSE_AWK_VAL_REF_ARGIDX) - { - /* an indexed value should not be assigned another map */ - qse_awk_rtx_seterrnum (run, QSE_AWK_EIDXVALMAP, QSE_NULL); - return -1; - } - - if (((qse_awk_val_ref_t*)a1)->id == QSE_AWK_VAL_REF_POS) - { - /* a positional should not be assigned a map */ - qse_awk_rtx_seterrnum (run, QSE_AWK_EPOSVALMAP, QSE_NULL); - return -1; - } - - a1_ref = (qse_awk_val_t**)((qse_awk_val_ref_t*)a1)->adr; - if ((*a1_ref)->type != QSE_AWK_VAL_NIL && - (*a1_ref)->type != QSE_AWK_VAL_MAP) - { - if (!(run->awk->opt.trait & QSE_AWK_FLEXMAP)) - { - /* cannot change a scalar value to a map */ - qse_awk_rtx_seterrnum (run, QSE_AWK_ESCALARTOMAP, QSE_NULL); - return -1; - } - } - if (a0->type == QSE_AWK_VAL_STR) { str.ptr = ((qse_awk_val_str_t*)a0)->val.ptr; @@ -752,14 +726,12 @@ static int fnc_split (qse_awk_rtx_t* run, const qse_awk_fnc_info_t* fi) t1 = qse_awk_rtx_makemapval (run); if (t1 == QSE_NULL) goto oops; - /* use the following 3 lines intead of - * qse_awk_rtx_setrefval (run, a1, t1); - * just for less overhead. - */ - qse_awk_rtx_refdownval (run, *a1_ref); - *a1_ref = t1; - qse_awk_rtx_refupval (run, *a1_ref); + qse_awk_rtx_refupval (run, t1); + x = qse_awk_rtx_setrefval (run, a1, t1); + qse_awk_rtx_refdownval (run, t1); + if (x <= -1) goto oops; + /* fill the map with actual values */ p = str.ptr; str_left = str.len; org_len = str.len; nflds = 0; @@ -907,6 +879,7 @@ static int fnc_toupper (qse_awk_rtx_t* run, const qse_awk_fnc_info_t* fi) return 0; } + static int __substitute (qse_awk_rtx_t* run, qse_long_t max_count) { qse_size_t nargs; @@ -972,54 +945,11 @@ static int __substitute (qse_awk_rtx_t* run, qse_long_t max_count) s2.ptr = QSE_STR_PTR(&run->inrec.line); s2.len = QSE_STR_LEN(&run->inrec.line); } - else if (((qse_awk_val_ref_t*)a2)->id == QSE_AWK_VAL_REF_POS) - { - qse_size_t idx; - - idx = (qse_size_t)((qse_awk_val_ref_t*)a2)->adr; - if (idx == 0) - { - s2.ptr = QSE_STR_PTR(&run->inrec.line); - s2.len = QSE_STR_LEN(&run->inrec.line); - } - else if (idx <= run->inrec.nflds) - { - s2.ptr = run->inrec.flds[idx-1].ptr; - s2.len = run->inrec.flds[idx-1].len; - } - else - { - s2.ptr = QSE_T(""); - s2.len = 0; - } - } else { - a2_ref = (qse_awk_val_t**)((qse_awk_val_ref_t*)a2)->adr; - - if ((*a2_ref)->type == QSE_AWK_VAL_MAP) - { - /* a map is not allowed as the third parameter. - * this is a prohibited condition regardless of QSE_AWK_FLEXMAP. - * i don't accept this. - * - * TODO: can i extend to replace something in a map??? - */ - qse_awk_rtx_seterrnum (run, QSE_AWK_EMAPPH, QSE_NULL); - goto oops; - } - - if ((*a2_ref)->type == QSE_AWK_VAL_STR) - { - s2.ptr = ((qse_awk_val_str_t*)(*a2_ref))->val.ptr; - s2.len = ((qse_awk_val_str_t*)(*a2_ref))->val.len; - } - else - { - s2.ptr = qse_awk_rtx_valtostrdup (run, *a2_ref, &s2.len); - if (s2.ptr == QSE_NULL) goto oops; - s2_free = (qse_char_t*)s2.ptr; - } + s2.ptr = qse_awk_rtx_valtostrdup (run, a2, &s2.len); + if (s2.ptr == QSE_NULL) goto oops; + s2_free = (qse_char_t*)s2.ptr; } if (qse_str_init (&new, run->awk->mmgr, s2.len) <= -1) @@ -1165,24 +1095,16 @@ static int __substitute (qse_awk_rtx_t* run, qse_long_t max_count) n = qse_awk_rtx_setrec (run, 0, QSE_STR_CSTR(&new)); if (n <= -1) goto oops; } - else if (((qse_awk_val_ref_t*)a2)->id == QSE_AWK_VAL_REF_POS) + else { int n; - n = qse_awk_rtx_setrec ( - run, (qse_size_t)((qse_awk_val_ref_t*)a2)->adr, - QSE_STR_CSTR(&new)); - - if (n <= -1) goto oops; - } - else - { v = qse_awk_rtx_makestrvalwithcstr (run, QSE_STR_CSTR(&new)); if (v == QSE_NULL) goto oops; - - qse_awk_rtx_refdownval (run, *a2_ref); - *a2_ref = v; - qse_awk_rtx_refupval (run, *a2_ref); + qse_awk_rtx_refupval (run, v); + n = qse_awk_rtx_setrefval (run, a2, v); + qse_awk_rtx_refdownval (run, v); + if (n <= -1) goto oops; } } diff --git a/qse/lib/awk/mod-dir.c b/qse/lib/awk/mod-dir.c index 57835148..a2e82972 100644 --- a/qse/lib/awk/mod-dir.c +++ b/qse/lib/awk/mod-dir.c @@ -275,21 +275,28 @@ static int read_byid (qse_awk_rtx_t* rtx, dir_list_t* list, qse_long_t id, qse_a return -1; } - if (y == 0) return 0; + if (y == 0) return 0; /* no more entry */ tmp = qse_awk_rtx_makestrvalwithstr (rtx, ent.name); - if (!tmp || qse_awk_rtx_setrefval (rtx, ref, tmp) <= -1) + if (!tmp) { list->errnum = awk_err_to_errnum (qse_awk_rtx_geterrnum (rtx)); - if (tmp) - { - qse_awk_rtx_refupval (rtx, tmp); - qse_awk_rtx_refdownval (rtx, tmp); - } return -1; } + else + { + int n; + qse_awk_rtx_refupval (rtx, tmp); + n = qse_awk_rtx_setrefval (rtx, ref, tmp); + qse_awk_rtx_refdownval (rtx, tmp); + if (n <= -1) + { + list->errnum = awk_err_to_errnum (qse_awk_rtx_geterrnum (rtx)); + return -1; + } + } - return 0; + return 1; /* has entry */ } else { diff --git a/qse/lib/awk/mod-sys.c b/qse/lib/awk/mod-sys.c index 7c33808c..08cdff2b 100644 --- a/qse/lib/awk/mod-sys.c +++ b/qse/lib/awk/mod-sys.c @@ -567,12 +567,11 @@ static int fnc_getnwifcfg (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi) tmp = qse_awk_rtx_makemapvalwithdata (rtx, md); if (tmp) { - if (qse_awk_rtx_setrefval (rtx, qse_awk_rtx_getarg (rtx, 2), tmp) <= -1) - { - qse_awk_rtx_refupval (rtx, tmp); - qse_awk_rtx_refdownval (rtx, tmp); - } - else ret = 0; + int x; + qse_awk_rtx_refupval (rtx, tmp); + x = qse_awk_rtx_setrefval (rtx, qse_awk_rtx_getarg (rtx, 2), tmp); + qse_awk_rtx_refdownval (rtx, tmp); + if (x >= 0) ret = 0; } } } diff --git a/qse/lib/awk/mod-uci.c b/qse/lib/awk/mod-uci.c index 637eda80..56f69903 100644 --- a/qse/lib/awk/mod-uci.c +++ b/qse/lib/awk/mod-uci.c @@ -471,12 +471,11 @@ static int getsection_byid ( tmp = qse_awk_rtx_makemapvalwithdata (rtx, md); if (tmp) { - if (qse_awk_rtx_setrefval (rtx, ref, tmp) <= -1) - { - qse_awk_rtx_refupval (rtx, tmp); - qse_awk_rtx_refdownval (rtx, tmp); - x = UCI_ERR_MEM; - } + int n; + qse_awk_rtx_refupval (rtx, tmp); + n = qse_awk_rtx_setrefval (rtx, ref, tmp); + qse_awk_rtx_refdownval (rtx, tmp); + if (n <= -1) x = UCI_ERR_MEM; /* this is not a correct error code. who cares? */ } else x = UCI_ERR_MEM; } @@ -534,10 +533,12 @@ static int getoption_byid ( map = qse_awk_rtx_makemapvalwithdata (rtx, md); if (map) { - if (qse_awk_rtx_setrefval (rtx, ref, map) <= -1) + int n; + qse_awk_rtx_refupval (rtx, map); + n = qse_awk_rtx_setrefval (rtx, ref, map); + qse_awk_rtx_refdownval (rtx, map); + if (n <= -1) { - qse_awk_rtx_refupval (rtx, map); - qse_awk_rtx_refdownval (rtx, map); map = QSE_NULL; x = UCI_ERR_MEM; } diff --git a/qse/lib/awk/run.c b/qse/lib/awk/run.c index 9740bbbd..c0246e6d 100644 --- a/qse/lib/awk/run.c +++ b/qse/lib/awk/run.c @@ -29,20 +29,12 @@ #define CMP_ERROR -99 #define DEF_BUF_CAPA 256 -#define STACK_INCREMENT 512 +#define RTX_STACK_INCREMENT 512 #define IDXBUFSIZE 64 #define MMGR(rtx) ((rtx)->awk->mmgr) -#define STACK_AT(rtx,n) ((rtx)->stack[(rtx)->stack_base+(n)]) -#define STACK_NARGS(rtx) (STACK_AT(rtx,3)) -#define STACK_ARG(rtx,n) STACK_AT(rtx,3+1+(n)) -#define STACK_LCL(rtx,n) STACK_AT(rtx,3+(qse_size_t)STACK_NARGS(rtx)+1+(n)) -#define STACK_RETVAL(rtx) STACK_AT(rtx,2) -#define STACK_GBL(rtx,n) ((rtx)->stack[(n)]) -#define STACK_RETVAL_GBL(rtx) ((rtx)->stack[(rtx)->awk->tree.ngbls+2]) - enum exit_level_t { EXIT_NONE, @@ -285,18 +277,18 @@ static QSE_INLINE qse_cstr_t* xstr_to_cstr (qse_xstr_t* xstr) QSE_INLINE qse_size_t qse_awk_rtx_getnargs (qse_awk_rtx_t* run) { - return (qse_size_t) STACK_NARGS (run); + return (qse_size_t) RTX_STACK_NARGS (run); } QSE_INLINE qse_awk_val_t* qse_awk_rtx_getarg (qse_awk_rtx_t* run, qse_size_t idx) { - return STACK_ARG (run, idx); + return RTX_STACK_ARG (run, idx); } QSE_INLINE qse_awk_val_t* qse_awk_rtx_getgbl (qse_awk_rtx_t* run, int id) { QSE_ASSERT (id >= 0 && id < (int)QSE_LDA_SIZE(run->awk->parse.gbls)); - return STACK_GBL (run, id); + return RTX_STACK_GBL (run, id); } const qse_xstr_t* qse_awk_rtx_getsubsep (qse_awk_rtx_t* run) @@ -308,49 +300,70 @@ const qse_xstr_t* qse_awk_rtx_getsubsep (qse_awk_rtx_t* run) * this function can handle a few special global variables that * require special treatment. */ static int set_global ( - qse_awk_rtx_t* rtx, qse_size_t idx, + qse_awk_rtx_t* rtx, int idx, qse_awk_nde_var_t* var, qse_awk_val_t* val) { qse_awk_val_t* old; qse_awk_rtx_ecb_t* ecb; - old = STACK_GBL (rtx, idx); - if (!(rtx->awk->opt.trait & QSE_AWK_FLEXMAP) && old->type == QSE_AWK_VAL_MAP) - { - /* once a variable becomes a map, - * it cannot be assigned with another value. - * you can only add a member using indexing. */ - if (var) + old = RTX_STACK_GBL (rtx, idx); + if (old == val) return 0; /* the old value is the same as the new value. nothing to do */ + + if (!(rtx->awk->opt.trait & QSE_AWK_FLEXMAP)) + { + qse_awk_errnum_t errnum = QSE_AWK_ENOERR; + + if (old->type == QSE_AWK_VAL_MAP && val->type != QSE_AWK_VAL_MAP) + errnum = QSE_AWK_EMAPNRA; + + if (val->type == QSE_AWK_VAL_MAP) { - /* global variable */ - SETERR_ARGX_LOC ( - rtx, - QSE_AWK_EMAPNRA, - xstr_to_cstr(&var->id.name), - &var->loc - ); + if (old->type != QSE_AWK_VAL_NIL) + errnum = QSE_AWK_EMAPNA; } else { - /* qse_awk_rtx_setgbl() has been called */ - qse_cstr_t ea; - ea.ptr = qse_awk_getgblname (rtx->awk, idx, &ea.len); - SETERR_ARGX (rtx, QSE_AWK_EMAPNRA, &ea); + if (old->type == QSE_AWK_VAL_MAP) errnum = QSE_AWK_EMAPNRA; } + + if (errnum != QSE_AWK_ENOERR) + { + /* once a variable becomes a map, it cannot be assigned + * others value than another map. you can only add a member + * using indexing. */ + if (var) + { + /* global variable */ + SETERR_ARGX_LOC ( + rtx, + errnum, + xstr_to_cstr(&var->id.name), + &var->loc + ); + } + else + { + /* qse_awk_rtx_setgbl() has been called */ + qse_cstr_t ea; + ea.ptr = qse_awk_getgblname (rtx->awk, idx, &ea.len); + SETERR_ARGX (rtx, errnum, &ea); + } - return -1; + return -1; + } } - /* all the basic builtin variables cannot be assigned a map. - * if you happen to add one and if that's allowed to be a map, - * you may have to change the condition here. - * but is this check really necessary??? */ - if (val->type == QSE_AWK_VAL_MAP && - idx >= QSE_AWK_MIN_GBL_ID && idx <= QSE_AWK_MAX_GBL_ID) + if (val->type == QSE_AWK_VAL_MAP) { - /* TODO: better error code */ - SETERR_COD (rtx, QSE_AWK_ESCALARTOMAP); - return -1; + if (idx >= QSE_AWK_MIN_GBL_ID && idx <= QSE_AWK_MAX_GBL_ID) + { + /* short-circuit check block to prevent the basic built-in variables + * from being assigned a map. if you happen to add one and if that's + * allowed to be a map, you may have to change the condition here. */ +/* TODO: use global variable attribute. can it be a map? can it be a scalar? is it read-only???? */ + SETERR_COD (rtx, QSE_AWK_ESCALARTOMAP); + return -1; + } } switch (idx) @@ -469,7 +482,7 @@ static int set_global ( if (shorten_record (rtx, (qse_size_t)lv) == -1) { /* adjust the error line */ - if (var) ADJERR_LOC (rtx, &var->loc); + /*if (var) ADJERR_LOC (rtx, &var->loc);*/ return -1; } } @@ -614,11 +627,10 @@ static int set_global ( break; } - } qse_awk_rtx_refdownval (rtx, old); - STACK_GBL(rtx,idx) = val; + RTX_STACK_GBL(rtx,idx) = val; qse_awk_rtx_refupval (rtx, val); for (ecb = (rtx)->ecb; ecb; ecb = ecb->next) @@ -630,8 +642,8 @@ static int set_global ( QSE_INLINE void qse_awk_rtx_setretval ( qse_awk_rtx_t* rtx, qse_awk_val_t* val) { - qse_awk_rtx_refdownval (rtx, STACK_RETVAL(rtx)); - STACK_RETVAL(rtx) = val; + qse_awk_rtx_refdownval (rtx, RTX_STACK_RETVAL(rtx)); + RTX_STACK_RETVAL(rtx) = val; /* should use the same trick as run_return */ qse_awk_rtx_refupval (rtx, val); } @@ -640,7 +652,7 @@ QSE_INLINE int qse_awk_rtx_setgbl ( qse_awk_rtx_t* rtx, int id, qse_awk_val_t* val) { QSE_ASSERT (id >= 0 && id < (int)QSE_LDA_SIZE(rtx->awk->parse.gbls)); - return set_global (rtx, (qse_size_t)id, QSE_NULL, val); + return set_global (rtx, id, QSE_NULL, val); } int qse_awk_rtx_setfilename ( @@ -1251,7 +1263,7 @@ static int defaultify_globals (qse_awk_rtx_t* rtx) qse_awk_rtx_refupval (rtx, tmp); - QSE_ASSERT (STACK_GBL(rtx,gtab[i].idx) == qse_awk_val_nil); + QSE_ASSERT (RTX_STACK_GBL(rtx,gtab[i].idx) == qse_awk_val_nil); if (qse_awk_rtx_setgbl (rtx, gtab[i].idx, tmp) == -1) { @@ -1279,9 +1291,9 @@ static void refdown_globals (qse_awk_rtx_t* run, int pop) while (ngbls > 0) { --ngbls; - qse_awk_rtx_refdownval (run, STACK_GBL(run,ngbls)); + qse_awk_rtx_refdownval (run, RTX_STACK_GBL(run,ngbls)); if (pop) __raw_pop (run); - else STACK_GBL(run,ngbls) = qse_awk_val_nil; + else RTX_STACK_GBL(run,ngbls) = qse_awk_val_nil; } } @@ -1312,7 +1324,7 @@ static void capture_retval_on_exit (void* arg) struct capture_retval_data_t* data; data = (struct capture_retval_data_t*)arg; - data->val = STACK_RETVAL(data->rtx); + data->val = RTX_STACK_RETVAL(data->rtx); qse_awk_rtx_refupval (data->rtx, data->val); } @@ -1332,7 +1344,7 @@ static int enter_stack_frame (qse_awk_rtx_t* rtx) /* secure space for a return value */ if (__raw_push(rtx,qse_awk_val_nil) == -1) goto oops; - /* secure space for STACK_NARGS */ + /* secure space for RTX_STACK_NARGS */ if (__raw_push(rtx,qse_awk_val_nil) == -1) goto oops; /* let the stack top remembered be the base of a new stack frame */ @@ -1367,7 +1379,7 @@ static qse_awk_val_t* run_bpae_loop (qse_awk_rtx_t* rtx) /* set nargs to zero */ nargs = 0; - STACK_NARGS(rtx) = (void*)nargs; + RTX_STACK_NARGS(rtx) = (void*)nargs; /* execute the BEGIN block */ for (nde = rtx->awk->tree.begin; @@ -1448,13 +1460,13 @@ static qse_awk_val_t* run_bpae_loop (qse_awk_rtx_t* rtx) /* derefrence all arguments. however, there should be no arguments * pushed to the stack as asserted below. we didn't push any arguments * for BEGIN/pattern action/END block execution.*/ - nargs = (qse_size_t)STACK_NARGS(rtx); + nargs = (qse_size_t)RTX_STACK_NARGS(rtx); QSE_ASSERT (nargs == 0); for (i = 0; i < nargs; i++) - qse_awk_rtx_refdownval (rtx, STACK_ARG(rtx,i)); + qse_awk_rtx_refdownval (rtx, RTX_STACK_ARG(rtx,i)); /* get the return value in the current stack frame */ - retv = STACK_RETVAL(rtx); + retv = RTX_STACK_RETVAL(rtx); if (ret <= -1) { @@ -1888,7 +1900,7 @@ static int run_block0 (qse_awk_rtx_t* rtx, qse_awk_nde_blk_t* nde) while (nlcls > 0) { --nlcls; - qse_awk_rtx_refdownval (rtx, STACK_LCL(rtx,nlcls)); + qse_awk_rtx_refdownval (rtx, RTX_STACK_LCL(rtx,nlcls)); __raw_pop (rtx); } @@ -2330,8 +2342,8 @@ static int run_return (qse_awk_rtx_t* run, qse_awk_nde_return_t* nde) } } - qse_awk_rtx_refdownval (run, STACK_RETVAL(run)); - STACK_RETVAL(run) = val; + qse_awk_rtx_refdownval (run, RTX_STACK_RETVAL(run)); + RTX_STACK_RETVAL(run) = val; /* NOTE: see eval_call() for the trick */ qse_awk_rtx_refupval (run, val); @@ -2354,8 +2366,8 @@ static int run_exit (qse_awk_rtx_t* run, qse_awk_nde_exit_t* nde) val = eval_expression (run, nde->val); if (val == QSE_NULL) return -1; - qse_awk_rtx_refdownval (run, STACK_RETVAL_GBL(run)); - STACK_RETVAL_GBL(run) = val; /* global return value */ + qse_awk_rtx_refdownval (run, RTX_STACK_RETVAL_GBL(run)); + RTX_STACK_RETVAL_GBL(run) = val; /* global return value */ qse_awk_rtx_refupval (run, val); } @@ -2599,13 +2611,22 @@ static int run_delete_unnamed (qse_awk_rtx_t* rtx, qse_awk_nde_var_t* var) { qse_awk_val_t* val; - if (var->type == QSE_AWK_NDE_GBL || - var->type == QSE_AWK_NDE_GBLIDX) - val = STACK_GBL (rtx,var->id.idxa); - else if (var->type == QSE_AWK_NDE_LCL || - var->type == QSE_AWK_NDE_LCLIDX) - val = STACK_LCL (rtx,var->id.idxa); - else val = STACK_ARG (rtx,var->id.idxa); + switch (var->type) + { + case QSE_AWK_NDE_GBL: + case QSE_AWK_NDE_GBLIDX: + val = RTX_STACK_GBL (rtx,var->id.idxa); + break; + + case QSE_AWK_NDE_LCL: + case QSE_AWK_NDE_LCLIDX: + val = RTX_STACK_LCL (rtx,var->id.idxa); + break; + + default: + val = RTX_STACK_ARG (rtx,var->id.idxa); + break; + } QSE_ASSERT (val != QSE_NULL); @@ -2625,28 +2646,35 @@ static int run_delete_unnamed (qse_awk_rtx_t* rtx, qse_awk_nde_var_t* var) /* no need to reduce the reference count of * the previous value because it was nil. */ - if (var->type == QSE_AWK_NDE_GBL || - var->type == QSE_AWK_NDE_GBLIDX) + switch (var->type) { - if (qse_awk_rtx_setgbl ( - rtx, (int)var->id.idxa, tmp) == -1) + case QSE_AWK_NDE_GBL: + case QSE_AWK_NDE_GBLIDX: { + int x; + qse_awk_rtx_refupval (rtx, tmp); + x = qse_awk_rtx_setgbl (rtx, (int)var->id.idxa, tmp); qse_awk_rtx_refdownval (rtx, tmp); - ADJERR_LOC (rtx, &var->loc); - return -1; + + if (x <= -1) + { + ADJERR_LOC (rtx, &var->loc); + return -1; + } + break; } - } - else if (var->type == QSE_AWK_NDE_LCL || - var->type == QSE_AWK_NDE_LCLIDX) - { - STACK_LCL(rtx,var->id.idxa) = tmp; - qse_awk_rtx_refupval (rtx, tmp); - } - else - { - STACK_ARG(rtx,var->id.idxa) = tmp; - qse_awk_rtx_refupval (rtx, tmp); + + case QSE_AWK_NDE_LCL: + case QSE_AWK_NDE_LCLIDX: + RTX_STACK_LCL(rtx,var->id.idxa) = tmp; + qse_awk_rtx_refupval (rtx, tmp); + break; + + default: + RTX_STACK_ARG(rtx,var->id.idxa) = tmp; + qse_awk_rtx_refupval (rtx, tmp); + break; } } else @@ -2717,52 +2745,69 @@ static int run_reset (qse_awk_rtx_t* rtx, qse_awk_nde_reset_t* nde) var = (qse_awk_nde_var_t*) nde->var; - if (var->type == QSE_AWK_NDE_NAMED) + switch (var->type) { - QSE_ASSERTX ( - var->type == QSE_AWK_NDE_NAMED && var->idx == QSE_NULL, - "if a named variable has an index part, something is definitely wrong"); + case QSE_AWK_NDE_NAMED: + QSE_ASSERTX ( + var->type == QSE_AWK_NDE_NAMED && var->idx == QSE_NULL, + "if a named variable has an index part, something is definitely wrong"); - /* a named variable can be reset if removed from a internal map - to manage it */ - qse_htb_delete (rtx->named, var->id.name.ptr, var->id.name.len); - } - else if (var->type == QSE_AWK_NDE_GBL || - var->type == QSE_AWK_NDE_LCL || - var->type == QSE_AWK_NDE_ARG) - { - qse_awk_val_t* val; + /* a named variable can be reset if removed from a internal map + to manage it */ + qse_htb_delete (rtx->named, var->id.name.ptr, var->id.name.len); + return 0; - if (var->type == QSE_AWK_NDE_GBL) - val = STACK_GBL(rtx,var->id.idxa); - else if (var->type == QSE_AWK_NDE_LCL) - val = STACK_LCL(rtx,var->id.idxa); - else val = STACK_ARG(rtx,var->id.idxa); - - QSE_ASSERT (val != QSE_NULL); - - if (val->type != QSE_AWK_VAL_NIL) + case QSE_AWK_NDE_GBL: + case QSE_AWK_NDE_LCL: + case QSE_AWK_NDE_ARG: { - qse_awk_rtx_refdownval (rtx, val); - if (var->type == QSE_AWK_NDE_GBL) - STACK_GBL(rtx,var->id.idxa) = qse_awk_val_nil; - else if (var->type == QSE_AWK_NDE_LCL) - STACK_LCL(rtx,var->id.idxa) = qse_awk_val_nil; - else - STACK_ARG(rtx,var->id.idxa) = qse_awk_val_nil; + qse_awk_val_t* val; + + switch (var->type) + { + case QSE_AWK_NDE_GBL: + val = RTX_STACK_GBL(rtx,var->id.idxa); + break; + + case QSE_AWK_NDE_LCL: + val = RTX_STACK_LCL(rtx,var->id.idxa); + break; + + case QSE_AWK_NDE_ARG: + val = RTX_STACK_ARG(rtx,var->id.idxa); + break; + } + + QSE_ASSERT (val != QSE_NULL); + + if (val->type != QSE_AWK_VAL_NIL) + { + qse_awk_rtx_refdownval (rtx, val); + switch (var->type) + { + case QSE_AWK_NDE_GBL: + RTX_STACK_GBL(rtx,var->id.idxa) = qse_awk_val_nil; + break; + + case QSE_AWK_NDE_LCL: + RTX_STACK_LCL(rtx,var->id.idxa) = qse_awk_val_nil; + break; + + case QSE_AWK_NDE_ARG: + RTX_STACK_ARG(rtx,var->id.idxa) = qse_awk_val_nil; + break; + } + } + return 0; } - } - else - { - QSE_ASSERTX ( - !"should never happen - wrong target for reset", - "the reset statement can only be called with plain variables"); - SETERR_LOC (rtx, QSE_AWK_EBADARG, &var->loc); - return -1; + default: + QSE_ASSERTX ( + !"should never happen - wrong target for reset", + "the reset statement can only be called with plain variables"); + SETERR_LOC (rtx, QSE_AWK_EBADARG, &var->loc); + return -1; } - - return 0; } static int run_print (qse_awk_rtx_t* rtx, qse_awk_nde_print_t* nde) @@ -3494,7 +3539,7 @@ static qse_awk_val_t* do_assignment_scalar ( case QSE_AWK_NDE_LCL: { - qse_awk_val_t* old = STACK_LCL(run,var->id.idxa); + qse_awk_val_t* old = RTX_STACK_LCL(run,var->id.idxa); if (!(run->awk->opt.trait & QSE_AWK_FLEXMAP) && old->type == QSE_AWK_VAL_MAP) { /* once the variable becomes a map, @@ -3506,14 +3551,14 @@ static qse_awk_val_t* do_assignment_scalar ( } qse_awk_rtx_refdownval (run, old); - STACK_LCL(run,var->id.idxa) = val; + RTX_STACK_LCL(run,var->id.idxa) = val; qse_awk_rtx_refupval (run, val); break; } case QSE_AWK_NDE_ARG: { - qse_awk_val_t* old = STACK_ARG(run,var->id.idxa); + qse_awk_val_t* old = RTX_STACK_ARG(run,var->id.idxa); if (!(run->awk->opt.trait & QSE_AWK_FLEXMAP) && old->type == QSE_AWK_VAL_MAP) { /* once the variable becomes a map, @@ -3525,7 +3570,7 @@ static qse_awk_val_t* do_assignment_scalar ( } qse_awk_rtx_refdownval (run, old); - STACK_ARG(run,var->id.idxa) = val; + RTX_STACK_ARG(run,var->id.idxa) = val; qse_awk_rtx_refupval (run, val); break; } @@ -3562,10 +3607,10 @@ static qse_awk_val_t* do_assignment_map ( else { map = (var->type == QSE_AWK_NDE_GBLIDX)? - (qse_awk_val_map_t*)STACK_GBL(run,var->id.idxa): + (qse_awk_val_map_t*)RTX_STACK_GBL(run,var->id.idxa): (var->type == QSE_AWK_NDE_LCLIDX)? - (qse_awk_val_map_t*)STACK_LCL(run,var->id.idxa): - (qse_awk_val_map_t*)STACK_ARG(run,var->id.idxa); + (qse_awk_val_map_t*)RTX_STACK_LCL(run,var->id.idxa): + (qse_awk_val_map_t*)RTX_STACK_ARG(run,var->id.idxa); } if (map->type == QSE_AWK_VAL_NIL) @@ -3580,49 +3625,50 @@ static qse_awk_val_t* do_assignment_map ( return QSE_NULL; } - if (var->type == QSE_AWK_NDE_NAMEDIDX) + switch (var->type) { - /* doesn't have to decrease the reference count - * of the previous value here as it is done by - * qse_htb_upsert */ - if (qse_htb_upsert ( - run->named, - var->id.name.ptr, - var->id.name.len, - tmp, - 0) == QSE_NULL) + case QSE_AWK_NDE_NAMEDIDX: { + /* doesn't have to decrease the reference count + * of the previous value here as it is done by + * qse_htb_upsert */ qse_awk_rtx_refupval (run, tmp); - qse_awk_rtx_refdownval (run, tmp); + if (qse_htb_upsert (run->named, var->id.name.ptr, var->id.name.len, tmp, 0) == QSE_NULL) + { + qse_awk_rtx_refdownval (run, tmp); + SETERR_LOC (run, QSE_AWK_ENOMEM, &var->loc); + return QSE_NULL; + } - SETERR_LOC (run, QSE_AWK_ENOMEM, &var->loc); - return QSE_NULL; + break; } - qse_awk_rtx_refupval (run, tmp); - } - else if (var->type == QSE_AWK_NDE_GBLIDX) - { - qse_awk_rtx_refupval (run, tmp); - if (qse_awk_rtx_setgbl (run, (int)var->id.idxa, tmp) == -1) + case QSE_AWK_NDE_GBLIDX: { + int x; + + qse_awk_rtx_refupval (run, tmp); + x = qse_awk_rtx_setgbl (run, (int)var->id.idxa, tmp); qse_awk_rtx_refdownval (run, tmp); - ADJERR_LOC (run, &var->loc); - return QSE_NULL; + if (x <= -1) + { + ADJERR_LOC (run, &var->loc); + return QSE_NULL; + } + break; } - qse_awk_rtx_refdownval (run, tmp); - } - else if (var->type == QSE_AWK_NDE_LCLIDX) - { - qse_awk_rtx_refdownval (run, (qse_awk_val_t*)map); - STACK_LCL(run,var->id.idxa) = tmp; - qse_awk_rtx_refupval (run, tmp); - } - else /* if (var->type == QSE_AWK_NDE_ARGIDX) */ - { - qse_awk_rtx_refdownval (run, (qse_awk_val_t*)map); - STACK_ARG(run,var->id.idxa) = tmp; - qse_awk_rtx_refupval (run, tmp); + + case QSE_AWK_NDE_LCLIDX: + qse_awk_rtx_refdownval (run, (qse_awk_val_t*)map); + RTX_STACK_LCL(run,var->id.idxa) = tmp; + qse_awk_rtx_refupval (run, tmp); + break; + + default: /* QSE_AWK_NDE_ARGIDX */ + qse_awk_rtx_refdownval (run, (qse_awk_val_t*)map); + RTX_STACK_ARG(run,var->id.idxa) = tmp; + qse_awk_rtx_refupval (run, tmp); + break; } map = (qse_awk_val_map_t*) tmp; @@ -5565,9 +5611,9 @@ static qse_awk_val_t* eval_fun (qse_awk_rtx_t* run, qse_awk_nde_t* nde) } /* run->stack_base has not been set for this - * stack frame. so the STACK_ARG macro cannot be used as in - * qse_awk_rtx_refdownval (run, STACK_ARG(run,nargs));*/ -#define UNWIND_RTX_STACK_ARG(rtx,nargs) \ + * stack frame. so the RTX_STACK_ARG macro cannot be used as in + * qse_awk_rtx_refdownval (run, RTX_STACK_ARG(run,nargs));*/ +#define UNWIND_RTX_RTX_STACK_ARG(rtx,nargs) \ do { \ while ((nargs) > 0) \ { \ @@ -5577,7 +5623,7 @@ static qse_awk_val_t* eval_fun (qse_awk_rtx_t* run, qse_awk_nde_t* nde) } \ } while (0) -#define UNWIND_RTX_STACK_BASE(rtx) \ +#define UNWIND_RTX_RTX_STACK_BASE(rtx) \ do { \ __raw_pop (rtx); /* nargs */ \ __raw_pop (rtx); /* return */ \ @@ -5587,8 +5633,8 @@ static qse_awk_val_t* eval_fun (qse_awk_rtx_t* run, qse_awk_nde_t* nde) #define UNWIND_RTX_STACK(rtx,nargs) \ do { \ - UNWIND_RTX_STACK_ARG(rtx,nargs); \ - UNWIND_RTX_STACK_BASE(rtx); \ + UNWIND_RTX_RTX_STACK_ARG(rtx,nargs); \ + UNWIND_RTX_RTX_STACK_BASE(rtx); \ } while (0) static qse_awk_val_t* __eval_call ( @@ -5692,7 +5738,7 @@ static qse_awk_val_t* __eval_call ( nargs = argpusher (run, call, apdata); if (nargs == (qse_size_t)-1) { - UNWIND_RTX_STACK_BASE (run); + UNWIND_RTX_RTX_STACK_BASE (run); return QSE_NULL; } @@ -5717,7 +5763,7 @@ static qse_awk_val_t* __eval_call ( } run->stack_base = saved_stack_top; - STACK_NARGS(run) = (void*)nargs; + RTX_STACK_NARGS(run) = (void*)nargs; #ifdef DEBUG_RUN qse_dprintf (QSE_T("running function body\n")); @@ -5768,21 +5814,21 @@ static qse_awk_val_t* __eval_call ( } /* refdown args in the run.stack */ - nargs = (qse_size_t)STACK_NARGS(run); + nargs = (qse_size_t)RTX_STACK_NARGS(run); #ifdef DEBUG_RUN qse_dprintf (QSE_T("block run complete nargs = %d\n"), (int)nargs); #endif for (i = 0; i < nargs; i++) { - qse_awk_rtx_refdownval (run, STACK_ARG(run,i)); + qse_awk_rtx_refdownval (run, RTX_STACK_ARG(run,i)); } #ifdef DEBUG_RUN qse_dprintf (QSE_T("got return value\n")); #endif - v = STACK_RETVAL(run); + v = RTX_STACK_RETVAL(run); if (n == -1) { if (run->errinf.num == QSE_AWK_ENOERR && errhandler != QSE_NULL) @@ -5791,19 +5837,19 @@ static qse_awk_val_t* __eval_call ( * invoked from qse_awk_rtx_call(). Under this * circumstance, this stack frame is the first * activated and the stack base is the first element - * after the global variables. so STACK_RETVAL(run) - * effectively becomes STACK_RETVAL_GBL(run). + * after the global variables. so RTX_STACK_RETVAL(run) + * effectively becomes RTX_STACK_RETVAL_GBL(run). * As __eval_call() returns QSE_NULL on error and - * the reference count of STACK_RETVAL(run) should be + * the reference count of RTX_STACK_RETVAL(run) should be * decremented, it can't get the return value * if it turns out to be terminated by exit(). * The return value could be destroyed by then. * Unlikely, run_bpae_loop() just checks if run->errinf.num - * is QSE_AWK_ENOERR and gets STACK_RETVAL_GBL(run) + * is QSE_AWK_ENOERR and gets RTX_STACK_RETVAL_GBL(run) * to determine if it is terminated by exit(). * * The handler capture_retval_on_exit() - * increments the reference of STACK_RETVAL(run) + * increments the reference of RTX_STACK_RETVAL(run) * and stores the pointer into accompanying space. * This way, the return value is preserved upon * termination by exit() out to the caller. @@ -5815,7 +5861,7 @@ static qse_awk_val_t* __eval_call ( * has to return a error, the return value is just * destroyed and replaced by nil */ qse_awk_rtx_refdownval (run, v); - STACK_RETVAL(run) = qse_awk_val_nil; + RTX_STACK_RETVAL(run) = qse_awk_val_nil; } else { @@ -5858,7 +5904,7 @@ static qse_size_t push_arg_from_vals ( qse_awk_rtx_refupval (rtx, pafv->args[nargs]); qse_awk_rtx_refdownval (rtx, pafv->args[nargs]); - UNWIND_RTX_STACK_ARG (rtx, nargs); + UNWIND_RTX_RTX_STACK_ARG (rtx, nargs); SETERR_LOC (rtx, QSE_AWK_ENOMEM, &call->loc); return (qse_size_t)-1; } @@ -5892,7 +5938,7 @@ static qse_size_t push_arg_from_nde ( if (get_reference (rtx, p, &ref) == -1) { - UNWIND_RTX_STACK_ARG (rtx, nargs); + UNWIND_RTX_RTX_STACK_ARG (rtx, nargs); return (qse_size_t)-1; } @@ -5915,7 +5961,7 @@ static qse_size_t push_arg_from_nde ( if (v == QSE_NULL) { - UNWIND_RTX_STACK_ARG (rtx, nargs); + UNWIND_RTX_RTX_STACK_ARG (rtx, nargs); return (qse_size_t)-1; } @@ -5929,7 +5975,7 @@ static qse_size_t push_arg_from_nde ( qse_awk_rtx_refupval (rtx, v); qse_awk_rtx_refdownval (rtx, v); - UNWIND_RTX_STACK_ARG (rtx, nargs); + UNWIND_RTX_RTX_STACK_ARG (rtx, nargs); SETERR_LOC (rtx, QSE_AWK_ENOMEM, &call->loc); return (qse_size_t)-1; } @@ -5987,15 +6033,16 @@ static int get_reference ( } case QSE_AWK_NDE_GBL: - *ref = (qse_awk_val_t**)&STACK_GBL(run,tgt->id.idxa); + /* *ref = (qse_awk_val_t**)&RTX_STACK_GBL(run,tgt->id.idxa); */ + *ref = (qse_awk_val_t**)((qse_size_t)tgt->id.idxa); return 0; case QSE_AWK_NDE_LCL: - *ref = (qse_awk_val_t**)&STACK_LCL(run,tgt->id.idxa); + *ref = (qse_awk_val_t**)&RTX_STACK_LCL(run,tgt->id.idxa); return 0; case QSE_AWK_NDE_ARG: - *ref = (qse_awk_val_t**)&STACK_ARG(run,tgt->id.idxa); + *ref = (qse_awk_val_t**)&RTX_STACK_ARG(run,tgt->id.idxa); return 0; case QSE_AWK_NDE_NAMEDIDX: @@ -6025,21 +6072,21 @@ static int get_reference ( case QSE_AWK_NDE_GBLIDX: tmp = get_reference_indexed (run, tgt, - (qse_awk_val_t**)&STACK_GBL(run,tgt->id.idxa)); + (qse_awk_val_t**)&RTX_STACK_GBL(run,tgt->id.idxa)); if (tmp == QSE_NULL) return -1; *ref = tmp; return 0; case QSE_AWK_NDE_LCLIDX: tmp = get_reference_indexed (run, tgt, - (qse_awk_val_t**)&STACK_LCL(run,tgt->id.idxa)); + (qse_awk_val_t**)&RTX_STACK_LCL(run,tgt->id.idxa)); if (tmp == QSE_NULL) return -1; *ref = tmp; return 0; case QSE_AWK_NDE_ARGIDX: tmp = get_reference_indexed (run, tgt, - (qse_awk_val_t**)&STACK_ARG(run,tgt->id.idxa)); + (qse_awk_val_t**)&RTX_STACK_ARG(run,tgt->id.idxa)); if (tmp == QSE_NULL) return -1; *ref = tmp; return 0; @@ -6199,17 +6246,17 @@ static qse_awk_val_t* eval_named (qse_awk_rtx_t* run, qse_awk_nde_t* nde) static qse_awk_val_t* eval_gbl (qse_awk_rtx_t* run, qse_awk_nde_t* nde) { - return STACK_GBL(run,((qse_awk_nde_var_t*)nde)->id.idxa); + return RTX_STACK_GBL(run,((qse_awk_nde_var_t*)nde)->id.idxa); } static qse_awk_val_t* eval_lcl (qse_awk_rtx_t* run, qse_awk_nde_t* nde) { - return STACK_LCL(run,((qse_awk_nde_var_t*)nde)->id.idxa); + return RTX_STACK_LCL(run,((qse_awk_nde_var_t*)nde)->id.idxa); } static qse_awk_val_t* eval_arg (qse_awk_rtx_t* run, qse_awk_nde_t* nde) { - return STACK_ARG(run,((qse_awk_nde_var_t*)nde)->id.idxa); + return RTX_STACK_ARG(run,((qse_awk_nde_var_t*)nde)->id.idxa); } static qse_awk_val_t* eval_indexed ( @@ -6281,19 +6328,19 @@ static qse_awk_val_t* eval_namedidx (qse_awk_rtx_t* run, qse_awk_nde_t* nde) static qse_awk_val_t* eval_gblidx (qse_awk_rtx_t* run, qse_awk_nde_t* nde) { return eval_indexed (run, (qse_awk_nde_var_t*)nde, - (qse_awk_val_t**)&STACK_GBL(run,((qse_awk_nde_var_t*)nde)->id.idxa)); + (qse_awk_val_t**)&RTX_STACK_GBL(run,((qse_awk_nde_var_t*)nde)->id.idxa)); } static qse_awk_val_t* eval_lclidx (qse_awk_rtx_t* run, qse_awk_nde_t* nde) { return eval_indexed (run, (qse_awk_nde_var_t*)nde, - (qse_awk_val_t**)&STACK_LCL(run,((qse_awk_nde_var_t*)nde)->id.idxa)); + (qse_awk_val_t**)&RTX_STACK_LCL(run,((qse_awk_nde_var_t*)nde)->id.idxa)); } static qse_awk_val_t* eval_argidx (qse_awk_rtx_t* run, qse_awk_nde_t* nde) { return eval_indexed (run, (qse_awk_nde_var_t*)nde, - (qse_awk_val_t**)&STACK_ARG(run,((qse_awk_nde_var_t*)nde)->id.idxa)); + (qse_awk_val_t**)&RTX_STACK_ARG(run,((qse_awk_nde_var_t*)nde)->id.idxa)); } static qse_awk_val_t* eval_pos (qse_awk_rtx_t* run, qse_awk_nde_t* nde) @@ -6495,7 +6542,7 @@ static int __raw_push (qse_awk_rtx_t* run, void* val) void** tmp; qse_size_t n; - n = run->stack_limit + STACK_INCREMENT; + n = run->stack_limit + RTX_STACK_INCREMENT; tmp = (void**) QSE_AWK_REALLOC ( run->awk, run->stack, n * QSE_SIZEOF(void*)); @@ -6561,7 +6608,7 @@ static int shorten_record (qse_awk_rtx_t* run, qse_size_t nflds) if (nflds > 1) { - v = STACK_GBL(run, QSE_AWK_GBL_OFS); + v = RTX_STACK_GBL(run, QSE_AWK_GBL_OFS); qse_awk_rtx_refupval (run, v); if (v->type == QSE_AWK_VAL_NIL) @@ -7328,36 +7375,37 @@ wp_mod_main: } qse_awk_rtx_refupval (rtx, v); - if (v->type == QSE_AWK_VAL_NIL) + switch (v->type) { - ch = QSE_T('\0'); - ch_len = 0; - } - else if (v->type == QSE_AWK_VAL_INT) - { - ch = (qse_char_t)((qse_awk_val_int_t*)v)->val; - ch_len = 1; - } - else if (v->type == QSE_AWK_VAL_FLT) - { - ch = (qse_char_t)((qse_awk_val_flt_t*)v)->val; - ch_len = 1; - } - else if (v->type == QSE_AWK_VAL_STR) - { - ch_len = ((qse_awk_val_str_t*)v)->val.len; - if (ch_len > 0) - { - ch = ((qse_awk_val_str_t*)v)->val.ptr[0]; + case QSE_AWK_VAL_NIL: + ch = QSE_T('\0'); + ch_len = 0; + break; + + case QSE_AWK_VAL_INT: + ch = (qse_char_t)((qse_awk_val_int_t*)v)->val; ch_len = 1; - } - else ch = QSE_T('\0'); - } - else - { - qse_awk_rtx_refdownval (rtx, v); - SETERR_COD (rtx, QSE_AWK_EVALTYPE); - return QSE_NULL; + break; + + case QSE_AWK_VAL_FLT: + ch = (qse_char_t)((qse_awk_val_flt_t*)v)->val; + ch_len = 1; + break; + + case QSE_AWK_VAL_STR: + ch_len = ((qse_awk_val_str_t*)v)->val.len; + if (ch_len > 0) + { + ch = ((qse_awk_val_str_t*)v)->val.ptr[0]; + ch_len = 1; + } + else ch = QSE_T('\0'); + break; + + default: + qse_awk_rtx_refdownval (rtx, v); + SETERR_COD (rtx, QSE_AWK_EVALTOCHR); + return QSE_NULL; } if (wp[WP_PRECISION] == -1 || wp[WP_PRECISION] == 0 || wp[WP_PRECISION] > (qse_long_t)ch_len) diff --git a/qse/lib/awk/std.c b/qse/lib/awk/std.c index 4f068264..7b9f46d8 100644 --- a/qse/lib/awk/std.c +++ b/qse/lib/awk/std.c @@ -2536,14 +2536,20 @@ done: if (ret >= 0) { - if (rv && qse_awk_rtx_setrefval (rtx, qse_awk_rtx_getarg (rtx, 2), rv) >= 0) + qse_awk_val_t* retv; + + if (rv) { - qse_awk_rtx_setretval (rtx, qse_awk_val_zero); - } - else - { - qse_awk_rtx_setretval (rtx, qse_awk_val_negone); + int x; + qse_awk_rtx_refupval (rtx, rv); + x = qse_awk_rtx_setrefval (rtx, qse_awk_rtx_getarg (rtx, 2), rv); + qse_awk_rtx_refdownval (rtx, rv); + if (x <= -1) retv = qse_awk_val_negone; + else retv = qse_awk_val_zero; } + else retv = qse_awk_val_negone; + + qse_awk_rtx_setretval (rtx, qse_awk_val_zero); } return ret; diff --git a/qse/lib/awk/val.c b/qse/lib/awk/val.c index 79fb52eb..b3848ffa 100644 --- a/qse/lib/awk/val.c +++ b/qse/lib/awk/val.c @@ -1296,48 +1296,58 @@ static int val_ref_to_str ( qse_awk_rtx_t* rtx, const qse_awk_val_ref_t* ref, qse_awk_rtx_valtostr_out_t* out) { - if (ref->id == QSE_AWK_VAL_REF_POS) + switch (ref->id) { - qse_size_t idx; + case QSE_AWK_VAL_REF_POS: + { + qse_size_t idx; - /* special case when the reference value is - * pointing to the positional */ + /* special case when the reference value is + * pointing to the positional */ - idx = (qse_size_t)ref->adr; - if (idx == 0) - { - return str_to_str ( - rtx, - QSE_STR_PTR(&rtx->inrec.line), - QSE_STR_LEN(&rtx->inrec.line), - out - ); + idx = (qse_size_t)ref->adr; + if (idx == 0) + { + return str_to_str ( + rtx, + QSE_STR_PTR(&rtx->inrec.line), + QSE_STR_LEN(&rtx->inrec.line), + out + ); + } + else if (idx <= rtx->inrec.nflds) + { + return str_to_str ( + rtx, + rtx->inrec.flds[idx-1].ptr, + rtx->inrec.flds[idx-1].len, + out + ); + } + else + { + return str_to_str (rtx, QSE_T(""), 0, out); + } } - else if (idx <= rtx->inrec.nflds) - { - return str_to_str ( - rtx, - rtx->inrec.flds[idx-1].ptr, - rtx->inrec.flds[idx-1].len, - out - ); - } - else - { - return str_to_str (rtx, QSE_T(""), 0, out); - } - } - else - { - 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 ((*xref)->type != QSE_AWK_VAL_REF); + case QSE_AWK_VAL_REF_GBL: + { + qse_size_t idx = (qse_size_t)ref->adr; + return qse_awk_rtx_valtostr (rtx, RTX_STACK_GBL (rtx, idx), out); + } - /* make a recursive call back to the caller */ - return qse_awk_rtx_valtostr (rtx, *xref, out); + 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 ((*xref)->type != QSE_AWK_VAL_REF); + + /* make a recursive call back to the caller */ + return qse_awk_rtx_valtostr (rtx, *xref, out); + } } } @@ -1373,7 +1383,9 @@ int qse_awk_rtx_valtostr ( case QSE_AWK_VAL_MAP: { if (rtx->awk->opt.trait & QSE_AWK_FLEXMAP) + { return str_to_str (rtx, QSE_T("#MAP"), 4, out); + } break; } @@ -1391,7 +1403,7 @@ int qse_awk_rtx_valtostr ( v->type ); #endif - qse_awk_rtx_seterrnum (rtx, QSE_AWK_EVALTYPE, QSE_NULL); + qse_awk_rtx_seterrnum (rtx, QSE_AWK_EVALTOSTR, QSE_NULL); return -1; } @@ -1458,47 +1470,57 @@ qse_wchar_t* qse_awk_rtx_valtowcsdup ( static int val_ref_to_num ( qse_awk_rtx_t* rtx, const qse_awk_val_ref_t* ref, qse_long_t* l, qse_flt_t* r) { - if (ref->id == QSE_AWK_VAL_REF_POS) + switch (ref->id) { - qse_size_t idx; + case QSE_AWK_VAL_REF_POS: + { + qse_size_t idx; - idx = (qse_size_t)ref->adr; - if (idx == 0) - { - return qse_awk_rtx_strtonum ( - rtx, 0, - QSE_STR_PTR(&rtx->inrec.line), - QSE_STR_LEN(&rtx->inrec.line), - l, r - ); + idx = (qse_size_t)ref->adr; + if (idx == 0) + { + return qse_awk_rtx_strtonum ( + rtx, 0, + QSE_STR_PTR(&rtx->inrec.line), + QSE_STR_LEN(&rtx->inrec.line), + l, r + ); + } + else if (idx <= rtx->inrec.nflds) + { + return qse_awk_rtx_strtonum ( + rtx, 0, + rtx->inrec.flds[idx-1].ptr, + rtx->inrec.flds[idx-1].len, + l, r + ); + } + else + { + return qse_awk_rtx_strtonum ( + rtx, 0, QSE_T(""), 0, l, r + ); + } } - else if (idx <= rtx->inrec.nflds) - { - return qse_awk_rtx_strtonum ( - rtx, 0, - rtx->inrec.flds[idx-1].ptr, - rtx->inrec.flds[idx-1].len, - l, r - ); - } - else - { - return qse_awk_rtx_strtonum ( - rtx, 0, QSE_T(""), 0, l, r - ); - } - } - else - { - 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 ((*xref)->type != QSE_AWK_VAL_REF); + case QSE_AWK_VAL_REF_GBL: + { + qse_size_t idx = (qse_size_t)ref->adr; + return qse_awk_rtx_valtonum (rtx, RTX_STACK_GBL (rtx, idx), l, r); + } - /* make a recursive call back to the caller */ - return qse_awk_rtx_valtonum (rtx, *xref, l, r); + 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 ((*xref)->type != QSE_AWK_VAL_REF); + + /* make a recursive call back to the caller */ + return qse_awk_rtx_valtonum (rtx, *xref, l, r); + } } } @@ -1549,7 +1571,7 @@ int qse_awk_rtx_valtonum ( ); #endif - qse_awk_rtx_seterrnum (rtx, QSE_AWK_EVALTYPE, QSE_NULL); + qse_awk_rtx_seterrnum (rtx, QSE_AWK_EVALTONUM, QSE_NULL); return -1; /* error */ } @@ -1648,8 +1670,7 @@ qse_long_t qse_awk_rtx_hashval (qse_awk_rtx_t* rtx, qse_awk_val_t* v) v->type ); #endif - - qse_awk_rtx_seterrnum (rtx, QSE_AWK_EVALTYPE, QSE_NULL); + qse_awk_rtx_seterrnum (rtx, QSE_AWK_EHASHVAL, QSE_NULL); return -1; } @@ -1672,45 +1693,107 @@ int qse_awk_rtx_setrefval (qse_awk_rtx_t* rtx, qse_awk_val_ref_t* ref, qse_awk_v return -1; } - if (ref->id == QSE_AWK_VAL_REF_POS) + switch (ref->id) { - if (val->type == QSE_AWK_VAL_STR) + case QSE_AWK_VAL_REF_POS: { - return qse_awk_rtx_setrec ( - rtx, (qse_size_t)ref->adr, - &((qse_awk_val_str_t*)val)->val - ); + + switch (val->type) + { + case QSE_AWK_VAL_MAP: + /* a map is assigned to a positional. this is disallowed. */ + qse_awk_rtx_seterrnum (rtx, QSE_AWK_EPOSVALMAP, QSE_NULL); + return -1; + + case QSE_AWK_VAL_STR: + { + int x; + + /* handle this separately from the default case + * for no duplication. jumping to the default case + * and callingqse_awk_rtx_valtostrdup() would also work, anyway. */ + qse_awk_rtx_refupval (rtx, val); + x = qse_awk_rtx_setrec ( + rtx, (qse_size_t)ref->adr, + &((qse_awk_val_str_t*)val)->val + ); + qse_awk_rtx_refdownval (rtx, val); + return x; + } + + default: + { + qse_xstr_t str; + int x; + + str.ptr = qse_awk_rtx_valtostrdup (rtx, val, &str.len); + qse_awk_rtx_refupval (rtx, val); + x = qse_awk_rtx_setrec (rtx, (qse_size_t)ref->adr, &str); + qse_awk_rtx_refdownval (rtx, val); + QSE_AWK_FREE (rtx->awk, str.ptr); + return x; + } + } } - else + + case QSE_AWK_VAL_REF_GBL: + return qse_awk_rtx_setgbl (rtx, (int)ref->adr, val); + + case QSE_AWK_VAL_REF_NAMEDIDX: + case QSE_AWK_VAL_REF_GBLIDX: + case QSE_AWK_VAL_REF_LCLIDX: + case QSE_AWK_VAL_REF_ARGIDX: + if (val->type == QSE_AWK_VAL_MAP) + { + /* an indexed variable cannot be assigned a map. + * in other cases, it falls down to the default case. */ + qse_awk_rtx_seterrnum (rtx, QSE_AWK_EIDXVALMAP, QSE_NULL); + return -1; + } + /* fall through */ + + default: { - qse_xstr_t str; - int x; - - str.ptr = qse_awk_rtx_valtostrdup (rtx, val, &str.len); - x = qse_awk_rtx_setrec (rtx, (qse_size_t)ref->adr, &str); - QSE_AWK_FREE (rtx->awk, str.ptr); - return x; + qse_awk_val_t** rref; + + rref = (qse_awk_val_t**)ref->adr; + if (val->type == QSE_AWK_VAL_MAP) + { + /* new value: map, old value: nil or map => ok */ + if ((*rref)->type != QSE_AWK_VAL_NIL && + (*rref)->type != QSE_AWK_VAL_MAP) + { + if (!(rtx->awk->opt.trait & QSE_AWK_FLEXMAP)) + { + /* cannot change a scalar value to a map */ + qse_awk_rtx_seterrnum (rtx, QSE_AWK_ESCALARTOMAP, QSE_NULL); + return -1; + } + } + } + else + { + /* new value: scalar, old value: nil or scalar => ok */ + if ((*rref)->type == QSE_AWK_VAL_MAP) + { + if (!(rtx->awk->opt.trait & QSE_AWK_FLEXMAP)) + { + qse_awk_rtx_seterrnum (rtx, QSE_AWK_EMAPTOSCALAR, QSE_NULL); + return -1; + } + } + } + + if (*rref != val) + { + /* if the new value is not the same as the old value */ + qse_awk_rtx_refdownval (rtx, *rref); + *rref = val; + qse_awk_rtx_refupval (rtx, *rref); + } + return 0; } } - else - { - qse_awk_val_t** rref; - -/* TODO: handle QSE_AWK_FLEXMAP... -if FLEXMAP is not set.. check if rref is nil or map if value is map. -also check if rref is nil... scalar if valeu is scalar.. -but is this really necessary? i feel all these awk quarkiness is nasty.. -*/ - - rref = (qse_awk_val_t**)ref->adr; - if (*rref != val) - { - qse_awk_rtx_refdownval (rtx, *rref); - *rref = val; - qse_awk_rtx_refupval (rtx, *rref); - } - return 0; - } } #if 0