added qse_awk_seterrfmt()/qse_awk_rtx_seterrfmt()
fixed wrong reference counting in __fnc_asort()
This commit is contained in:
		| @ -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) | ||||
| 			{ | ||||
| 				/* delete the elements not added yet */ | ||||
| 			/* decrement the reference count of the values not added to the map */ | ||||
| 			do | ||||
| 			{ | ||||
| 					qse_awk_rtx_freeval(rtx, va[i], 0); | ||||
| 				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); | ||||
|  | ||||
| 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) 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); | ||||
| 	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