- deleted unnecessary callback functions - on_loop_enter() & on_loop_exit()
- modified qse_awk_rtx_loop() and Awk::loop() to return the return value - deprecated the callback totally from the Awk class: may readd it in the future. - added POC code to pass arguments by reference for intrinsic functions. POC ok. more works needed for full support. not enabled.
This commit is contained in:
		| @ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * $Id: Awk.cpp 235 2009-07-15 10:43:31Z hyunghwan.chung $ | ||||
|  * $Id: Awk.cpp 236 2009-07-16 08:27:53Z hyunghwan.chung $ | ||||
|  * | ||||
|    Copyright 2006-2009 Chung, Hyung-Hwan. | ||||
|  | ||||
| @ -21,6 +21,9 @@ | ||||
| #include "../cmn/mem.h" | ||||
| #include "awk.h" | ||||
|  | ||||
| // enable this once addFunction() is extended with argument spec (rxv...). | ||||
| //#define PASS_BY_REFERENCE | ||||
|  | ||||
| ///////////////////////////////// | ||||
| QSE_BEGIN_NAMESPACE(QSE) | ||||
| ///////////////////////////////// | ||||
| @ -994,7 +997,7 @@ int Awk::Run::getGlobal (int id, Value& g) const | ||||
|  | ||||
| Awk::Awk () : awk (QSE_NULL), functionMap (QSE_NULL), | ||||
| 	sourceIn (this, Source::READ), sourceOut (this, Source::WRITE), | ||||
| 	runCallback (false), runctx (this) | ||||
| 	runctx (this) | ||||
|  | ||||
| { | ||||
| 	errinf.num = (errnum_t)ERR_NOERR; | ||||
| @ -1140,7 +1143,6 @@ int Awk::open () | ||||
| 	qse_map_setfreeer (functionMap, QSE_MAP_VAL, free_function_map_value); | ||||
| 	qse_map_setscale (functionMap, QSE_MAP_KEY, QSE_SIZEOF(qse_char_t)); | ||||
|  | ||||
| 	runCallback = false; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @ -1162,7 +1164,6 @@ void Awk::close () | ||||
| 	} | ||||
|  | ||||
| 	clearError (); | ||||
| 	runCallback = false; | ||||
| } | ||||
|  | ||||
| Awk::Run* Awk::parse (Source& in, Source& out)  | ||||
| @ -1195,19 +1196,27 @@ Awk::Run* Awk::parse (Source& in, Source& out) | ||||
| 	return &runctx; | ||||
| } | ||||
|  | ||||
| int Awk::loop ()  | ||||
| int Awk::loop (Value* ret) | ||||
| { | ||||
| 	QSE_ASSERT (awk != QSE_NULL); | ||||
| 	QSE_ASSERT (runctx.rtx != QSE_NULL); | ||||
|  | ||||
| 	int n = qse_awk_rtx_loop (runctx.rtx); | ||||
| 	if (n <= -1) retrieveError (&runctx); | ||||
| 	return n; | ||||
| 	val_t* rv = qse_awk_rtx_loop (runctx.rtx); | ||||
| 	if (rv == QSE_NULL)  | ||||
| 	{ | ||||
| 		retrieveError (&runctx); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	ret->setVal (&runctx, rv); | ||||
| 	qse_awk_rtx_refdownval (runctx.rtx, rv); | ||||
| 	 | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int Awk::call ( | ||||
| 	const char_t* name, Value* ret, | ||||
| 	const Value* args, size_t nargs)  | ||||
| 	const Value* args, size_t nargs) | ||||
| { | ||||
| 	QSE_ASSERT (awk != QSE_NULL); | ||||
| 	QSE_ASSERT (runctx.rtx != QSE_NULL); | ||||
| @ -1260,21 +1269,11 @@ int Awk::init_runctx () | ||||
| 	if (runctx.rtx != QSE_NULL) return 0; | ||||
|  | ||||
| 	qse_awk_rio_t rio; | ||||
| 	qse_awk_rcb_t rcb; | ||||
|  | ||||
| 	rio.pipe    = pipeHandler; | ||||
| 	rio.file    = fileHandler; | ||||
| 	rio.console = consoleHandler; | ||||
|  | ||||
| 	if (runCallback) | ||||
| 	{ | ||||
| 		QSE_MEMSET (&rcb, 0, QSE_SIZEOF(rcb)); | ||||
| 		rcb.on_loop_enter = onLoopEnter; | ||||
| 		rcb.on_loop_exit  = onLoopExit; | ||||
| 		rcb.on_statement  = onStatement; | ||||
| 		rcb.udd           = &runctx; | ||||
| 	} | ||||
|  | ||||
| 	rtx_t* rtx = qse_awk_rtx_open ( | ||||
| 		awk, QSE_SIZEOF(rxtn_t), &rio, (qse_cstr_t*)runarg.ptr); | ||||
| 	if (rtx == QSE_NULL)  | ||||
| @ -1288,7 +1287,6 @@ int Awk::init_runctx () | ||||
| 	rxtn_t* rxtn = (rxtn_t*) QSE_XTN (rtx); | ||||
| 	rxtn->run = &runctx; | ||||
|  | ||||
| 	if (runCallback) qse_awk_rtx_setrcb (rtx, &rcb); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @ -1357,12 +1355,23 @@ int Awk::dispatch_function (Run* run, const cstr_t* name) | ||||
| 	for (i = 0; i < nargs; i++) | ||||
| 	{ | ||||
| 		val_t* v = qse_awk_rtx_getarg (run->rtx, i); | ||||
| #ifdef PASS_BY_REFERENCE | ||||
| 		QSE_ASSERT (v->type == QSE_AWK_VAL_REF); | ||||
| 		val_t** ref = (val_t**)((qse_awk_val_ref_t*)v)->adr; | ||||
| 		if (args[i].setVal (run, *ref) == -1) | ||||
| 		{ | ||||
| 			run->setError (ERR_NOMEM); | ||||
| 			if (args != buf) delete[] args; | ||||
| 			return -1; | ||||
| 		} | ||||
| #else | ||||
| 		if (args[i].setVal (run, v) == -1) | ||||
| 		{ | ||||
| 			run->setError (ERR_NOMEM); | ||||
| 			if (args != buf) delete[] args; | ||||
| 			return -1; | ||||
| 		} | ||||
| #endif | ||||
| 	} | ||||
| 	 | ||||
| 	Value ret (run); | ||||
| @ -1372,6 +1381,28 @@ int Awk::dispatch_function (Run* run, const cstr_t* name) | ||||
| 	try { n = (this->*handler) (*run, ret, args, nargs, name); } | ||||
| 	catch (...) { n = -1; } | ||||
|  | ||||
| #ifdef PASS_BY_REFERENCE | ||||
| 	if (n >= 0) | ||||
| 	{ | ||||
| 		for (i = 0; i < nargs; i++) | ||||
| 		{ | ||||
| 			QSE_ASSERTX (args[i].run == run,  | ||||
| 				"Do NOT change Run from function handler"); | ||||
|  | ||||
| 			val_t* v = qse_awk_rtx_getarg (run->rtx, i); | ||||
| 			val_t* nv = args[i].toVal(); | ||||
|  | ||||
| 			if (nv == v) continue; | ||||
|  | ||||
| 			QSE_ASSERT (v->type == QSE_AWK_VAL_REF); | ||||
| 			val_t** ref = (val_t**)((qse_awk_val_ref_t*)v)->adr; | ||||
| 	 | ||||
| 			qse_awk_rtx_refdownval (run->rtx, *ref); | ||||
| 			*ref = nv; | ||||
| 			qse_awk_rtx_refupval (run->rtx, *ref); | ||||
| 		} | ||||
| 	} | ||||
| #endif | ||||
| 	if (args != buf) delete[] args; | ||||
|  | ||||
| 	if (n <= -1)  | ||||
| @ -1505,9 +1536,15 @@ int Awk::addFunction ( | ||||
| 	 | ||||
| 	size_t nameLen = qse_strlen(name); | ||||
|  | ||||
| 	void* p = qse_awk_addfnc (awk, name, nameLen, | ||||
| 	                          0, minArgs, maxArgs, QSE_NULL,  | ||||
| 	                          functionHandler); | ||||
| 	void* p = qse_awk_addfnc ( | ||||
| 		awk, name, nameLen, | ||||
| 		0, minArgs, maxArgs, | ||||
| #ifdef PASS_BY_REFERENCE | ||||
| 		QSE_T("R"), // pass all arguments by reference | ||||
| #else | ||||
| 		QSE_NULL, | ||||
| #endif | ||||
| 		functionHandler); | ||||
| 	if (p == QSE_NULL)  | ||||
| 	{ | ||||
| 		qse_awk_free (awk, tmp); | ||||
| @ -1542,16 +1579,6 @@ int Awk::deleteFunction (const char_t* name) | ||||
| 	return n; | ||||
| } | ||||
|  | ||||
| void Awk::enableRunCallback ()  | ||||
| { | ||||
| 	runCallback = true; | ||||
| } | ||||
|  | ||||
| void Awk::disableRunCallback ()  | ||||
| { | ||||
| 	runCallback = false; | ||||
| } | ||||
|  | ||||
| int Awk::getWord ( | ||||
| 	const char_t* ow, qse_size_t owl, | ||||
| 	const char_t** nw, qse_size_t* nwl)  | ||||
| @ -1590,20 +1617,6 @@ int Awk::unsetAllWords () | ||||
| 	return qse_awk_setword (awk, QSE_NULL, 0, QSE_NULL, 0); | ||||
| } | ||||
|  | ||||
|  | ||||
| bool Awk::onLoopEnter (Run& run) | ||||
| { | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| void Awk::onLoopExit (Run& run, const Value& ret) | ||||
| { | ||||
| } | ||||
|  | ||||
| void Awk::onStatement (Run& run, size_t line) | ||||
| { | ||||
| } | ||||
|  | ||||
| Awk::ssize_t Awk::readSource ( | ||||
| 	awk_t* awk, qse_awk_sio_cmd_t cmd, char_t* data, size_t count) | ||||
| { | ||||
| @ -1762,28 +1775,6 @@ int Awk::functionHandler (rtx_t* rtx, const cstr_t* name) | ||||
| 	return rxtn->run->awk->dispatch_function (rxtn->run, name); | ||||
| }	 | ||||
|  | ||||
| int Awk::onLoopEnter (rtx_t* rtx, void* data) | ||||
| { | ||||
| 	Run* run = (Run*)data; | ||||
| 	return run->awk->onLoopEnter(*run)? 0: -1; | ||||
| } | ||||
|  | ||||
| void Awk::onLoopExit (rtx_t* rtx, val_t* ret, void* data) | ||||
| { | ||||
| 	Run* run = (Run*)data; | ||||
|  | ||||
| 	Value x; | ||||
| 	if (x.setVal (run, ret) == -1)  | ||||
| 		qse_awk_rtx_seterrnum (run->rtx, (errnum_t)ERR_NOMEM); | ||||
| 	else run->awk->onLoopExit (*run, x); | ||||
| } | ||||
|  | ||||
| void Awk::onStatement (rtx_t* rtx, size_t line, void* data) | ||||
| { | ||||
| 	Run* run = (Run*)data; | ||||
| 	run->awk->onStatement (*run, line); | ||||
| } | ||||
|  | ||||
| Awk::real_t Awk::pow (awk_t* awk, real_t x, real_t y) | ||||
| { | ||||
| 	xtn_t* xtn = (xtn_t*) QSE_XTN (awk); | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * $Id: run.c 235 2009-07-15 10:43:31Z hyunghwan.chung $ | ||||
|  * $Id: run.c 236 2009-07-16 08:27:53Z hyunghwan.chung $ | ||||
|  * | ||||
|    Copyright 2006-2009 Chung, Hyung-Hwan. | ||||
|  | ||||
| @ -1318,30 +1318,17 @@ static void exit_stack_frame (qse_awk_rtx_t* run) | ||||
| 	run->stack_base = (qse_size_t)run->stack[run->stack_base+0]; | ||||
| } | ||||
|  | ||||
| static int run_bpae_loop (qse_awk_rtx_t* rtx) | ||||
| static qse_awk_val_t* run_bpae_loop (qse_awk_rtx_t* rtx) | ||||
| { | ||||
| 	qse_awk_nde_t* nde; | ||||
| 	qse_size_t nargs, i; | ||||
| 	qse_awk_val_t* v; | ||||
| 	qse_awk_val_t* retv; | ||||
| 	int ret = 0; | ||||
|  | ||||
| 	/* set nargs to zero */ | ||||
| 	nargs = 0; | ||||
| 	STACK_NARGS(rtx) = (void*)nargs; | ||||
|  | ||||
| 	/* call the callback */ | ||||
| 	if (rtx->rcb.on_loop_enter != QSE_NULL) | ||||
| 	{ | ||||
| 		qse_awk_rtx_seterrnum (rtx, QSE_AWK_ENOERR); | ||||
| 		ret = rtx->rcb.on_loop_enter (rtx, rtx->rcb.udd); | ||||
| 		if (ret <= -1)  | ||||
| 		{ | ||||
| 			if (rtx->errinf.num == QSE_AWK_ENOMEM) | ||||
| 				qse_awk_rtx_seterrnum (rtx, QSE_AWK_EUNKNOWN); | ||||
| 			ret = -1; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* execute the BEGIN block */ | ||||
| 	for (nde = rtx->awk->tree.begin;  | ||||
| 	     ret == 0 && nde != QSE_NULL && rtx->exit_level < EXIT_GLOBAL; | ||||
| @ -1357,7 +1344,7 @@ static int run_bpae_loop (qse_awk_rtx_t* rtx) | ||||
| 		if (run_block (rtx, blk) == -1) ret = -1; | ||||
| 	} | ||||
|  | ||||
| 	if (ret == -1 && rtx->errinf.num == QSE_AWK_ENOERR)  | ||||
| 	if (ret <= -1 && rtx->errinf.num == QSE_AWK_ENOERR)  | ||||
| 	{ | ||||
| 		/* an error is returned with no error number set. | ||||
| 		 * this feature is used by eval_expression() to | ||||
| @ -1374,10 +1361,10 @@ static int run_bpae_loop (qse_awk_rtx_t* rtx) | ||||
| 	     rtx->awk->tree.end != QSE_NULL) &&  | ||||
| 	     rtx->exit_level < EXIT_GLOBAL) | ||||
| 	{ | ||||
| 		if (run_pattern_blocks(rtx) == -1) ret = -1; | ||||
| 		if (run_pattern_blocks(rtx) <= -1) ret = -1; | ||||
| 	} | ||||
|  | ||||
| 	if (ret == -1 && rtx->errinf.num == QSE_AWK_ENOERR) | ||||
| 	if (ret <= -1 && rtx->errinf.num == QSE_AWK_ENOERR) | ||||
| 	{ | ||||
| 		/* an error is returned with no error number set. | ||||
| 		 * this feature is used by eval_expression() to | ||||
| @ -1401,7 +1388,7 @@ static int run_bpae_loop (qse_awk_rtx_t* rtx) | ||||
|  | ||||
| 		rtx->active_block = blk; | ||||
| 		rtx->exit_level = EXIT_NONE; | ||||
| 		if (run_block (rtx, blk) == -1) ret = -1; | ||||
| 		if (run_block (rtx, blk) <= -1) ret = -1; | ||||
| 		else if (rtx->exit_level >= EXIT_GLOBAL)  | ||||
| 		{ | ||||
| 			/* once exit is called inside one of END blocks, | ||||
| @ -1410,7 +1397,7 @@ static int run_bpae_loop (qse_awk_rtx_t* rtx) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (ret == -1 && rtx->errinf.num == QSE_AWK_ENOERR) | ||||
| 	if (ret <= -1 && rtx->errinf.num == QSE_AWK_ENOERR) | ||||
| 	{ | ||||
| 		/* an error is returned with no error number set. | ||||
| 		 * this feature is used by eval_expression() to | ||||
| @ -1430,39 +1417,34 @@ static int run_bpae_loop (qse_awk_rtx_t* rtx) | ||||
| 		qse_awk_rtx_refdownval (rtx, STACK_ARG(rtx,i)); | ||||
|  | ||||
| 	/* get the return value in the current stack frame */ | ||||
| 	v = STACK_RETVAL(rtx); | ||||
| 	retv = STACK_RETVAL(rtx); | ||||
|  | ||||
| 	if (rtx->rcb.on_loop_exit != QSE_NULL) | ||||
| 	if (ret <= -1) | ||||
| 	{ | ||||
| 		/* we call the on_exit handler regardless of ret.  | ||||
| 		 * the return value passed is the global return value | ||||
| 		 * in the stack. */ | ||||
| 		rtx->rcb.on_loop_exit (rtx, v, rtx->rcb.udd); | ||||
| 		/* end the life of the global return value upon error */ | ||||
| 		qse_awk_rtx_refdownval (rtx, retv); | ||||
| 		retv = QSE_NULL; | ||||
| 	} | ||||
|  | ||||
| 	/* end the life of the global return value */ | ||||
| 	qse_awk_rtx_refdownval (rtx, v); | ||||
|  | ||||
| 	return ret; | ||||
| 	return retv; | ||||
| } | ||||
|  | ||||
| /* start the BEGIN-pattern block-END loop */ | ||||
| int qse_awk_rtx_loop (qse_awk_rtx_t* rtx) | ||||
| qse_awk_val_t* qse_awk_rtx_loop (qse_awk_rtx_t* rtx) | ||||
| { | ||||
| 	int ret; | ||||
| 	qse_awk_val_t* retv = QSE_NULL; | ||||
|  | ||||
| 	rtx->exit_level = EXIT_NONE; | ||||
|  | ||||
| 	ret = enter_stack_frame (rtx); | ||||
| 	if (ret == 0) | ||||
| 	if (enter_stack_frame (rtx) == 0) | ||||
| 	{ | ||||
| 		ret = run_bpae_loop (rtx); | ||||
| 		retv = run_bpae_loop (rtx); | ||||
| 		exit_stack_frame (rtx); | ||||
| 	} | ||||
|  | ||||
| 	/* reset the exit level */ | ||||
| 	rtx->exit_level = EXIT_NONE; | ||||
| 	return ret; | ||||
| 	return retv; | ||||
| } | ||||
|  | ||||
| /* call an AWK function */ | ||||
| @ -5846,7 +5828,8 @@ static qse_size_t push_arg_from_nde ( | ||||
| 			 qse_strlen(fnc_arg_spec) > nargs)); | ||||
|  | ||||
| 		if (fnc_arg_spec != QSE_NULL &&  | ||||
| 		    fnc_arg_spec[nargs] == QSE_T('r')) | ||||
| 		    (fnc_arg_spec[nargs] == QSE_T('r') || | ||||
| 		     fnc_arg_spec[0] == QSE_T('R'))) | ||||
| 		{ | ||||
| 			qse_awk_val_t** ref; | ||||
| 			       | ||||
| @ -5872,6 +5855,7 @@ static qse_size_t push_arg_from_nde ( | ||||
| 		{ | ||||
| 			v = eval_expression (rtx, p); | ||||
| 		} | ||||
|  | ||||
| 		if (v == QSE_NULL) | ||||
| 		{ | ||||
| 			UNWIND_RTX_STACK_ARG (rtx, nargs); | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * $Id: tree.h 235 2009-07-15 10:43:31Z hyunghwan.chung $ | ||||
|  * $Id: tree.h 236 2009-07-16 08:27:53Z hyunghwan.chung $ | ||||
|  * | ||||
|    Copyright 2006-2009 Chung, Hyung-Hwan. | ||||
|  | ||||
| @ -76,6 +76,8 @@ enum qse_awk_nde_type_t | ||||
| 	QSE_AWK_NDE_GETLINE | ||||
| }; | ||||
|  | ||||
| typedef enum qse_awk_nde_type_t qse_awk_nde_type_t; | ||||
|  | ||||
| enum qse_awk_in_type_t | ||||
| { | ||||
| 	/* the order of these values match  | ||||
| @ -149,7 +151,7 @@ struct qse_awk_fun_t | ||||
| }; | ||||
|  | ||||
| #define QSE_AWK_NDE_HDR \ | ||||
| 	int type; \ | ||||
| 	qse_awk_nde_type_t type; \ | ||||
| 	qse_size_t line; \ | ||||
| 	qse_awk_nde_t* next | ||||
|  | ||||
| @ -162,7 +164,7 @@ struct qse_awk_nde_t | ||||
| struct qse_awk_nde_blk_t | ||||
| { | ||||
| 	QSE_AWK_NDE_HDR; | ||||
| 	qse_size_t nlcls; | ||||
| 	qse_size_t nlcls; /* number of local variables */ | ||||
| 	qse_awk_nde_t* body; | ||||
| }; | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user