implemented call-by-reference parameters of normal awk functions partially. it has yet to be refined further
This commit is contained in:
parent
040ee69eb7
commit
4255f9599f
@ -448,7 +448,7 @@ struct qse_awk_fun_t
|
|||||||
{
|
{
|
||||||
qse_cstr_t name;
|
qse_cstr_t name;
|
||||||
qse_size_t nargs;
|
qse_size_t nargs;
|
||||||
qse_char_t* argspec; /* similar to the argument spec of qse_awk_fnc_arg_t. supports v & r only */
|
qse_char_t* argspec; /* similar to the argument spec of qse_awk_fnc_arg_t. supports v & r only. */
|
||||||
qse_awk_nde_t* body;
|
qse_awk_nde_t* body;
|
||||||
};
|
};
|
||||||
typedef struct qse_awk_fun_t qse_awk_fun_t;
|
typedef struct qse_awk_fun_t qse_awk_fun_t;
|
||||||
|
@ -1301,9 +1301,7 @@ int Awk::loop (Value* ret)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Awk::call (
|
int Awk::call (const char_t* name, Value* ret, const Value* args, size_t nargs)
|
||||||
const char_t* name, Value* ret,
|
|
||||||
const Value* args, size_t nargs)
|
|
||||||
{
|
{
|
||||||
QSE_ASSERT (this->awk != QSE_NULL);
|
QSE_ASSERT (this->awk != QSE_NULL);
|
||||||
QSE_ASSERT (this->runctx.rtx != QSE_NULL);
|
QSE_ASSERT (this->runctx.rtx != QSE_NULL);
|
||||||
@ -1329,7 +1327,7 @@ int Awk::call (
|
|||||||
for (size_t i = 0; i < nargs; i++) ptr[i] = (val_t*)args[i];
|
for (size_t i = 0; i < nargs; i++) ptr[i] = (val_t*)args[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
val_t* rv = qse_awk_rtx_call (this->runctx.rtx, name, ptr, nargs);
|
val_t* rv = qse_awk_rtx_call(this->runctx.rtx, name, ptr, nargs);
|
||||||
|
|
||||||
if (ptr != QSE_NULL && ptr != buf) qse_awk_freemem (awk, ptr);
|
if (ptr != QSE_NULL && ptr != buf) qse_awk_freemem (awk, ptr);
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ static void free_fun (qse_htb_t* map, void* vptr, qse_size_t vlen)
|
|||||||
/* f->name doesn't have to be freed */
|
/* f->name doesn't have to be freed */
|
||||||
/*qse_awk_freemem (awk, f->name);*/
|
/*qse_awk_freemem (awk, f->name);*/
|
||||||
|
|
||||||
|
if (f->argspec) qse_awk_freemem (awk, f->argspec);
|
||||||
qse_awk_clrpt (awk, f->body);
|
qse_awk_clrpt (awk, f->body);
|
||||||
qse_awk_freemem (awk, f);
|
qse_awk_freemem (awk, f);
|
||||||
}
|
}
|
||||||
|
@ -1180,8 +1180,10 @@ static int parse_progunit (qse_awk_t* awk)
|
|||||||
static qse_awk_nde_t* parse_function (qse_awk_t* awk)
|
static qse_awk_nde_t* parse_function (qse_awk_t* awk)
|
||||||
{
|
{
|
||||||
qse_cstr_t name;
|
qse_cstr_t name;
|
||||||
qse_awk_nde_t* body;
|
qse_awk_nde_t* body = QSE_NULL;
|
||||||
qse_awk_fun_t* fun;
|
qse_awk_fun_t* fun = QSE_NULL;
|
||||||
|
qse_char_t* argspec = QSE_NULL;
|
||||||
|
qse_size_t argspeccapa = 0;
|
||||||
qse_size_t nargs, g;
|
qse_size_t nargs, g;
|
||||||
qse_htb_pair_t* pair;
|
qse_htb_pair_t* pair;
|
||||||
qse_awk_loc_t xloc;
|
qse_awk_loc_t xloc;
|
||||||
@ -1201,7 +1203,7 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk)
|
|||||||
|
|
||||||
name.len = QSE_STR_LEN(awk->tok.name);
|
name.len = QSE_STR_LEN(awk->tok.name);
|
||||||
name.ptr = QSE_STR_PTR(awk->tok.name);
|
name.ptr = QSE_STR_PTR(awk->tok.name);
|
||||||
|
|
||||||
/* note that i'm assigning to rederr in the 'if' conditions below.
|
/* note that i'm assigning to rederr in the 'if' conditions below.
|
||||||
* i'm not checking equality */
|
* i'm not checking equality */
|
||||||
/* check if it is a builtin function */
|
/* check if it is a builtin function */
|
||||||
@ -1226,27 +1228,18 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* get the next token */
|
/* get the next token */
|
||||||
if (get_token(awk) <= -1)
|
if (get_token(awk) <= -1) goto oops;
|
||||||
{
|
|
||||||
qse_awk_freemem (awk, name.ptr);
|
|
||||||
return QSE_NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* match a left parenthesis */
|
/* match a left parenthesis */
|
||||||
if (!MATCH(awk,TOK_LPAREN))
|
if (!MATCH(awk,TOK_LPAREN))
|
||||||
{
|
{
|
||||||
/* a function name is not followed by a left parenthesis */
|
/* a function name is not followed by a left parenthesis */
|
||||||
SETERR_TOK (awk, QSE_AWK_ELPAREN);
|
SETERR_TOK (awk, QSE_AWK_ELPAREN);
|
||||||
qse_awk_freemem (awk, name.ptr);
|
goto oops;
|
||||||
return QSE_NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get the next token */
|
/* get the next token */
|
||||||
if (get_token(awk) <= -1)
|
if (get_token(awk) <= -1) goto oops;
|
||||||
{
|
|
||||||
qse_awk_freemem (awk, name.ptr);
|
|
||||||
return QSE_NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* make sure that parameter table is empty */
|
/* make sure that parameter table is empty */
|
||||||
QSE_ASSERT (QSE_ARR_SIZE(awk->parse.params) == 0);
|
QSE_ASSERT (QSE_ARR_SIZE(awk->parse.params) == 0);
|
||||||
@ -1255,11 +1248,7 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk)
|
|||||||
if (MATCH(awk,TOK_RPAREN))
|
if (MATCH(awk,TOK_RPAREN))
|
||||||
{
|
{
|
||||||
/* no function parameter found. get the next token */
|
/* no function parameter found. get the next token */
|
||||||
if (get_token(awk) <= -1)
|
if (get_token(awk) <= -1) goto oops;
|
||||||
{
|
|
||||||
qse_awk_freemem (awk, name.ptr);
|
|
||||||
return QSE_NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1268,12 +1257,26 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk)
|
|||||||
qse_char_t* pa;
|
qse_char_t* pa;
|
||||||
qse_size_t pal;
|
qse_size_t pal;
|
||||||
|
|
||||||
|
if (MATCH(awk, TOK_BAND))
|
||||||
|
{
|
||||||
|
/* pass-by-reference argument */
|
||||||
|
nargs = QSE_ARR_SIZE(awk->parse.params);
|
||||||
|
if (nargs >= argspeccapa)
|
||||||
|
{
|
||||||
|
qse_size_t i, newcapa = QSE_ALIGNTO_POW2(nargs + 1, 64);
|
||||||
|
argspec = qse_awk_reallocmem(awk, argspec, newcapa * QSE_SIZEOF(*argspec));
|
||||||
|
if (!argspec) goto oops;
|
||||||
|
for (i = argspeccapa; i < newcapa; i++) argspec[i] = QSE_T(' ');
|
||||||
|
argspeccapa = newcapa;
|
||||||
|
}
|
||||||
|
argspec[nargs] = QSE_T('r');
|
||||||
|
if (get_token(awk) <= -1) goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
if (!MATCH(awk,TOK_IDENT))
|
if (!MATCH(awk,TOK_IDENT))
|
||||||
{
|
{
|
||||||
qse_awk_freemem (awk, name.ptr);
|
|
||||||
qse_arr_clear (awk->parse.params);
|
|
||||||
SETERR_TOK (awk, QSE_AWK_EBADPAR);
|
SETERR_TOK (awk, QSE_AWK_EBADPAR);
|
||||||
return QSE_NULL;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
pa = QSE_STR_PTR(awk->tok.name);
|
pa = QSE_STR_PTR(awk->tok.name);
|
||||||
@ -1291,68 +1294,43 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk)
|
|||||||
* name or other parameters */
|
* name or other parameters */
|
||||||
if (((awk->opt.trait & QSE_AWK_STRICTNAMING) &&
|
if (((awk->opt.trait & QSE_AWK_STRICTNAMING) &&
|
||||||
qse_strxncmp (pa, pal, name.ptr, name.len) == 0) ||
|
qse_strxncmp (pa, pal, name.ptr, name.len) == 0) ||
|
||||||
qse_arr_search (awk->parse.params, 0, pa, pal) != QSE_ARR_NIL)
|
qse_arr_search(awk->parse.params, 0, pa, pal) != QSE_ARR_NIL)
|
||||||
{
|
{
|
||||||
qse_awk_freemem (awk, name.ptr);
|
SETERR_ARG_LOC (awk, QSE_AWK_EDUPPAR, pa, pal, &awk->tok.loc);
|
||||||
qse_arr_clear (awk->parse.params);
|
goto oops;
|
||||||
SETERR_ARG_LOC (
|
|
||||||
awk, QSE_AWK_EDUPPAR,
|
|
||||||
pa, pal, &awk->tok.loc);
|
|
||||||
return QSE_NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* push the parameter to the parameter list */
|
/* push the parameter to the parameter list */
|
||||||
if (QSE_ARR_SIZE(awk->parse.params) >= QSE_AWK_MAX_PARAMS)
|
if (QSE_ARR_SIZE(awk->parse.params) >= QSE_AWK_MAX_PARAMS)
|
||||||
{
|
{
|
||||||
qse_awk_freemem (awk, name.ptr);
|
|
||||||
qse_arr_clear (awk->parse.params);
|
|
||||||
SETERR_LOC (awk, QSE_AWK_EPARTM, &awk->tok.loc);
|
SETERR_LOC (awk, QSE_AWK_EPARTM, &awk->tok.loc);
|
||||||
return QSE_NULL;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qse_arr_insert(awk->parse.params, QSE_ARR_SIZE(awk->parse.params), pa, pal) == QSE_ARR_NIL)
|
if (qse_arr_insert(awk->parse.params, QSE_ARR_SIZE(awk->parse.params), pa, pal) == QSE_ARR_NIL)
|
||||||
{
|
{
|
||||||
qse_awk_freemem (awk, name.ptr);
|
|
||||||
qse_arr_clear (awk->parse.params);
|
|
||||||
SETERR_LOC (awk, QSE_AWK_ENOMEM, &awk->tok.loc);
|
SETERR_LOC (awk, QSE_AWK_ENOMEM, &awk->tok.loc);
|
||||||
return QSE_NULL;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_token (awk) <= -1)
|
if (get_token(awk) <= -1) goto oops;
|
||||||
{
|
|
||||||
qse_awk_freemem (awk, name.ptr);
|
|
||||||
qse_arr_clear (awk->parse.params);
|
|
||||||
return QSE_NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MATCH(awk,TOK_RPAREN)) break;
|
if (MATCH(awk,TOK_RPAREN)) break;
|
||||||
|
|
||||||
if (!MATCH(awk,TOK_COMMA))
|
if (!MATCH(awk,TOK_COMMA))
|
||||||
{
|
{
|
||||||
qse_awk_freemem (awk, name.ptr);
|
|
||||||
qse_arr_clear (awk->parse.params);
|
|
||||||
SETERR_TOK (awk, QSE_AWK_ECOMMA);
|
SETERR_TOK (awk, QSE_AWK_ECOMMA);
|
||||||
return QSE_NULL;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (get_token(awk) <= -1)
|
if (get_token(awk) <= -1) goto oops;
|
||||||
{
|
|
||||||
qse_awk_freemem (awk, name.ptr);
|
|
||||||
qse_arr_clear (awk->parse.params);
|
|
||||||
return QSE_NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
while (MATCH(awk,TOK_NEWLINE));
|
while (MATCH(awk,TOK_NEWLINE));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_token(awk) <= -1)
|
if (get_token(awk) <= -1) goto oops;
|
||||||
{
|
|
||||||
qse_awk_freemem (awk, name.ptr);
|
|
||||||
qse_arr_clear (awk->parse.params);
|
|
||||||
return QSE_NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* function body can be placed on a different line
|
/* function body can be placed on a different line
|
||||||
@ -1361,28 +1339,16 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk)
|
|||||||
* available only when the option is set. */
|
* available only when the option is set. */
|
||||||
while (MATCH(awk,TOK_NEWLINE))
|
while (MATCH(awk,TOK_NEWLINE))
|
||||||
{
|
{
|
||||||
if (get_token(awk) <= -1)
|
if (get_token(awk) <= -1) goto oops;
|
||||||
{
|
|
||||||
qse_awk_freemem (awk, name.ptr);
|
|
||||||
qse_arr_clear (awk->parse.params);
|
|
||||||
return QSE_NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if the function body starts with a left brace */
|
/* check if the function body starts with a left brace */
|
||||||
if (!MATCH(awk,TOK_LBRACE))
|
if (!MATCH(awk,TOK_LBRACE))
|
||||||
{
|
{
|
||||||
qse_awk_freemem (awk, name.ptr);
|
|
||||||
qse_arr_clear (awk->parse.params);
|
|
||||||
SETERR_TOK (awk, QSE_AWK_ELBRACE);
|
SETERR_TOK (awk, QSE_AWK_ELBRACE);
|
||||||
return QSE_NULL;
|
goto oops;
|
||||||
}
|
|
||||||
if (get_token(awk) <= -1)
|
|
||||||
{
|
|
||||||
qse_awk_freemem (awk, name.ptr);
|
|
||||||
qse_arr_clear (awk->parse.params);
|
|
||||||
return QSE_NULL;
|
|
||||||
}
|
}
|
||||||
|
if (get_token(awk) <= -1) goto oops;
|
||||||
|
|
||||||
/* remember the current function name so that the body parser
|
/* remember the current function name so that the body parser
|
||||||
* can know the name of the current function being parsed */
|
* can know the name of the current function being parsed */
|
||||||
@ -1391,18 +1357,13 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk)
|
|||||||
|
|
||||||
/* actual function body */
|
/* actual function body */
|
||||||
xloc = awk->ptok.loc;
|
xloc = awk->ptok.loc;
|
||||||
body = parse_block_dc (awk, &xloc, 1);
|
body = parse_block_dc(awk, &xloc, 1);
|
||||||
|
|
||||||
/* clear the current function name remembered */
|
/* clear the current function name remembered */
|
||||||
awk->tree.cur_fun.ptr = QSE_NULL;
|
awk->tree.cur_fun.ptr = QSE_NULL;
|
||||||
awk->tree.cur_fun.len = 0;
|
awk->tree.cur_fun.len = 0;
|
||||||
|
|
||||||
if (body == QSE_NULL)
|
if (!body) goto oops;
|
||||||
{
|
|
||||||
qse_awk_freemem (awk, name.ptr);
|
|
||||||
qse_arr_clear (awk->parse.params);
|
|
||||||
return QSE_NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: study furthur if the parameter names should be saved
|
/* TODO: study furthur if the parameter names should be saved
|
||||||
* for some reasons - might be needed for better deparsing output */
|
* for some reasons - might be needed for better deparsing output */
|
||||||
@ -1413,15 +1374,14 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk)
|
|||||||
fun = (qse_awk_fun_t*)qse_awk_callocmem(awk, QSE_SIZEOF(*fun));
|
fun = (qse_awk_fun_t*)qse_awk_callocmem(awk, QSE_SIZEOF(*fun));
|
||||||
if (fun == QSE_NULL)
|
if (fun == QSE_NULL)
|
||||||
{
|
{
|
||||||
qse_awk_freemem (awk, name.ptr);
|
|
||||||
qse_awk_clrpt (awk, body);
|
|
||||||
ADJERR_LOC (awk, &awk->tok.loc);
|
ADJERR_LOC (awk, &awk->tok.loc);
|
||||||
return QSE_NULL;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*fun->name.ptr = QSE_NULL;*/ /* function name is set below */
|
/*fun->name.ptr = QSE_NULL;*/ /* function name is set below */
|
||||||
fun->name.len = 0;
|
fun->name.len = 0;
|
||||||
fun->nargs = nargs;
|
fun->nargs = nargs;
|
||||||
|
fun->argspec = argspec;
|
||||||
fun->body = body;
|
fun->body = body;
|
||||||
|
|
||||||
pair = qse_htb_insert(awk->tree.funs, name.ptr, name.len, fun, 0);
|
pair = qse_htb_insert(awk->tree.funs, name.ptr, name.len, fun, 0);
|
||||||
@ -1430,11 +1390,8 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk)
|
|||||||
/* if qse_htb_insert() fails for other reasons than memory
|
/* if qse_htb_insert() fails for other reasons than memory
|
||||||
* shortage, there should be implementaion errors as duplicate
|
* shortage, there should be implementaion errors as duplicate
|
||||||
* functions are detected earlier in this function */
|
* functions are detected earlier in this function */
|
||||||
qse_awk_freemem (awk, name.ptr);
|
|
||||||
qse_awk_clrpt (awk, body);
|
|
||||||
qse_awk_freemem (awk, fun);
|
|
||||||
SETERR_LOC (awk, QSE_AWK_ENOMEM, &awk->tok.loc);
|
SETERR_LOC (awk, QSE_AWK_ENOMEM, &awk->tok.loc);
|
||||||
return QSE_NULL;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* do some trick to save a string. make it back-point at the key part
|
/* do some trick to save a string. make it back-point at the key part
|
||||||
@ -1446,6 +1403,14 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk)
|
|||||||
/* remove an undefined function call entry from the parse.fun table */
|
/* remove an undefined function call entry from the parse.fun table */
|
||||||
qse_htb_delete (awk->parse.funs, fun->name.ptr, name.len);
|
qse_htb_delete (awk->parse.funs, fun->name.ptr, name.len);
|
||||||
return body;
|
return body;
|
||||||
|
|
||||||
|
oops:
|
||||||
|
if (body) qse_awk_clrpt (awk, body);
|
||||||
|
if (argspec) qse_awk_freemem (awk, argspec);
|
||||||
|
if (fun) qse_awk_freemem (awk, fun);
|
||||||
|
qse_awk_freemem (awk, name.ptr);
|
||||||
|
qse_arr_clear (awk->parse.params);
|
||||||
|
return QSE_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static qse_awk_nde_t* parse_begin (qse_awk_t* awk)
|
static qse_awk_nde_t* parse_begin (qse_awk_t* awk)
|
||||||
@ -5109,7 +5074,6 @@ static qse_awk_nde_t* parse_fun_as_value (qse_awk_t* awk, const qse_cstr_t* nam
|
|||||||
nde->name.len = name->len;
|
nde->name.len = name->len;
|
||||||
nde->funptr = funptr;
|
nde->funptr = funptr;
|
||||||
|
|
||||||
|
|
||||||
return (qse_awk_nde_t*)nde;
|
return (qse_awk_nde_t*)nde;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -6690,10 +6654,10 @@ static int deparse (qse_awk_t* awk)
|
|||||||
|
|
||||||
if (awk->opt.trait & QSE_AWK_CRLF)
|
if (awk->opt.trait & QSE_AWK_CRLF)
|
||||||
{
|
{
|
||||||
if (put_char (awk, QSE_T('\r')) <= -1) EXIT_DEPARSE ();
|
if (put_char(awk, QSE_T('\r')) <= -1) EXIT_DEPARSE ();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (put_char (awk, QSE_T('\n')) <= -1) EXIT_DEPARSE ();
|
if (put_char(awk, QSE_T('\n')) <= -1) EXIT_DEPARSE ();
|
||||||
}
|
}
|
||||||
|
|
||||||
chain = awk->tree.chain;
|
chain = awk->tree.chain;
|
||||||
@ -6701,7 +6665,7 @@ static int deparse (qse_awk_t* awk)
|
|||||||
{
|
{
|
||||||
if (chain->pattern != QSE_NULL)
|
if (chain->pattern != QSE_NULL)
|
||||||
{
|
{
|
||||||
if (qse_awk_prnptnpt (awk, chain->pattern) <= -1) EXIT_DEPARSE ();
|
if (qse_awk_prnptnpt(awk, chain->pattern) <= -1) EXIT_DEPARSE ();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chain->action == QSE_NULL)
|
if (chain->action == QSE_NULL)
|
||||||
@ -6709,26 +6673,26 @@ static int deparse (qse_awk_t* awk)
|
|||||||
/* blockless pattern */
|
/* blockless pattern */
|
||||||
if (awk->opt.trait & QSE_AWK_CRLF)
|
if (awk->opt.trait & QSE_AWK_CRLF)
|
||||||
{
|
{
|
||||||
if (put_char (awk, QSE_T('\r')) <= -1) EXIT_DEPARSE ();
|
if (put_char(awk, QSE_T('\r')) <= -1) EXIT_DEPARSE ();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (put_char (awk, QSE_T('\n')) <= -1) EXIT_DEPARSE ();
|
if (put_char(awk, QSE_T('\n')) <= -1) EXIT_DEPARSE ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (chain->pattern != QSE_NULL)
|
if (chain->pattern != QSE_NULL)
|
||||||
{
|
{
|
||||||
if (put_char (awk, QSE_T(' ')) <= -1) EXIT_DEPARSE ();
|
if (put_char(awk, QSE_T(' ')) <= -1) EXIT_DEPARSE ();
|
||||||
}
|
}
|
||||||
if (qse_awk_prnpt (awk, chain->action) <= -1) EXIT_DEPARSE ();
|
if (qse_awk_prnpt(awk, chain->action) <= -1) EXIT_DEPARSE ();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (awk->opt.trait & QSE_AWK_CRLF)
|
if (awk->opt.trait & QSE_AWK_CRLF)
|
||||||
{
|
{
|
||||||
if (put_char (awk, QSE_T('\r')) <= -1) EXIT_DEPARSE ();
|
if (put_char(awk, QSE_T('\r')) <= -1) EXIT_DEPARSE ();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (put_char (awk, QSE_T('\n')) <= -1) EXIT_DEPARSE ();
|
if (put_char(awk, QSE_T('\n')) <= -1) EXIT_DEPARSE ();
|
||||||
|
|
||||||
chain = chain->next;
|
chain = chain->next;
|
||||||
}
|
}
|
||||||
@ -6739,9 +6703,9 @@ static int deparse (qse_awk_t* awk)
|
|||||||
|
|
||||||
qse_awk_getkwname (awk, QSE_AWK_KWID_END, &kw);
|
qse_awk_getkwname (awk, QSE_AWK_KWID_END, &kw);
|
||||||
|
|
||||||
if (qse_awk_putsrcstrn (awk, kw.ptr, kw.len) <= -1) EXIT_DEPARSE ();
|
if (qse_awk_putsrcstrn(awk, kw.ptr, kw.len) <= -1) EXIT_DEPARSE ();
|
||||||
if (qse_awk_putsrcstr (awk, QSE_T(" ")) <= -1) EXIT_DEPARSE ();
|
if (qse_awk_putsrcstr(awk, QSE_T(" ")) <= -1) EXIT_DEPARSE ();
|
||||||
if (qse_awk_prnnde (awk, nde) <= -1) EXIT_DEPARSE ();
|
if (qse_awk_prnnde(awk, nde) <= -1) EXIT_DEPARSE ();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (awk->opt.trait & QSE_AWK_CRLF)
|
if (awk->opt.trait & QSE_AWK_CRLF)
|
||||||
@ -6802,9 +6766,8 @@ static qse_htb_walk_t deparse_func (qse_htb_t* map, qse_htb_pair_t* pair, void*
|
|||||||
|
|
||||||
for (i = 0; i < fun->nargs; )
|
for (i = 0; i < fun->nargs; )
|
||||||
{
|
{
|
||||||
n = qse_awk_inttostr (
|
if (fun->argspec && fun->argspec[i] == 'r') PUT_S (df, QSE_T("&"));
|
||||||
df->awk, i++, 10,
|
n = qse_awk_inttostr (df->awk, i++, 10, QSE_T("__p"), df->tmp, df->tmp_len);
|
||||||
QSE_T("__p"), df->tmp, df->tmp_len);
|
|
||||||
QSE_ASSERT (n != (qse_size_t)-1);
|
QSE_ASSERT (n != (qse_size_t)-1);
|
||||||
PUT_SX (df, df->tmp, n);
|
PUT_SX (df, df->tmp, n);
|
||||||
|
|
||||||
@ -6817,7 +6780,7 @@ static qse_htb_walk_t deparse_func (qse_htb_t* map, qse_htb_pair_t* pair, void*
|
|||||||
|
|
||||||
PUT_C (df, QSE_T('\n'));
|
PUT_C (df, QSE_T('\n'));
|
||||||
|
|
||||||
if (qse_awk_prnpt (df->awk, fun->body) <= -1) return -1;
|
if (qse_awk_prnpt(df->awk, fun->body) <= -1) return -1;
|
||||||
if (df->awk->opt.trait & QSE_AWK_CRLF)
|
if (df->awk->opt.trait & QSE_AWK_CRLF)
|
||||||
{
|
{
|
||||||
PUT_C (df, QSE_T('\r'));
|
PUT_C (df, QSE_T('\r'));
|
||||||
|
@ -110,8 +110,8 @@ struct pafv
|
|||||||
|
|
||||||
#define ADJERR_LOC(rtx,l) do { (rtx)->errinf.loc = *(l); } while (0)
|
#define ADJERR_LOC(rtx,l) do { (rtx)->errinf.loc = *(l); } while (0)
|
||||||
|
|
||||||
static qse_size_t push_arg_from_vals (
|
static qse_size_t push_arg_from_vals (qse_awk_rtx_t* rtx, qse_awk_nde_fncall_t* call, void* data);
|
||||||
qse_awk_rtx_t* rtx, qse_awk_nde_fncall_t* call, void* data);
|
static qse_size_t push_arg_from_nde (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 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);
|
static void fini_rtx (qse_awk_rtx_t* rtx, int fini_globals);
|
||||||
@ -192,27 +192,21 @@ static qse_awk_val_t* eval_incpre (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde);
|
|||||||
static qse_awk_val_t* eval_incpst (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde);
|
static qse_awk_val_t* eval_incpst (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde);
|
||||||
static qse_awk_val_t* eval_cnd (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde);
|
static qse_awk_val_t* eval_cnd (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde);
|
||||||
|
|
||||||
static qse_awk_val_t* eval_fncall_fncall_fun_ex (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde, void(*errhandler)(void*), void* eharg);
|
static qse_awk_val_t* eval_fncall_fun_ex (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde, void(*errhandler)(void*), void* eharg);
|
||||||
|
|
||||||
static qse_awk_val_t* eval_fncall_fnc (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde);
|
static qse_awk_val_t* eval_fncall_fnc (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde);
|
||||||
static qse_awk_val_t* eval_fncall_fncall_fun (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde);
|
static qse_awk_val_t* eval_fncall_fun (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde);
|
||||||
static qse_awk_val_t* eval_fncall_var (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde);
|
static qse_awk_val_t* eval_fncall_var (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde);
|
||||||
|
|
||||||
static qse_awk_val_t* __eval_call (
|
static qse_awk_val_t* __eval_call (
|
||||||
qse_awk_rtx_t* rtx,
|
qse_awk_rtx_t* rtx,
|
||||||
qse_awk_nde_t* nde,
|
qse_awk_nde_t* nde,
|
||||||
const qse_char_t* fnc_arg_spec,
|
|
||||||
qse_awk_fun_t* fun,
|
qse_awk_fun_t* fun,
|
||||||
qse_size_t(*argpusher)(qse_awk_rtx_t*,qse_awk_nde_fncall_t*,void*),
|
qse_size_t(*argpusher)(qse_awk_rtx_t*,qse_awk_nde_fncall_t*,void*),
|
||||||
void* apdata,
|
void* apdata, /* data to argpusher */
|
||||||
void(*errhandler)(void*),
|
void(*errhandler)(void*),
|
||||||
void* eharg);
|
void* eharg);
|
||||||
|
|
||||||
static qse_awk_val_t* eval_call (
|
|
||||||
qse_awk_rtx_t* rtx, qse_awk_nde_t* nde,
|
|
||||||
const qse_char_t* fnc_arg_spec, qse_awk_fun_t* fun,
|
|
||||||
void(*errhandler)(void*), void* eharg);
|
|
||||||
|
|
||||||
static int get_reference (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde, qse_awk_val_t*** ref);
|
static int get_reference (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde, qse_awk_val_t*** ref);
|
||||||
static qse_awk_val_t** get_reference_indexed (qse_awk_rtx_t* rtx, qse_awk_nde_var_t* nde, qse_awk_val_t** val);
|
static qse_awk_val_t** get_reference_indexed (qse_awk_rtx_t* rtx, qse_awk_nde_var_t* nde, qse_awk_val_t** val);
|
||||||
|
|
||||||
@ -1557,6 +1551,14 @@ qse_awk_val_t* qse_awk_rtx_callfun (qse_awk_rtx_t* rtx, qse_awk_fun_t* fun, qse_
|
|||||||
}
|
}
|
||||||
/*rtx->exit_level = EXIT_NONE;*/
|
/*rtx->exit_level = EXIT_NONE;*/
|
||||||
|
|
||||||
|
if (fun->argspec)
|
||||||
|
{
|
||||||
|
/* this function contains call-by-reference parameters.
|
||||||
|
* i don't support the call here as it requires variables */
|
||||||
|
qse_awk_rtx_seterrfmt (rtx, QSE_AWK_EPERM, QSE_NULL, QSE_T("not allowed to call '%.*js' with call-by-reference parameters"), (int)fun->name.len, fun->name.ptr);
|
||||||
|
return QSE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* forge a fake node containing a function call */
|
/* forge a fake node containing a function call */
|
||||||
QSE_MEMSET (&call, 0, QSE_SIZEOF(call));
|
QSE_MEMSET (&call, 0, QSE_SIZEOF(call));
|
||||||
call.type = QSE_AWK_NDE_FNCALL_FUN;
|
call.type = QSE_AWK_NDE_FNCALL_FUN;
|
||||||
@ -1577,12 +1579,7 @@ qse_awk_val_t* qse_awk_rtx_callfun (qse_awk_rtx_t* rtx, qse_awk_fun_t* fun, qse_
|
|||||||
crdata.rtx = rtx;
|
crdata.rtx = rtx;
|
||||||
crdata.val = QSE_NULL;
|
crdata.val = QSE_NULL;
|
||||||
|
|
||||||
v = __eval_call (
|
v = __eval_call(rtx, (qse_awk_nde_t*)&call, fun, push_arg_from_vals, (void*)&pafv, capture_retval_on_exit, &crdata);
|
||||||
rtx, (qse_awk_nde_t*)&call, QSE_NULL, fun,
|
|
||||||
push_arg_from_vals, (void*)&pafv,
|
|
||||||
capture_retval_on_exit,
|
|
||||||
&crdata
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!v)
|
if (!v)
|
||||||
{
|
{
|
||||||
@ -1606,32 +1603,28 @@ qse_awk_val_t* qse_awk_rtx_callfun (qse_awk_rtx_t* rtx, qse_awk_fun_t* fun, qse_
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* call an AWK function by name */
|
/* call an AWK function by name */
|
||||||
qse_awk_val_t* qse_awk_rtx_call (
|
qse_awk_val_t* qse_awk_rtx_call (qse_awk_rtx_t* rtx, const qse_char_t* name, qse_awk_val_t* args[], qse_size_t nargs)
|
||||||
qse_awk_rtx_t* rtx, const qse_char_t* name,
|
|
||||||
qse_awk_val_t* args[], qse_size_t nargs)
|
|
||||||
{
|
{
|
||||||
qse_awk_fun_t* fun;
|
qse_awk_fun_t* fun;
|
||||||
|
|
||||||
fun = qse_awk_rtx_findfun (rtx, name);
|
fun = qse_awk_rtx_findfun(rtx, name);
|
||||||
if (fun == QSE_NULL) return QSE_NULL;
|
if (!fun) return QSE_NULL;
|
||||||
|
|
||||||
return qse_awk_rtx_callfun (rtx, fun, args, nargs);
|
return qse_awk_rtx_callfun(rtx, fun, args, nargs);
|
||||||
}
|
}
|
||||||
|
|
||||||
qse_awk_val_t* qse_awk_rtx_callwithstrs (
|
qse_awk_val_t* qse_awk_rtx_callwithstrs (qse_awk_rtx_t* rtx, const qse_char_t* name, const qse_char_t* args[], qse_size_t nargs)
|
||||||
qse_awk_rtx_t* rtx, const qse_char_t* name,
|
|
||||||
const qse_char_t* args[], qse_size_t nargs)
|
|
||||||
{
|
{
|
||||||
qse_size_t i;
|
qse_size_t i;
|
||||||
qse_awk_val_t** v, * ret;
|
qse_awk_val_t** v, * ret;
|
||||||
|
|
||||||
v = qse_awk_rtx_allocmem (rtx, QSE_SIZEOF(*v) * nargs);
|
v = qse_awk_rtx_allocmem (rtx, QSE_SIZEOF(*v) * nargs);
|
||||||
if (v == QSE_NULL) return QSE_NULL;
|
if (!v) return QSE_NULL;
|
||||||
|
|
||||||
for (i = 0; i < nargs; i++)
|
for (i = 0; i < nargs; i++)
|
||||||
{
|
{
|
||||||
v[i] = qse_awk_rtx_makestrvalwithstr (rtx, args[i]);
|
v[i] = qse_awk_rtx_makestrvalwithstr (rtx, args[i]);
|
||||||
if (v[i] == QSE_NULL)
|
if (!v[i])
|
||||||
{
|
{
|
||||||
ret = QSE_NULL;
|
ret = QSE_NULL;
|
||||||
goto oops;
|
goto oops;
|
||||||
@ -1640,7 +1633,7 @@ qse_awk_val_t* qse_awk_rtx_callwithstrs (
|
|||||||
qse_awk_rtx_refupval (rtx, v[i]);
|
qse_awk_rtx_refupval (rtx, v[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = qse_awk_rtx_call (rtx, name, v, nargs);
|
ret = qse_awk_rtx_call(rtx, name, v, nargs);
|
||||||
|
|
||||||
oops:
|
oops:
|
||||||
while (i > 0)
|
while (i > 0)
|
||||||
@ -2225,14 +2218,12 @@ struct foreach_walker_t
|
|||||||
int ret;
|
int ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
static qse_htb_walk_t walk_foreach (
|
static qse_htb_walk_t walk_foreach (qse_htb_t* map, qse_htb_pair_t* pair, void* arg)
|
||||||
qse_htb_t* map, qse_htb_pair_t* pair, void* arg)
|
|
||||||
{
|
{
|
||||||
struct foreach_walker_t* w = (struct foreach_walker_t*)arg;
|
struct foreach_walker_t* w = (struct foreach_walker_t*)arg;
|
||||||
qse_awk_val_t* str;
|
qse_awk_val_t* str;
|
||||||
|
|
||||||
str = (qse_awk_val_t*) qse_awk_rtx_makestrval (
|
str = (qse_awk_val_t*)qse_awk_rtx_makestrval(w->rtx, QSE_HTB_KPTR(pair), QSE_HTB_KLEN(pair));
|
||||||
w->rtx, QSE_HTB_KPTR(pair), QSE_HTB_KLEN(pair));
|
|
||||||
if (str == QSE_NULL)
|
if (str == QSE_NULL)
|
||||||
{
|
{
|
||||||
ADJERR_LOC (w->rtx, &w->var->loc);
|
ADJERR_LOC (w->rtx, &w->var->loc);
|
||||||
@ -2241,14 +2232,14 @@ static qse_htb_walk_t walk_foreach (
|
|||||||
}
|
}
|
||||||
|
|
||||||
qse_awk_rtx_refupval (w->rtx, str);
|
qse_awk_rtx_refupval (w->rtx, str);
|
||||||
if (do_assignment (w->rtx, w->var, str) == QSE_NULL)
|
if (do_assignment(w->rtx, w->var, str) == QSE_NULL)
|
||||||
{
|
{
|
||||||
qse_awk_rtx_refdownval (w->rtx, str);
|
qse_awk_rtx_refdownval (w->rtx, str);
|
||||||
w->ret = -1;
|
w->ret = -1;
|
||||||
return QSE_HTB_WALK_STOP;
|
return QSE_HTB_WALK_STOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (run_statement (w->rtx, w->body) == -1)
|
if (run_statement(w->rtx, w->body) == -1)
|
||||||
{
|
{
|
||||||
qse_awk_rtx_refdownval (w->rtx, str);
|
qse_awk_rtx_refdownval (w->rtx, str);
|
||||||
w->ret = -1;
|
w->ret = -1;
|
||||||
@ -2283,19 +2274,17 @@ static int run_foreach (qse_awk_rtx_t* rtx, qse_awk_nde_foreach_t* nde)
|
|||||||
qse_awk_val_type_t rvtype;
|
qse_awk_val_type_t rvtype;
|
||||||
|
|
||||||
test = (qse_awk_nde_exp_t*)nde->test;
|
test = (qse_awk_nde_exp_t*)nde->test;
|
||||||
QSE_ASSERT (
|
QSE_ASSERT (test->type == QSE_AWK_NDE_EXP_BIN && test->opcode == QSE_AWK_BINOP_IN);
|
||||||
test->type == QSE_AWK_NDE_EXP_BIN &&
|
|
||||||
test->opcode == QSE_AWK_BINOP_IN);
|
|
||||||
|
|
||||||
/* chained expressions should not be allowed
|
/* chained expressions should not be allowed
|
||||||
* by the parser first of all */
|
* by the parser first of all */
|
||||||
QSE_ASSERT (test->right->next == QSE_NULL);
|
QSE_ASSERT (test->right->next == QSE_NULL);
|
||||||
|
|
||||||
rv = eval_expression (rtx, test->right);
|
rv = eval_expression(rtx, test->right);
|
||||||
if (rv == QSE_NULL) return -1;
|
if (rv == QSE_NULL) return -1;
|
||||||
|
|
||||||
qse_awk_rtx_refupval (rtx, rv);
|
qse_awk_rtx_refupval (rtx, rv);
|
||||||
rvtype = QSE_AWK_RTX_GETVALTYPE (rtx, rv);
|
rvtype = QSE_AWK_RTX_GETVALTYPE(rtx, rv);
|
||||||
if (rvtype == QSE_AWK_VAL_NIL)
|
if (rvtype == QSE_AWK_VAL_NIL)
|
||||||
{
|
{
|
||||||
/* just return without excuting the loop body */
|
/* just return without excuting the loop body */
|
||||||
@ -3256,7 +3245,7 @@ static qse_awk_val_t* eval_expression0 (qse_awk_rtx_t* run, qse_awk_nde_t* nde)
|
|||||||
eval_incpst,
|
eval_incpst,
|
||||||
eval_cnd,
|
eval_cnd,
|
||||||
eval_fncall_fnc,
|
eval_fncall_fnc,
|
||||||
eval_fncall_fncall_fun,
|
eval_fncall_fun,
|
||||||
eval_fncall_var,
|
eval_fncall_var,
|
||||||
eval_int,
|
eval_int,
|
||||||
eval_flt,
|
eval_flt,
|
||||||
@ -3424,7 +3413,7 @@ static qse_awk_val_t* do_assignment (qse_awk_rtx_t* rtx, qse_awk_nde_t* var, qse
|
|||||||
case QSE_AWK_NDE_GBL:
|
case QSE_AWK_NDE_GBL:
|
||||||
case QSE_AWK_NDE_LCL:
|
case QSE_AWK_NDE_LCL:
|
||||||
case QSE_AWK_NDE_ARG:
|
case QSE_AWK_NDE_ARG:
|
||||||
ret = do_assignment_nonidx (rtx, (qse_awk_nde_var_t*)var, val);
|
ret = do_assignment_nonidx(rtx, (qse_awk_nde_var_t*)var, val);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QSE_AWK_NDE_NAMEDIDX:
|
case QSE_AWK_NDE_NAMEDIDX:
|
||||||
@ -3438,7 +3427,7 @@ static qse_awk_val_t* do_assignment (qse_awk_rtx_t* rtx, qse_awk_nde_t* var, qse
|
|||||||
goto exit_on_error;
|
goto exit_on_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = do_assignment_idx (rtx, (qse_awk_nde_var_t*)var, val);
|
ret = do_assignment_idx(rtx, (qse_awk_nde_var_t*)var, val);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QSE_AWK_NDE_POS:
|
case QSE_AWK_NDE_POS:
|
||||||
@ -3449,7 +3438,7 @@ static qse_awk_val_t* do_assignment (qse_awk_rtx_t* rtx, qse_awk_nde_t* var, qse
|
|||||||
goto exit_on_error;
|
goto exit_on_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = do_assignment_pos (rtx, (qse_awk_nde_pos_t*)var, val);
|
ret = do_assignment_pos(rtx, (qse_awk_nde_pos_t*)var, val);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -3506,9 +3495,7 @@ static qse_awk_val_t* do_assignment_nonidx (qse_awk_rtx_t* run, qse_awk_nde_var_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (qse_htb_upsert (run->named, var->id.name.ptr, var->id.name.len, val, 0) == 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);
|
SETERR_LOC (run, QSE_AWK_ENOMEM, &var->loc);
|
||||||
return QSE_NULL;
|
return QSE_NULL;
|
||||||
@ -3579,7 +3566,7 @@ static qse_awk_val_t* do_assignment_nonidx (qse_awk_rtx_t* run, qse_awk_nde_var_
|
|||||||
return QSE_NULL;
|
return QSE_NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qse_awk_rtx_refdownval (run, old);
|
qse_awk_rtx_refdownval (run, old);
|
||||||
RTX_STACK_ARG(run,var->id.idxa) = val;
|
RTX_STACK_ARG(run,var->id.idxa) = val;
|
||||||
qse_awk_rtx_refupval (run, val);
|
qse_awk_rtx_refupval (run, val);
|
||||||
@ -5748,31 +5735,47 @@ static qse_awk_val_t* eval_cnd (qse_awk_rtx_t* run, qse_awk_nde_t* nde)
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static qse_awk_val_t* eval_fncall_fnc (qse_awk_rtx_t* run, qse_awk_nde_t* nde)
|
static qse_awk_val_t* eval_fncall_fnc (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde)
|
||||||
{
|
{
|
||||||
/* intrinsic function */
|
/* intrinsic function */
|
||||||
qse_awk_nde_fncall_t* call = (qse_awk_nde_fncall_t*)nde;
|
qse_awk_nde_fncall_t* call = (qse_awk_nde_fncall_t*)nde;
|
||||||
/* the parser must make sure taht the number of arguments
|
/* the parser must make sure that the number of arguments is proper */
|
||||||
* is proper */
|
|
||||||
QSE_ASSERT (call->nargs >= call->u.fnc.spec.arg.min && call->nargs <= call->u.fnc.spec.arg.max);
|
QSE_ASSERT (call->nargs >= call->u.fnc.spec.arg.min && call->nargs <= call->u.fnc.spec.arg.max);
|
||||||
return eval_call(run, nde, call->u.fnc.spec.arg.spec, QSE_NULL, QSE_NULL, QSE_NULL);
|
return __eval_call(rtx, nde, QSE_NULL, push_arg_from_nde, (void*)call->u.fnc.spec.arg.spec, QSE_NULL, QSE_NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static QSE_INLINE qse_awk_val_t* eval_fncall_fncall_fun_ex (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde, void(*errhandler)(void*), void* eharg)
|
static QSE_INLINE qse_awk_val_t* eval_fncall_fun_ex (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde, void(*errhandler)(void*), void* eharg)
|
||||||
{
|
{
|
||||||
qse_awk_nde_fncall_t* call = (qse_awk_nde_fncall_t*)nde;
|
qse_awk_nde_fncall_t* call = (qse_awk_nde_fncall_t*)nde;
|
||||||
qse_awk_fun_t* fun;
|
qse_awk_fun_t* fun;
|
||||||
qse_htb_pair_t* pair;
|
qse_htb_pair_t* pair;
|
||||||
|
|
||||||
pair = qse_htb_search(rtx->awk->tree.funs, call->u.fun.name.ptr, call->u.fun.name.len);
|
if (!call->u.fun.fun)
|
||||||
if (pair == QSE_NULL)
|
|
||||||
{
|
{
|
||||||
SETERR_ARGX_LOC (rtx, QSE_AWK_EFUNNF, &call->u.fun.name, &nde->loc);
|
/* there can be multiple runtime instances for a single awk object.
|
||||||
return QSE_NULL;
|
* changing the parse tree from one runtime instance can affect
|
||||||
}
|
* other instances. however i do change the parse tree without protection
|
||||||
|
* hoping that the pointer assignment is atomic. (call->u.fun.fun = fun).
|
||||||
|
* i don't mind each instance performs a search duplicately for a short while */
|
||||||
|
|
||||||
fun = (qse_awk_fun_t*)QSE_HTB_VPTR(pair);
|
pair = qse_htb_search(rtx->awk->tree.funs, call->u.fun.name.ptr, call->u.fun.name.len);
|
||||||
QSE_ASSERT (fun != QSE_NULL);
|
if (!pair)
|
||||||
|
{
|
||||||
|
SETERR_ARGX_LOC (rtx, QSE_AWK_EFUNNF, &call->u.fun.name, &nde->loc);
|
||||||
|
return QSE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun = (qse_awk_fun_t*)QSE_HTB_VPTR(pair);
|
||||||
|
QSE_ASSERT (fun != QSE_NULL);
|
||||||
|
|
||||||
|
/* cache the search result */
|
||||||
|
call->u.fun.fun = fun;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* use the cached function */
|
||||||
|
fun = call->u.fun.fun;
|
||||||
|
}
|
||||||
|
|
||||||
if (call->nargs > fun->nargs)
|
if (call->nargs > fun->nargs)
|
||||||
{
|
{
|
||||||
@ -5782,12 +5785,12 @@ static QSE_INLINE qse_awk_val_t* eval_fncall_fncall_fun_ex (qse_awk_rtx_t* rtx,
|
|||||||
return QSE_NULL;
|
return QSE_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return eval_call(rtx, nde, QSE_NULL, fun, errhandler, eharg);
|
return __eval_call(rtx, nde, fun, push_arg_from_nde, QSE_NULL, errhandler, eharg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static qse_awk_val_t* eval_fncall_fncall_fun (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde)
|
static qse_awk_val_t* eval_fncall_fun (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde)
|
||||||
{
|
{
|
||||||
return eval_fncall_fncall_fun_ex(rtx, nde, QSE_NULL, QSE_NULL);
|
return eval_fncall_fun_ex(rtx, nde, QSE_NULL, QSE_NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static qse_awk_val_t* eval_fncall_var (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde)
|
static qse_awk_val_t* eval_fncall_var (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde)
|
||||||
@ -5806,7 +5809,8 @@ static qse_awk_val_t* eval_fncall_var (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rv = eval_call(rtx, nde, QSE_NULL, ((qse_awk_val_fun_t*)fv)->fun, QSE_NULL, QSE_NULL);
|
qse_awk_fun_t* fun = ((qse_awk_val_fun_t*)fv)->fun;
|
||||||
|
rv = __eval_call(rtx, nde, fun, push_arg_from_nde, QSE_NULL, QSE_NULL, QSE_NULL);
|
||||||
}
|
}
|
||||||
qse_awk_rtx_refdownval (rtx, fv);
|
qse_awk_rtx_refdownval (rtx, fv);
|
||||||
|
|
||||||
@ -5841,14 +5845,9 @@ static qse_awk_val_t* eval_fncall_var (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde)
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static qse_awk_val_t* __eval_call (
|
static qse_awk_val_t* __eval_call (
|
||||||
qse_awk_rtx_t* run,
|
qse_awk_rtx_t* rtx, qse_awk_nde_t* nde, qse_awk_fun_t* fun,
|
||||||
qse_awk_nde_t* nde,
|
qse_size_t(*argpusher)(qse_awk_rtx_t*,qse_awk_nde_fncall_t*,void*), void* apdata,
|
||||||
const qse_char_t* fnc_arg_spec,
|
void(*errhandler)(void*), void* eharg)
|
||||||
qse_awk_fun_t* fun,
|
|
||||||
qse_size_t(*argpusher)(qse_awk_rtx_t*,qse_awk_nde_fncall_t*,void*),
|
|
||||||
void* apdata,
|
|
||||||
void(*errhandler)(void*),
|
|
||||||
void* eharg)
|
|
||||||
{
|
{
|
||||||
qse_awk_nde_fncall_t* call = (qse_awk_nde_fncall_t*)nde;
|
qse_awk_nde_fncall_t* call = (qse_awk_nde_fncall_t*)nde;
|
||||||
qse_size_t saved_stack_top;
|
qse_size_t saved_stack_top;
|
||||||
@ -5896,68 +5895,67 @@ static qse_awk_val_t* __eval_call (
|
|||||||
* ---------------------
|
* ---------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
QSE_ASSERT (QSE_SIZEOF(void*) >= QSE_SIZEOF(run->stack_top));
|
QSE_ASSERT (QSE_SIZEOF(void*) >= QSE_SIZEOF(rtx->stack_top));
|
||||||
QSE_ASSERT (QSE_SIZEOF(void*) >= QSE_SIZEOF(run->stack_base));
|
QSE_ASSERT (QSE_SIZEOF(void*) >= QSE_SIZEOF(rtx->stack_base));
|
||||||
|
|
||||||
saved_stack_top = run->stack_top;
|
saved_stack_top = rtx->stack_top;
|
||||||
|
|
||||||
#ifdef DEBUG_RUN
|
#ifdef DEBUG_RUN
|
||||||
qse_errputstrf (QSE_T("setting up function stack frame top=%zd base=%zd\n"),
|
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_size_t)run->stack_top, (qse_size_t)run->stack_base);
|
|
||||||
#endif
|
#endif
|
||||||
if (__raw_push(run,(void*)run->stack_base) == -1)
|
if (__raw_push(rtx,(void*)rtx->stack_base) == -1)
|
||||||
{
|
{
|
||||||
SETERR_LOC (run, QSE_AWK_ENOMEM, &nde->loc);
|
SETERR_LOC (rtx, QSE_AWK_ENOMEM, &nde->loc);
|
||||||
return QSE_NULL;
|
return QSE_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (__raw_push(run,(void*)saved_stack_top) == -1)
|
if (__raw_push(rtx,(void*)saved_stack_top) == -1)
|
||||||
{
|
{
|
||||||
__raw_pop (run);
|
__raw_pop (rtx);
|
||||||
SETERR_LOC (run, QSE_AWK_ENOMEM, &nde->loc);
|
SETERR_LOC (rtx, QSE_AWK_ENOMEM, &nde->loc);
|
||||||
return QSE_NULL;
|
return QSE_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* secure space for a return value. */
|
/* secure space for a return value. */
|
||||||
if (__raw_push(run,qse_awk_val_nil) == -1)
|
if (__raw_push(rtx,qse_awk_val_nil) == -1)
|
||||||
{
|
{
|
||||||
__raw_pop (run);
|
__raw_pop (rtx);
|
||||||
__raw_pop (run);
|
__raw_pop (rtx);
|
||||||
SETERR_LOC (run, QSE_AWK_ENOMEM, &nde->loc);
|
SETERR_LOC (rtx, QSE_AWK_ENOMEM, &nde->loc);
|
||||||
return QSE_NULL;
|
return QSE_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* secure space for nargs */
|
/* secure space for nargs */
|
||||||
if (__raw_push(run,qse_awk_val_nil) == -1)
|
if (__raw_push(rtx,qse_awk_val_nil) == -1)
|
||||||
{
|
{
|
||||||
__raw_pop (run);
|
__raw_pop (rtx);
|
||||||
__raw_pop (run);
|
__raw_pop (rtx);
|
||||||
__raw_pop (run);
|
__raw_pop (rtx);
|
||||||
SETERR_LOC (run, QSE_AWK_ENOMEM, &nde->loc);
|
SETERR_LOC (rtx, QSE_AWK_ENOMEM, &nde->loc);
|
||||||
return QSE_NULL;
|
return QSE_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* push all arguments onto the stack */
|
/* push all arguments onto the stack */
|
||||||
nargs = argpusher(run, call, apdata);
|
nargs = argpusher(rtx, call, apdata);
|
||||||
if (nargs == (qse_size_t)-1)
|
if (nargs == (qse_size_t)-1)
|
||||||
{
|
{
|
||||||
UNWIND_RTX_STACK_BASE (run);
|
UNWIND_RTX_STACK_BASE (rtx);
|
||||||
return QSE_NULL;
|
return QSE_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSE_ASSERT (nargs == call->nargs);
|
QSE_ASSERT (nargs == call->nargs);
|
||||||
|
|
||||||
if (fun != QSE_NULL)
|
if (fun)
|
||||||
{
|
{
|
||||||
/* extra step for normal awk functions */
|
/* extra step for normal awk functions */
|
||||||
|
|
||||||
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 */
|
||||||
if (__raw_push(run,qse_awk_val_nil) == -1)
|
if (__raw_push(rtx,qse_awk_val_nil) == -1)
|
||||||
{
|
{
|
||||||
UNWIND_RTX_STACK (run, nargs);
|
UNWIND_RTX_STACK (rtx, nargs);
|
||||||
SETERR_LOC (run, QSE_AWK_ENOMEM, &nde->loc);
|
SETERR_LOC (rtx, QSE_AWK_ENOMEM, &nde->loc);
|
||||||
return QSE_NULL;
|
return QSE_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5965,18 +5963,18 @@ static qse_awk_val_t* __eval_call (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
run->stack_base = saved_stack_top;
|
rtx->stack_base = saved_stack_top;
|
||||||
RTX_STACK_NARGS(run) = (void*)nargs;
|
RTX_STACK_NARGS(rtx) = (void*)nargs;
|
||||||
|
|
||||||
#ifdef DEBUG_RUN
|
#ifdef DEBUG_RUN
|
||||||
qse_errputstrf (QSE_T("running function body\n"));
|
qse_errputstrf (QSE_T("rtxning function body\n"));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (fun != QSE_NULL)
|
if (fun)
|
||||||
{
|
{
|
||||||
/* normal awk function */
|
/* normal awk function */
|
||||||
QSE_ASSERT (fun->body->type == QSE_AWK_NDE_BLK);
|
QSE_ASSERT (fun->body->type == QSE_AWK_NDE_BLK);
|
||||||
n = run_block(run,(qse_awk_nde_blk_t*)fun->body);
|
n = run_block(rtx,(qse_awk_nde_blk_t*)fun->body);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -5989,24 +5987,24 @@ static qse_awk_val_t* __eval_call (
|
|||||||
|
|
||||||
if (call->u.fnc.spec.impl)
|
if (call->u.fnc.spec.impl)
|
||||||
{
|
{
|
||||||
run->errinf.num = QSE_AWK_ENOERR;
|
rtx->errinf.num = QSE_AWK_ENOERR;
|
||||||
|
|
||||||
n = call->u.fnc.spec.impl(run, &call->u.fnc.info);
|
n = call->u.fnc.spec.impl(rtx, &call->u.fnc.info);
|
||||||
|
|
||||||
if (n <= -1)
|
if (n <= -1)
|
||||||
{
|
{
|
||||||
if (run->errinf.num == QSE_AWK_ENOERR)
|
if (rtx->errinf.num == QSE_AWK_ENOERR)
|
||||||
{
|
{
|
||||||
/* the handler has not set the error.
|
/* the handler has not set the error.
|
||||||
* fix it */
|
* fix it */
|
||||||
SETERR_ARGX_LOC (
|
SETERR_ARGX_LOC (
|
||||||
run, QSE_AWK_EFNCIMPL,
|
rtx, QSE_AWK_EFNCIMPL,
|
||||||
&call->u.fnc.info.name, &nde->loc
|
&call->u.fnc.info.name, &nde->loc
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ADJERR_LOC (run, &nde->loc);
|
ADJERR_LOC (rtx, &nde->loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* correct the return code just in case */
|
/* correct the return code just in case */
|
||||||
@ -6015,43 +6013,76 @@ static qse_awk_val_t* __eval_call (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* refdown args in the run.stack */
|
/* refdown args in the rtx.stack */
|
||||||
nargs = (qse_size_t)RTX_STACK_NARGS(run);
|
nargs = (qse_size_t)RTX_STACK_NARGS(rtx);
|
||||||
#ifdef DEBUG_RUN
|
#ifdef DEBUG_RUN
|
||||||
qse_errputstrf (QSE_T("block run complete nargs = %d\n"), (int)nargs);
|
qse_errputstrf (QSE_T("block rtx complete nargs = %d\n"), (int)nargs);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (i = 0; i < nargs; i++)
|
if (fun && fun->argspec)
|
||||||
{
|
{
|
||||||
qse_awk_rtx_refdownval (run, RTX_STACK_ARG(run,i));
|
/* set back the values for call-by-reference parameters of normal functions.
|
||||||
|
* the intrinsic functions are not handled here but their implementation would
|
||||||
|
* call qse_awk_rtx_setrefval() */
|
||||||
|
|
||||||
|
qse_awk_nde_t* p;
|
||||||
|
|
||||||
|
p = call->args;
|
||||||
|
for (i = 0; i < nargs; i++)
|
||||||
|
{
|
||||||
|
if (fun->argspec[i] == QSE_T('r'))
|
||||||
|
{
|
||||||
|
/* TODO: change this part.. */
|
||||||
|
qse_awk_val_t** ref;
|
||||||
|
qse_awk_val_ref_t* refv;
|
||||||
|
|
||||||
|
/* TODO: ERROR CHECK. no extra memory set */
|
||||||
|
get_reference (rtx, p, &ref);
|
||||||
|
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));
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i = 0; i < nargs; i++)
|
||||||
|
{
|
||||||
|
qse_awk_rtx_refdownval (rtx, RTX_STACK_ARG(rtx,i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_RUN
|
#ifdef DEBUG_RUN
|
||||||
qse_errputstrf (QSE_T("got return value\n"));
|
qse_errputstrf (QSE_T("got return value\n"));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
v = RTX_STACK_RETVAL(run);
|
v = RTX_STACK_RETVAL(rtx);
|
||||||
if (n == -1)
|
if (n == -1)
|
||||||
{
|
{
|
||||||
if (run->errinf.num == QSE_AWK_ENOERR && errhandler != QSE_NULL)
|
if (rtx->errinf.num == QSE_AWK_ENOERR && errhandler != QSE_NULL)
|
||||||
{
|
{
|
||||||
/* errhandler is passed only when __eval_call() is
|
/* errhandler is passed only when __eval_call() is
|
||||||
* invoked from qse_awk_rtx_call(). Under this
|
* invoked from qse_awk_rtx_call(). Under this
|
||||||
* circumstance, this stack frame is the first
|
* circumstance, this stack frame is the first
|
||||||
* activated and the stack base is the first element
|
* activated and the stack base is the first element
|
||||||
* after the global variables. so RTX_STACK_RETVAL(run)
|
* after the global variables. so RTX_STACK_RETVAL(rtx)
|
||||||
* effectively becomes RTX_STACK_RETVAL_GBL(run).
|
* effectively becomes RTX_STACK_RETVAL_GBL(rtx).
|
||||||
* As __eval_call() returns QSE_NULL on error and
|
* As __eval_call() returns QSE_NULL on error and
|
||||||
* the reference count of RTX_STACK_RETVAL(run) should be
|
* the reference count of RTX_STACK_RETVAL(rtx) should be
|
||||||
* decremented, it can't get the return value
|
* decremented, it can't get the return value
|
||||||
* if it turns out to be terminated by exit().
|
* if it turns out to be terminated by exit().
|
||||||
* The return value could be destroyed by then.
|
* The return value could be destroyed by then.
|
||||||
* Unlikely, run_bpae_loop() just checks if run->errinf.num
|
* Unlikely, rtx_bpae_loop() just checks if rtx->errinf.num
|
||||||
* is QSE_AWK_ENOERR and gets RTX_STACK_RETVAL_GBL(run)
|
* is QSE_AWK_ENOERR and gets RTX_STACK_RETVAL_GBL(rtx)
|
||||||
* to determine if it is terminated by exit().
|
* to determine if it is terminated by exit().
|
||||||
*
|
*
|
||||||
* The handler capture_retval_on_exit()
|
* The handler capture_retval_on_exit()
|
||||||
* increments the reference of RTX_STACK_RETVAL(run)
|
* increments the reference of RTX_STACK_RETVAL(rtx)
|
||||||
* and stores the pointer into accompanying space.
|
* and stores the pointer into accompanying space.
|
||||||
* This way, the return value is preserved upon
|
* This way, the return value is preserved upon
|
||||||
* termination by exit() out to the caller.
|
* termination by exit() out to the caller.
|
||||||
@ -6062,28 +6093,27 @@ static qse_awk_val_t* __eval_call (
|
|||||||
/* if the earlier operations failed and this function
|
/* if the earlier operations failed and this function
|
||||||
* has to return a error, the return value is just
|
* has to return a error, the return value is just
|
||||||
* destroyed and replaced by nil */
|
* destroyed and replaced by nil */
|
||||||
qse_awk_rtx_refdownval (run, v);
|
qse_awk_rtx_refdownval (rtx, v);
|
||||||
RTX_STACK_RETVAL(run) = qse_awk_val_nil;
|
RTX_STACK_RETVAL(rtx) = qse_awk_val_nil;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* this trick has been mentioned in run_return.
|
/* this trick has been mentioned in rtx_return.
|
||||||
* adjust the reference count of the return value.
|
* adjust the reference count of the return value.
|
||||||
* the value must not be freed even if the reference count
|
* the value must not be freed even if the reference count
|
||||||
* reached zero because its reference has been incremented
|
* reached zero because its reference has been incremented
|
||||||
* in run_return or directly by qse_awk_rtx_setretval()
|
* in rtx_return or directly by qse_awk_rtx_setretval()
|
||||||
* regardless of its reference count. */
|
* regardless of its reference count. */
|
||||||
qse_awk_rtx_refdownval_nofree (run, v);
|
qse_awk_rtx_refdownval_nofree (rtx, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
run->stack_top = (qse_size_t)run->stack[run->stack_base+1];
|
rtx->stack_top = (qse_size_t)rtx->stack[rtx->stack_base+1];
|
||||||
run->stack_base = (qse_size_t)run->stack[run->stack_base+0];
|
rtx->stack_base = (qse_size_t)rtx->stack[rtx->stack_base+0];
|
||||||
|
|
||||||
if (run->exit_level == EXIT_FUNCTION) run->exit_level = EXIT_NONE;
|
if (rtx->exit_level == EXIT_FUNCTION) rtx->exit_level = EXIT_NONE;
|
||||||
|
|
||||||
#ifdef DEBUG_RUN
|
#ifdef DEBUG_RUN
|
||||||
qse_errputstrf (QSE_T("returning from function top=%zd, base=%zd\n"),
|
qse_errputstrf (QSE_T("returning from function top=%zd, base=%zd\n"), (qse_size_t)rtx->stack_top, (qse_size_t)rtx->stack_base);
|
||||||
(qse_size_t)run->stack_top, (qse_size_t)run->stack_base);
|
|
||||||
#endif
|
#endif
|
||||||
return (n == -1)? QSE_NULL: v;
|
return (n == -1)? QSE_NULL: v;
|
||||||
}
|
}
|
||||||
@ -6125,27 +6155,20 @@ static qse_size_t push_arg_from_nde (qse_awk_rtx_t* rtx, qse_awk_nde_fncall_t* c
|
|||||||
|
|
||||||
for (p = call->args, nargs = 0; p != QSE_NULL; p = p->next, nargs++)
|
for (p = call->args, nargs = 0; p != QSE_NULL; p = p->next, nargs++)
|
||||||
{
|
{
|
||||||
QSE_ASSERT (
|
/* if fnc_arg_spec is to be provided, it must contain as many characters as nargs */
|
||||||
fnc_arg_spec == QSE_NULL ||
|
|
||||||
(fnc_arg_spec != QSE_NULL &&
|
|
||||||
qse_strlen(fnc_arg_spec) > nargs));
|
|
||||||
|
|
||||||
if (fnc_arg_spec &&
|
if (fnc_arg_spec && (fnc_arg_spec[nargs] == QSE_T('r') || fnc_arg_spec[0] == QSE_T('R')))
|
||||||
(fnc_arg_spec[nargs] == QSE_T('r') ||
|
|
||||||
fnc_arg_spec[0] == QSE_T('R')))
|
|
||||||
{
|
{
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* p->type-QSE_AWK_NDE_NAMED assumes that the
|
/* 'p->type - QSE_AWK_NDE_NAMED' must produce a relevant QSE_AWK_VAL_REF_XXX value. */
|
||||||
* derived value matches QSE_AWK_VAL_REF_XXX */
|
v = qse_awk_rtx_makerefval(rtx, p->type - QSE_AWK_NDE_NAMED, ref);
|
||||||
v = qse_awk_rtx_makerefval (
|
|
||||||
rtx, p->type-QSE_AWK_NDE_NAMED, ref);
|
|
||||||
}
|
}
|
||||||
else if (fnc_arg_spec && fnc_arg_spec[nargs] == QSE_T('x'))
|
else if (fnc_arg_spec && fnc_arg_spec[nargs] == QSE_T('x'))
|
||||||
{
|
{
|
||||||
@ -6185,11 +6208,6 @@ static qse_size_t push_arg_from_nde (qse_awk_rtx_t* rtx, qse_awk_nde_fncall_t* c
|
|||||||
return nargs;
|
return nargs;
|
||||||
}
|
}
|
||||||
|
|
||||||
static qse_awk_val_t* eval_call (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde, const qse_char_t* fnc_arg_spec, qse_awk_fun_t* fun, void(*errhandler)(void*), void* eharg)
|
|
||||||
{
|
|
||||||
return __eval_call(rtx, nde, fnc_arg_spec, fun, push_arg_from_nde, (void*)fnc_arg_spec, errhandler, eharg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int get_reference (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde, qse_awk_val_t*** ref)
|
static int get_reference (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde, qse_awk_val_t*** ref)
|
||||||
{
|
{
|
||||||
qse_awk_nde_var_t* tgt = (qse_awk_nde_var_t*)nde;
|
qse_awk_nde_var_t* tgt = (qse_awk_nde_var_t*)nde;
|
||||||
|
@ -206,6 +206,7 @@ struct qse_awk_nde_fncall_t
|
|||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
qse_cstr_t name;
|
qse_cstr_t name;
|
||||||
|
qse_awk_fun_t* fun; /* cache it */
|
||||||
} fun;
|
} fun;
|
||||||
|
|
||||||
/* minimum information of a intrinsic function
|
/* minimum information of a intrinsic function
|
||||||
|
@ -700,7 +700,7 @@ reswitch:
|
|||||||
const qse_wchar_t* usp;
|
const qse_wchar_t* usp;
|
||||||
qse_size_t uwid;
|
qse_size_t uwid;
|
||||||
|
|
||||||
if (flagc & FLAGC_ZEROPAD) padc = ' ';
|
if (flagc & FLAGC_ZEROPAD) padc = T(' ');
|
||||||
usp = va_arg(ap, qse_wchar_t*);
|
usp = va_arg(ap, qse_wchar_t*);
|
||||||
|
|
||||||
if (flagc & FLAGC_DOT)
|
if (flagc & FLAGC_DOT)
|
||||||
|
Loading…
Reference in New Issue
Block a user