From 3368c91834821060723875b9462b3dfe4d7d8927 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Mon, 29 Apr 2019 09:40:13 +0000 Subject: [PATCH] have implemented the function-pointer-as-value feature experimentally --- qse/include/qse/awk/awk.h | 8 +- qse/lib/awk/awk-prv.h | 16 +++ qse/lib/awk/err.c | 1 + qse/lib/awk/parse.c | 228 +++++++++++++++++++++----------------- qse/lib/awk/run.c | 77 ++++++++----- qse/lib/awk/tree.c | 31 ++++-- qse/lib/awk/tree.h | 15 ++- qse/lib/awk/val.c | 21 ++-- 8 files changed, 248 insertions(+), 149 deletions(-) diff --git a/qse/include/qse/awk/awk.h b/qse/include/qse/awk/awk.h index a0fdefd1..e486fb31 100644 --- a/qse/include/qse/awk/awk.h +++ b/qse/include/qse/awk/awk.h @@ -367,14 +367,15 @@ enum qse_awk_nde_type_t QSE_AWK_NDE_EXP_INCPRE, QSE_AWK_NDE_EXP_INCPST, QSE_AWK_NDE_CND, - QSE_AWK_NDE_FNC, - QSE_AWK_NDE_FUN, - QSE_AWK_NDE_FCV, + QSE_AWK_NDE_FNCALL_FNC, + QSE_AWK_NDE_FNCALL_FUN, + QSE_AWK_NDE_FNCALL_VAR, QSE_AWK_NDE_INT, QSE_AWK_NDE_FLT, QSE_AWK_NDE_STR, QSE_AWK_NDE_MBS, QSE_AWK_NDE_REX, + QSE_AWK_NDE_FUN, /* keep this order for the following items otherwise, you may have * to change eval_incpre and eval_incpst in run.c as well as @@ -1276,6 +1277,7 @@ enum qse_awk_errnum_t QSE_AWK_EARGTF, /**< too few arguments */ QSE_AWK_EARGTM, /**< too many arguments */ QSE_AWK_EFUNNF, /**< function '${0}' not found */ + QSE_AWK_ENOTFUN, /**< non-function value in '%{0}' */ QSE_AWK_ENOTDEL, /**< '${0}' not deletable */ QSE_AWK_ENOTMAP, /**< value not a map */ QSE_AWK_ENOTMAPIN, /**< right-hand side of 'in' not a map */ diff --git a/qse/lib/awk/awk-prv.h b/qse/lib/awk/awk-prv.h index d3af8054..852fcc13 100644 --- a/qse/lib/awk/awk-prv.h +++ b/qse/lib/awk/awk-prv.h @@ -54,6 +54,22 @@ typedef struct qse_awk_tree_t qse_awk_tree_t; #define FEATURE_SCACHE_BLOCK_UNIT 16 #define FEATURE_SCACHE_BLOCK_SIZE 128 +/* [NOTE] the function value support implemented is very limited. + * it supports very primitive way to call a function via a variable. + * only user-defined functions are supported. neither builtin functions + * nor module functions are not supported yet. + * ----------------------------------------------------- + * function x(a,b,c) { print a, b, c; } + * BEGIN { q = x; q(1, 2, 3); } # this works + * BEGIN { q[1]=x; q[1](1,2,3); } # this doesn't work. same as q[1] %% (1, 2, 3) or q[1] %% 3 + * BEGIN { q[1]=x; y=q[1]; y(1,2,3); } # this works. + * ----------------------------------------------------- + * function __printer(a,b,c) { print a, b, c; } + * function show(printer, a,b,c) { printer(a, b, c); } + * BEGIN { show(__printer, 10, 20, 30); } ## passing the function value as an argumnet is ok. + */ +#define ENABLE_FEATURE_FUN_AS_VALUE + #define QSE_AWK_MAX_GBLS 9999 #define QSE_AWK_MAX_LCLS 9999 #define QSE_AWK_MAX_PARAMS 9999 diff --git a/qse/lib/awk/err.c b/qse/lib/awk/err.c index bb3e1052..217f535b 100644 --- a/qse/lib/awk/err.c +++ b/qse/lib/awk/err.c @@ -119,6 +119,7 @@ const qse_char_t* qse_awk_dflerrstr (const qse_awk_t* awk, qse_awk_errnum_t errn QSE_T("too few arguments"), QSE_T("too many arguments"), QSE_T("function '${0}' not found"), + QSE_T("non-function value in '${0}'"), QSE_T("'${0}' not deletable"), QSE_T("value not a map"), QSE_T("right-hand side of the 'in' operator not a map"), diff --git a/qse/lib/awk/parse.c b/qse/lib/awk/parse.c index cf87179c..1a4dfae6 100644 --- a/qse/lib/awk/parse.c +++ b/qse/lib/awk/parse.c @@ -96,7 +96,7 @@ enum tok_t TOK_LS, TOK_IN, TOK_EXP, - TOK_CONCAT, + TOK_CONCAT, /* %% */ TOK_LPAREN, TOK_RPAREN, @@ -111,7 +111,7 @@ enum tok_t TOK_COLON, TOK_DBLCOLON, TOK_QUEST, - TOK_DBLAT, + /*TOK_DBLAT,*/ /* == begin reserved words == */ /* === extended reserved words === */ @@ -223,7 +223,7 @@ static qse_awk_nde_t* parse_primary_ident (qse_awk_t* awk, const qse_awk_loc_t* static qse_awk_nde_t* parse_hashidx (qse_awk_t* awk, const qse_cstr_t* name, const qse_awk_loc_t* xloc); #define FNCALL_FLAG_NOARG (1 << 0) /* no argument */ -#define FNCALL_FLAG_FCV (1 << 1) +#define FNCALL_FLAG_VAR (1 << 1) static qse_awk_nde_t* parse_fncall (qse_awk_t* awk, const qse_cstr_t* name, qse_awk_fnc_t* fnc, const qse_awk_loc_t* xloc, int flags); static qse_awk_nde_t* parse_primary_ident_segs (qse_awk_t* awk, const qse_awk_loc_t* xloc, const qse_cstr_t* full, const qse_cstr_t segs[], int nsegs); @@ -1117,17 +1117,17 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk) } /* duplicate the name before it's overridden by get_token() */ - name.ptr = qse_strxdup (name.ptr, name.len, awk->mmgr); + name.ptr = qse_awk_strxdup(awk, name.ptr, name.len); if (name.ptr == QSE_NULL) { - SETERR_LOC (awk, QSE_AWK_ENOMEM, &awk->tok.loc); + ADJERR_LOC (awk, &awk->tok.loc); return QSE_NULL; } /* get the next token */ if (get_token(awk) <= -1) { - QSE_AWK_FREE (awk, name.ptr); + qse_awk_freemem (awk, name.ptr); return QSE_NULL; } @@ -1136,14 +1136,14 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk) { /* a function name is not followed by a left parenthesis */ SETERR_TOK (awk, QSE_AWK_ELPAREN); - QSE_AWK_FREE (awk, name.ptr); + qse_awk_freemem (awk, name.ptr); return QSE_NULL; - } + } /* get the next token */ if (get_token(awk) <= -1) { - QSE_AWK_FREE (awk, name.ptr); + qse_awk_freemem (awk, name.ptr); return QSE_NULL; } @@ -1156,7 +1156,7 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk) /* no function parameter found. get the next token */ if (get_token(awk) <= -1) { - QSE_AWK_FREE (awk, name.ptr); + qse_awk_freemem (awk, name.ptr); return QSE_NULL; } } @@ -1169,7 +1169,7 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk) if (!MATCH(awk,TOK_IDENT)) { - QSE_AWK_FREE (awk, name.ptr); + qse_awk_freemem (awk, name.ptr); qse_arr_clear (awk->parse.params); SETERR_TOK (awk, QSE_AWK_EBADPAR); return QSE_NULL; @@ -1192,7 +1192,7 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk) qse_strxncmp (pa, pal, name.ptr, name.len) == 0) || qse_arr_search (awk->parse.params, 0, pa, pal) != QSE_ARR_NIL) { - QSE_AWK_FREE (awk, name.ptr); + qse_awk_freemem (awk, name.ptr); qse_arr_clear (awk->parse.params); SETERR_ARG_LOC ( awk, QSE_AWK_EDUPPAR, @@ -1203,35 +1203,32 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk) /* push the parameter to the parameter list */ if (QSE_ARR_SIZE(awk->parse.params) >= QSE_AWK_MAX_PARAMS) { - QSE_AWK_FREE (awk, name.ptr); + qse_awk_freemem (awk, name.ptr); qse_arr_clear (awk->parse.params); SETERR_LOC (awk, QSE_AWK_EPARTM, &awk->tok.loc); return QSE_NULL; } - 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_FREE (awk, name.ptr); + qse_awk_freemem (awk, name.ptr); qse_arr_clear (awk->parse.params); SETERR_LOC (awk, QSE_AWK_ENOMEM, &awk->tok.loc); return QSE_NULL; - } + } if (get_token (awk) <= -1) { - QSE_AWK_FREE (awk, name.ptr); + 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_COMMA)) { - QSE_AWK_FREE (awk, name.ptr); + qse_awk_freemem (awk, name.ptr); qse_arr_clear (awk->parse.params); SETERR_TOK (awk, QSE_AWK_ECOMMA); return QSE_NULL; @@ -1241,7 +1238,7 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk) { if (get_token(awk) <= -1) { - QSE_AWK_FREE (awk, name.ptr); + qse_awk_freemem (awk, name.ptr); qse_arr_clear (awk->parse.params); return QSE_NULL; } @@ -1251,7 +1248,7 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk) if (get_token(awk) <= -1) { - QSE_AWK_FREE (awk, name.ptr); + qse_awk_freemem (awk, name.ptr); qse_arr_clear (awk->parse.params); return QSE_NULL; } @@ -1265,7 +1262,7 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk) { if (get_token(awk) <= -1) { - QSE_AWK_FREE (awk, name.ptr); + qse_awk_freemem (awk, name.ptr); qse_arr_clear (awk->parse.params); return QSE_NULL; } @@ -1274,15 +1271,14 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk) /* check if the function body starts with a left brace */ if (!MATCH(awk,TOK_LBRACE)) { - QSE_AWK_FREE (awk, name.ptr); + qse_awk_freemem (awk, name.ptr); qse_arr_clear (awk->parse.params); - SETERR_TOK (awk, QSE_AWK_ELBRACE); return QSE_NULL; } if (get_token(awk) <= -1) { - QSE_AWK_FREE (awk, name.ptr); + qse_awk_freemem (awk, name.ptr); qse_arr_clear (awk->parse.params); return QSE_NULL; } @@ -1302,7 +1298,7 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk) if (body == QSE_NULL) { - QSE_AWK_FREE (awk, name.ptr); + qse_awk_freemem (awk, name.ptr); qse_arr_clear (awk->parse.params); return QSE_NULL; } @@ -1313,10 +1309,10 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk) /* parameter names are not required anymore. clear them */ qse_arr_clear (awk->parse.params); - 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) { - QSE_AWK_FREE (awk, name.ptr); + qse_awk_freemem (awk, name.ptr); qse_awk_clrpt (awk, body); ADJERR_LOC (awk, &awk->tok.loc); return QSE_NULL; @@ -1327,15 +1323,15 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk) fun->nargs = nargs; 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); if (pair == QSE_NULL) { /* if qse_htb_insert() fails for other reasons than memory * shortage, there should be implementaion errors as duplicate * functions are detected earlier in this function */ - QSE_AWK_FREE (awk, name.ptr); + qse_awk_freemem (awk, name.ptr); qse_awk_clrpt (awk, body); - QSE_AWK_FREE (awk, fun); + qse_awk_freemem (awk, fun); SETERR_LOC (awk, QSE_AWK_ENOMEM, &awk->tok.loc); return QSE_NULL; } @@ -1344,7 +1340,7 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk) * of the pair */ fun->name.ptr = QSE_HTB_KPTR(pair); fun->name.len = QSE_HTB_KLEN(pair); - QSE_AWK_FREE (awk, name.ptr); + qse_awk_freemem (awk, name.ptr); /* remove an undefined function call entry from the parse.fun table */ qse_htb_delete (awk->parse.funs, fun->name.ptr, name.len); @@ -1415,16 +1411,15 @@ static qse_awk_chain_t* parse_action_block ( { QSE_ASSERT (MATCH(awk,TOK_LBRACE)); if (get_token(awk) <= -1) return QSE_NULL; - nde = parse_block_dc (awk, &xloc, 1); + nde = parse_block_dc(awk, &xloc, 1); if (nde == QSE_NULL) return QSE_NULL; } - chain = (qse_awk_chain_t*) - QSE_AWK_ALLOC (awk, QSE_SIZEOF(qse_awk_chain_t)); + chain = (qse_awk_chain_t*)qse_awk_callocmem(awk, QSE_SIZEOF(*chain)); if (chain == QSE_NULL) { qse_awk_clrpt (awk, nde); - SETERR_LOC (awk, QSE_AWK_ENOMEM, &xloc); + ADJERR_LOC (awk, &xloc); return QSE_NULL; } @@ -3052,8 +3047,7 @@ static qse_awk_nde_t* parse_statement_nb ( return nde; } -static qse_awk_nde_t* parse_statement ( - qse_awk_t* awk, const qse_awk_loc_t* xloc) +static qse_awk_nde_t* parse_statement (qse_awk_t* awk, const qse_awk_loc_t* xloc) { qse_awk_nde_t* nde; @@ -3065,12 +3059,11 @@ static qse_awk_nde_t* parse_statement ( if (MATCH(awk,TOK_SEMICOLON)) { - /* null statement */ - nde = (qse_awk_nde_t*) - QSE_AWK_ALLOC (awk, QSE_SIZEOF(qse_awk_nde_t)); - if (nde == QSE_NULL) + /* null statement */ + nde = (qse_awk_nde_t*)qse_awk_callocmem(awk, QSE_SIZEOF(*nde)); + if (!nde) { - SETERR_LOC (awk, QSE_AWK_ENOMEM, xloc); + ADJERR_LOC (awk, xloc); return QSE_NULL; } @@ -3080,7 +3073,7 @@ static qse_awk_nde_t* parse_statement ( if (get_token(awk) <= -1) { - QSE_AWK_FREE (awk, nde); + qse_awk_freemem (awk, nde); return QSE_NULL; } } @@ -3150,8 +3143,7 @@ static int assign_to_opcode (qse_awk_t* awk) return -1; } -static qse_awk_nde_t* parse_expr_basic ( - qse_awk_t* awk, const qse_awk_loc_t* xloc) +static qse_awk_nde_t* parse_expr_basic (qse_awk_t* awk, const qse_awk_loc_t* xloc) { qse_awk_nde_t* nde, * n1, * n2; @@ -3170,7 +3162,7 @@ static qse_awk_nde_t* parse_expr_basic ( return QSE_NULL; } - eloc = awk->tok.loc; + eloc = awk->tok.loc; n1 = parse_expr_withdc (awk, &eloc); if (n1 == QSE_NULL) { @@ -3201,14 +3193,13 @@ static qse_awk_nde_t* parse_expr_basic ( return QSE_NULL; } - cnd = (qse_awk_nde_cnd_t*) QSE_AWK_ALLOC ( - awk, QSE_SIZEOF(qse_awk_nde_cnd_t)); + cnd = (qse_awk_nde_cnd_t*)qse_awk_callocmem(awk, QSE_SIZEOF(*cnd)); if (cnd == QSE_NULL) { qse_awk_clrpt (awk, nde); qse_awk_clrpt (awk, n1); qse_awk_clrpt (awk, n2); - SETERR_LOC (awk, QSE_AWK_ENOMEM, xloc); + ADJERR_LOC (awk, xloc); return QSE_NULL; } @@ -3225,8 +3216,7 @@ static qse_awk_nde_t* parse_expr_basic ( return nde; } -static qse_awk_nde_t* parse_expr ( - qse_awk_t* awk, const qse_awk_loc_t* xloc) +static qse_awk_nde_t* parse_expr (qse_awk_t* awk, const qse_awk_loc_t* xloc) { qse_awk_nde_t* x, * y; qse_awk_nde_ass_t* nde; @@ -3258,7 +3248,6 @@ static qse_awk_nde_t* parse_expr ( { qse_awk_loc_t eloc; - eloc = awk->tok.loc; y = parse_expr_withdc (awk, &eloc); } @@ -3268,14 +3257,12 @@ static qse_awk_nde_t* parse_expr ( return QSE_NULL; } - nde = (qse_awk_nde_ass_t*) - QSE_AWK_ALLOC (awk, QSE_SIZEOF(qse_awk_nde_ass_t)); + nde = (qse_awk_nde_ass_t*)qse_awk_callocmem(awk, QSE_SIZEOF(*nde)); if (nde == QSE_NULL) { qse_awk_clrpt (awk, x); qse_awk_clrpt (awk, y); - - SETERR_LOC (awk, QSE_AWK_ENOMEM, xloc); + ADJERR_LOC (awk, xloc); return QSE_NULL; } @@ -3289,8 +3276,7 @@ static qse_awk_nde_t* parse_expr ( return (qse_awk_nde_t*)nde; } -static qse_awk_nde_t* parse_expr_withdc ( - qse_awk_t* awk, const qse_awk_loc_t* xloc) +static qse_awk_nde_t* parse_expr_withdc (qse_awk_t* awk, const qse_awk_loc_t* xloc) { qse_awk_nde_t* nde; @@ -4271,7 +4257,7 @@ static QSE_INLINE int isfunname (qse_awk_t* awk, const qse_cstr_t* name) /* check if it is an awk function being processed currently */ if (awk->tree.cur_fun.ptr) { - if (qse_strxncmp (awk->tree.cur_fun.ptr, awk->tree.cur_fun.len, name->ptr, name->len) == 0) + if (qse_strxncmp(awk->tree.cur_fun.ptr, awk->tree.cur_fun.len, name->ptr, name->len) == 0) { /* the current function begin parsed */ return FNTYPE_FUN; @@ -4306,7 +4292,6 @@ static QSE_INLINE int isfnname (qse_awk_t* awk, const qse_cstr_t* name) return isfunname(awk, name); } - static qse_awk_nde_t* parse_primary_int (qse_awk_t* awk, const qse_awk_loc_t* xloc) { qse_awk_nde_int_t* nde; @@ -4786,7 +4771,7 @@ static qse_awk_nde_t* parse_primary (qse_awk_t* awk, const qse_awk_loc_t* xloc) qse_awk_nde_t* var = QSE_NULL; qse_awk_loc_t ploc; - left = parse_primary_nopipe (awk, xloc); + left = parse_primary_nopipe(awk, xloc); if (left == QSE_NULL) goto oops; /* handle the piping part */ @@ -4800,8 +4785,7 @@ static qse_awk_nde_t* parse_primary (qse_awk_t* awk, const qse_awk_loc_t* xloc) { intype = QSE_AWK_IN_PIPE; } - else if (MATCH(awk,TOK_LOR) && - (awk->opt.trait & QSE_AWK_RWPIPE)) + else if (MATCH(awk,TOK_LOR) && (awk->opt.trait & QSE_AWK_RWPIPE)) { intype = QSE_AWK_IN_RWPIPE; } @@ -4810,11 +4794,10 @@ static qse_awk_nde_t* parse_primary (qse_awk_t* awk, const qse_awk_loc_t* xloc) if (intype == -1) break; if (preget_token(awk) <= -1) goto oops; - if (awk->ntok.type != TOK_GETLINE) break; /* consume ntok('getline') */ - get_token (awk); + get_token(awk); /* no error check needed as it's guaranteeded to succeed for preget_token() above */ /* get the next token */ if (get_token(awk) <= -1) goto oops; @@ -4861,7 +4844,7 @@ static qse_awk_nde_t* parse_primary (qse_awk_t* awk, const qse_awk_loc_t* xloc) } novar: - nde = (qse_awk_nde_getline_t*) qse_awk_callocmem (awk, QSE_SIZEOF(*nde)); + nde = (qse_awk_nde_getline_t*)qse_awk_callocmem(awk, QSE_SIZEOF(*nde)); if (nde == QSE_NULL) { ADJERR_LOC (awk, xloc); @@ -4890,22 +4873,24 @@ oops: static qse_awk_nde_t* parse_variable (qse_awk_t* awk, const qse_awk_loc_t* xloc, qse_awk_nde_type_t type, const qse_cstr_t* name, qse_size_t idxa) { qse_awk_nde_var_t* nde; - int fcv = 0; + int is_fcv = 0; + if (MATCH(awk,TOK_LPAREN)) + { + #if defined(ENABLE_FEATURE_FUN_AS_VALUE) /* if (MATCH(awk,TOK_LPAREN) && (!(awk->opt.trait & QSE_AWK_BLANKCONCAT) || (awk->tok.loc.line == xloc->line && awk->tok.loc.colm == xloc->colm + name->len))) */ - - if (MATCH(awk,TOK_LPAREN)) - { if (awk->tok.loc.line == xloc->line && awk->tok.loc.colm == xloc->colm + name->len) { - fcv = 1; + is_fcv = 1; } - else if (!(awk->opt.trait & QSE_AWK_BLANKCONCAT)) + else + #endif + if (!(awk->opt.trait & QSE_AWK_BLANKCONCAT)) { /* if concatenation by blanks is not allowed, the explicit * concatenation operator(%%) must be used. so it is obvious @@ -4934,8 +4919,12 @@ static qse_awk_nde_t* parse_variable (qse_awk_t* awk, const qse_awk_loc_t* xloc, nde->id.idxa = idxa; nde->idx = QSE_NULL; - if (!fcv) return (qse_awk_nde_t*)nde; - return parse_fncall(awk, (const qse_cstr_t*)nde, QSE_NULL, xloc, FNCALL_FLAG_FCV); +#if defined(ENABLE_FEATURE_FUN_AS_VALUE) + if (!is_fcv) return (qse_awk_nde_t*)nde; + return parse_fncall(awk, (const qse_cstr_t*)nde, QSE_NULL, xloc, FNCALL_FLAG_VAR); +#else + return (qse_awk_nde_t*)nde; +#endif } static int dup_ident_and_get_next (qse_awk_t* awk, const qse_awk_loc_t* xloc, qse_cstr_t* name, int max) @@ -4950,10 +4939,10 @@ static int dup_ident_and_get_next (qse_awk_t* awk, const qse_awk_loc_t* xloc, qs name[nsegs].len = QSE_STR_LEN(awk->tok.name); /* duplicate the identifier */ - name[nsegs].ptr = qse_strxdup (name[nsegs].ptr, name[nsegs].len, awk->mmgr); + name[nsegs].ptr = qse_awk_strxdup(awk, name[nsegs].ptr, name[nsegs].len); if (name[nsegs].ptr == QSE_NULL) { - SETERR_LOC (awk, QSE_AWK_ENOMEM, xloc); + ADJERR_LOC (awk, xloc); goto oops; } @@ -4987,10 +4976,33 @@ static int dup_ident_and_get_next (qse_awk_t* awk, const qse_awk_loc_t* xloc, qs return nsegs; oops: - while (nsegs > 0) QSE_AWK_FREE (awk, name[--nsegs].ptr); + while (nsegs > 0) qse_awk_freemem (awk, name[--nsegs].ptr); return -1; } +#if defined(ENABLE_FEATURE_FUN_AS_VALUE) +static qse_awk_nde_t* parse_fun_as_value (qse_awk_t* awk, const qse_cstr_t* name, const qse_awk_loc_t* xloc) +{ + qse_awk_nde_fun_t* nde; + + /* create the node for the literal */ + nde = (qse_awk_nde_fun_t*)qse_awk_callocmem(awk, QSE_SIZEOF(*nde)); + if (nde == QSE_NULL) + { + ADJERR_LOC (awk, xloc); + return QSE_NULL; + } + + nde->type = QSE_AWK_NDE_FUN; + nde->loc = *xloc; + nde->name.ptr = name->ptr; + nde->name.len = name->len; + + + return (qse_awk_nde_t*)nde; +} +#endif + static qse_awk_nde_t* parse_primary_ident_noseg (qse_awk_t* awk, const qse_awk_loc_t* xloc, const qse_cstr_t* name) { qse_awk_fnc_t* fnc; @@ -5071,7 +5083,11 @@ static qse_awk_nde_t* parse_primary_ident_noseg (qse_awk_t* awk, const qse_awk_l else { /* function name appeared without () */ + #if defined(ENABLE_FEATURE_FUN_AS_VALUE) + nde = parse_fun_as_value(awk, name, xloc); + #else SETERR_ARG_LOC (awk, QSE_AWK_EFUNRED, name->ptr, name->len, xloc); + #endif } } else if (awk->opt.trait & QSE_AWK_IMPLICIT) @@ -5084,6 +5100,7 @@ static qse_awk_nde_t* parse_primary_ident_noseg (qse_awk_t* awk, const qse_awk_l * by a left parenthesis if concatenation by blanks * is not allowed. */ + int is_fncall_var = 0; if (MATCH(awk,TOK_LPAREN) && (!(awk->opt.trait & QSE_AWK_BLANKCONCAT) || @@ -5091,11 +5108,15 @@ static qse_awk_nde_t* parse_primary_ident_noseg (qse_awk_t* awk, const qse_awk_l awk->tok.loc.colm == xloc->colm + name->len))) { /* it is a function call to an undefined function yet */ - if (qse_htb_search(awk->parse.named, name->ptr, name->len) != QSE_NULL) { /* the function call conflicts with a named variable */ + #if defined(ENABLE_FEATURE_FUN_AS_VALUE) + is_fncall_var = 1; + goto named_var; + #else SETERR_ARG_LOC (awk, QSE_AWK_EVARRED, name->ptr, name->len, xloc); + #endif } else { @@ -5106,6 +5127,10 @@ static qse_awk_nde_t* parse_primary_ident_noseg (qse_awk_t* awk, const qse_awk_l { qse_awk_nde_var_t* tmp; + #if defined(ENABLE_FEATURE_FUN_AS_VALUE) + named_var: + #endif + /* if there is a space between the name and the left parenthesis * while the name is not resolved to anything, we treat the space * as concatention by blanks. so we handle the name as a named @@ -5116,7 +5141,7 @@ static qse_awk_nde_t* parse_primary_ident_noseg (qse_awk_t* awk, const qse_awk_l { /* collect unique instances of a named variable * for reference */ - if (qse_htb_upsert (awk->parse.named, name->ptr, name->len, QSE_NULL, 0) == QSE_NULL) + if (qse_htb_upsert(awk->parse.named, name->ptr, name->len, QSE_NULL, 0) == QSE_NULL) { SETERR_LOC (awk, QSE_AWK_ENOMEM, xloc); QSE_AWK_FREE (awk, tmp); @@ -5129,8 +5154,12 @@ static qse_awk_nde_t* parse_primary_ident_noseg (qse_awk_t* awk, const qse_awk_l tmp->id.name.len = name->len; tmp->id.idxa = (qse_size_t)-1; tmp->idx = QSE_NULL; - nde = (qse_awk_nde_t*)tmp; + + #if defined(ENABLE_FEATURE_FUN_AS_VALUE) + if (is_fncall_var) + nde = parse_fncall(awk, (const qse_cstr_t*)nde, QSE_NULL, xloc, FNCALL_FLAG_VAR); + #endif } } } @@ -5216,8 +5245,7 @@ static qse_awk_nde_t* parse_primary_ident_segs (qse_awk_t* awk, const qse_awk_lo return nde; } -static qse_awk_nde_t* parse_primary_ident ( - qse_awk_t* awk, const qse_awk_loc_t* xloc) +static qse_awk_nde_t* parse_primary_ident (qse_awk_t* awk, const qse_awk_loc_t* xloc) { qse_awk_nde_t* nde = QSE_NULL; qse_cstr_t name[2]; /* TODO: support more than 2 segments??? */ @@ -5225,13 +5253,13 @@ static qse_awk_nde_t* parse_primary_ident ( QSE_ASSERT (MATCH(awk,TOK_IDENT)); - nsegs = dup_ident_and_get_next (awk, xloc, name, QSE_COUNTOF(name)); + nsegs = dup_ident_and_get_next(awk, xloc, name, QSE_COUNTOF(name)); if (nsegs <= -1) return QSE_NULL; if (nsegs <= 1) { nde = parse_primary_ident_noseg (awk, xloc, &name[0]); - if (!nde) QSE_AWK_FREE (awk, name[0].ptr); + if (!nde) qse_awk_freemem (awk, name[0].ptr); } else { @@ -5240,7 +5268,7 @@ static qse_awk_nde_t* parse_primary_ident ( int i; for (capa = 0, i = 0; i < nsegs; i++) capa += name[i].len + 2; /* +2 for :: */ - full.ptr = qse_awk_allocmem (awk, QSE_SIZEOF(*full.ptr) * (capa + 1)); + full.ptr = qse_awk_allocmem(awk, QSE_SIZEOF(*full.ptr) * (capa + 1)); if (full.ptr) { capa = qse_strncpy (&full.ptr[0], name[0].ptr, name[0].len); @@ -5252,12 +5280,12 @@ static qse_awk_nde_t* parse_primary_ident ( full.ptr[capa] = QSE_T('\0'); full.len = capa; - nde = parse_primary_ident_segs (awk, xloc, &full, name, nsegs); - if (!nde || nde->type != QSE_AWK_NDE_FNC) + nde = parse_primary_ident_segs(awk, xloc, &full, name, nsegs); + if (!nde || nde->type != QSE_AWK_NDE_FNCALL_FNC) { /* the FNC node takes the full name but other * nodes don't. so i need to free it. i know it's ugly. */ - QSE_AWK_FREE (awk, full.ptr); + qse_awk_freemem (awk, full.ptr); } } else @@ -5267,7 +5295,7 @@ static qse_awk_nde_t* parse_primary_ident ( } /* i don't need the name segments */ - while (nsegs > 0) QSE_AWK_FREE (awk, name[--nsegs].ptr); + while (nsegs > 0) qse_awk_freemem (awk, name[--nsegs].ptr); } return nde; @@ -5414,7 +5442,7 @@ static qse_awk_nde_t* parse_hashidx (qse_awk_t* awk, const qse_cstr_t* name, con exit_func: qse_awk_clrpt (awk, idx); - QSE_AWK_FREE (awk, nde); + qse_awk_freemem (awk, nde); return QSE_NULL; } @@ -5482,17 +5510,17 @@ make_node: goto oops; } - if (flags & FNCALL_FLAG_FCV) + if (flags & FNCALL_FLAG_VAR) { - call->type = QSE_AWK_NDE_FCV; + call->type = QSE_AWK_NDE_FNCALL_VAR; call->loc = *xloc; - call->u.fcv.var = (qse_awk_nde_var_t*)name; /* name is a pointer to a variable node */ + call->u.var.var = (qse_awk_nde_var_t*)name; /* name is a pointer to a variable node */ call->args = head; call->nargs = nargs; } else if (fnc) { - call->type = QSE_AWK_NDE_FNC; + call->type = QSE_AWK_NDE_FNCALL_FNC; call->loc = *xloc; call->u.fnc.info.name.ptr = name->ptr; @@ -5516,7 +5544,7 @@ make_node: } else { - call->type = QSE_AWK_NDE_FUN; + call->type = QSE_AWK_NDE_FNCALL_FUN; call->loc = *xloc; call->u.fun.name.ptr = name->ptr; call->u.fun.name.len = name->len; @@ -5534,7 +5562,7 @@ make_node: return (qse_awk_nde_t*)call; oops: - if (call) QSE_AWK_FREE (awk, call); + if (call) qse_awk_freemem (awk, call); if (head) qse_awk_clrpt (awk, head); return QSE_NULL; } diff --git a/qse/lib/awk/run.c b/qse/lib/awk/run.c index aa25e195..b4a59a56 100644 --- a/qse/lib/awk/run.c +++ b/qse/lib/awk/run.c @@ -224,13 +224,13 @@ static qse_awk_val_t* eval_incpre (qse_awk_rtx_t* run, qse_awk_nde_t* nde); static qse_awk_val_t* eval_incpst (qse_awk_rtx_t* run, qse_awk_nde_t* nde); static qse_awk_val_t* eval_cnd (qse_awk_rtx_t* run, qse_awk_nde_t* nde); -static qse_awk_val_t* eval_fun_ex ( +static qse_awk_val_t* eval_fncall_fncall_fun_ex ( qse_awk_rtx_t* run, qse_awk_nde_t* nde, void(*errhandler)(void*), void* eharg); -static qse_awk_val_t* eval_fnc (qse_awk_rtx_t* run, qse_awk_nde_t* nde); -static qse_awk_val_t* eval_fun (qse_awk_rtx_t* run, qse_awk_nde_t* nde); -static qse_awk_val_t* eval_fcv (qse_awk_rtx_t* run, qse_awk_nde_t* nde); +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_fncall_fun (qse_awk_rtx_t* run, qse_awk_nde_t* nde); +static qse_awk_val_t* eval_fncall_var (qse_awk_rtx_t* run, qse_awk_nde_t* nde); static qse_awk_val_t* __eval_call ( qse_awk_rtx_t* run, @@ -257,6 +257,7 @@ static qse_awk_val_t* eval_flt (qse_awk_rtx_t* run, qse_awk_nde_t* nde); static qse_awk_val_t* eval_str (qse_awk_rtx_t* run, qse_awk_nde_t* nde); static qse_awk_val_t* eval_mbs (qse_awk_rtx_t* run, qse_awk_nde_t* nde); static qse_awk_val_t* eval_rex (qse_awk_rtx_t* run, qse_awk_nde_t* nde); +static qse_awk_val_t* eval_fun (qse_awk_rtx_t* run, qse_awk_nde_t* nde); static qse_awk_val_t* eval_named (qse_awk_rtx_t* run, qse_awk_nde_t* nde); static qse_awk_val_t* eval_gbl (qse_awk_rtx_t* run, qse_awk_nde_t* nde); static qse_awk_val_t* eval_lcl (qse_awk_rtx_t* run, qse_awk_nde_t* nde); @@ -1630,7 +1631,7 @@ qse_awk_val_t* qse_awk_rtx_callfun ( /* forge a fake node containing a function call */ QSE_MEMSET (&call, 0, QSE_SIZEOF(call)); - call.type = QSE_AWK_NDE_FUN; + call.type = QSE_AWK_NDE_FNCALL_FUN; call.u.fun.name = fun->name; call.nargs = nargs; @@ -3326,14 +3327,15 @@ static qse_awk_val_t* eval_expression0 (qse_awk_rtx_t* run, qse_awk_nde_t* nde) eval_incpre, eval_incpst, eval_cnd, - eval_fnc, - eval_fun, - eval_fcv, + eval_fncall_fnc, + eval_fncall_fncall_fun, + eval_fncall_var, eval_int, eval_flt, eval_str, eval_mbs, eval_rex, + eval_fun, eval_named, eval_gbl, eval_lcl, @@ -3350,10 +3352,9 @@ static qse_awk_val_t* eval_expression0 (qse_awk_rtx_t* run, qse_awk_nde_t* nde) qse_awk_val_t* v; - 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](run, nde); if (v != QSE_NULL && run->exit_level >= EXIT_GLOBAL) { @@ -5602,7 +5603,7 @@ static qse_awk_val_t* eval_cnd (qse_awk_rtx_t* run, qse_awk_nde_t* nde) return v; } -static qse_awk_val_t* eval_fnc (qse_awk_rtx_t* run, qse_awk_nde_t* nde) +static qse_awk_val_t* eval_fncall_fnc (qse_awk_rtx_t* run, qse_awk_nde_t* nde) { /* intrinsic function */ qse_awk_nde_fncall_t* call = (qse_awk_nde_fncall_t*)nde; @@ -5612,7 +5613,7 @@ static qse_awk_val_t* eval_fnc (qse_awk_rtx_t* run, qse_awk_nde_t* nde) return eval_call(run, nde, call->u.fnc.spec.arg.spec, QSE_NULL, QSE_NULL, QSE_NULL); } -static QSE_INLINE qse_awk_val_t* eval_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_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_fun_t* fun; @@ -5639,29 +5640,28 @@ static QSE_INLINE qse_awk_val_t* eval_fun_ex (qse_awk_rtx_t* rtx, qse_awk_nde_t* return eval_call(rtx, nde, QSE_NULL, fun, errhandler, eharg); } -static qse_awk_val_t* eval_fun (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) { - return eval_fun_ex(rtx, nde, QSE_NULL, QSE_NULL); + return eval_fncall_fncall_fun_ex(rtx, nde, QSE_NULL, QSE_NULL); } -static qse_awk_val_t* eval_fcv (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) { qse_awk_nde_fncall_t* call = (qse_awk_nde_fncall_t*)nde; qse_awk_val_t* fv, * rv; - fv = eval_expression(rtx, (qse_awk_nde_t*)call->u.fcv.var); + fv = eval_expression(rtx, (qse_awk_nde_t*)call->u.var.var); if (!fv) return QSE_NULL; qse_awk_rtx_refupval (rtx, fv); if (QSE_AWK_RTX_GETVALTYPE(rtx, fv) != QSE_AWK_VAL_FUN) { - /*SETERR_ARGX_LOC (rtx, QSE_AWK_EFUNNF, &call->u.fun.name, &nde->loc);*/ -/*printf ("NOT FUNCTION VALUE\n");*/ + SETERR_ARGX_LOC (rtx, QSE_AWK_ENOTFUN, &call->u.var.var->id.name, &nde->loc); rv = QSE_NULL; } else { - rv = eval_call(rtx, nde, QSE_NULL, ((qse_awk_val_fun_t*)fv)->fun, QSE_NULL, QSE_NULL ); + rv = eval_call(rtx, nde, QSE_NULL, ((qse_awk_val_fun_t*)fv)->fun, QSE_NULL, QSE_NULL); } qse_awk_rtx_refdownval (rtx, fv); @@ -6002,19 +6002,18 @@ static qse_size_t push_arg_from_nde (qse_awk_rtx_t* rtx, qse_awk_nde_fncall_t* c 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')) { /* a regular expression is passed to * the function as it is */ - v = eval_expression0 (rtx, p); + v = eval_expression0(rtx, p); } else { - v = eval_expression (rtx, p); + v = eval_expression(rtx, p); } - if (v == QSE_NULL) + if (!v) { UNWIND_RTX_STACK_ARG (rtx, nargs); return (qse_size_t)-1; @@ -6043,7 +6042,7 @@ static qse_size_t push_arg_from_nde (qse_awk_rtx_t* rtx, qse_awk_nde_fncall_t* c 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); + 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) @@ -6264,6 +6263,32 @@ static qse_awk_val_t* eval_rex (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde) return val; } +static qse_awk_val_t* eval_fun (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde) +{ + qse_awk_val_t* val; + qse_awk_fun_t* fun; + qse_htb_pair_t* pair; + + fun = ((qse_awk_nde_fun_t*)nde)->ptr; + if (!fun) + { + /* TODO: support bultin functions?, support module functions? */ + pair = qse_htb_search(rtx->awk->tree.funs, ((qse_awk_nde_fun_t*)nde)->name.ptr, ((qse_awk_nde_fun_t*)nde)->name.len); + if (!pair) + { + SETERR_ARGX_LOC (rtx, QSE_AWK_EFUNNF, &((qse_awk_nde_fun_t*)nde)->name, &nde->loc); + return QSE_NULL; + } + + fun = (qse_awk_fun_t*)QSE_HTB_VPTR(pair); + QSE_ASSERT (fun != QSE_NULL); + } + + val = qse_awk_rtx_makefunval(rtx, fun); + if (!val) ADJERR_LOC (rtx, &nde->loc); + return val; +} + static qse_awk_val_t* eval_named (qse_awk_rtx_t* rtx, qse_awk_nde_t* nde) { qse_htb_pair_t* pair; diff --git a/qse/lib/awk/tree.c b/qse/lib/awk/tree.c index 8b24153d..4c8579fa 100644 --- a/qse/lib/awk/tree.c +++ b/qse/lib/awk/tree.c @@ -497,6 +497,14 @@ static int print_expr (qse_awk_t* awk, qse_awk_nde_t* nde) break; } + case QSE_AWK_NDE_FUN: + { + PUT_SRCSTRN (awk, + ((qse_awk_nde_fun_t*)nde)->name.ptr, + ((qse_awk_nde_fun_t*)nde)->name.len); + break; + } + case QSE_AWK_NDE_ARG: { qse_char_t tmp[QSE_SIZEOF(qse_awk_int_t)*8+2]; @@ -710,7 +718,7 @@ static int print_expr (qse_awk_t* awk, qse_awk_nde_t* nde) break; } - case QSE_AWK_NDE_FNC: + case QSE_AWK_NDE_FNCALL_FNC: { qse_awk_nde_fncall_t* px = (qse_awk_nde_fncall_t*)nde; PUT_SRCSTRN (awk, px->u.fnc.info.name.ptr, px->u.fnc.info.name.len); @@ -720,7 +728,7 @@ static int print_expr (qse_awk_t* awk, qse_awk_nde_t* nde) break; } - case QSE_AWK_NDE_FUN: + case QSE_AWK_NDE_FNCALL_FUN: { qse_awk_nde_fncall_t* px = (qse_awk_nde_fncall_t*)nde; PUT_SRCSTRN (awk, px->u.fun.name.ptr, px->u.fun.name.len); @@ -730,10 +738,10 @@ static int print_expr (qse_awk_t* awk, qse_awk_nde_t* nde) break; } - case QSE_AWK_NDE_FCV: + case QSE_AWK_NDE_FNCALL_VAR: { qse_awk_nde_fncall_t* px = (qse_awk_nde_fncall_t*)nde; - PRINT_EXPR (awk, (qse_awk_nde_t*)px->u.fcv.var); + PRINT_EXPR (awk, (qse_awk_nde_t*)px->u.var.var); PUT_SRCSTR (awk, QSE_T("(")); PRINT_EXPR_LIST (awk, px->args); PUT_SRCSTR (awk, QSE_T(")")); @@ -1402,6 +1410,13 @@ void qse_awk_clrpt (qse_awk_t* awk, qse_awk_nde_t* tree) break; } + case QSE_AWK_NDE_FUN: + { + QSE_AWK_FREE (awk, ((qse_awk_nde_fun_t*)p)->name.ptr); + QSE_AWK_FREE (awk, p); + break; + } + case QSE_AWK_NDE_NAMED: case QSE_AWK_NDE_GBL: case QSE_AWK_NDE_LCL: @@ -1434,7 +1449,7 @@ void qse_awk_clrpt (qse_awk_t* awk, qse_awk_nde_t* tree) break; } - case QSE_AWK_NDE_FNC: + case QSE_AWK_NDE_FNCALL_FNC: { qse_awk_nde_fncall_t* px = (qse_awk_nde_fncall_t*)p; /* QSE_AWK_FREE (awk, px->u.fnc); */ @@ -1444,7 +1459,7 @@ void qse_awk_clrpt (qse_awk_t* awk, qse_awk_nde_t* tree) break; } - case QSE_AWK_NDE_FUN: + case QSE_AWK_NDE_FNCALL_FUN: { qse_awk_nde_fncall_t* px = (qse_awk_nde_fncall_t*)p; QSE_AWK_FREE (awk, px->u.fun.name.ptr); @@ -1453,10 +1468,10 @@ void qse_awk_clrpt (qse_awk_t* awk, qse_awk_nde_t* tree) break; } - case QSE_AWK_NDE_FCV: + case QSE_AWK_NDE_FNCALL_VAR: { qse_awk_nde_fncall_t* px = (qse_awk_nde_fncall_t*)p; - qse_awk_clrpt (awk, px->u.fcv.var); + qse_awk_clrpt (awk, (qse_awk_nde_t*)px->u.var.var); qse_awk_clrpt (awk, px->args); QSE_AWK_FREE (awk, p); break; diff --git a/qse/lib/awk/tree.h b/qse/lib/awk/tree.h index ad10f766..7c2de98a 100644 --- a/qse/lib/awk/tree.h +++ b/qse/lib/awk/tree.h @@ -59,10 +59,11 @@ typedef struct qse_awk_nde_pos_t qse_awk_nde_pos_t; typedef struct qse_awk_nde_int_t qse_awk_nde_int_t; typedef struct qse_awk_nde_flt_t qse_awk_nde_flt_t; - typedef struct qse_awk_nde_str_t qse_awk_nde_str_t; typedef struct qse_awk_nde_mbs_t qse_awk_nde_mbs_t; typedef struct qse_awk_nde_rex_t qse_awk_nde_rex_t; +typedef struct qse_awk_nde_fun_t qse_awk_nde_fun_t; + typedef struct qse_awk_nde_var_t qse_awk_nde_var_t; typedef struct qse_awk_nde_fncall_t qse_awk_nde_fncall_t; typedef struct qse_awk_nde_getline_t qse_awk_nde_getline_t; @@ -173,6 +174,14 @@ struct qse_awk_nde_rex_t void* code[2]; /* [0]: case sensitive, [1]: case insensitive */ }; +/* QSE_AWK_NDE_FUN - function as a value */ +struct qse_awk_nde_fun_t +{ + QSE_AWK_NDE_HDR; + qse_cstr_t name; /* function name */ + qse_awk_fun_t* ptr; /* QSE_NULL or actual pointer */ +}; + /* QSE_AWK_NDE_NAMED, QSE_AWK_NDE_GBL, * QSE_AWK_NDE_LCL, QSE_AWK_NDE_ARG * QSE_AWK_NDE_NAMEDIDX, QSE_AWK_NDE_GBLIDX, @@ -188,7 +197,7 @@ struct qse_awk_nde_var_t qse_awk_nde_t* idx; /* QSE_NULL for non-XXXXIDX */ }; -/* QSE_AWK_NDE_FNC, QSE_AWK_NDE_FUN */ +/* QSE_AWK_NDE_FNCALL_FNC, QSE_AWK_NDE_FNCALL_FUN, QSE_AWK_NDE_FNCALL_VAR */ struct qse_awk_nde_fncall_t { QSE_AWK_NDE_HDR; @@ -210,7 +219,7 @@ struct qse_awk_nde_fncall_t struct { qse_awk_nde_var_t* var; - } fcv; + } var; } u; qse_awk_nde_t* args; qse_size_t nargs; diff --git a/qse/lib/awk/val.c b/qse/lib/awk/val.c index d1fae342..8b6596a3 100644 --- a/qse/lib/awk/val.c +++ b/qse/lib/awk/val.c @@ -402,7 +402,7 @@ qse_awk_val_t* qse_awk_rtx_makembsval (qse_awk_rtx_t* rtx, const qse_mchar_t* pt qse_awk_val_mbs_t* val = QSE_NULL; qse_size_t xsz = len * QSE_SIZEOF(*ptr); - val = (qse_awk_val_mbs_t*)QSE_AWK_ALLOC(rtx->awk, QSE_SIZEOF(qse_awk_val_mbs_t) + xsz + QSE_SIZEOF(*ptr)); + val = (qse_awk_val_mbs_t*)qse_awk_callocmem(rtx->awk, QSE_SIZEOF(qse_awk_val_mbs_t) + xsz + QSE_SIZEOF(*ptr)); if (val == QSE_NULL) { qse_awk_rtx_seterrnum (rtx, QSE_AWK_ENOMEM, QSE_NULL); @@ -437,7 +437,7 @@ qse_awk_val_t* qse_awk_rtx_makerexval (qse_awk_rtx_t* rtx, const qse_cstr_t* str * the total size is just large enough for all these. */ totsz = QSE_SIZEOF(*val) + (QSE_SIZEOF(*str->ptr) * (str->len + 1)); - val = (qse_awk_val_rex_t*) QSE_AWK_ALLOC (rtx->awk, totsz); + val = (qse_awk_val_rex_t*)qse_awk_callocmem(rtx->awk, totsz); if (val == QSE_NULL) { qse_awk_rtx_seterrnum (rtx, QSE_AWK_ENOMEM, QSE_NULL); @@ -702,7 +702,7 @@ qse_awk_val_t* qse_awk_rtx_makerefval ( } else { - val = (qse_awk_val_ref_t*)QSE_AWK_ALLOC(rtx->awk, QSE_SIZEOF(qse_awk_val_ref_t)); + val = (qse_awk_val_ref_t*)qse_awk_callocmem(rtx->awk, QSE_SIZEOF(*val)); if (!val) { qse_awk_rtx_seterrnum (rtx, QSE_AWK_ENOMEM, QSE_NULL); @@ -723,7 +723,7 @@ qse_awk_val_t* qse_awk_rtx_makefunval (qse_awk_rtx_t* rtx, const qse_awk_fun_t* { qse_awk_val_fun_t* val; - val = (qse_awk_val_fun_t*)QSE_AWK_ALLOC(rtx->awk, QSE_SIZEOF(qse_awk_val_fun_t)); + val = (qse_awk_val_fun_t*)qse_awk_callocmem(rtx->awk, QSE_SIZEOF(*val)); if (!val) { qse_awk_rtx_seterrnum (rtx, QSE_AWK_ENOMEM, QSE_NULL); @@ -731,6 +731,9 @@ qse_awk_val_t* qse_awk_rtx_makefunval (qse_awk_rtx_t* rtx, const qse_awk_fun_t* } val->v_type = QSE_AWK_VAL_FUN; + val->ref = 0; + val->stat = 0; + val->nstr = 0; val->fun = (qse_awk_fun_t*)fun; return (qse_awk_val_t*)val; @@ -869,7 +872,7 @@ void qse_awk_rtx_freeval (qse_awk_rtx_t* rtx, qse_awk_val_t* val, int cache) } case QSE_AWK_VAL_FUN: - /* nothing to do */ + QSE_AWK_FREE (rtx->awk, val); break; } @@ -1468,7 +1471,7 @@ static int val_ref_to_str (qse_awk_rtx_t* rtx, const qse_awk_val_ref_t* ref, qse int qse_awk_rtx_valtostr (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_awk_rtx_valtostr_out_t* out) { - qse_awk_val_type_t vtype = QSE_AWK_RTX_GETVALTYPE (rtx, v); + qse_awk_val_type_t vtype = QSE_AWK_RTX_GETVALTYPE(rtx, v); switch (vtype) { @@ -1519,7 +1522,7 @@ int qse_awk_rtx_valtostr (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_awk_rt case QSE_AWK_VAL_FUN: { - return qse_awk_rtx_makestrval2(rtx, QSE_T("@@"), 1, ((qse_awk_val_fun_t*)v)->fun->name.ptr, ((qse_awk_val_fun_t*)v)->fun->name.len); + return str_to_str(rtx, ((qse_awk_val_fun_t*)v)->fun->name.ptr, ((qse_awk_val_fun_t*)v)->fun->name.len, out); } } @@ -1823,7 +1826,7 @@ int qse_awk_rtx_valtonum (qse_awk_rtx_t* rtx, const qse_awk_val_t* v, qse_awk_in case QSE_AWK_VAL_FUN: { - /* TODO: */ + /* unable to convert a function to a number */ break; } } @@ -2163,7 +2166,7 @@ void qse_awk_dprintval (qse_awk_rtx_t* run, qse_awk_val_t* val) break; case QSE_AWK_VAL_FUN: - qse_errputstrf (QSE_T("@@%.*s"), (int)((qse_awk_val_fun_t*)val)->fun->name.len, ((qse_awk_val_fun_t*)val)->fun->name.ptr); + qse_errputstrf (QSE_T("%.*s"), (int)((qse_awk_val_fun_t*)val)->fun->name.len, ((qse_awk_val_fun_t*)val)->fun->name.ptr); break; default: