awk: make builtin definitions more understandable, no code changes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
640212ae0e
commit
786ca197ad
@ -331,8 +331,7 @@ if ((n) & TC_NUMBER ) debug_printf_parse(" NUMBER" ); \
|
|||||||
#define OPNMASK 0x007F
|
#define OPNMASK 0x007F
|
||||||
|
|
||||||
/* operator priority is a highest byte (even: r->l, odd: l->r grouping)
|
/* operator priority is a highest byte (even: r->l, odd: l->r grouping)
|
||||||
* For builtins it has different meaning: n n s3 s2 s1 v3 v2 v1,
|
* (for builtins it has different meaning)
|
||||||
* n - min. number of args, vN - resolve Nth arg to var, sN - resolve to string
|
|
||||||
*/
|
*/
|
||||||
#undef P
|
#undef P
|
||||||
#undef PRIMASK
|
#undef PRIMASK
|
||||||
@ -430,8 +429,6 @@ static const char tokenlist[] ALIGN1 =
|
|||||||
/* compiler adds trailing "\0" */
|
/* compiler adds trailing "\0" */
|
||||||
;
|
;
|
||||||
|
|
||||||
#define OC_B OC_BUILTIN
|
|
||||||
|
|
||||||
static const uint32_t tokeninfo[] ALIGN4 = {
|
static const uint32_t tokeninfo[] ALIGN4 = {
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@ -464,20 +461,43 @@ static const uint32_t tokeninfo[] ALIGN4 = {
|
|||||||
OC_RETURN|Vx, OC_EXIT|Nx,
|
OC_RETURN|Vx, OC_EXIT|Nx,
|
||||||
ST_WHILE,
|
ST_WHILE,
|
||||||
0, /* else */
|
0, /* else */
|
||||||
OC_B|B_an|P(0x83), OC_B|B_co|P(0x41), OC_B|B_ls|P(0x83), OC_B|B_or|P(0x83),
|
// OC_B's are builtins with enforced minimum number of arguments (two upper bits).
|
||||||
OC_B|B_rs|P(0x83), OC_B|B_xo|P(0x83),
|
// Highest byte bit pattern: nn s3s2s1 v3v2v1
|
||||||
OC_FBLTIN|Sx|F_cl, OC_FBLTIN|Sx|F_sy, OC_FBLTIN|Sx|F_ff, OC_B|B_a2|P(0x83),
|
// nn - min. number of args, sN - resolve Nth arg to string, vN - resolve to var
|
||||||
OC_FBLTIN|Nx|F_co, OC_FBLTIN|Nx|F_ex, OC_FBLTIN|Nx|F_in, OC_FBLTIN|Nx|F_lg,
|
// OC_FBLTIN's are builtins with one optional argument,
|
||||||
OC_FBLTIN|F_rn, OC_FBLTIN|Nx|F_si, OC_FBLTIN|Nx|F_sq, OC_FBLTIN|Nx|F_sr,
|
// TODO: enforce exactly one arg for: system, close, cos, sin, exp, int, log, sqrt
|
||||||
OC_B|B_ge|P(0xd6), OC_B|B_gs|P(0xb6), OC_B|B_ix|P(0x9b), /* OC_FBLTIN|Sx|F_le, was here */
|
// zero args for: rand systime
|
||||||
OC_B|B_ma|P(0x89), OC_B|B_sp|P(0x8b), OC_SPRINTF, OC_B|B_su|P(0xb6),
|
// Do have one optional arg: fflush, srand, length
|
||||||
OC_B|B_ss|P(0x8f), OC_FBLTIN|F_ti, OC_B|B_ti|P(0x0b), OC_B|B_mt|P(0x0b),
|
#define OC_B OC_BUILTIN
|
||||||
OC_B|B_lo|P(0x49), OC_B|B_up|P(0x49),
|
#define A1 P(0x40) /*one arg*/
|
||||||
OC_FBLTIN|Sx|F_le, /* TC_LENGTH */
|
#define A2 P(0x80) /*two args*/
|
||||||
OC_GETLINE|SV|P(0),
|
#define A3 P(0xc0) /*three args*/
|
||||||
0, 0,
|
#define __v P(1)
|
||||||
0,
|
#define _vv P(3)
|
||||||
0 /* TC_END */
|
#define __s__v P(9)
|
||||||
|
#define __s_vv P(0x0b)
|
||||||
|
#define __svvv P(0x0f)
|
||||||
|
#define _ss_vv P(0x1b)
|
||||||
|
#define _s_vv_ P(0x16)
|
||||||
|
#define ss_vv_ P(0x36)
|
||||||
|
OC_B|B_an|_vv|A2, OC_B|B_co|__v|A1, OC_B|B_ls|_vv|A2, OC_B|B_or|_vv|A2, // and compl lshift or
|
||||||
|
OC_B|B_rs|_vv|A2, OC_B|B_xo|_vv|A2, // rshift xor
|
||||||
|
OC_FBLTIN|Sx|F_cl, OC_FBLTIN|Sx|F_sy, OC_FBLTIN|Sx|F_ff, OC_B|B_a2|_vv|A2, // close system fflush atan2
|
||||||
|
OC_FBLTIN|Nx|F_co, OC_FBLTIN|Nx|F_ex, OC_FBLTIN|Nx|F_in, OC_FBLTIN|Nx|F_lg, // cos exp int log
|
||||||
|
OC_FBLTIN|F_rn, OC_FBLTIN|Nx|F_si, OC_FBLTIN|Nx|F_sq, OC_FBLTIN|Nx|F_sr, // rand sin sqrt srand
|
||||||
|
OC_B|B_ge|_s_vv_|A3, OC_B|B_gs|ss_vv_|A2, OC_B|B_ix|_ss_vv|A2, // gensub gsub index /*length was here*/
|
||||||
|
OC_B|B_ma|__s__v|A2, OC_B|B_sp|__s_vv|A2, OC_SPRINTF, OC_B|B_su|ss_vv_|A2, // match split sprintf sub
|
||||||
|
OC_B|B_ss|__svvv|A2, OC_FBLTIN|F_ti, OC_B|B_ti|__s_vv, OC_B|B_mt|__s_vv, // substr systime strftime mktime
|
||||||
|
OC_B|B_lo|__s__v|A1, OC_B|B_up|__s__v|A1, // tolower toupper
|
||||||
|
OC_FBLTIN|Sx|F_le, // length
|
||||||
|
OC_GETLINE|SV, // getline
|
||||||
|
0, 0, // func function
|
||||||
|
0, // BEGIN
|
||||||
|
0 // END
|
||||||
|
#undef A1
|
||||||
|
#undef A2
|
||||||
|
#undef A3
|
||||||
|
#undef OC_B
|
||||||
};
|
};
|
||||||
|
|
||||||
/* internal variable names and their initial values */
|
/* internal variable names and their initial values */
|
||||||
@ -1630,6 +1650,7 @@ static void chain_group(void)
|
|||||||
debug_printf_parse("%s: OC_BREAK\n", __func__);
|
debug_printf_parse("%s: OC_BREAK\n", __func__);
|
||||||
n = chain_node(OC_EXEC);
|
n = chain_node(OC_EXEC);
|
||||||
n->a.n = break_ptr;
|
n->a.n = break_ptr;
|
||||||
|
//TODO: if break_ptr is NULL, syntax error (not in the loop)?
|
||||||
chain_expr(t_info);
|
chain_expr(t_info);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1637,6 +1658,7 @@ static void chain_group(void)
|
|||||||
debug_printf_parse("%s: OC_CONTINUE\n", __func__);
|
debug_printf_parse("%s: OC_CONTINUE\n", __func__);
|
||||||
n = chain_node(OC_EXEC);
|
n = chain_node(OC_EXEC);
|
||||||
n->a.n = continue_ptr;
|
n->a.n = continue_ptr;
|
||||||
|
//TODO: if continue_ptr is NULL, syntax error (not in the loop)?
|
||||||
chain_expr(t_info);
|
chain_expr(t_info);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1799,8 +1821,8 @@ static regex_t *as_regex(node *op, regex_t *preg)
|
|||||||
return icase ? op->r.ire : op->l.re;
|
return icase ? op->r.ire : op->l.re;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TMPVAR (&G.as_regex__tmpvar)
|
|
||||||
//tmpvar = nvalloc(1);
|
//tmpvar = nvalloc(1);
|
||||||
|
#define TMPVAR (&G.as_regex__tmpvar)
|
||||||
// We use a single "static" tmpvar (instead of on-stack or malloced one)
|
// We use a single "static" tmpvar (instead of on-stack or malloced one)
|
||||||
// to decrease memory consumption in deeply-recursive awk programs.
|
// to decrease memory consumption in deeply-recursive awk programs.
|
||||||
// The rule to work safely is to never call evaluate() while our static
|
// The rule to work safely is to never call evaluate() while our static
|
||||||
@ -2720,8 +2742,6 @@ static var *evaluate(node *op, var *res)
|
|||||||
#define sreg (G.evaluate__sreg)
|
#define sreg (G.evaluate__sreg)
|
||||||
|
|
||||||
var *tmpvars;
|
var *tmpvars;
|
||||||
#define TMPVAR0 (tmpvars)
|
|
||||||
#define TMPVAR1 (tmpvars + 1)
|
|
||||||
|
|
||||||
if (!op)
|
if (!op)
|
||||||
return setvar_s(res, NULL);
|
return setvar_s(res, NULL);
|
||||||
@ -2729,6 +2749,8 @@ static var *evaluate(node *op, var *res)
|
|||||||
debug_printf_eval("entered %s()\n", __func__);
|
debug_printf_eval("entered %s()\n", __func__);
|
||||||
|
|
||||||
tmpvars = nvalloc(2);
|
tmpvars = nvalloc(2);
|
||||||
|
#define TMPVAR0 (tmpvars)
|
||||||
|
#define TMPVAR1 (tmpvars + 1)
|
||||||
|
|
||||||
while (op) {
|
while (op) {
|
||||||
struct {
|
struct {
|
||||||
@ -3166,7 +3188,7 @@ static var *evaluate(node *op, var *res)
|
|||||||
rstream *rsm;
|
rstream *rsm;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
rsm = (rstream *)hash_search(fdhash, L.s);
|
rsm = (rstream *)hash_search(fdhash, L.s);
|
||||||
debug_printf_eval("OC_FBLTIN F_cl rsm:%p\n", rsm);
|
debug_printf_eval("OC_FBLTIN close: op1:%p s:'%s' rsm:%p\n", op1, L.s, rsm);
|
||||||
if (rsm) {
|
if (rsm) {
|
||||||
debug_printf_eval("OC_FBLTIN F_cl "
|
debug_printf_eval("OC_FBLTIN F_cl "
|
||||||
"rsm->is_pipe:%d, ->F:%p\n",
|
"rsm->is_pipe:%d, ->F:%p\n",
|
||||||
@ -3177,6 +3199,11 @@ static var *evaluate(node *op, var *res)
|
|||||||
*/
|
*/
|
||||||
if (rsm->F)
|
if (rsm->F)
|
||||||
err = rsm->is_pipe ? pclose(rsm->F) : fclose(rsm->F);
|
err = rsm->is_pipe ? pclose(rsm->F) : fclose(rsm->F);
|
||||||
|
//TODO: fix this case:
|
||||||
|
// $ awk 'BEGIN { print close(""); print ERRNO }'
|
||||||
|
// -1
|
||||||
|
// close of redirection that was never opened
|
||||||
|
// (we print 0, 0)
|
||||||
free(rsm->buffer);
|
free(rsm->buffer);
|
||||||
hash_remove(fdhash, L.s);
|
hash_remove(fdhash, L.s);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user