enhanced parse_primary_ident() in lib/awk/parse.c
also fixed a memory leak in the function changed name of some data types
This commit is contained in:
		| @ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * $Id: parse.c 475 2011-05-23 17:02:35Z hyunghwan.chung $ | ||||
|  * $Id: parse.c 485 2011-05-29 15:15:52Z hyunghwan.chung $ | ||||
|  * | ||||
|     Copyright 2006-2011 Chung, Hyung-Hwan. | ||||
|     This file is part of QSE. | ||||
| @ -554,18 +554,21 @@ static int parse (qse_awk_t* awk) | ||||
| 				if (qse_htb_search (awk->tree.funs,  | ||||
| 					QSE_HTB_KPTR(p), QSE_HTB_KLEN(p)) == QSE_NULL) | ||||
| 				{ | ||||
| 					qse_awk_nde_call_t* call; | ||||
| 					 | ||||
| 					qse_awk_nde_t* nde; | ||||
|  | ||||
| 					/* see parse_fncall() for what is | ||||
| 					 * stored into awk->tree.funs */ | ||||
| 					call = (qse_awk_nde_call_t*)QSE_HTB_VPTR(p); | ||||
| 					nde = (qse_awk_nde_t*)QSE_HTB_VPTR(p); | ||||
|  | ||||
| 					SETERR_ARG_LOC ( | ||||
| 						awk,  | ||||
| 						QSE_AWK_EFUNNF,  | ||||
| 						QSE_HTB_KPTR(p), | ||||
| 						QSE_HTB_KLEN(p), | ||||
| 						&call->loc | ||||
| 						&nde->loc | ||||
| 					); | ||||
|  | ||||
| 					goto oops; | ||||
| 				} | ||||
|  | ||||
| @ -4365,15 +4368,13 @@ static qse_awk_nde_t* parse_primary ( | ||||
| 	return left; | ||||
| } | ||||
|  | ||||
| static int isfnname (qse_awk_t* awk, const qse_char_t* name, qse_size_t len) | ||||
| { | ||||
| 	if (qse_awk_getfnc (awk, name, len) != QSE_NULL)  | ||||
| 	{ | ||||
| 		/* implicit function */ | ||||
| 		return 1; | ||||
| 	} | ||||
| #define FNTYPE_UNKNOWN 0 | ||||
| #define FNTYPE_FNC 1 | ||||
| #define FNTYPE_FUN 2 | ||||
|  | ||||
| 	/* check if it is an awk function */ | ||||
| static QSE_INLINE int isfunname (qse_awk_t* awk, const qse_char_t* name, qse_size_t len) | ||||
| { | ||||
| 	/* check if it is an awk function being processed currently */ | ||||
| 	if (awk->tree.cur_fun.ptr != QSE_NULL) | ||||
| 	{ | ||||
| 		if (qse_strxncmp ( | ||||
| @ -4381,28 +4382,87 @@ static int isfnname (qse_awk_t* awk, const qse_char_t* name, qse_size_t len) | ||||
| 			name, len) == 0) | ||||
| 		{ | ||||
| 			/* the current function begin parsed */ | ||||
| 			return 2;	 | ||||
| 			return FNTYPE_FUN; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* check the funtion name in the function table */ | ||||
| 	if (qse_htb_search (awk->tree.funs, name, len) != QSE_NULL) | ||||
| 	{ | ||||
| 		/* one of the functions defined previously */ | ||||
| 		return 2; | ||||
| 		return FNTYPE_FUN; | ||||
| 	} | ||||
|  | ||||
| 	/* check if it is a function not resolved so far */ | ||||
| 	if (qse_htb_search (awk->parse.funs, name, len) != QSE_NULL)  | ||||
| 	{ | ||||
| 		/* one of the function calls not resolved so far. */  | ||||
| 		return 2; | ||||
| 		return FNTYPE_FUN; | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| 	return FNTYPE_UNKNOWN; | ||||
| } | ||||
|  | ||||
| static QSE_INLINE int isfnname (qse_awk_t* awk, const qse_char_t* name, qse_size_t len) | ||||
| { | ||||
| 	if (qse_awk_getfnc (awk, name, len) != QSE_NULL)  | ||||
| 	{ | ||||
| 		/* implicit function */ | ||||
| 		return FNTYPE_FNC; | ||||
| 	} | ||||
|  | ||||
| 	return isfunname (awk, name, len); | ||||
| } | ||||
|  | ||||
| static qse_awk_nde_t* parse_variable ( | ||||
| 	qse_awk_t* awk, const qse_awk_loc_t* xloc, qse_awk_nde_type_t type, | ||||
| 	qse_char_t* nameptr, qse_size_t namelen, qse_size_t idxa) | ||||
| { | ||||
| 	qse_awk_nde_var_t* nde; | ||||
|  | ||||
| 	if ((awk->option & QSE_AWK_EXPLICIT) &&  | ||||
| 	    !(awk->option & QSE_AWK_IMPLICIT)) | ||||
| 	{ | ||||
| 		/* if explicit only, the concatenation operator(.) | ||||
| 		 * must be used. so it is obvious that it is a function | ||||
| 		 * call, which is illegal for a variable.  | ||||
| 		 * if implicit, "var_xxx (1)" may be concatenation of | ||||
| 		 * the value of var_xxx and 1. | ||||
| 		 */ | ||||
| 		if (MATCH(awk,TOK_LPAREN)) | ||||
| 		{ | ||||
| 			/* a variable is not a function */ | ||||
| 			SETERR_ARG_LOC ( | ||||
| 				awk, QSE_AWK_EFUNNAM, | ||||
| 				nameptr, namelen, xloc); | ||||
| 			return QSE_NULL; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	nde = (qse_awk_nde_var_t*) QSE_AWK_ALLOC ( | ||||
| 		awk, QSE_SIZEOF(qse_awk_nde_var_t)); | ||||
| 	if (nde == QSE_NULL)  | ||||
| 	{ | ||||
| 		SETERR_LOC (awk, QSE_AWK_ENOMEM, xloc); | ||||
| 		return QSE_NULL; | ||||
| 	} | ||||
|  | ||||
| 	nde->type = type; | ||||
| 	nde->loc = *xloc; | ||||
| 	nde->next = QSE_NULL; | ||||
| 	/*nde->id.name.ptr = QSE_NULL;*/ | ||||
| 	nde->id.name.ptr = nameptr; | ||||
| 	nde->id.name.len = namelen; | ||||
| 	nde->id.idxa = idxa; | ||||
| 	nde->idx = QSE_NULL; | ||||
|  | ||||
| 	return (qse_awk_nde_t*)nde; | ||||
| } | ||||
|  | ||||
| static qse_awk_nde_t* parse_primary_ident ( | ||||
| 	qse_awk_t* awk, const qse_awk_loc_t* xloc) | ||||
| { | ||||
| 	qse_awk_nde_t* nde = QSE_NULL; | ||||
| 	qse_char_t* namedup; | ||||
| 	qse_size_t namelen; | ||||
| 	qse_awk_fnc_t* fnc; | ||||
| @ -4430,9 +4490,11 @@ static qse_awk_nde_t* parse_primary_ident ( | ||||
| 	fnc = qse_awk_getfnc (awk, namedup, namelen); | ||||
| 	if (fnc != QSE_NULL) | ||||
| 	{ | ||||
| 		qse_awk_nde_t* nde; | ||||
|  | ||||
| 		if (!MATCH(awk,TOK_LPAREN)) | ||||
| 		if (MATCH(awk,TOK_LPAREN)) | ||||
| 		{ | ||||
| 			nde = parse_fncall (awk, namedup, namelen, fnc, xloc, 0); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			if (fnc->dfl0) | ||||
| 			{ | ||||
| @ -4440,253 +4502,129 @@ static qse_awk_nde_t* parse_primary_ident ( | ||||
| 				 * when () is missing. i.e. length */ | ||||
| 				nde = parse_fncall ( | ||||
| 					awk, namedup, namelen, fnc, xloc, 1); | ||||
| 				if (nde == QSE_NULL)  | ||||
| 					QSE_AWK_FREE (awk, namedup); | ||||
| 				return (qse_awk_nde_t*)nde; | ||||
| 			} | ||||
|  | ||||
| 			/* an intrinsic function should be in the form  | ||||
| 		 	 * of the function call */ | ||||
| 			QSE_AWK_FREE (awk, namedup); | ||||
| 			SETERR_TOK (awk, QSE_AWK_ELPAREN); | ||||
| 			return QSE_NULL; | ||||
| 			else | ||||
| 			{ | ||||
| 				/* an intrinsic function should be in the form  | ||||
| 		 		 * of the function call */ | ||||
| 				SETERR_TOK (awk, QSE_AWK_ELPAREN); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		nde = parse_fncall (awk, namedup, namelen, fnc, xloc, 0); | ||||
| 		if (nde == QSE_NULL) QSE_AWK_FREE (awk, namedup); | ||||
| 		return (qse_awk_nde_t*)nde; | ||||
| 	} | ||||
|  | ||||
| 	/* now we know that namedup is a normal identifier. */ | ||||
| 	if (MATCH(awk,TOK_LBRACK))  | ||||
| 	else if (MATCH(awk,TOK_LBRACK))  | ||||
| 	{ | ||||
| 		qse_awk_nde_t* nde; | ||||
| 		nde = parse_hashidx (awk, namedup, namelen, xloc); | ||||
| 		if (nde == QSE_NULL) QSE_AWK_FREE (awk, namedup); | ||||
| 		return (qse_awk_nde_t*)nde; | ||||
| 	} | ||||
| 	else if ((idxa = qse_lda_rsearch (awk->parse.lcls, QSE_LDA_SIZE(awk->parse.lcls), namedup, namelen)) != QSE_LDA_NIL) | ||||
| 	{ | ||||
| 		/* local variable */ | ||||
|  | ||||
| 		qse_awk_nde_var_t* nde; | ||||
|  | ||||
| 		if ((awk->option & QSE_AWK_EXPLICIT) &&  | ||||
| 		    !(awk->option & QSE_AWK_IMPLICIT)) | ||||
| 		{ | ||||
| 			/* if explicit only, the concatenation operator(.) | ||||
| 			 * must be used. so it is obvious that it is a function | ||||
| 			 * call, which is illegal for a local variable.  | ||||
| 			 * if implicit, "local_var (1)" may be concatenation of | ||||
| 			 * the value of local_var and 1. | ||||
| 			 */ | ||||
| 			if (MATCH(awk,TOK_LPAREN)) | ||||
| 			{ | ||||
| 				/* a local variable is not a function */ | ||||
| 				SETERR_ARG_LOC ( | ||||
| 					awk, QSE_AWK_EFUNNAM, | ||||
| 					namedup, namelen, xloc); | ||||
| 				QSE_AWK_FREE (awk, namedup); | ||||
| 				return QSE_NULL; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		nde = (qse_awk_nde_var_t*) QSE_AWK_ALLOC ( | ||||
| 			awk, QSE_SIZEOF(qse_awk_nde_var_t)); | ||||
| 		if (nde == QSE_NULL)  | ||||
| 		{ | ||||
| 			SETERR_LOC (awk, QSE_AWK_ENOMEM, xloc); | ||||
| 			QSE_AWK_FREE (awk, namedup); | ||||
| 			return QSE_NULL; | ||||
| 		} | ||||
|  | ||||
| 		nde->type = QSE_AWK_NDE_LCL; | ||||
| 		nde->loc = *xloc; | ||||
| 		nde->next = QSE_NULL; | ||||
| 		/*nde->id.name.ptr = QSE_NULL;*/ | ||||
| 		nde->id.name.ptr = namedup; | ||||
| 		nde->id.name.len = namelen; | ||||
| 		nde->id.idxa = idxa; | ||||
| 		nde->idx = QSE_NULL; | ||||
|  | ||||
| 		return (qse_awk_nde_t*)nde; | ||||
| 		nde = parse_variable ( | ||||
| 			awk, xloc, QSE_AWK_NDE_LCL, | ||||
| 			namedup, namelen, idxa); | ||||
| 	} | ||||
| 	else if ((idxa = qse_lda_search (awk->parse.params, 0, namedup, namelen)) != QSE_LDA_NIL) | ||||
| 	{ | ||||
| 		/* parameter */ | ||||
|  | ||||
| 		qse_awk_nde_var_t* nde; | ||||
|  | ||||
| 		if ((awk->option & QSE_AWK_EXPLICIT) &&  | ||||
| 		    !(awk->option & QSE_AWK_IMPLICIT)) | ||||
| 		{ | ||||
| 			if (MATCH(awk,TOK_LPAREN)) | ||||
| 			{ | ||||
| 				/* a parameter is not a function */ | ||||
| 				SETERR_ARG_LOC ( | ||||
| 					awk, QSE_AWK_EFUNNAM, | ||||
| 					namedup, namelen, xloc); | ||||
| 				QSE_AWK_FREE (awk, namedup); | ||||
| 				return QSE_NULL; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		nde = (qse_awk_nde_var_t*) QSE_AWK_ALLOC ( | ||||
| 			awk, QSE_SIZEOF(qse_awk_nde_var_t)); | ||||
| 		if (nde == QSE_NULL)  | ||||
| 		{ | ||||
| 			QSE_AWK_FREE (awk, namedup); | ||||
| 			SETERR_LOC (awk, QSE_AWK_ENOMEM, xloc); | ||||
| 			return QSE_NULL; | ||||
| 		} | ||||
|  | ||||
| 		nde->type = QSE_AWK_NDE_ARG; | ||||
| 		nde->loc = *xloc; | ||||
| 		nde->next = QSE_NULL; | ||||
| 		/*nde->id.name = QSE_NULL;*/ | ||||
| 		nde->id.name.ptr = namedup; | ||||
| 		nde->id.name.len = namelen; | ||||
| 		nde->id.idxa = idxa; | ||||
| 		nde->idx = QSE_NULL; | ||||
|  | ||||
| 		return (qse_awk_nde_t*)nde; | ||||
| 		nde = parse_variable ( | ||||
| 			awk, xloc, QSE_AWK_NDE_ARG, | ||||
| 			namedup, namelen, idxa); | ||||
| 	} | ||||
| 	else if ((idxa = get_global (awk, namedup, namelen)) != QSE_LDA_NIL) | ||||
| 	{ | ||||
| 		/* global variable */ | ||||
|  | ||||
| 		qse_awk_nde_var_t* nde; | ||||
|  | ||||
| 		if ((awk->option & QSE_AWK_EXPLICIT) &&  | ||||
| 		    !(awk->option & QSE_AWK_IMPLICIT)) | ||||
| 		{ | ||||
| 			if (MATCH(awk,TOK_LPAREN)) | ||||
| 			{ | ||||
| 				/* a global variable is not a function */ | ||||
| 				SETERR_ARG_LOC ( | ||||
| 					awk, QSE_AWK_EFUNNAM, | ||||
| 					namedup, namelen, xloc); | ||||
| 				QSE_AWK_FREE (awk, namedup); | ||||
| 				return QSE_NULL; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		nde = (qse_awk_nde_var_t*) QSE_AWK_ALLOC ( | ||||
| 			awk, QSE_SIZEOF(qse_awk_nde_var_t)); | ||||
| 		if (nde == QSE_NULL)  | ||||
| 		{ | ||||
| 			QSE_AWK_FREE (awk, namedup); | ||||
| 			SETERR_LOC (awk, QSE_AWK_ENOMEM, xloc); | ||||
| 			return QSE_NULL; | ||||
| 		} | ||||
|  | ||||
| 		nde->type = QSE_AWK_NDE_GBL; | ||||
| 		nde->loc = *xloc; | ||||
| 		nde->next = QSE_NULL; | ||||
| 		/*nde->id.name = QSE_NULL;*/ | ||||
| 		nde->id.name.ptr = namedup; | ||||
| 		nde->id.name.len = namelen; | ||||
| 		nde->id.idxa = idxa; | ||||
| 		nde->idx = QSE_NULL; | ||||
|  | ||||
| 		return (qse_awk_nde_t*)nde; | ||||
| 		nde = parse_variable ( | ||||
| 			awk, xloc, QSE_AWK_NDE_GBL, | ||||
| 			namedup, namelen, idxa); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		int fnname = isfnname (awk, namedup, namelen); | ||||
| 		int fntype = isfunname (awk, namedup, namelen); | ||||
|  | ||||
| 		if (fnname) | ||||
| 		if (fntype) | ||||
| 		{ | ||||
| 			qse_awk_nde_t* nde; | ||||
| 			QSE_ASSERT (fntype == FNTYPE_FUN); | ||||
|  | ||||
| 			if (!MATCH(awk,TOK_LPAREN)) | ||||
| 			if (MATCH(awk,TOK_LPAREN)) | ||||
| 			{ | ||||
| 				/* function named appeared without () */ | ||||
| 				if (fnname == 1) | ||||
| 				{ | ||||
| 					SETERR_ARG_LOC ( | ||||
| 						awk, QSE_AWK_EFNCRED, | ||||
| 						namedup, namelen, xloc); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					SETERR_ARG_LOC ( | ||||
| 						awk, QSE_AWK_EFUNRED,  | ||||
| 						namedup, namelen, xloc); | ||||
| 				} | ||||
| 				/* must be a function name */ | ||||
| 				QSE_ASSERT (qse_htb_search ( | ||||
| 					awk->parse.named, namedup, namelen) == QSE_NULL); | ||||
|  | ||||
| 				QSE_AWK_FREE (awk, namedup); | ||||
| 				return QSE_NULL; | ||||
| 				nde = parse_fncall ( | ||||
| 					awk, namedup, namelen, QSE_NULL, xloc,  0); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				/* function name appeared without () or ` */ | ||||
| 				SETERR_ARG_LOC ( | ||||
| 					awk, QSE_AWK_EFUNRED,  | ||||
| 					namedup, namelen, xloc | ||||
| 				); | ||||
| 			} | ||||
|  | ||||
| 			/* must be a function name */ | ||||
| 			QSE_ASSERT (qse_htb_search ( | ||||
| 				awk->parse.named, namedup, namelen) == QSE_NULL); | ||||
|  | ||||
| 			nde = parse_fncall ( | ||||
| 				awk, namedup, namelen, QSE_NULL, xloc,  0); | ||||
| 			if (nde == QSE_NULL) QSE_AWK_FREE (awk, namedup); | ||||
| 			return (qse_awk_nde_t*)nde; | ||||
| 		} | ||||
| 		else if (awk->option & QSE_AWK_IMPLICIT)  | ||||
| 		{ | ||||
| 			/* if the name is followed by ( or ` without no spaces  | ||||
| 			 * in the implicit mode, the name is considered a function | ||||
| 			 * name though it has not been seen/resolved */ | ||||
|  | ||||
| 			if (MATCH(awk,TOK_LPAREN) && | ||||
| 			    awk->tok.loc.line == xloc->line && | ||||
| 			    awk->tok.loc.colm == xloc->colm + namelen) | ||||
| 			{ | ||||
| 				qse_awk_nde_t* nde; | ||||
|  | ||||
| 				/* a function call to a yet undefined function */ | ||||
| 				if (qse_htb_search (awk->parse.named,  | ||||
| 					namedup, namelen) != QSE_NULL) | ||||
|  | ||||
| 				if (qse_htb_search ( | ||||
| 					awk->parse.named, namedup, namelen) != QSE_NULL) | ||||
| 				{ | ||||
| 					/* a function call conflicts with a named variable */ | ||||
| 					SETERR_ARG_LOC ( | ||||
| 						awk, QSE_AWK_EVARRED, | ||||
| 						namedup, namelen, xloc); | ||||
| 					QSE_AWK_FREE (awk, namedup); | ||||
| 					return QSE_NULL; | ||||
| 						namedup, namelen, xloc | ||||
| 					); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					nde = parse_fncall ( | ||||
| 						awk, namedup, namelen, QSE_NULL, xloc, 0); | ||||
| 				} | ||||
|  | ||||
| 				nde = parse_fncall ( | ||||
| 					awk, namedup, namelen, QSE_NULL, xloc,  0); | ||||
| 				if (nde == QSE_NULL) QSE_AWK_FREE (awk, namedup); | ||||
| 				return (qse_awk_nde_t*)nde; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				qse_awk_nde_var_t* nde; | ||||
| 				qse_awk_nde_var_t* tmp; | ||||
|  | ||||
| 				/* named variable */ | ||||
| 				nde = (qse_awk_nde_var_t*) QSE_AWK_ALLOC ( | ||||
| 				tmp = (qse_awk_nde_var_t*) QSE_AWK_ALLOC ( | ||||
| 					awk, QSE_SIZEOF(qse_awk_nde_var_t)); | ||||
| 				if (nde == QSE_NULL)  | ||||
| 				{ | ||||
| 					QSE_AWK_FREE (awk, namedup); | ||||
| 					SETERR_LOC (awk, QSE_AWK_ENOMEM, xloc); | ||||
| 					return QSE_NULL; | ||||
| 				} | ||||
| 	 | ||||
| 				nde->type = QSE_AWK_NDE_NAMED; | ||||
| 				nde->loc = *xloc; | ||||
| 				nde->next = QSE_NULL; | ||||
| 				nde->id.name.ptr = namedup; | ||||
| 				nde->id.name.len = namelen; | ||||
| 				nde->id.idxa = (qse_size_t)-1; | ||||
| 				nde->idx = QSE_NULL; | ||||
| 	 | ||||
| 				/* collect unique instances of a named variable  | ||||
| 				 * for reference */ | ||||
| 				if (qse_htb_upsert ( | ||||
| 					awk->parse.named,  | ||||
| 					namedup, namelen, QSE_NULL, 0) == QSE_NULL) | ||||
| 				if (tmp == QSE_NULL)  | ||||
| 				{ | ||||
| 					SETERR_LOC (awk, QSE_AWK_ENOMEM, xloc); | ||||
| 					QSE_AWK_FREE (awk, nde); | ||||
| 					return QSE_NULL; | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					/* collect unique instances of a named variable  | ||||
| 					 * for reference */ | ||||
| 					if (qse_htb_upsert ( | ||||
| 						awk->parse.named,  | ||||
| 						namedup, namelen, QSE_NULL, 0) == QSE_NULL) | ||||
| 					{ | ||||
| 						SETERR_LOC (awk, QSE_AWK_ENOMEM, xloc); | ||||
| 						QSE_AWK_FREE (awk, tmp); | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| 						tmp->type = QSE_AWK_NDE_NAMED; | ||||
| 						tmp->loc = *xloc; | ||||
| 						tmp->next = QSE_NULL; | ||||
| 						tmp->id.name.ptr = namedup; | ||||
| 						tmp->id.name.len = namelen; | ||||
| 						tmp->id.idxa = (qse_size_t)-1; | ||||
| 						tmp->idx = QSE_NULL; | ||||
|  | ||||
| 				return (qse_awk_nde_t*)nde; | ||||
| 						nde = (qse_awk_nde_t*)tmp; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| @ -4695,19 +4633,21 @@ static qse_awk_nde_t* parse_primary_ident ( | ||||
| 			{ | ||||
| 				/* it is a function call as the name is followed  | ||||
| 				 * by ( and implicit variables are disabled. */ | ||||
| 				qse_awk_nde_t* nde; | ||||
| 				nde = parse_fncall ( | ||||
| 					awk, namedup, namelen, QSE_NULL, xloc,  0); | ||||
| 				if (nde == QSE_NULL) QSE_AWK_FREE (awk, namedup); | ||||
| 				return (qse_awk_nde_t*)nde; | ||||
| 			} | ||||
|  | ||||
| 			/* undefined variable */ | ||||
| 			SETERR_ARG_LOC (awk, QSE_AWK_EUNDEF, namedup, namelen, xloc); | ||||
| 			QSE_AWK_FREE (awk, namedup); | ||||
| 			return QSE_NULL; | ||||
| 			else | ||||
| 			{ | ||||
| 				/* undefined variable */ | ||||
| 				SETERR_ARG_LOC (	 | ||||
| 					awk, QSE_AWK_EUNDEF, namedup, namelen, xloc | ||||
| 				); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (nde == QSE_NULL) QSE_AWK_FREE (awk, namedup); | ||||
| 	return nde; | ||||
| } | ||||
|  | ||||
| static qse_awk_nde_t* parse_hashidx ( | ||||
| @ -4832,17 +4772,17 @@ static qse_awk_nde_t* parse_hashidx ( | ||||
| 	if (awk->option & QSE_AWK_IMPLICIT)  | ||||
| 	{ | ||||
| 		int fnname = isfnname (awk, name, namelen); | ||||
| 		if (fnname == 1) | ||||
| 		switch (fnname) | ||||
| 		{ | ||||
| 			SETERR_ARG_LOC (	 | ||||
| 				awk, QSE_AWK_EFNCRED, name, namelen, xloc); | ||||
| 			goto exit_func; | ||||
| 		} | ||||
| 		else if (fnname == 2) | ||||
| 		{ | ||||
| 			SETERR_ARG_LOC (	 | ||||
| 				awk, QSE_AWK_EFUNRED, name, namelen, xloc); | ||||
| 			goto exit_func; | ||||
| 			case FNTYPE_FNC: | ||||
| 				SETERR_ARG_LOC (	 | ||||
| 					awk, QSE_AWK_EFNCRED, name, namelen, xloc); | ||||
| 				goto exit_func; | ||||
|  | ||||
| 			case FNTYPE_FUN: | ||||
| 				SETERR_ARG_LOC (	 | ||||
| 					awk, QSE_AWK_EFUNRED, name, namelen, xloc); | ||||
| 				goto exit_func; | ||||
| 		} | ||||
|  | ||||
| 		QSE_ASSERT (fnname == 0); | ||||
| @ -4873,7 +4813,7 @@ static qse_awk_nde_t* parse_fncall ( | ||||
| 	qse_awk_fnc_t* fnc, const qse_awk_loc_t* xloc, int noarg) | ||||
| { | ||||
| 	qse_awk_nde_t* head, * curr, * nde; | ||||
| 	qse_awk_nde_call_t* call; | ||||
| 	qse_awk_nde_fncall_t* call; | ||||
| 	qse_size_t nargs; | ||||
|  | ||||
| 	head = curr = QSE_NULL; | ||||
| @ -4943,8 +4883,8 @@ static qse_awk_nde_t* parse_fncall ( | ||||
| 	} | ||||
|  | ||||
| make_node: | ||||
| 	call = (qse_awk_nde_call_t*)  | ||||
| 		QSE_AWK_ALLOC (awk, QSE_SIZEOF(qse_awk_nde_call_t)); | ||||
| 	call = (qse_awk_nde_fncall_t*)  | ||||
| 		QSE_AWK_ALLOC (awk, QSE_SIZEOF(qse_awk_nde_fncall_t)); | ||||
| 	if (call == QSE_NULL)  | ||||
| 	{ | ||||
| 		if (head != QSE_NULL) qse_awk_clrpt (awk, head); | ||||
| @ -4958,22 +4898,13 @@ make_node: | ||||
| 		call->loc = *xloc; | ||||
| 		call->next = QSE_NULL; | ||||
|  | ||||
| 		/*call->what.fnc = fnc; */ | ||||
| 		call->what.fnc.name.ptr = name; | ||||
| 		call->what.fnc.name.len = namelen; | ||||
|  | ||||
| 		/* NOTE: oname is the original as in the fnc table. | ||||
| 		 *       it would not duplicated here and not freed in | ||||
| 		 *       qse_awk_clrpt either. so qse_awk_delfnc between | ||||
| 		 *       qse_awk_parse and qse_awk_run may cause the program  | ||||
| 		 *       to fail. */ | ||||
| 		call->what.fnc.oname.ptr = fnc->name.ptr; | ||||
| 		call->what.fnc.oname.len = fnc->name.len; | ||||
|  | ||||
| 		call->what.fnc.arg.min = fnc->arg.min; | ||||
| 		call->what.fnc.arg.max = fnc->arg.max; | ||||
| 		call->what.fnc.arg.spec = fnc->arg.spec; | ||||
| 		call->what.fnc.handler = fnc->handler; | ||||
| 		/*call->u.fnc = fnc; */ | ||||
| 		call->u.fnc.name.ptr = name; | ||||
| 		call->u.fnc.name.len = namelen; | ||||
| 		call->u.fnc.arg.min = fnc->arg.min; | ||||
| 		call->u.fnc.arg.max = fnc->arg.max; | ||||
| 		call->u.fnc.arg.spec = fnc->arg.spec; | ||||
| 		call->u.fnc.handler = fnc->handler; | ||||
|  | ||||
| 		call->args = head; | ||||
| 		call->nargs = nargs; | ||||
| @ -4983,8 +4914,8 @@ make_node: | ||||
| 		call->type = QSE_AWK_NDE_FUN; | ||||
| 		call->loc = *xloc; | ||||
| 		call->next = QSE_NULL; | ||||
| 		call->what.fun.name.ptr = name;  | ||||
| 		call->what.fun.name.len = namelen; | ||||
| 		call->u.fun.name.ptr = name;  | ||||
| 		call->u.fun.name.len = namelen; | ||||
| 		call->args = head; | ||||
| 		call->nargs = nargs; | ||||
|  | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * $Id: run.c 480 2011-05-25 14:00:19Z hyunghwan.chung $ | ||||
|  * $Id: run.c 485 2011-05-29 15:15:52Z hyunghwan.chung $ | ||||
|  * | ||||
|     Copyright 2006-2011 Chung, Hyung-Hwan. | ||||
|     This file is part of QSE. | ||||
| @ -95,7 +95,7 @@ struct pafv | ||||
| #define ADJERR_LOC(rtx,l) do { (rtx)->errinf.loc = *(l); } while (0) | ||||
|  | ||||
| static qse_size_t push_arg_from_vals ( | ||||
| 	qse_awk_rtx_t* rtx, qse_awk_nde_call_t* call, void* data); | ||||
| 	qse_awk_rtx_t* rtx, qse_awk_nde_fncall_t* call, void* data); | ||||
|  | ||||
| static int init_rtx (qse_awk_rtx_t* rtx, qse_awk_t* awk, qse_awk_rio_t* rio); | ||||
| static void fini_rtx (qse_awk_rtx_t* rtx, int fini_globals); | ||||
| @ -212,7 +212,7 @@ static qse_awk_val_t* __eval_call ( | ||||
| 	qse_awk_nde_t* nde,  | ||||
| 	const qse_char_t* fnc_arg_spec, | ||||
| 	qse_awk_fun_t* fun,  | ||||
| 	qse_size_t(*argpusher)(qse_awk_rtx_t*,qse_awk_nde_call_t*,void*), | ||||
| 	qse_size_t(*argpusher)(qse_awk_rtx_t*,qse_awk_nde_fncall_t*,void*), | ||||
| 	void* apdata, | ||||
| 	void(*errhandler)(void*), | ||||
| 	void* eharg); | ||||
| @ -1542,7 +1542,7 @@ qse_awk_val_t* qse_awk_rtx_callfun ( | ||||
| 	struct capture_retval_data_t crdata; | ||||
| 	qse_awk_val_t* v; | ||||
| 	struct pafv pafv/*= { args, nargs }*/; | ||||
| 	qse_awk_nde_call_t call; | ||||
| 	qse_awk_nde_fncall_t call; | ||||
|  | ||||
| 	QSE_ASSERT (fun != QSE_NULL); | ||||
|  | ||||
| @ -1561,7 +1561,7 @@ qse_awk_val_t* qse_awk_rtx_callfun ( | ||||
| 	/* forge a fake node containing a function call */ | ||||
| 	QSE_MEMSET (&call, 0, QSE_SIZEOF(call)); | ||||
| 	call.type = QSE_AWK_NDE_FUN; | ||||
| 	call.what.fun.name = fun->name; | ||||
| 	call.u.fun.name = fun->name; | ||||
| 	call.nargs = nargs; | ||||
|  | ||||
| 	/* check if the number of arguments given is more than expected */ | ||||
| @ -2561,181 +2561,192 @@ static int delete_indexed ( | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int run_delete_named (qse_awk_rtx_t* rtx, qse_awk_nde_var_t* var) | ||||
| { | ||||
| 	qse_htb_pair_t* pair; | ||||
|  | ||||
| 	QSE_ASSERTX ( | ||||
| 		(var->type == QSE_AWK_NDE_NAMED && var->idx == QSE_NULL) || | ||||
| 		(var->type == QSE_AWK_NDE_NAMEDIDX && var->idx != QSE_NULL), | ||||
| 		"if a named variable has an index part and a named indexed variable doesn't have an index part, the program is definitely wrong"); | ||||
|  | ||||
| 	pair = qse_htb_search ( | ||||
| 		rtx->named, var->id.name.ptr, var->id.name.len); | ||||
| 	if (pair == QSE_NULL) | ||||
| 	{ | ||||
| 		qse_awk_val_t* tmp; | ||||
|  | ||||
| 		/* value not set for the named variable.  | ||||
| 		 * create a map and assign it to the variable */ | ||||
|  | ||||
| 		tmp = qse_awk_rtx_makemapval (rtx); | ||||
| 		if (tmp == QSE_NULL)  | ||||
| 		{ | ||||
| 			/* adjust error line */ | ||||
| 			ADJERR_LOC (rtx, &var->loc); | ||||
| 			return -1; | ||||
| 		} | ||||
|  | ||||
| 		pair = qse_htb_upsert (rtx->named,  | ||||
| 			var->id.name.ptr, var->id.name.len, tmp, 0); | ||||
| 		if (pair == QSE_NULL) | ||||
| 		{ | ||||
| 			qse_awk_rtx_refupval (rtx, tmp); | ||||
| 			qse_awk_rtx_refdownval (rtx, tmp); | ||||
| 			SETERR_LOC (rtx, QSE_AWK_ENOMEM, &var->loc); | ||||
| 			return -1; | ||||
| 		} | ||||
|  | ||||
| 		/* as this is the assignment, it needs to update | ||||
| 		 * the reference count of the target value. */ | ||||
| 		qse_awk_rtx_refupval (rtx, tmp); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		qse_awk_val_t* val; | ||||
| 		qse_htb_t* map; | ||||
|  | ||||
| 		val = (qse_awk_val_t*)QSE_HTB_VPTR(pair); | ||||
| 		QSE_ASSERT (val != QSE_NULL); | ||||
|  | ||||
| 		if (val->type != QSE_AWK_VAL_MAP) | ||||
| 		{ | ||||
| 			SETERR_ARGX_LOC ( | ||||
| 				rtx, QSE_AWK_ENOTDEL,  | ||||
| 				xstr_to_cstr(&var->id.name), &var->loc); | ||||
| 			return -1; | ||||
| 		} | ||||
|  | ||||
| 		map = ((qse_awk_val_map_t*)val)->map; | ||||
| 		if (var->type == QSE_AWK_NDE_NAMEDIDX) | ||||
| 		{ | ||||
| 			if (delete_indexed (rtx, map, var) <= -1) | ||||
| 			{ | ||||
| 				return -1; | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			qse_htb_clear (map); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int run_delete_nonnamed (qse_awk_rtx_t* rtx, qse_awk_nde_var_t* var) | ||||
| { | ||||
| 	qse_awk_val_t* val; | ||||
|  | ||||
| 	if (var->type == QSE_AWK_NDE_GBL || | ||||
| 	    var->type == QSE_AWK_NDE_GBLIDX) | ||||
| 		val = STACK_GBL (rtx,var->id.idxa); | ||||
| 	else if (var->type == QSE_AWK_NDE_LCL || | ||||
| 	         var->type == QSE_AWK_NDE_LCLIDX) | ||||
| 		val = STACK_LCL (rtx,var->id.idxa); | ||||
| 	else val = STACK_ARG (rtx,var->id.idxa); | ||||
|  | ||||
| 	QSE_ASSERT (val != QSE_NULL); | ||||
|  | ||||
| 	if (val->type == QSE_AWK_VAL_NIL) | ||||
| 	{ | ||||
| 		qse_awk_val_t* tmp; | ||||
|  | ||||
| 		/* value not set. | ||||
| 		 * create a map and assign it to the variable */ | ||||
|  | ||||
| 		tmp = qse_awk_rtx_makemapval (rtx); | ||||
| 		if (tmp == QSE_NULL)  | ||||
| 		{ | ||||
| 			ADJERR_LOC (rtx, &var->loc); | ||||
| 			return -1; | ||||
| 		} | ||||
|  | ||||
| 		/* no need to reduce the reference count of | ||||
| 		 * the previous value because it was nil. */ | ||||
| 		if (var->type == QSE_AWK_NDE_GBL || | ||||
| 		    var->type == QSE_AWK_NDE_GBLIDX) | ||||
| 		{ | ||||
| 			if (qse_awk_rtx_setgbl ( | ||||
| 				rtx, (int)var->id.idxa, tmp) == -1) | ||||
| 			{ | ||||
| 				qse_awk_rtx_refupval (rtx, tmp); | ||||
| 				qse_awk_rtx_refdownval (rtx, tmp); | ||||
| 				ADJERR_LOC (rtx, &var->loc); | ||||
| 				return -1; | ||||
| 			} | ||||
| 		} | ||||
| 		else if (var->type == QSE_AWK_NDE_LCL || | ||||
| 		         var->type == QSE_AWK_NDE_LCLIDX) | ||||
| 		{ | ||||
| 			STACK_LCL(rtx,var->id.idxa) = tmp; | ||||
| 			qse_awk_rtx_refupval (rtx, tmp); | ||||
| 		} | ||||
| 		else  | ||||
| 		{ | ||||
| 			STACK_ARG(rtx,var->id.idxa) = tmp; | ||||
| 			qse_awk_rtx_refupval (rtx, tmp); | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		qse_htb_t* map; | ||||
|  | ||||
| 		if (val->type != QSE_AWK_VAL_MAP) | ||||
| 		{ | ||||
| 			SETERR_ARGX_LOC ( | ||||
| 				rtx, QSE_AWK_ENOTDEL, | ||||
| 				xstr_to_cstr(&var->id.name), &var->loc); | ||||
| 			return -1; | ||||
| 		} | ||||
|  | ||||
| 		map = ((qse_awk_val_map_t*)val)->map; | ||||
| 		if (var->type == QSE_AWK_NDE_GBLIDX || | ||||
| 		    var->type == QSE_AWK_NDE_LCLIDX || | ||||
| 		    var->type == QSE_AWK_NDE_ARGIDX) | ||||
| 		{ | ||||
| 			if (delete_indexed (rtx, map, var) <= -1) | ||||
| 			{ | ||||
| 				return -1; | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			qse_htb_clear (map); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int run_delete (qse_awk_rtx_t* rtx, qse_awk_nde_delete_t* nde) | ||||
| { | ||||
| 	qse_awk_nde_var_t* var; | ||||
|  | ||||
| 	var = (qse_awk_nde_var_t*) nde->var; | ||||
|  | ||||
| 	if (var->type == QSE_AWK_NDE_NAMED || | ||||
| 	    var->type == QSE_AWK_NDE_NAMEDIDX) | ||||
| 	switch (var->type) | ||||
| 	{ | ||||
| 		qse_htb_pair_t* pair; | ||||
| 		case QSE_AWK_NDE_NAMED: | ||||
| 		case QSE_AWK_NDE_NAMEDIDX: | ||||
| 			return run_delete_named (rtx, var); | ||||
| 		 | ||||
| 		case QSE_AWK_NDE_GBL: | ||||
| 		case QSE_AWK_NDE_LCL: | ||||
| 		case QSE_AWK_NDE_ARG: | ||||
| 		case QSE_AWK_NDE_GBLIDX: | ||||
| 		case QSE_AWK_NDE_LCLIDX: | ||||
| 		case QSE_AWK_NDE_ARGIDX: | ||||
| 			return run_delete_nonnamed (rtx, var); | ||||
|  | ||||
| 		QSE_ASSERTX ( | ||||
| 			(var->type == QSE_AWK_NDE_NAMED && var->idx == QSE_NULL) || | ||||
| 			(var->type == QSE_AWK_NDE_NAMEDIDX && var->idx != QSE_NULL), | ||||
| 			"if a named variable has an index part and a named indexed variable doesn't have an index part, the program is definitely wrong"); | ||||
|  | ||||
| 		pair = qse_htb_search ( | ||||
| 			rtx->named, var->id.name.ptr, var->id.name.len); | ||||
| 		if (pair == QSE_NULL) | ||||
| 		{ | ||||
| 			qse_awk_val_t* tmp; | ||||
|  | ||||
| 			/* value not set for the named variable.  | ||||
| 			 * create a map and assign it to the variable */ | ||||
|  | ||||
| 			tmp = qse_awk_rtx_makemapval (rtx); | ||||
| 			if (tmp == QSE_NULL)  | ||||
| 			{ | ||||
| 				/* adjust error line */ | ||||
| 				ADJERR_LOC (rtx, &nde->loc); | ||||
| 				return -1; | ||||
| 			} | ||||
|  | ||||
| 			pair = qse_htb_upsert (rtx->named,  | ||||
| 				var->id.name.ptr, var->id.name.len, tmp, 0); | ||||
| 			if (pair == QSE_NULL) | ||||
| 			{ | ||||
| 				qse_awk_rtx_refupval (rtx, tmp); | ||||
| 				qse_awk_rtx_refdownval (rtx, tmp); | ||||
| 				SETERR_LOC (rtx, QSE_AWK_ENOMEM, &var->loc); | ||||
| 				return -1; | ||||
| 			} | ||||
|  | ||||
| 			/* as this is the assignment, it needs to update | ||||
| 			 * the reference count of the target value. */ | ||||
| 			qse_awk_rtx_refupval (rtx, tmp); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			qse_awk_val_t* val; | ||||
| 			qse_htb_t* map; | ||||
|  | ||||
| 			val = (qse_awk_val_t*)QSE_HTB_VPTR(pair); | ||||
| 			QSE_ASSERT (val != QSE_NULL); | ||||
|  | ||||
| 			if (val->type != QSE_AWK_VAL_MAP) | ||||
| 			{ | ||||
| 				SETERR_ARGX_LOC ( | ||||
| 					rtx, QSE_AWK_ENOTDEL,  | ||||
| 					xstr_to_cstr(&var->id.name), &var->loc); | ||||
| 				return -1; | ||||
| 			} | ||||
|  | ||||
| 			map = ((qse_awk_val_map_t*)val)->map; | ||||
| 			if (var->type == QSE_AWK_NDE_NAMEDIDX) | ||||
| 			{ | ||||
| 				if (delete_indexed (rtx, map, var) <= -1) | ||||
| 				{ | ||||
| 					return -1; | ||||
| 				} | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				qse_htb_clear (map); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	else if (var->type == QSE_AWK_NDE_GBL || | ||||
| 	         var->type == QSE_AWK_NDE_LCL || | ||||
| 	         var->type == QSE_AWK_NDE_ARG || | ||||
| 	         var->type == QSE_AWK_NDE_GBLIDX || | ||||
| 	         var->type == QSE_AWK_NDE_LCLIDX || | ||||
| 	         var->type == QSE_AWK_NDE_ARGIDX) | ||||
| 	{ | ||||
| 		qse_awk_val_t* val; | ||||
|  | ||||
| 		if (var->type == QSE_AWK_NDE_GBL || | ||||
| 		    var->type == QSE_AWK_NDE_GBLIDX) | ||||
| 			val = STACK_GBL (rtx,var->id.idxa); | ||||
| 		else if (var->type == QSE_AWK_NDE_LCL || | ||||
| 		         var->type == QSE_AWK_NDE_LCLIDX) | ||||
| 			val = STACK_LCL (rtx,var->id.idxa); | ||||
| 		else val = STACK_ARG (rtx,var->id.idxa); | ||||
|  | ||||
| 		QSE_ASSERT (val != QSE_NULL); | ||||
|  | ||||
| 		if (val->type == QSE_AWK_VAL_NIL) | ||||
| 		{ | ||||
| 			qse_awk_val_t* tmp; | ||||
|  | ||||
| 			/* value not set. | ||||
| 			 * create a map and assign it to the variable */ | ||||
|  | ||||
| 			tmp = qse_awk_rtx_makemapval (rtx); | ||||
| 			if (tmp == QSE_NULL)  | ||||
| 			{ | ||||
| 				ADJERR_LOC (rtx, &nde->loc); | ||||
| 				return -1; | ||||
| 			} | ||||
|  | ||||
| 			/* no need to reduce the reference count of | ||||
| 			 * the previous value because it was nil. */ | ||||
| 			if (var->type == QSE_AWK_NDE_GBL || | ||||
| 			    var->type == QSE_AWK_NDE_GBLIDX) | ||||
| 			{ | ||||
| 				if (qse_awk_rtx_setgbl ( | ||||
| 					rtx, (int)var->id.idxa, tmp) == -1) | ||||
| 				{ | ||||
| 					qse_awk_rtx_refupval (rtx, tmp); | ||||
| 					qse_awk_rtx_refdownval (rtx, tmp); | ||||
| 					ADJERR_LOC (rtx, &var->loc); | ||||
| 					return -1; | ||||
| 				} | ||||
| 			} | ||||
| 			else if (var->type == QSE_AWK_NDE_LCL || | ||||
| 			         var->type == QSE_AWK_NDE_LCLIDX) | ||||
| 			{ | ||||
| 				STACK_LCL(rtx,var->id.idxa) = tmp; | ||||
| 				qse_awk_rtx_refupval (rtx, tmp); | ||||
| 			} | ||||
| 			else  | ||||
| 			{ | ||||
| 				STACK_ARG(rtx,var->id.idxa) = tmp; | ||||
| 				qse_awk_rtx_refupval (rtx, tmp); | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			qse_htb_t* map; | ||||
|  | ||||
| 			if (val->type != QSE_AWK_VAL_MAP) | ||||
| 			{ | ||||
| 				SETERR_ARGX_LOC ( | ||||
| 					rtx, QSE_AWK_ENOTDEL, | ||||
| 					xstr_to_cstr(&var->id.name), &var->loc); | ||||
| 				return -1; | ||||
| 			} | ||||
|  | ||||
| 			map = ((qse_awk_val_map_t*)val)->map; | ||||
| 			if (var->type == QSE_AWK_NDE_GBLIDX || | ||||
| 			    var->type == QSE_AWK_NDE_LCLIDX || | ||||
| 			    var->type == QSE_AWK_NDE_ARGIDX) | ||||
| 			{ | ||||
| 				if (delete_indexed (rtx, map, var) <= -1) | ||||
| 				{ | ||||
| 					return -1; | ||||
| 				} | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				qse_htb_clear (map); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		QSE_ASSERTX ( | ||||
| 			!"should never happen - wrong target for delete", | ||||
| 			"the delete statement cannot be called with other nodes than the variables such as a named variable, a named indexed variable, etc"); | ||||
|  | ||||
| 		SETERR_LOC (rtx, QSE_AWK_ERDELETE, &var->loc); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| 	QSE_ASSERTX ( | ||||
| 		!"should never happen - wrong target for delete", | ||||
| 		"the delete statement cannot be called with other nodes than the variables such as a named variable, a named indexed variable, etc"); | ||||
|  | ||||
| 	SETERR_LOC (rtx, QSE_AWK_ERDELETE, &var->loc); | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| static int run_reset (qse_awk_rtx_t* rtx, qse_awk_nde_reset_t* nde) | ||||
| @ -3376,82 +3387,96 @@ static qse_awk_val_t* do_assignment_scalar ( | ||||
| 	qse_awk_rtx_t* run, qse_awk_nde_var_t* var, qse_awk_val_t* val) | ||||
| { | ||||
| 	QSE_ASSERT ( | ||||
| 		(var->type == QSE_AWK_NDE_NAMED || | ||||
| 		 var->type == QSE_AWK_NDE_GBL || | ||||
| 		 var->type == QSE_AWK_NDE_LCL || | ||||
| 		 var->type == QSE_AWK_NDE_ARG) && var->idx == QSE_NULL); | ||||
| 		var->type == QSE_AWK_NDE_NAMED || | ||||
| 		var->type == QSE_AWK_NDE_GBL || | ||||
| 		var->type == QSE_AWK_NDE_LCL || | ||||
| 		var->type == QSE_AWK_NDE_ARG | ||||
| 	); | ||||
|  | ||||
| 	QSE_ASSERT (var->idx == QSE_NULL); | ||||
|  | ||||
| 	QSE_ASSERT ( | ||||
| 		(run->awk->option & QSE_AWK_MAPTOVAR) || | ||||
| 		val->type != QSE_AWK_VAL_MAP); | ||||
|  | ||||
| 	if (var->type == QSE_AWK_NDE_NAMED)  | ||||
| 	switch (var->type) | ||||
| 	{ | ||||
| 		qse_htb_pair_t* pair; | ||||
|  | ||||
| 		pair = qse_htb_search ( | ||||
| 			run->named, var->id.name.ptr, var->id.name.len); | ||||
| 		if (pair != QSE_NULL &&  | ||||
| 		    ((qse_awk_val_t*)QSE_HTB_VPTR(pair))->type == QSE_AWK_VAL_MAP) | ||||
| 		case QSE_AWK_NDE_NAMED: | ||||
| 		{ | ||||
| 			/* once a variable becomes a map, | ||||
| 			 * it cannot be changed to a scalar variable */ | ||||
| 			SETERR_ARGX_LOC ( | ||||
| 				run, QSE_AWK_EMAPTOSCALAR, | ||||
| 				xstr_to_cstr(&var->id.name), &var->loc); | ||||
| 			return QSE_NULL; | ||||
| 			qse_htb_pair_t* pair; | ||||
|  | ||||
| 			pair = qse_htb_search ( | ||||
| 				run->named, var->id.name.ptr, var->id.name.len); | ||||
| 			if (pair != QSE_NULL &&  | ||||
| 			    ((qse_awk_val_t*)QSE_HTB_VPTR(pair))->type == QSE_AWK_VAL_MAP) | ||||
| 			{ | ||||
| 				/* once a variable becomes a map, | ||||
| 				 * it cannot be changed to a scalar variable */ | ||||
| 				SETERR_ARGX_LOC ( | ||||
| 					run, QSE_AWK_EMAPTOSCALAR, | ||||
| 					xstr_to_cstr(&var->id.name), &var->loc); | ||||
| 				return QSE_NULL; | ||||
| 			} | ||||
|  | ||||
| 			if (qse_htb_upsert (run->named,  | ||||
| 				var->id.name.ptr, var->id.name.len, val, 0) == QSE_NULL) | ||||
| 			{ | ||||
| 				SETERR_LOC (run, QSE_AWK_ENOMEM, &var->loc); | ||||
| 				return QSE_NULL; | ||||
| 			} | ||||
|  | ||||
| 			qse_awk_rtx_refupval (run, val); | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		if (qse_htb_upsert (run->named,  | ||||
| 			var->id.name.ptr, var->id.name.len, val, 0) == QSE_NULL) | ||||
| 		case QSE_AWK_NDE_GBL: | ||||
| 		{ | ||||
| 			SETERR_LOC (run, QSE_AWK_ENOMEM, &var->loc); | ||||
| 			return QSE_NULL; | ||||
| 			if (set_global (run, var->id.idxa, var, val) == -1)  | ||||
| 			{ | ||||
| 				ADJERR_LOC (run, &var->loc); | ||||
| 				return QSE_NULL; | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		qse_awk_rtx_refupval (run, val); | ||||
| 	} | ||||
| 	else if (var->type == QSE_AWK_NDE_GBL)  | ||||
| 	{ | ||||
| 		if (set_global (run, var->id.idxa, var, val) == -1)  | ||||
| 		case QSE_AWK_NDE_LCL: | ||||
| 		{ | ||||
| 			ADJERR_LOC (run, &var->loc); | ||||
| 			return QSE_NULL; | ||||
| 		} | ||||
| 	} | ||||
| 	else if (var->type == QSE_AWK_NDE_LCL)  | ||||
| 	{ | ||||
| 		qse_awk_val_t* old = STACK_LCL(run,var->id.idxa); | ||||
| 		if (old->type == QSE_AWK_VAL_MAP) | ||||
| 		{	 | ||||
| 			/* once the variable becomes a map, | ||||
| 			 * it cannot be changed to a scalar variable */ | ||||
| 			SETERR_ARGX_LOC ( | ||||
| 				run, QSE_AWK_EMAPTOSCALAR,  | ||||
| 				xstr_to_cstr(&var->id.name), &var->loc); | ||||
| 			return QSE_NULL; | ||||
| 			qse_awk_val_t* old = STACK_LCL(run,var->id.idxa); | ||||
| 			if (old->type == QSE_AWK_VAL_MAP) | ||||
| 			{	 | ||||
| 				/* once the variable becomes a map, | ||||
| 				 * it cannot be changed to a scalar variable */ | ||||
| 				SETERR_ARGX_LOC ( | ||||
| 					run, QSE_AWK_EMAPTOSCALAR,  | ||||
| 					xstr_to_cstr(&var->id.name), &var->loc); | ||||
| 				return QSE_NULL; | ||||
| 			} | ||||
| 	 | ||||
| 			qse_awk_rtx_refdownval (run, old); | ||||
| 			STACK_LCL(run,var->id.idxa) = val; | ||||
| 			qse_awk_rtx_refupval (run, val); | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		qse_awk_rtx_refdownval (run, old); | ||||
| 		STACK_LCL(run,var->id.idxa) = val; | ||||
| 		qse_awk_rtx_refupval (run, val); | ||||
| 	} | ||||
| 	else /* if (var->type == QSE_AWK_NDE_ARG) */ | ||||
| 	{ | ||||
| 		qse_awk_val_t* old = STACK_ARG(run,var->id.idxa); | ||||
| 		if (old->type == QSE_AWK_VAL_MAP) | ||||
| 		{	 | ||||
| 			/* once the variable becomes a map, | ||||
| 			 * it cannot be changed to a scalar variable */ | ||||
| 			SETERR_ARGX_LOC ( | ||||
| 				run, QSE_AWK_EMAPTOSCALAR,  | ||||
| 				xstr_to_cstr(&var->id.name), &var->loc); | ||||
| 			return QSE_NULL; | ||||
| 		case QSE_AWK_NDE_ARG: | ||||
| 		{ | ||||
| 			qse_awk_val_t* old = STACK_ARG(run,var->id.idxa); | ||||
| 			if (old->type == QSE_AWK_VAL_MAP) | ||||
| 			{	 | ||||
| 				/* once the variable becomes a map, | ||||
| 				 * it cannot be changed to a scalar variable */ | ||||
| 				SETERR_ARGX_LOC ( | ||||
| 					run, QSE_AWK_EMAPTOSCALAR,  | ||||
| 					xstr_to_cstr(&var->id.name), &var->loc); | ||||
| 				return QSE_NULL; | ||||
| 			} | ||||
| 	 | ||||
| 			qse_awk_rtx_refdownval (run, old); | ||||
| 			STACK_ARG(run,var->id.idxa) = val; | ||||
| 			qse_awk_rtx_refupval (run, val); | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		qse_awk_rtx_refdownval (run, old); | ||||
| 		STACK_ARG(run,var->id.idxa) = val; | ||||
| 		qse_awk_rtx_refupval (run, val); | ||||
| 	} | ||||
|  | ||||
| 	return val; | ||||
| @ -5412,23 +5437,23 @@ static qse_awk_val_t* eval_cnd (qse_awk_rtx_t* run, qse_awk_nde_t* nde) | ||||
|  | ||||
| static qse_awk_val_t* eval_fnc (qse_awk_rtx_t* run, qse_awk_nde_t* nde) | ||||
| { | ||||
| 	qse_awk_nde_call_t* call = (qse_awk_nde_call_t*)nde; | ||||
| 	qse_awk_nde_fncall_t* call = (qse_awk_nde_fncall_t*)nde; | ||||
|  | ||||
| 	/* intrinsic function */ | ||||
| 	if (call->nargs < call->what.fnc.arg.min) | ||||
| 	if (call->nargs < call->u.fnc.arg.min) | ||||
| 	{ | ||||
| 		SETERR_LOC (run, QSE_AWK_EARGTF, &nde->loc); | ||||
| 		return QSE_NULL; | ||||
| 	} | ||||
|  | ||||
| 	if (call->nargs > call->what.fnc.arg.max) | ||||
| 	if (call->nargs > call->u.fnc.arg.max) | ||||
| 	{ | ||||
| 		SETERR_LOC (run, QSE_AWK_EARGTM, &nde->loc); | ||||
| 		return QSE_NULL; | ||||
| 	} | ||||
|  | ||||
| 	return eval_call ( | ||||
| 		run, nde, call->what.fnc.arg.spec,  | ||||
| 		run, nde, call->u.fnc.arg.spec,  | ||||
| 		QSE_NULL, QSE_NULL, QSE_NULL); | ||||
| } | ||||
|  | ||||
| @ -5436,17 +5461,17 @@ static qse_awk_val_t* eval_fun_ex ( | ||||
| 	qse_awk_rtx_t* rtx, qse_awk_nde_t* nde, | ||||
| 	void(*errhandler)(void*), void* eharg) | ||||
| { | ||||
| 	qse_awk_nde_call_t* call = (qse_awk_nde_call_t*)nde; | ||||
| 	qse_awk_nde_fncall_t* call = (qse_awk_nde_fncall_t*)nde; | ||||
| 	qse_awk_fun_t* fun; | ||||
| 	qse_htb_pair_t* pair; | ||||
|  | ||||
| 	pair = qse_htb_search (rtx->awk->tree.funs, | ||||
| 		call->what.fun.name.ptr, call->what.fun.name.len); | ||||
| 		call->u.fun.name.ptr, call->u.fun.name.len); | ||||
| 	if (pair == QSE_NULL)  | ||||
| 	{ | ||||
| 		SETERR_ARGX_LOC ( | ||||
| 			rtx, QSE_AWK_EFUNNF, | ||||
| 			xstr_to_cstr(&call->what.fun.name), &nde->loc); | ||||
| 			xstr_to_cstr(&call->u.fun.name), &nde->loc); | ||||
| 		return QSE_NULL; | ||||
| 	} | ||||
|  | ||||
| @ -5501,12 +5526,12 @@ static qse_awk_val_t* __eval_call ( | ||||
| 	qse_awk_nde_t* nde,  | ||||
| 	const qse_char_t* fnc_arg_spec, | ||||
| 	qse_awk_fun_t* fun,  | ||||
| 	qse_size_t(*argpusher)(qse_awk_rtx_t*,qse_awk_nde_call_t*,void*),  | ||||
| 	qse_size_t(*argpusher)(qse_awk_rtx_t*,qse_awk_nde_fncall_t*,void*),  | ||||
| 	void* apdata, | ||||
| 	void(*errhandler)(void*), | ||||
| 	void* eharg) | ||||
| { | ||||
| 	qse_awk_nde_call_t* call = (qse_awk_nde_call_t*)nde; | ||||
| 	qse_awk_nde_fncall_t* call = (qse_awk_nde_fncall_t*)nde; | ||||
| 	qse_size_t saved_stack_top; | ||||
| 	qse_size_t nargs, i; | ||||
| 	qse_awk_val_t* v; | ||||
| @ -5640,19 +5665,16 @@ static qse_awk_val_t* __eval_call ( | ||||
|  | ||||
| 		/* intrinsic function */ | ||||
| 		QSE_ASSERT ( | ||||
| 			call->nargs >= call->what.fnc.arg.min && | ||||
| 			call->nargs <= call->what.fnc.arg.max); | ||||
| 			call->nargs >= call->u.fnc.arg.min && | ||||
| 			call->nargs <= call->u.fnc.arg.max); | ||||
|  | ||||
| 		if (call->what.fnc.handler != QSE_NULL) | ||||
| 		if (call->u.fnc.handler != QSE_NULL) | ||||
| 		{ | ||||
| 			run->errinf.num = QSE_AWK_ENOERR; | ||||
|  | ||||
| 			/* NOTE: oname is used when the handler is invoked. | ||||
| 			 *       name might be differnt from oname if  | ||||
| 			 *       qse_awk_setword has been used */ | ||||
| 			n = call->what.fnc.handler ( | ||||
| 			n = call->u.fnc.handler ( | ||||
| 				run, | ||||
| 				xstr_to_cstr(&call->what.fnc.oname) | ||||
| 				xstr_to_cstr(&call->u.fnc.name) | ||||
| 			); | ||||
|  | ||||
| 			if (n <= -1) | ||||
| @ -5663,7 +5685,7 @@ static qse_awk_val_t* __eval_call ( | ||||
| 					 * fix it */  | ||||
| 					SETERR_ARGX_LOC ( | ||||
| 						run, QSE_AWK_EFNCIMPL,  | ||||
| 						xstr_to_cstr(&call->what.fnc.oname), | ||||
| 						xstr_to_cstr(&call->u.fnc.name), | ||||
| 						&nde->loc | ||||
| 					); | ||||
| 				} | ||||
| @ -5751,7 +5773,7 @@ static qse_awk_val_t* __eval_call ( | ||||
| } | ||||
|  | ||||
| static qse_size_t push_arg_from_vals ( | ||||
| 	qse_awk_rtx_t* rtx, qse_awk_nde_call_t* call, void* data) | ||||
| 	qse_awk_rtx_t* rtx, qse_awk_nde_fncall_t* call, void* data) | ||||
| { | ||||
| 	struct pafv* pafv = (struct pafv*)data; | ||||
| 	qse_size_t nargs = 0; | ||||
| @ -5780,7 +5802,7 @@ static qse_size_t push_arg_from_vals ( | ||||
| } | ||||
|  | ||||
| static qse_size_t push_arg_from_nde ( | ||||
| 	qse_awk_rtx_t* rtx, qse_awk_nde_call_t* call, void* data) | ||||
| 	qse_awk_rtx_t* rtx, qse_awk_nde_fncall_t* call, void* data) | ||||
| { | ||||
| 	qse_awk_nde_t* p; | ||||
| 	qse_awk_val_t* v; | ||||
| @ -6120,9 +6142,11 @@ static qse_awk_val_t* eval_named (qse_awk_rtx_t* run, qse_awk_nde_t* nde) | ||||
| { | ||||
| 	qse_htb_pair_t* pair; | ||||
| 		        | ||||
| 	pair = qse_htb_search (run->named,  | ||||
| 	pair = qse_htb_search ( | ||||
| 		run->named,  | ||||
| 		((qse_awk_nde_var_t*)nde)->id.name.ptr,  | ||||
| 		((qse_awk_nde_var_t*)nde)->id.name.len); | ||||
| 		((qse_awk_nde_var_t*)nde)->id.name.len | ||||
| 	); | ||||
|  | ||||
| 	return (pair == QSE_NULL)? qse_awk_val_nil: QSE_HTB_VPTR(pair); | ||||
| } | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * $Id: tree.c 474 2011-05-23 16:52:37Z hyunghwan.chung $ | ||||
|  * $Id: tree.c 485 2011-05-29 15:15:52Z hyunghwan.chung $ | ||||
|  * | ||||
|     Copyright 2006-2011 Chung, Hyung-Hwan. | ||||
|     This file is part of QSE. | ||||
| @ -540,9 +540,9 @@ static int print_expr (qse_awk_t* awk, qse_awk_nde_t* nde) | ||||
|  | ||||
| 		case QSE_AWK_NDE_FNC: | ||||
| 		{ | ||||
| 			qse_awk_nde_call_t* px = (qse_awk_nde_call_t*)nde; | ||||
| 			qse_awk_nde_fncall_t* px = (qse_awk_nde_fncall_t*)nde; | ||||
| 			PUT_SRCSTRX (awk,  | ||||
| 				px->what.fnc.name.ptr, px->what.fnc.name.len); | ||||
| 				px->u.fnc.name.ptr, px->u.fnc.name.len); | ||||
| 			PUT_SRCSTR (awk, QSE_T("(")); | ||||
| 			PRINT_EXPR_LIST (awk, px->args); | ||||
| 			PUT_SRCSTR (awk, QSE_T(")")); | ||||
| @ -551,9 +551,9 @@ static int print_expr (qse_awk_t* awk, qse_awk_nde_t* nde) | ||||
|  | ||||
| 		case QSE_AWK_NDE_FUN: | ||||
| 		{ | ||||
| 			qse_awk_nde_call_t* px = (qse_awk_nde_call_t*)nde; | ||||
| 			qse_awk_nde_fncall_t* px = (qse_awk_nde_fncall_t*)nde; | ||||
| 			PUT_SRCSTRX (awk,  | ||||
| 				px->what.fun.name.ptr, px->what.fun.name.len); | ||||
| 				px->u.fun.name.ptr, px->u.fun.name.len); | ||||
| 			PUT_SRCSTR (awk, QSE_T("(")); | ||||
| 			PRINT_EXPR_LIST (awk, px->args); | ||||
| 			PUT_SRCSTR (awk, QSE_T(")")); | ||||
| @ -1276,9 +1276,9 @@ void qse_awk_clrpt (qse_awk_t* awk, qse_awk_nde_t* tree) | ||||
|  | ||||
| 			case QSE_AWK_NDE_FNC: | ||||
| 			{ | ||||
| 				qse_awk_nde_call_t* px = (qse_awk_nde_call_t*)p; | ||||
| 				/* QSE_AWK_FREE (awk, px->what.fnc); */ | ||||
| 				QSE_AWK_FREE (awk, px->what.fnc.name.ptr); | ||||
| 				qse_awk_nde_fncall_t* px = (qse_awk_nde_fncall_t*)p; | ||||
| 				/* QSE_AWK_FREE (awk, px->u.fnc); */ | ||||
| 				QSE_AWK_FREE (awk, px->u.fnc.name.ptr); | ||||
| 				qse_awk_clrpt (awk, px->args); | ||||
| 				QSE_AWK_FREE (awk, p); | ||||
| 				break; | ||||
| @ -1286,8 +1286,8 @@ void qse_awk_clrpt (qse_awk_t* awk, qse_awk_nde_t* tree) | ||||
|  | ||||
| 			case QSE_AWK_NDE_FUN: | ||||
| 			{ | ||||
| 				qse_awk_nde_call_t* px = (qse_awk_nde_call_t*)p; | ||||
| 				QSE_AWK_FREE (awk, px->what.fun.name.ptr); | ||||
| 				qse_awk_nde_fncall_t* px = (qse_awk_nde_fncall_t*)p; | ||||
| 				QSE_AWK_FREE (awk, px->u.fun.name.ptr); | ||||
| 				qse_awk_clrpt (awk, px->args); | ||||
| 				QSE_AWK_FREE (awk, p); | ||||
| 				break; | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * $Id: tree.h 473 2011-05-23 03:38:03Z hyunghwan.chung $ | ||||
|  * $Id: tree.h 485 2011-05-29 15:15:52Z hyunghwan.chung $ | ||||
|  * | ||||
|     Copyright 2006-2011 Chung, Hyung-Hwan. | ||||
|     This file is part of QSE. | ||||
| @ -57,7 +57,7 @@ typedef struct qse_awk_nde_real_t      qse_awk_nde_real_t; | ||||
| typedef struct qse_awk_nde_str_t       qse_awk_nde_str_t; | ||||
| typedef struct qse_awk_nde_rex_t       qse_awk_nde_rex_t; | ||||
| typedef struct qse_awk_nde_var_t       qse_awk_nde_var_t; | ||||
| typedef struct qse_awk_nde_call_t      qse_awk_nde_call_t; | ||||
| typedef struct qse_awk_nde_fncall_t    qse_awk_nde_fncall_t; | ||||
| typedef struct qse_awk_nde_getline_t   qse_awk_nde_getline_t; | ||||
|  | ||||
| typedef struct qse_awk_nde_if_t        qse_awk_nde_if_t; | ||||
| @ -175,7 +175,7 @@ struct qse_awk_nde_var_t | ||||
| }; | ||||
|  | ||||
| /* QSE_AWK_NDE_FNC, QSE_AWK_NDE_FUN */ | ||||
| struct qse_awk_nde_call_t | ||||
| struct qse_awk_nde_fncall_t | ||||
| { | ||||
| 	QSE_AWK_NDE_HDR; | ||||
| 	union | ||||
| @ -191,10 +191,6 @@ struct qse_awk_nde_call_t | ||||
| 		{ | ||||
| 			qse_xstr_t name; | ||||
|  | ||||
| 			/* original name. if qse_awk_setword has been  | ||||
| 			 * invoked, oname can be different from name */ | ||||
| 			qse_xstr_t oname; | ||||
|  | ||||
| 			struct | ||||
| 			{ | ||||
| 				qse_size_t min; | ||||
| @ -204,7 +200,7 @@ struct qse_awk_nde_call_t | ||||
|  | ||||
| 			qse_awk_fnc_fun_t handler; | ||||
| 		} fnc; | ||||
| 	} what; | ||||
| 	} u; | ||||
| 	qse_awk_nde_t* args; | ||||
| 	qse_size_t nargs; | ||||
| }; | ||||
|  | ||||
		Reference in New Issue
	
	Block a user