- 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:
2009-07-17 02:27:53 +00:00
parent f0f2db5e8a
commit 6b31c85427
11 changed files with 181 additions and 218 deletions

View File

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

View File

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

View File

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