diff --git a/qse/cmd/awk/awk.c b/qse/cmd/awk/awk.c index 201c145e..57c519fc 100644 --- a/qse/cmd/awk/awk.c +++ b/qse/cmd/awk/awk.c @@ -206,7 +206,7 @@ static qse_htb_walk_t print_awk_value ( else { dprint (QSE_T("***OUT OF MEMORY***\n")); - } + } } else { diff --git a/qse/include/qse/awk/awk.h b/qse/include/qse/awk/awk.h index edaae3a4..361340cf 100644 --- a/qse/include/qse/awk/awk.h +++ b/qse/include/qse/awk/awk.h @@ -1681,6 +1681,14 @@ QSE_EXPORT void qse_awk_seterrnum ( * an error message */ ); +QSE_EXPORT void qse_awk_seterrfmt ( + qse_awk_t* awk, + qse_awk_errnum_t errnum, + qse_awk_loc_t* errloc, + const qse_char_t* msgfmt, + ... +); + /** * The qse_awk_seterrinf() function sets the error information. This function * may be useful if you want to set a custom error message rather than letting @@ -1691,6 +1699,7 @@ QSE_EXPORT void qse_awk_seterrinf ( const qse_awk_errinf_t* errinf /**< error information */ ); + /** * The qse_awk_geterror() function gets error information via parameters. */ @@ -2367,6 +2376,14 @@ QSE_EXPORT void qse_awk_rtx_seterrinf ( const qse_awk_errinf_t* errinf /**< error information */ ); +QSE_EXPORT void qse_awk_rtx_seterrfmt ( + qse_awk_rtx_t* rtx, + qse_awk_errnum_t errnum, + const qse_awk_loc_t* errloc, + const qse_char_t* errfmt, + ... +); + /** * The qse_awk_rtx_seterror() function sets error information. */ diff --git a/qse/lib/awk/Awk.cpp b/qse/lib/awk/Awk.cpp index ea4cd2c0..c9e804c8 100644 --- a/qse/lib/awk/Awk.cpp +++ b/qse/lib/awk/Awk.cpp @@ -652,7 +652,7 @@ int Awk::Value::setIndexedVal (Run* r, const Index& idx, val_t* v) { QSE_ASSERT (r != QSE_NULL); - if (QSE_AWK_RTX_GETVALTYPE (r->rtx, val) != QSE_AWK_VAL_MAP) + if (QSE_AWK_RTX_GETVALTYPE (r->rtx, this->val) != QSE_AWK_VAL_MAP) { // the previous value is not a map. // a new map value needs to be created first. @@ -666,8 +666,7 @@ int Awk::Value::setIndexedVal (Run* r, const Index& idx, val_t* v) qse_awk_rtx_refupval (r->rtx, map); // update the map with a given value - if (qse_awk_rtx_setmapvalfld ( - r->rtx, map, idx.ptr, idx.len, v) == QSE_NULL) + if (qse_awk_rtx_setmapvalfld(r->rtx, map, idx.ptr, idx.len, v) == QSE_NULL) { qse_awk_rtx_refdownval (r->rtx, map); r->awk->retrieveError (r); @@ -678,7 +677,7 @@ int Awk::Value::setIndexedVal (Run* r, const Index& idx, val_t* v) if (this->run) { // if val is not nil, this->run can't be NULL - qse_awk_rtx_refdownval (this->run->rtx, val); + qse_awk_rtx_refdownval (this->run->rtx, this->val); } this->run = r; @@ -700,8 +699,7 @@ int Awk::Value::setIndexedVal (Run* r, const Index& idx, val_t* v) } // update the map with a given value - if (qse_awk_rtx_setmapvalfld ( - r->rtx, val, idx.ptr, idx.len, v) == QSE_NULL) + if (qse_awk_rtx_setmapvalfld(r->rtx, val, idx.ptr, idx.len, v) == QSE_NULL) { r->awk->retrieveError (r); return -1; diff --git a/qse/lib/awk/err.c b/qse/lib/awk/err.c index 217f535b..32dce9f5 100644 --- a/qse/lib/awk/err.c +++ b/qse/lib/awk/err.c @@ -207,22 +207,21 @@ void qse_awk_geterrinf (const qse_awk_t* awk, qse_awk_errinf_t* errinf) } } -void qse_awk_geterror ( - const qse_awk_t* awk, qse_awk_errnum_t* errnum, - const qse_char_t** errmsg, qse_awk_loc_t* errloc) +void qse_awk_geterror (const qse_awk_t* awk, qse_awk_errnum_t* errnum, const qse_char_t** errmsg, qse_awk_loc_t* errloc) { - if (errnum != QSE_NULL) *errnum = awk->errinf.num; - if (errmsg != QSE_NULL) + if (errnum) *errnum = awk->errinf.num; + if (errmsg) { *errmsg = (awk->errinf.msg[0] == QSE_T('\0'))? qse_awk_geterrstr(awk)(awk,awk->errinf.num): awk->errinf.msg; } - if (errloc != QSE_NULL) *errloc = awk->errinf.loc; + if (errloc) *errloc = awk->errinf.loc; } -void qse_awk_seterrnum ( - qse_awk_t* awk, qse_awk_errnum_t errnum, const qse_cstr_t* errarg) + + +void qse_awk_seterrnum (qse_awk_t* awk, qse_awk_errnum_t errnum, const qse_cstr_t* errarg) { qse_awk_seterror (awk, errnum, errarg, QSE_NULL); } @@ -232,9 +231,21 @@ void qse_awk_seterrinf (qse_awk_t* awk, const qse_awk_errinf_t* errinf) QSE_MEMCPY (&awk->errinf, errinf, QSE_SIZEOF(*errinf)); } -void qse_awk_seterror ( - qse_awk_t* awk, qse_awk_errnum_t errnum, const qse_cstr_t* errarg, - const qse_awk_loc_t* errloc) +void qse_awk_seterrfmt (qse_awk_t* awk, qse_awk_errnum_t errnum, qse_awk_loc_t* errloc, const qse_char_t* errfmt, ...) +{ + va_list ap; + + QSE_MEMSET (&awk->errinf, 0, QSE_SIZEOF(awk->errinf)); + awk->errinf.num = errnum; + + va_start (ap, errfmt); + qse_strxvfmt (awk->errinf.msg, QSE_COUNTOF(awk->errinf.msg), errfmt, ap); + va_end (ap); + + if (errloc) awk->errinf.loc = *errloc; +} + +void qse_awk_seterror (qse_awk_t* awk, qse_awk_errnum_t errnum, const qse_cstr_t* errarg, const qse_awk_loc_t* errloc) { const qse_char_t* errfmt; @@ -243,14 +254,12 @@ void qse_awk_seterror ( errfmt = qse_awk_geterrstr(awk)(awk,errnum); QSE_ASSERT (errfmt != QSE_NULL); - qse_strxfncpy ( - awk->errinf.msg, QSE_COUNTOF(awk->errinf.msg), - errfmt, errarg - ); + qse_strxfncpy (awk->errinf.msg, QSE_COUNTOF(awk->errinf.msg), errfmt, errarg); if (errloc != QSE_NULL) awk->errinf.loc = *errloc; } + qse_awk_errnum_t qse_awk_rtx_geterrnum (const qse_awk_rtx_t* rtx) { return rtx->errinf.num; @@ -301,9 +310,22 @@ void qse_awk_rtx_seterrinf (qse_awk_rtx_t* rtx, const qse_awk_errinf_t* errinf) QSE_MEMCPY (&rtx->errinf, errinf, QSE_SIZEOF(*errinf)); } -void qse_awk_rtx_seterror ( - qse_awk_rtx_t* rtx, qse_awk_errnum_t errnum, const qse_cstr_t* errarg, - const qse_awk_loc_t* errloc) +void qse_awk_rtx_seterrfmt (qse_awk_rtx_t* rtx, qse_awk_errnum_t errnum, const qse_awk_loc_t* errloc, const qse_char_t* errfmt, ...) +{ + va_list ap; + + QSE_MEMSET (&rtx->errinf, 0, QSE_SIZEOF(rtx->errinf)); + rtx->errinf.num = errnum; + + va_start (ap, errfmt); + qse_strxvfmt (rtx->errinf.msg, QSE_COUNTOF(rtx->errinf.msg), errfmt, ap); + va_end (ap); + + if (errloc) rtx->errinf.loc = *errloc; +} + + +void qse_awk_rtx_seterror (qse_awk_rtx_t* rtx, qse_awk_errnum_t errnum, const qse_cstr_t* errarg, const qse_awk_loc_t* errloc) { const qse_char_t* errfmt; diff --git a/qse/lib/awk/fnc.c b/qse/lib/awk/fnc.c index 8b98c97c..4f00929b 100644 --- a/qse/lib/awk/fnc.c +++ b/qse/lib/awk/fnc.c @@ -1562,7 +1562,7 @@ static QSE_INLINE int __fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* qse_size_t nargs; qse_awk_val_t* a0, * a0_val, * a1, * a2; qse_awk_val_type_t a0_type, v_type; - qse_awk_val_t* r, * rmap; + qse_awk_val_t* r, * rmap = QSE_NULL; 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_NULL; @@ -1585,7 +1585,7 @@ static QSE_INLINE int __fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* goto done; } - qse_awk_rtx_seterrnum (rtx, QSE_AWK_ENOTMAP, QSE_NULL); + qse_awk_rtx_seterrfmt (rtx, QSE_AWK_ENOTMAP, QSE_NULL, QSE_T("source not a map")); return -1; } @@ -1601,7 +1601,7 @@ static QSE_INLINE int __fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* a2 = qse_awk_rtx_getarg(rtx, 2); if (QSE_AWK_RTX_GETVALTYPE(rtx, a2) != QSE_AWK_VAL_FUN) { - qse_awk_rtx_seterrnum (rtx, QSE_AWK_EINVAL, QSE_NULL); + qse_awk_rtx_seterrfmt (rtx, QSE_AWK_EINVAL, QSE_NULL, QSE_T("comparator not a function")); return -1; } @@ -1609,7 +1609,7 @@ static QSE_INLINE int __fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* if (fun->nargs < 2) { /* the comparison accepts less than 2 arguments */ - qse_awk_rtx_seterrnum (rtx, QSE_AWK_EINVAL, QSE_NULL); + qse_awk_rtx_seterrfmt (rtx, QSE_AWK_EINVAL, QSE_NULL, QSE_T("%.*s not accepting 2 arguments"), (int)fun->name.len, fun->name.ptr); return -1; } } @@ -1638,11 +1638,12 @@ static QSE_INLINE int __fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* while (i > 0) { --i; - qse_awk_rtx_freeval (rtx, va[i], 0); + qse_awk_rtx_refdownval (rtx, va[i]); } qse_awk_rtx_freemem (rtx, va); return -1; } + qse_awk_rtx_refupval (rtx, va[i]); i++; } while (qse_awk_rtx_getnextmapvalitr(rtx, a0_val, &itr)); @@ -1651,7 +1652,9 @@ static QSE_INLINE int __fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* { do { - va[i++] = (qse_awk_val_t*)QSE_AWK_VAL_MAP_ITR_VAL(&itr); + va[i] = (qse_awk_val_t*)QSE_AWK_VAL_MAP_ITR_VAL(&itr); + qse_awk_rtx_refupval (rtx, va[i]); + i++; } while (qse_awk_rtx_getnextmapvalitr(rtx, a0_val, &itr)); } @@ -1670,17 +1673,14 @@ static QSE_INLINE int __fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* if (x <= -1 || !(rmap = qse_awk_rtx_makemapval(rtx))) { - if (sort_keys) - { - for (i = 0; i < msz; i++) qse_awk_rtx_freeval (rtx, va[i], 0); - } + for (i = 0; i < msz; i++) qse_awk_rtx_refdownval (rtx, va[i]); qse_awk_rtx_freemem (rtx, va); return -1; } for (i = 0; i < msz; i++) { - qse_char_t ridx[128]; + qse_char_t ridx[128]; /* TODO: make it dynamic? can overflow? */ qse_size_t ridx_len; ridx_len = qse_fmtuintmax ( @@ -1695,32 +1695,42 @@ static QSE_INLINE int __fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* if (qse_awk_rtx_setmapvalfld(rtx, rmap, ridx, ridx_len, va[i]) == QSE_NULL) { - qse_awk_rtx_freeval (rtx, rmap, 0); /* this delete the elements added. */ - if (sort_keys) + /* decrement the reference count of the values not added to the map */ + do { - /* delete the elements not added yet */ - do - { - qse_awk_rtx_freeval(rtx, va[i], 0); - i++; - } - while (i < msz); + qse_awk_rtx_refdownval (rtx, va[i]); + i++; } + while (i < msz); + qse_awk_rtx_freeval (rtx, rmap, 0); /* this derefs the elements added. */ qse_awk_rtx_freemem (rtx, va); return -1; } + + qse_awk_rtx_refdownval (rtx, va[i]); /* deref it as it has been added to the map */ } rv = msz; qse_awk_rtx_freemem (rtx, va); - qse_awk_rtx_refupval (rtx, rmap); - x = qse_awk_rtx_setrefval (rtx, (qse_awk_val_ref_t*)a1, rmap); - qse_awk_rtx_refdownval (rtx, rmap); - if (x <= -1) return -1; - done: r = qse_awk_rtx_makeintval(rtx, rv); + if (!r) return -1; + + if (rmap) + { + /* rmap can be NULL when a jump has been made for an empty source + * at the beginning of this fucntion */ + qse_awk_rtx_refupval (rtx, rmap); + x = qse_awk_rtx_setrefval (rtx, (qse_awk_val_ref_t*)a1, rmap); + qse_awk_rtx_refdownval (rtx, rmap); + if (x <= -1) + { + qse_awk_rtx_freeval (rtx, r, 0); + return -1; + } + } + qse_awk_rtx_setretval (rtx, r); return 0; } diff --git a/qse/lib/awk/run.c b/qse/lib/awk/run.c index ec51a78f..d059c9b1 100644 --- a/qse/lib/awk/run.c +++ b/qse/lib/awk/run.c @@ -1197,10 +1197,8 @@ static void fini_rtx (qse_awk_rtx_t* rtx, int fini_globals) { while (rtx->scache_count[i] > 0) { - qse_awk_val_str_t* t = - rtx->scache[i][--rtx->scache_count[i]]; - qse_awk_rtx_freeval ( - rtx, (qse_awk_val_t*)t, 0); + qse_awk_val_str_t* t = rtx->scache[i][--rtx->scache_count[i]]; + qse_awk_rtx_freeval (rtx, (qse_awk_val_t*)t, 0); } } }