added qse_awk_seterrfmt()/qse_awk_rtx_seterrfmt()

fixed wrong reference counting in __fnc_asort()
This commit is contained in:
hyung-hwan 2019-05-08 07:15:17 +00:00
parent df47611d9d
commit 2e19b848e5
6 changed files with 99 additions and 54 deletions

View File

@ -1681,6 +1681,14 @@ QSE_EXPORT void qse_awk_seterrnum (
* an error message */ * 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 * 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 * 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 */ const qse_awk_errinf_t* errinf /**< error information */
); );
/** /**
* The qse_awk_geterror() function gets error information via parameters. * 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 */ 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. * The qse_awk_rtx_seterror() function sets error information.
*/ */

View File

@ -652,7 +652,7 @@ int Awk::Value::setIndexedVal (Run* r, const Index& idx, val_t* v)
{ {
QSE_ASSERT (r != QSE_NULL); 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. // the previous value is not a map.
// a new map value needs to be created first. // 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); qse_awk_rtx_refupval (r->rtx, map);
// update the map with a given value // update the map with a given value
if (qse_awk_rtx_setmapvalfld ( if (qse_awk_rtx_setmapvalfld(r->rtx, map, idx.ptr, idx.len, v) == QSE_NULL)
r->rtx, map, idx.ptr, idx.len, v) == QSE_NULL)
{ {
qse_awk_rtx_refdownval (r->rtx, map); qse_awk_rtx_refdownval (r->rtx, map);
r->awk->retrieveError (r); r->awk->retrieveError (r);
@ -678,7 +677,7 @@ int Awk::Value::setIndexedVal (Run* r, const Index& idx, val_t* v)
if (this->run) if (this->run)
{ {
// if val is not nil, this->run can't be NULL // 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; 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 // update the map with a given value
if (qse_awk_rtx_setmapvalfld ( if (qse_awk_rtx_setmapvalfld(r->rtx, val, idx.ptr, idx.len, v) == QSE_NULL)
r->rtx, val, idx.ptr, idx.len, v) == QSE_NULL)
{ {
r->awk->retrieveError (r); r->awk->retrieveError (r);
return -1; return -1;

View File

@ -207,22 +207,21 @@ void qse_awk_geterrinf (const qse_awk_t* awk, qse_awk_errinf_t* errinf)
} }
} }
void qse_awk_geterror ( void qse_awk_geterror (const qse_awk_t* awk, qse_awk_errnum_t* errnum, const qse_char_t** errmsg, qse_awk_loc_t* errloc)
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 (errnum) *errnum = awk->errinf.num;
if (errmsg != QSE_NULL) if (errmsg)
{ {
*errmsg = (awk->errinf.msg[0] == QSE_T('\0'))? *errmsg = (awk->errinf.msg[0] == QSE_T('\0'))?
qse_awk_geterrstr(awk)(awk,awk->errinf.num): qse_awk_geterrstr(awk)(awk,awk->errinf.num):
awk->errinf.msg; 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); 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)); QSE_MEMCPY (&awk->errinf, errinf, QSE_SIZEOF(*errinf));
} }
void qse_awk_seterror ( void qse_awk_seterrfmt (qse_awk_t* awk, qse_awk_errnum_t errnum, qse_awk_loc_t* errloc, const qse_char_t* errfmt, ...)
qse_awk_t* awk, qse_awk_errnum_t errnum, const qse_cstr_t* errarg, {
const qse_awk_loc_t* errloc) 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; const qse_char_t* errfmt;
@ -243,14 +254,12 @@ void qse_awk_seterror (
errfmt = qse_awk_geterrstr(awk)(awk,errnum); errfmt = qse_awk_geterrstr(awk)(awk,errnum);
QSE_ASSERT (errfmt != QSE_NULL); QSE_ASSERT (errfmt != QSE_NULL);
qse_strxfncpy ( qse_strxfncpy (awk->errinf.msg, QSE_COUNTOF(awk->errinf.msg), errfmt, errarg);
awk->errinf.msg, QSE_COUNTOF(awk->errinf.msg),
errfmt, errarg
);
if (errloc != QSE_NULL) awk->errinf.loc = *errloc; if (errloc != QSE_NULL) awk->errinf.loc = *errloc;
} }
qse_awk_errnum_t qse_awk_rtx_geterrnum (const qse_awk_rtx_t* rtx) qse_awk_errnum_t qse_awk_rtx_geterrnum (const qse_awk_rtx_t* rtx)
{ {
return rtx->errinf.num; 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)); QSE_MEMCPY (&rtx->errinf, errinf, QSE_SIZEOF(*errinf));
} }
void qse_awk_rtx_seterror ( 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, ...)
qse_awk_rtx_t* rtx, qse_awk_errnum_t errnum, const qse_cstr_t* errarg, {
const qse_awk_loc_t* errloc) 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; const qse_char_t* errfmt;

