more code to support call-by-reference parameters of a normal awk function

This commit is contained in:
hyung-hwan 2019-06-07 16:31:16 +00:00
parent 4255f9599f
commit 7e4cc9a7c8
5 changed files with 120 additions and 94 deletions

View File

@ -2659,7 +2659,6 @@ QSE_EXPORT qse_awk_val_map_itr_t* qse_awk_rtx_getnextmapvalitr (
qse_awk_val_map_itr_t* itr qse_awk_val_map_itr_t* itr
); );
/** /**
* The qse_awk_rtx_makerefval() function creates a reference value. * The qse_awk_rtx_makerefval() function creates a reference value.
* \return value on success, #QSE_NULL on failure * \return value on success, #QSE_NULL on failure

View File

@ -439,6 +439,18 @@ struct qse_awk_mod_data_t
qse_awk_mod_t mod; qse_awk_mod_t mod;
}; };
#define QSE_AWK_RTX_INIT_REF_VAL(refval, _id, _adr, _nrefs) \
do { \
(refval)->v_type = QSE_AWK_VAL_REF; \
(refval)->ref = (_nrefs); \
(refval)->stat = 0; \
(refval)->nstr = 0; \
(refval)->fcb = 0; \
(refval)->id = (_id); \
(refval)->adr = (_adr); \
} while(0);
#if defined(__cplusplus) #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #endif

View File

@ -6865,7 +6865,11 @@ int qse_awk_putsrcstrn (
#include "mod-sys.h" #include "mod-sys.h"
#if defined(MOO_ENABLE_AWKMOD_MPI) #if defined(MOO_ENABLE_AWKMOD_MPI)
#include "../awkmod/mod-sed.h" #include "../awkmod/mod-mpi.h"
#endif
#if defined(MOO_ENABLE_AWKMOD_MYSQL)
#include "../awkmod/mod-mysql.h"
#endif #endif
#if defined(MOO_ENABLE_AWKMOD_SED) #if defined(MOO_ENABLE_AWKMOD_SED)
@ -6890,13 +6894,18 @@ static struct
{ {
{ QSE_T("dir"), qse_awk_mod_dir }, { QSE_T("dir"), qse_awk_mod_dir },
{ QSE_T("math"), qse_awk_mod_math }, { QSE_T("math"), qse_awk_mod_math },
#if defined(HAVE_MPI) #if defined(MOO_ENABLE_AWKMOD_MPI)
{ QSE_T("mpi"), qse_awk_mod_mpi }, { QSE_T("mpi"), qse_awk_mod_mpi },
#endif #endif
#if defined(MOO_ENABLE_AWKMOD_MYSQL)
{ QSE_T("mysql"), qse_awk_mod_mysql },
#endif
#if defined(MOO_ENABLE_AWKMOD_SED)
{ QSE_T("sed"), qse_awk_mod_sed }, { QSE_T("sed"), qse_awk_mod_sed },
#endif
{ QSE_T("str"), qse_awk_mod_str }, { QSE_T("str"), qse_awk_mod_str },
{ QSE_T("sys"), qse_awk_mod_sys }, { QSE_T("sys"), qse_awk_mod_sys },
#if defined(HAVE_UCI) #if defined(MOO_ENABLE_AWKMOD_UCI)
{ QSE_T("uci"), qse_awk_mod_uci } { QSE_T("uci"), qse_awk_mod_uci }
#endif #endif
}; };

View File

@ -3231,7 +3231,7 @@ static qse_awk_val_t* eval_expression (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde)
return v; return v;
} }
static qse_awk_val_t* eval_expression0 (qse_awk_rtx_t* run, qse_awk_nde_t* nde) static qse_awk_val_t* eval_expression0 (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde)
{ {
static eval_expr_t __evaluator[] = static eval_expr_t __evaluator[] =
{ {
@ -3271,18 +3271,18 @@ static qse_awk_val_t* eval_expression0 (qse_awk_rtx_t* run, qse_awk_nde_t* nde)
QSE_ASSERT (nde->type >= QSE_AWK_NDE_GRP && (nde->type - QSE_AWK_NDE_GRP) < QSE_COUNTOF(__evaluator)); QSE_ASSERT (nde->type >= QSE_AWK_NDE_GRP && (nde->type - QSE_AWK_NDE_GRP) < QSE_COUNTOF(__evaluator));
v = __evaluator[nde->type-QSE_AWK_NDE_GRP](run, nde); v = __evaluator[nde->type-QSE_AWK_NDE_GRP](rtx, nde);
if (v != QSE_NULL && run->exit_level >= EXIT_GLOBAL) if (v != QSE_NULL && rtx->exit_level >= EXIT_GLOBAL)
{ {
qse_awk_rtx_refupval (run, v); qse_awk_rtx_refupval (rtx, v);
qse_awk_rtx_refdownval (run, v); qse_awk_rtx_refdownval (rtx, v);
/* returns QSE_NULL as if an error occurred but /* returns QSE_NULL as if an error occurred but
* clears the error number. run_main will * clears the error number. run_main will
* detect this condition and treat it as a * detect this condition and treat it as a
* non-error condition.*/ * non-error condition.*/
run->errinf.num = QSE_AWK_ENOERR; rtx->errinf.num = QSE_AWK_ENOERR;
return QSE_NULL; return QSE_NULL;
} }
@ -3331,7 +3331,7 @@ loop:
return val; return val;
} }
static qse_awk_val_t* eval_assignment (qse_awk_rtx_t* run, qse_awk_nde_t* nde) static qse_awk_val_t* eval_assignment (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde)
{ {
qse_awk_val_t* val, * ret; qse_awk_val_t* val, * ret;
qse_awk_nde_ass_t* ass = (qse_awk_nde_ass_t*)nde; qse_awk_nde_ass_t* ass = (qse_awk_nde_ass_t*)nde;
@ -3340,17 +3340,17 @@ static qse_awk_val_t* eval_assignment (qse_awk_rtx_t* run, qse_awk_nde_t* nde)
QSE_ASSERT (ass->right != QSE_NULL); QSE_ASSERT (ass->right != QSE_NULL);
QSE_ASSERT (ass->right->next == QSE_NULL); QSE_ASSERT (ass->right->next == QSE_NULL);
val = eval_expression (run, ass->right); val = eval_expression (rtx, ass->right);
if (val == QSE_NULL) return QSE_NULL; if (val == QSE_NULL) return QSE_NULL;
qse_awk_rtx_refupval (run, val); qse_awk_rtx_refupval (rtx, val);
if (ass->opcode != QSE_AWK_ASSOP_NONE) if (ass->opcode != QSE_AWK_ASSOP_NONE)
{ {
qse_awk_val_t* val2, * tmp; qse_awk_val_t* val2, * tmp;
static binop_func_t binop_func[] = static binop_func_t binop_func[] =
{ {
/* this table must match qse_awk_assop_type_t in run.h */ /* this table must match qse_awk_assop_type_t in rtx.h */
QSE_NULL, /* QSE_AWK_ASSOP_NONE */ QSE_NULL, /* QSE_AWK_ASSOP_NONE */
eval_binop_plus, eval_binop_plus,
eval_binop_minus, eval_binop_minus,
@ -3368,36 +3368,36 @@ static qse_awk_val_t* eval_assignment (qse_awk_rtx_t* run, qse_awk_nde_t* nde)
}; };
QSE_ASSERT (ass->left->next == QSE_NULL); QSE_ASSERT (ass->left->next == QSE_NULL);
val2 = eval_expression (run, ass->left); val2 = eval_expression(rtx, ass->left);
if (val2 == QSE_NULL) if (val2 == QSE_NULL)
{ {
qse_awk_rtx_refdownval (run, val); qse_awk_rtx_refdownval (rtx, val);
return QSE_NULL; return QSE_NULL;
} }
qse_awk_rtx_refupval (run, val2); qse_awk_rtx_refupval (rtx, val2);
QSE_ASSERT (ass->opcode >= 0); QSE_ASSERT (ass->opcode >= 0);
QSE_ASSERT (ass->opcode < QSE_COUNTOF(binop_func)); QSE_ASSERT (ass->opcode < QSE_COUNTOF(binop_func));
QSE_ASSERT (binop_func[ass->opcode] != QSE_NULL); QSE_ASSERT (binop_func[ass->opcode] != QSE_NULL);
tmp = binop_func[ass->opcode] (run, val2, val); tmp = binop_func[ass->opcode](rtx, val2, val);
if (tmp == QSE_NULL) if (tmp == QSE_NULL)
{ {
qse_awk_rtx_refdownval (run, val2); qse_awk_rtx_refdownval (rtx, val2);
qse_awk_rtx_refdownval (run, val); qse_awk_rtx_refdownval (rtx, val);
return QSE_NULL; return QSE_NULL;
} }
qse_awk_rtx_refdownval (run, val2); qse_awk_rtx_refdownval (rtx, val2);
qse_awk_rtx_refdownval (run, val); qse_awk_rtx_refdownval (rtx, val);
val = tmp; val = tmp;
qse_awk_rtx_refupval (run, val); qse_awk_rtx_refupval (rtx, val);
} }
ret = do_assignment (run, ass->left, val); ret = do_assignment(rtx, ass->left, val);
qse_awk_rtx_refdownval (run, val); qse_awk_rtx_refdownval (rtx, val);
return ret; return ret;
} }
@ -3599,8 +3599,7 @@ retry:
case QSE_AWK_NDE_NAMEDIDX: case QSE_AWK_NDE_NAMEDIDX:
{ {
qse_htb_pair_t* pair; qse_htb_pair_t* pair;
pair = qse_htb_search ( pair = qse_htb_search(rtx->named, var->id.name.ptr, var->id.name.len);
rtx->named, var->id.name.ptr, var->id.name.len);
map = (pair == QSE_NULL)? map = (pair == QSE_NULL)?
(qse_awk_val_map_t*)qse_awk_val_nil: (qse_awk_val_map_t*)qse_awk_val_nil:
(qse_awk_val_map_t*)QSE_HTB_VPTR(pair); (qse_awk_val_map_t*)QSE_HTB_VPTR(pair);
@ -5360,7 +5359,7 @@ static qse_awk_val_t* eval_binop_nm (qse_awk_rtx_t* run, qse_awk_nde_t* left, qs
return res; return res;
} }
static qse_awk_val_t* eval_unary (qse_awk_rtx_t* run, qse_awk_nde_t* nde) static qse_awk_val_t* eval_unary (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde)
{ {
qse_awk_val_t* left, * res = QSE_NULL; qse_awk_val_t* left, * res = QSE_NULL;
qse_awk_nde_exp_t* exp = (qse_awk_nde_exp_t*)nde; qse_awk_nde_exp_t* exp = (qse_awk_nde_exp_t*)nde;
@ -5379,19 +5378,19 @@ static qse_awk_val_t* eval_unary (qse_awk_rtx_t* run, qse_awk_nde_t* nde)
exp->opcode == QSE_AWK_UNROP_BNOT); exp->opcode == QSE_AWK_UNROP_BNOT);
QSE_ASSERT (exp->left->next == QSE_NULL); QSE_ASSERT (exp->left->next == QSE_NULL);
left = eval_expression (run, exp->left); left = eval_expression (rtx, exp->left);
if (left == QSE_NULL) return QSE_NULL; if (left == QSE_NULL) return QSE_NULL;
qse_awk_rtx_refupval (run, left); qse_awk_rtx_refupval (rtx, left);
switch (exp->opcode) switch (exp->opcode)
{ {
case QSE_AWK_UNROP_MINUS: case QSE_AWK_UNROP_MINUS:
n = qse_awk_rtx_valtonum (run, left, &l, &r); n = qse_awk_rtx_valtonum (rtx, left, &l, &r);
if (n <= -1) goto exit_func; if (n <= -1) goto exit_func;
res = (n == 0)? qse_awk_rtx_makeintval (run, -l): res = (n == 0)? qse_awk_rtx_makeintval (rtx, -l):
qse_awk_rtx_makefltval (run, -r); qse_awk_rtx_makefltval (rtx, -r);
break; break;
case QSE_AWK_UNROP_LNOT: case QSE_AWK_UNROP_LNOT:
@ -5400,37 +5399,37 @@ static qse_awk_val_t* eval_unary (qse_awk_rtx_t* run, qse_awk_nde_t* nde)
/* 0 if the string length is greater than 0. /* 0 if the string length is greater than 0.
* 1 if it's empty */ * 1 if it's empty */
res = qse_awk_rtx_makeintval ( res = qse_awk_rtx_makeintval (
run, !(((qse_awk_val_str_t*)left)->val.len > 0)); rtx, !(((qse_awk_val_str_t*)left)->val.len > 0));
} }
else else
{ {
n = qse_awk_rtx_valtonum (run, left, &l, &r); n = qse_awk_rtx_valtonum (rtx, left, &l, &r);
if (n <= -1) goto exit_func; if (n <= -1) goto exit_func;
res = (n == 0)? qse_awk_rtx_makeintval (run, !l): res = (n == 0)? qse_awk_rtx_makeintval (rtx, !l):
qse_awk_rtx_makefltval (run, !r); qse_awk_rtx_makefltval (rtx, !r);
} }
break; break;
case QSE_AWK_UNROP_BNOT: case QSE_AWK_UNROP_BNOT:
n = qse_awk_rtx_valtoint (run, left, &l); n = qse_awk_rtx_valtoint (rtx, left, &l);
if (n <= -1) goto exit_func; if (n <= -1) goto exit_func;
res = qse_awk_rtx_makeintval (run, ~l); res = qse_awk_rtx_makeintval (rtx, ~l);
break; break;
case QSE_AWK_UNROP_PLUS: case QSE_AWK_UNROP_PLUS:
n = qse_awk_rtx_valtonum (run, left, &l, &r); n = qse_awk_rtx_valtonum (rtx, left, &l, &r);
if (n <= -1) goto exit_func; if (n <= -1) goto exit_func;
res = (n == 0)? qse_awk_rtx_makeintval (run, l): res = (n == 0)? qse_awk_rtx_makeintval (rtx, l):
qse_awk_rtx_makefltval (run, r); qse_awk_rtx_makefltval (rtx, r);
break; break;
} }
exit_func: exit_func:
qse_awk_rtx_refdownval (run, left); qse_awk_rtx_refdownval (rtx, left);
if (res == QSE_NULL) ADJERR_LOC (run, &nde->loc); if (res == QSE_NULL) ADJERR_LOC (rtx, &nde->loc);
return res; return res;
} }
@ -5903,6 +5902,7 @@ static qse_awk_val_t* __eval_call (
#ifdef DEBUG_RUN #ifdef DEBUG_RUN
qse_errputstrf (QSE_T("setting up function stack frame top=%zd base=%zd\n"), (qse_size_t)rtx->stack_top, (qse_size_t)rtx->stack_base); qse_errputstrf (QSE_T("setting up function stack frame top=%zd base=%zd\n"), (qse_size_t)rtx->stack_top, (qse_size_t)rtx->stack_base);
#endif #endif
if (__raw_push(rtx,(void*)rtx->stack_base) == -1) if (__raw_push(rtx,(void*)rtx->stack_base) == -1)
{ {
SETERR_LOC (rtx, QSE_AWK_ENOMEM, &nde->loc); SETERR_LOC (rtx, QSE_AWK_ENOMEM, &nde->loc);
@ -5949,6 +5949,26 @@ static qse_awk_val_t* __eval_call (
{ {
/* extra step for normal awk functions */ /* extra step for normal awk functions */
if (fun->argspec)
{
/* sanity check for call-by-reference parameters of a normal awk function.
* it tests if each call-by-reference argument is referenceable. */
qse_awk_nde_t* p = call->args;
for (i = 0; i < nargs; i++)
{
if (fun->argspec[i] == QSE_T('r'))
{
qse_awk_val_t** ref;
if (get_reference(rtx, p, &ref) <= -1)
{
UNWIND_RTX_STACK (rtx, nargs);
return QSE_NULL;
}
}
p = p->next;
}
}
while (nargs < fun->nargs) while (nargs < fun->nargs)
{ {
/* push as many nils as the number of missing actual arguments */ /* push as many nils as the number of missing actual arguments */
@ -5967,7 +5987,7 @@ static qse_awk_val_t* __eval_call (
RTX_STACK_NARGS(rtx) = (void*)nargs; RTX_STACK_NARGS(rtx) = (void*)nargs;
#ifdef DEBUG_RUN #ifdef DEBUG_RUN
qse_errputstrf (QSE_T("rtxning function body\n")); qse_errputstrf (QSE_T("running function body\n"));
#endif #endif
if (fun) if (fun)
@ -6025,24 +6045,16 @@ static qse_awk_val_t* __eval_call (
* the intrinsic functions are not handled here but their implementation would * the intrinsic functions are not handled here but their implementation would
* call qse_awk_rtx_setrefval() */ * call qse_awk_rtx_setrefval() */
qse_awk_nde_t* p; qse_awk_nde_t* p = call->args;
p = call->args;
for (i = 0; i < nargs; i++) for (i = 0; i < nargs; i++)
{ {
if (fun->argspec[i] == QSE_T('r')) if (fun->argspec[i] == QSE_T('r'))
{ {
/* TODO: change this part.. */
qse_awk_val_t** ref; qse_awk_val_t** ref;
qse_awk_val_ref_t* refv; qse_awk_val_ref_t refv;
get_reference (rtx, p, &ref); /* no failure check as it must succeed here for the check done above */
/* TODO: ERROR CHECK. no extra memory set */ QSE_AWK_RTX_INIT_REF_VAL (&refv, p->type - QSE_AWK_NDE_NAMED, ref, 5); /* initialize a fake reference variable */
get_reference (rtx, p, &ref); qse_awk_rtx_setrefval (rtx, &refv, RTX_STACK_ARG(rtx, i));
refv = qse_awk_rtx_makerefval(rtx, p->type - QSE_AWK_NDE_NAMED, ref);
qse_awk_rtx_refupval (rtx, refv);
qse_awk_rtx_setrefval (rtx, refv, RTX_STACK_ARG(rtx, i));
qse_awk_rtx_refdownval (rtx, refv);
} }
qse_awk_rtx_refdownval (rtx, RTX_STACK_ARG(rtx,i)); qse_awk_rtx_refdownval (rtx, RTX_STACK_ARG(rtx,i));
@ -6161,7 +6173,7 @@ static qse_size_t push_arg_from_nde (qse_awk_rtx_t* rtx, qse_awk_nde_fncall_t* c
{ {
qse_awk_val_t** ref; qse_awk_val_t** ref;
if (get_reference(rtx, p, &ref) == -1) if (get_reference(rtx, p, &ref) <= -1)
{ {
UNWIND_RTX_STACK_ARG (rtx, nargs); UNWIND_RTX_STACK_ARG (rtx, nargs);
return (qse_size_t)-1; return (qse_size_t)-1;

View File

@ -664,16 +664,10 @@ qse_awk_val_t* qse_awk_rtx_makerefval (qse_awk_rtx_t* rtx, int id, qse_awk_val_t
if (!val) return QSE_NULL; if (!val) return QSE_NULL;
} }
val->v_type = QSE_AWK_VAL_REF; QSE_AWK_RTX_INIT_REF_VAL (val, id, adr, 0);
val->ref = 0;
val->stat = 0;
val->nstr = 0;
val->fcb = 0;
val->id = id;
val->adr = adr;
return (qse_awk_val_t*)val; return (qse_awk_val_t*)val;
} }
qse_awk_val_t* qse_awk_rtx_makefunval (qse_awk_rtx_t* rtx, const qse_awk_fun_t* fun) qse_awk_val_t* qse_awk_rtx_makefunval (qse_awk_rtx_t* rtx, const qse_awk_fun_t* fun)
{ {
qse_awk_val_fun_t* val; qse_awk_val_fun_t* val;