enhanced Awk and StdAwk to be able to handle argument reference

This commit is contained in:
hyung-hwan 2013-01-07 08:33:48 +00:00
parent d9f961c6c3
commit 2624acb308
7 changed files with 108 additions and 98 deletions

View File

@ -1085,7 +1085,7 @@ public:
typedef int (Awk::*FunctionHandler) (
Run& run,
Value& ret,
const Value* args,
Value* args,
size_t nargs,
const fnc_info_t* fi
);
@ -1098,6 +1098,7 @@ public:
const char_t* name, ///< function name
size_t minArgs, ///< minimum numbers of arguments
size_t maxArgs, ///< maximum numbers of arguments
const char_t* argSpec, ///< argument specification
FunctionHandler handler, ///< function handler
int validOpts = 0 ///< valid if these options are set
);

View File

@ -142,18 +142,18 @@ protected:
int __build_environ (Run* run, void* envptr);
// intrinsic functions
int rand (Run& run, Value& ret, const Value* args, size_t nargs,
int rand (Run& run, Value& ret, Value* args, size_t nargs,
const char_t* name, size_t len);
int srand (Run& run, Value& ret, const Value* args, size_t nargs,
int srand (Run& run, Value& ret, Value* args, size_t nargs,
const char_t* name, size_t len);
int system (Run& run, Value& ret, const Value* args, size_t nargs,
int system (Run& run, Value& ret, Value* args, size_t nargs,
const char_t* name, size_t len);
qse_cmgr_t* getcmgr (const char_t* ioname);
int setioattr (Run& run, Value& ret, const Value* args, size_t nargs,
int setioattr (Run& run, Value& ret, Value* args, size_t nargs,
const char_t* name, size_t len);
int getioattr (Run& run, Value& ret, const Value* args, size_t nargs,
int getioattr (Run& run, Value& ret, Value* args, size_t nargs,
const char_t* name, size_t len);
// pipe io handlers

View File

@ -23,9 +23,6 @@
#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)
/////////////////////////////////
@ -1359,6 +1356,7 @@ void Awk::setMaxDepth (depth_t id, size_t depth)
int Awk::dispatch_function (Run* run, const fnc_info_t* fi)
{
pair_t* pair;
bool has_ref_arg = false;
pair = qse_htb_search (functionMap, fi->name.ptr, fi->name.len);
if (pair == QSE_NULL)
@ -1387,24 +1385,51 @@ int Awk::dispatch_function (Run* run, const fnc_info_t* fi)
for (i = 0; i < nargs; i++)
{
int xx;
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)
if (v->type == QSE_AWK_VAL_REF)
{
qse_awk_val_ref_t* ref = (qse_awk_val_ref_t*)v;
if (ref->id == qse_awk_val_ref_t::QSE_AWK_VAL_REF_POS)
{
qse_size_t idx = (qse_size_t)ref->adr;
if (idx == 0)
{
xx = args[i].setStr (run,
QSE_STR_PTR(&run->rtx->inrec.line),
QSE_STR_LEN(&run->rtx->inrec.line));
}
else if (idx <= run->rtx->inrec.nflds)
{
xx = args[i].setStr (run,
run->rtx->inrec.flds[idx-1].ptr,
run->rtx->inrec.flds[idx-1].len);
}
else
{
xx = args[i].setStr (run, QSE_T(""), 0);
}
}
else
{
xx = args[i].setVal (run, *(ref->adr));
}
has_ref_arg = true;
}
else
{
xx = args[i].setVal (run, v);
}
if (xx <= -1)
{
run->setError (QSE_AWK_ENOMEM);
if (args != buf) delete[] args;
return -1;
}
#else
if (args[i].setVal (run, v) == -1)
{
run->setError (QSE_AWK_ENOMEM);
if (args != buf) delete[] args;
return -1;
}
#endif
}
Value ret (run);
@ -1414,28 +1439,25 @@ int Awk::dispatch_function (Run* run, const fnc_info_t* fi)
try { n = (this->*handler) (*run, ret, args, nargs, fi); }
catch (...) { n = -1; }
#ifdef PASS_BY_REFERENCE
if (n >= 0)
if (n >= 0 && has_ref_arg)
{
for (i = 0; i < nargs; i++)
{
QSE_ASSERTX (args[i].run == run,
"Do NOT change Run from function handler");
"Do NOT change the run field 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);
if (v->type == QSE_AWK_VAL_REF)
{
if (qse_awk_rtx_setrefval (run->rtx, (qse_awk_val_ref_t*)v, args[i].toVal()) <= -1)
{
n = -1;
break;
}
}
#endif
}
}
if (args != buf) delete[] args;
if (n <= -1)
@ -1559,7 +1581,7 @@ int Awk::getGlobal (int id, Value& v)
int Awk::addFunction (
const char_t* name, size_t minArgs, size_t maxArgs,
FunctionHandler handler, int validOpts)
const char_t* argSpec, FunctionHandler handler, int validOpts)
{
QSE_ASSERT (awk != QSE_NULL);
@ -1578,9 +1600,7 @@ int Awk::addFunction (
QSE_MEMSET (&spec, 0, QSE_SIZEOF(spec));
spec.arg.min = minArgs;
spec.arg.max = maxArgs;
#ifdef PASS_BY_REFERENCE
spec.arg.spec = QSE_T("R"); // pass all arguments by reference
#endif
spec.arg.spec = argSpec;
spec.impl = functionHandler;
spec.trait = validOpts;

View File

@ -73,17 +73,6 @@
QSE_BEGIN_NAMESPACE(QSE)
/////////////////////////////////
#define ADDFNC(name,min,max,impl,vopts) \
do { \
if (addFunction (name, min, max, \
(FunctionHandler)impl, vopts) == -1) \
{ \
Awk::close (); \
return -1; \
} \
} while (0)
StdAwk::ioattr_t StdAwk::default_ioattr;
static qse_sio_t* open_sio (Awk* awk, StdAwk::Run* run, const qse_char_t* file, int flags)
@ -141,11 +130,11 @@ int StdAwk::open ()
goto oops;
}
if (addFunction (QSE_T("rand"), 0, 0, (FunctionHandler)&StdAwk::rand, 0) <= -1 ||
addFunction (QSE_T("srand"), 0, 1, (FunctionHandler)&StdAwk::srand, 0) <= -1 ||
addFunction (QSE_T("system"), 1, 1, (FunctionHandler)&StdAwk::system, 0) <= -1 ||
addFunction (QSE_T("setioattr"), 3, 3, (FunctionHandler)&StdAwk::setioattr, QSE_AWK_RIO) <= -1 ||
addFunction (QSE_T("getioattr"), 2, 2, (FunctionHandler)&StdAwk::getioattr, QSE_AWK_RIO) <= -1)
if (addFunction (QSE_T("rand"), 0, 0, QSE_NULL, (FunctionHandler)&StdAwk::rand, 0) <= -1 ||
addFunction (QSE_T("srand"), 0, 1, QSE_NULL, (FunctionHandler)&StdAwk::srand, 0) <= -1 ||
addFunction (QSE_T("system"), 1, 1, QSE_NULL, (FunctionHandler)&StdAwk::system, 0) <= -1 ||
addFunction (QSE_T("setioattr"), 3, 3, QSE_NULL, (FunctionHandler)&StdAwk::setioattr, QSE_AWK_RIO) <= -1 ||
addFunction (QSE_T("getioattr"), 3, 3, QSE_T("vvr"), (FunctionHandler)&StdAwk::getioattr, QSE_AWK_RIO) <= -1)
{
goto oops;
}
@ -348,7 +337,7 @@ int StdAwk::make_additional_globals (Run* run)
return 0;
}
int StdAwk::rand (Run& run, Value& ret, const Value* args, size_t nargs,
int StdAwk::rand (Run& run, Value& ret, Value* args, size_t nargs,
const char_t* name, size_t len)
{
#define RANDV_MAX QSE_TYPE_MAX(long_t)
@ -358,7 +347,7 @@ int StdAwk::rand (Run& run, Value& ret, const Value* args, size_t nargs,
#undef RANDV_MAX
}
int StdAwk::srand (Run& run, Value& ret, const Value* args, size_t nargs,
int StdAwk::srand (Run& run, Value& ret, Value* args, size_t nargs,
const char_t* name, size_t len)
{
long_t prevSeed = (long_t)this->seed;
@ -384,7 +373,7 @@ int StdAwk::srand (Run& run, Value& ret, const Value* args, size_t nargs,
return ret.setInt ((long_t)prevSeed);
}
int StdAwk::system (Run& run, Value& ret, const Value* args, size_t nargs,
int StdAwk::system (Run& run, Value& ret, Value* args, size_t nargs,
const char_t* name, size_t len)
{
size_t l;
@ -457,7 +446,7 @@ static int timeout_code (const qse_char_t* name)
}
int StdAwk::setioattr (
Run& run, Value& ret, const Value* args, size_t nargs,
Run& run, Value& ret, Value* args, size_t nargs,
const char_t* name, size_t len)
{
QSE_ASSERT (this->cmgrtab_inited == true);
@ -531,7 +520,7 @@ int StdAwk::setioattr (
}
int StdAwk::getioattr (
Run& run, Value& ret, const Value* args, size_t nargs,
Run& run, Value& ret, Value* args, size_t nargs,
const char_t* name, size_t len)
{
QSE_ASSERT (this->cmgrtab_inited == true);
@ -541,12 +530,12 @@ int StdAwk::getioattr (
ptr[0] = args[0].toStr(&l[0]);
ptr[1] = args[1].toStr(&l[1]);
if (qse_strxchr (ptr[0], l[0], QSE_T('\0')) ||
qse_strxchr (ptr[1], l[1], QSE_T('\0')))
{
return ret.setInt ((long_t)-1);
}
int xx = -1;
/* ionames must not contains a null character */
if (qse_strxchr (ptr[0], l[0], QSE_T('\0')) == QSE_NULL &&
qse_strxchr (ptr[1], l[1], QSE_T('\0')) == QSE_NULL)
{
ioattr_t* ioattr = get_ioattr (ptr[0], l[0]);
if (ioattr == QSE_NULL) ioattr = &StdAwk::default_ioattr;
@ -554,21 +543,20 @@ int StdAwk::getioattr (
if ((tmout = timeout_code(ptr[1])) >= 0)
{
if (ioattr->tmout[tmout].nsec == 0)
return ret.setInt ((long_t)ioattr->tmout[tmout].sec);
xx = args[2].setInt ((long_t)ioattr->tmout[tmout].sec);
else
return ret.setFlt ((qse_flt_t)ioattr->tmout[tmout].sec + QSE_NSEC_TO_SEC((qse_flt_t)ioattr->tmout[tmout].nsec));
xx = args[2].setFlt ((qse_flt_t)ioattr->tmout[tmout].sec + QSE_NSEC_TO_SEC((qse_flt_t)ioattr->tmout[tmout].nsec));
}
#if defined(QSE_CHAR_IS_WCHAR)
else if (qse_strcasecmp (ptr[1], QSE_T("codepage")) == 0)
{
return ret.setStr (ioattr->cmgr_name);
xx = args[2].setStr (ioattr->cmgr_name);
}
#endif
else
{
// unknown attribute name
return ret.setInt ((long_t)-1);
}
// unknown attribute name or errors
return ret.setInt ((long_t)xx);
}
int StdAwk::open_nwio (Pipe& io, int flags, void* nwad)

View File

@ -2520,15 +2520,13 @@ done:
while (i > 0)
{
i--;
if (v[i]->type != QSE_AWK_VAL_STR)
QSE_AWK_FREE (rtx->awk, ptr[i]);
if (v[i]->type != QSE_AWK_VAL_STR) QSE_AWK_FREE (rtx->awk, ptr[i]);
}
if (ret >= 0)
{
if (rv)
if (rv && qse_awk_rtx_setrefval (rtx, qse_awk_rtx_getarg (rtx, 2), rv) >= 0)
{
qse_awk_rtx_setrefval (rtx, qse_awk_rtx_getarg (rtx, 2), rv);
qse_awk_rtx_setretval (rtx, qse_awk_val_zero);
}
else

View File

@ -1703,9 +1703,12 @@ but is this really necessary? i feel all these awk quarkiness is nasty..
*/
rref = (qse_awk_val_t**)ref->adr;
if (*rref != val)
{
qse_awk_rtx_refdownval (rtx, *rref);
*rref = val;
qse_awk_rtx_refupval (rtx, *rref);
}
return 0;
}
}

View File

@ -58,13 +58,13 @@ public:
/* this is for demonstration only.
* you can use sys::sleep() instead */
if (addFunction (QSE_T("sleep"), 1, 1,
if (addFunction (QSE_T("sleep"), 1, 1, QSE_NULL,
(FunctionHandler)&MyAwk::sleep) <= -1) goto oops;
if (addFunction (QSE_T("sumintarray"), 1, 1,
if (addFunction (QSE_T("sumintarray"), 1, 1, QSE_NULL,
(FunctionHandler)&MyAwk::sumintarray) <= -1) goto oops;
if (addFunction (QSE_T("arrayindices"), 1, 1,
if (addFunction (QSE_T("arrayindices"), 1, 1, QSE_NULL,
(FunctionHandler)&MyAwk::arrayindices) <= -1) goto oops;
return 0;
@ -75,7 +75,7 @@ public:
}
int sleep (
Run& run, Value& ret, const Value* args, size_t nargs,
Run& run, Value& ret, Value* args, size_t nargs,
const char_t* name, size_t len)
{
if (args[0].isIndexed())
@ -106,7 +106,7 @@ public:
}
int sumintarray (
Run& run, Value& ret, const Value* args, size_t nargs,
Run& run, Value& ret, Value* args, size_t nargs,
const char_t* name, size_t len)
{
// BEGIN {
@ -138,7 +138,7 @@ public:
int arrayindices (
Run& run,
Value& ret,
const Value* args,
Value* args,
size_t nargs,
const char_t* name,
size_t len)