From 59ad30bab27453d12d460728666f01020d8e923c Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Sat, 7 Mar 2020 16:24:02 +0000 Subject: [PATCH] fixed a bug when assigning NF with a large number than the current number of records --- qse/include/qse/awk/awk.h | 9 ++++ qse/lib/awk/rec.c | 94 ++++++++++++++++++++++++++++++++ qse/lib/awk/run.c | 111 +++++--------------------------------- 3 files changed, 117 insertions(+), 97 deletions(-) diff --git a/qse/include/qse/awk/awk.h b/qse/include/qse/awk/awk.h index 64e067b5..65553fad 100644 --- a/qse/include/qse/awk/awk.h +++ b/qse/include/qse/awk/awk.h @@ -2656,6 +2656,15 @@ QSE_EXPORT int qse_awk_rtx_setrec ( const qse_cstr_t* str /**< string */ ); +/** + * The qse_awk_rtx_truncrec() function lowered the number of fields in a record. + * The caller must ensure that \a nflds is less than the current number of fields + */ +QSE_EXPORT int qse_awk_rtx_truncrec ( + qse_awk_rtx_t* rtx, + qse_size_t nflds +); + /** * The qse_awk_rtx_isnilval() function determines if a value * is a nil value. diff --git a/qse/lib/awk/rec.c b/qse/lib/awk/rec.c index e9d9fc85..5f752aec 100644 --- a/qse/lib/awk/rec.c +++ b/qse/lib/awk/rec.c @@ -518,3 +518,97 @@ static int recomp_record_fields (qse_awk_rtx_t* run, qse_size_t lv, const qse_cs return 0; } +int qse_awk_rtx_truncrec (qse_awk_rtx_t* rtx, qse_size_t nflds) +{ + qse_awk_val_t* v; + qse_char_t* ofs_free = QSE_NULL, * ofs_ptr; + qse_size_t ofs_len, i; + qse_str_t tmp; + qse_awk_val_type_t vtype; + + QSE_ASSERT (nflds <= rtx->inrec.nflds); + + if (nflds > 1) + { + v = RTX_STACK_GBL(rtx, QSE_AWK_GBL_OFS); + qse_awk_rtx_refupval (rtx, v); + vtype = QSE_AWK_RTX_GETVALTYPE(rtx, v); + + if (vtype == QSE_AWK_VAL_NIL) + { + /* OFS not set */ + ofs_ptr = QSE_T(" "); + ofs_len = 1; + } + else if (vtype == QSE_AWK_VAL_STR) + { + ofs_ptr = ((qse_awk_val_str_t*)v)->val.ptr; + ofs_len = ((qse_awk_val_str_t*)v)->val.len; + } + else + { + qse_awk_rtx_valtostr_out_t out; + + out.type = QSE_AWK_RTX_VALTOSTR_CPLDUP; + if (qse_awk_rtx_valtostr (rtx, v, &out) <= -1) return -1; + + ofs_ptr = out.u.cpldup.ptr; + ofs_len = out.u.cpldup.len; + ofs_free = ofs_ptr; + } + } + + if (qse_str_init(&tmp, qse_awk_rtx_getmmgr(rtx), QSE_STR_LEN(&rtx->inrec.line)) <= -1) + { + if (ofs_free) qse_awk_rtx_freemem (rtx, ofs_free); + if (nflds > 1) qse_awk_rtx_refdownval (rtx, v); + qse_awk_rtx_seterrnum (rtx, QSE_AWK_ENOMEM, QSE_NULL); + return -1; + } + + for (i = 0; i < nflds; i++) + { + if (i > 0 && qse_str_ncat(&tmp,ofs_ptr,ofs_len) == (qse_size_t)-1) + { + qse_str_fini (&tmp); + if (ofs_free) qse_awk_rtx_freemem (rtx, ofs_free); + if (nflds > 1) qse_awk_rtx_refdownval (rtx, v); + qse_awk_rtx_seterrnum (rtx, QSE_AWK_ENOMEM, QSE_NULL); + return -1; + } + + if (qse_str_ncat (&tmp, rtx->inrec.flds[i].ptr, rtx->inrec.flds[i].len) == (qse_size_t)-1) + { + qse_str_fini (&tmp); + if (ofs_free) qse_awk_rtx_freemem (rtx, ofs_free); + if (nflds > 1) qse_awk_rtx_refdownval (rtx, v); + qse_awk_rtx_seterrnum (rtx, QSE_AWK_ENOMEM, QSE_NULL); + return -1; + } + } + + if (ofs_free) qse_awk_rtx_freemem (rtx, ofs_free); + if (nflds > 1) qse_awk_rtx_refdownval (rtx, v); + + v = (qse_awk_val_t*)qse_awk_rtx_makestrvalwithcstr(rtx, QSE_STR_XSTR(&tmp)); + if (!v) + { + qse_str_fini (&tmp); + return -1; + } + + qse_awk_rtx_refdownval (rtx, rtx->inrec.d0); + rtx->inrec.d0 = v; + qse_awk_rtx_refupval (rtx, rtx->inrec.d0); + + qse_str_swap (&tmp, &rtx->inrec.line); + qse_str_fini (&tmp); + + for (i = nflds; i < rtx->inrec.nflds; i++) + { + qse_awk_rtx_refdownval (rtx, rtx->inrec.flds[i].val); + } + + rtx->inrec.nflds = nflds; + return 0; +} diff --git a/qse/lib/awk/run.c b/qse/lib/awk/run.c index a27f234a..aad7dc0d 100644 --- a/qse/lib/awk/run.c +++ b/qse/lib/awk/run.c @@ -235,7 +235,6 @@ static int __raw_push (qse_awk_rtx_t* rtx, void* val); } while (0) static int read_record (qse_awk_rtx_t* rtx); -static int shorten_record (qse_awk_rtx_t* rtx, qse_size_t nflds); static qse_char_t* idxnde_to_str (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde, qse_char_t* buf, qse_size_t* len); @@ -481,15 +480,28 @@ static int set_global (qse_awk_rtx_t* rtx, int idx, qse_awk_nde_var_t* var, qse_ n = qse_awk_rtx_valtoint(rtx, val, &lv); if (n <= -1) return -1; + if (lv < 0) + { + qse_awk_rtx_seterrfmt (rtx, QSE_AWK_EINVAL, QSE_NULL, QSE_T("negative value into NF")); + return -1; + } + if (lv < (qse_awk_int_t)rtx->inrec.nflds) { - if (shorten_record(rtx, (qse_size_t)lv) == -1) + if (qse_awk_rtx_truncrec(rtx, (qse_size_t)lv) == -1) { /* adjust the error line */ /*if (var) ADJERR_LOC (rtx, &var->loc);*/ return -1; } } + else if (lv > (qse_awk_int_t)rtx->inrec.nflds) + { + qse_cstr_t cs; + cs.ptr = QSE_T(""); + cs.len = 0; + if (qse_awk_rtx_setrec(rtx, lv, &cs) <= -1) return -1; + } break; } @@ -6857,101 +6869,6 @@ read_again: return 1; } -static int shorten_record (qse_awk_rtx_t* rtx, qse_size_t nflds) -{ - qse_awk_val_t* v; - qse_char_t* ofs_free = QSE_NULL, * ofs_ptr; - qse_size_t ofs_len, i; - qse_str_t tmp; - qse_awk_val_type_t vtype; - - QSE_ASSERT (nflds <= rtx->inrec.nflds); - - if (nflds > 1) - { - v = RTX_STACK_GBL(rtx, QSE_AWK_GBL_OFS); - qse_awk_rtx_refupval (rtx, v); - vtype = QSE_AWK_RTX_GETVALTYPE(rtx, v); - - if (vtype == QSE_AWK_VAL_NIL) - { - /* OFS not set */ - ofs_ptr = QSE_T(" "); - ofs_len = 1; - } - else if (vtype == QSE_AWK_VAL_STR) - { - ofs_ptr = ((qse_awk_val_str_t*)v)->val.ptr; - ofs_len = ((qse_awk_val_str_t*)v)->val.len; - } - else - { - qse_awk_rtx_valtostr_out_t out; - - out.type = QSE_AWK_RTX_VALTOSTR_CPLDUP; - if (qse_awk_rtx_valtostr (rtx, v, &out) <= -1) return -1; - - ofs_ptr = out.u.cpldup.ptr; - ofs_len = out.u.cpldup.len; - ofs_free = ofs_ptr; - } - } - - if (qse_str_init(&tmp, qse_awk_rtx_getmmgr(rtx), QSE_STR_LEN(&rtx->inrec.line)) <= -1) - { - if (ofs_free) qse_awk_rtx_freemem (rtx, ofs_free); - if (nflds > 1) qse_awk_rtx_refdownval (rtx, v); - SETERR_COD (rtx, QSE_AWK_ENOMEM); - return -1; - } - - for (i = 0; i < nflds; i++) - { - if (i > 0 && qse_str_ncat(&tmp,ofs_ptr,ofs_len) == (qse_size_t)-1) - { - qse_str_fini (&tmp); - if (ofs_free) qse_awk_rtx_freemem (rtx, ofs_free); - if (nflds > 1) qse_awk_rtx_refdownval (rtx, v); - SETERR_COD (rtx, QSE_AWK_ENOMEM); - return -1; - } - - if (qse_str_ncat (&tmp, rtx->inrec.flds[i].ptr, rtx->inrec.flds[i].len) == (qse_size_t)-1) - { - qse_str_fini (&tmp); - if (ofs_free) qse_awk_rtx_freemem (rtx, ofs_free); - if (nflds > 1) qse_awk_rtx_refdownval (rtx, v); - SETERR_COD (rtx, QSE_AWK_ENOMEM); - return -1; - } - } - - if (ofs_free) qse_awk_rtx_freemem (rtx, ofs_free); - if (nflds > 1) qse_awk_rtx_refdownval (rtx, v); - - v = (qse_awk_val_t*)qse_awk_rtx_makestrvalwithcstr(rtx, QSE_STR_XSTR(&tmp)); - if (!v) - { - qse_str_fini (&tmp); - return -1; - } - - qse_awk_rtx_refdownval (rtx, rtx->inrec.d0); - rtx->inrec.d0 = v; - qse_awk_rtx_refupval (rtx, rtx->inrec.d0); - - qse_str_swap (&tmp, &rtx->inrec.line); - qse_str_fini (&tmp); - - for (i = nflds; i < rtx->inrec.nflds; i++) - { - qse_awk_rtx_refdownval (rtx, rtx->inrec.flds[i].val); - } - - rtx->inrec.nflds = nflds; - return 0; -} - static qse_char_t* idxnde_to_str (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde, qse_char_t* buf, qse_size_t* len) { qse_char_t* str;