added qse_awk_seterrfmt()/qse_awk_rtx_seterrfmt()
fixed wrong reference counting in __fnc_asort()
This commit is contained in:
		@ -206,7 +206,7 @@ static qse_htb_walk_t print_awk_value (
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			dprint (QSE_T("***OUT OF MEMORY***\n"));
 | 
			
		||||
		}	
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
 | 
			
		||||
@ -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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user