View File

@ -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_size_t nargs;
qse_awk_val_t* a0, * a0_val, * a1, * a2; qse_awk_val_t* a0, * a0_val, * a1, * a2;
qse_awk_val_type_t a0_type, v_type; 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_int_t rv = 0; /* as if no element in the map */
qse_awk_val_map_itr_t itr; qse_awk_val_map_itr_t itr;
qse_awk_fun_t* fun = QSE_NULL; 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; 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; 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); a2 = qse_awk_rtx_getarg(rtx, 2);
if (QSE_AWK_RTX_GETVALTYPE(rtx, a2) != QSE_AWK_VAL_FUN) 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; 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) if (fun->nargs < 2)
{ {
/* the comparison accepts less than 2 arguments */ /* 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; 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) while (i > 0)
{ {
--i; --i;
qse_awk_rtx_freeval (rtx, va[i], 0); qse_awk_rtx_refdownval (rtx, va[i]);
} }
qse_awk_rtx_freemem (rtx, va); qse_awk_rtx_freemem (rtx, va);
return -1; return -1;
} }
qse_awk_rtx_refupval (rtx, va[i]);
i++; i++;
} }
while (qse_awk_rtx_getnextmapvalitr(rtx, a0_val, &itr)); 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 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)); 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 (x <= -1 || !(rmap = qse_awk_rtx_makemapval(rtx)))
{ {
if (sort_keys) for (i = 0; i < msz; i++) qse_awk_rtx_refdownval (rtx, va[i]);
{
for (i = 0; i < msz; i++) qse_awk_rtx_freeval (rtx, va[i], 0);
}
qse_awk_rtx_freemem (rtx, va); qse_awk_rtx_freemem (rtx, va);
return -1; return -1;
} }
for (i = 0; i < msz; i++) 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; qse_size_t ridx_len;
ridx_len = qse_fmtuintmax ( 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) 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. */ /* decrement the reference count of the values not added to the map */
if (sort_keys)
{
/* delete the elements not added yet */
do do
{ {
qse_awk_rtx_freeval(rtx, va[i], 0); qse_awk_rtx_refdownval (rtx, va[i]);
i++; i++;
} }
while (i < msz); while (i < msz);
} qse_awk_rtx_freeval (rtx, rmap, 0); /* this derefs the elements added. */
qse_awk_rtx_freemem (rtx, va); qse_awk_rtx_freemem (rtx, va);
return -1; return -1;
} }
qse_awk_rtx_refdownval (rtx, va[i]); /* deref it as it has been added to the map */
} }
rv = msz; rv = msz;
qse_awk_rtx_freemem (rtx, va); qse_awk_rtx_freemem (rtx, va);
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); qse_awk_rtx_refupval (rtx, rmap);
x = qse_awk_rtx_setrefval (rtx, (qse_awk_val_ref_t*)a1, rmap); x = qse_awk_rtx_setrefval (rtx, (qse_awk_val_ref_t*)a1, rmap);
qse_awk_rtx_refdownval (rtx, rmap); qse_awk_rtx_refdownval (rtx, rmap);
if (x <= -1) return -1; if (x <= -1)
{
qse_awk_rtx_freeval (rtx, r, 0);
return -1;
}
}
done:
r = qse_awk_rtx_makeintval(rtx, rv);
qse_awk_rtx_setretval (rtx, r); qse_awk_rtx_setretval (rtx, r);
return 0; return 0;
} }

View File

@ -1197,10 +1197,8 @@ static void fini_rtx (qse_awk_rtx_t* rtx, int fini_globals)
{ {
while (rtx->scache_count[i] > 0) while (rtx->scache_count[i] > 0)
{ {
qse_awk_val_str_t* t = qse_awk_val_str_t* t = rtx->scache[i][--rtx->scache_count[i]];
rtx->scache[i][--rtx->scache_count[i]]; qse_awk_rtx_freeval (rtx, (qse_awk_val_t*)t, 0);
qse_awk_rtx_freeval (
rtx, (qse_awk_val_t*)t, 0);
} }
} }
} }