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

@ -206,7 +206,7 @@ static qse_htb_walk_t print_awk_value (
else
{
dprint (QSE_T("***OUT OF MEMORY***\n"));
}
}
}
else
{

View File

@ -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.
*/

View File

@ -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;

View File

@ -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;

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_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;
}

View File

@ -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);
}
}
}