diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2021-07-02 17:32:08 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-07-02 17:32:08 +0200 |
commit | 786ca197ad1305607efaccb067c19931d9e765b1 (patch) | |
tree | 3844aa19ef61498d8c7ad25a33a5914671bed526 | |
parent | 640212ae0ea8a1b47cd73a080d77b25b9f3ccd40 (diff) | |
download | busybox-w32-786ca197ad1305607efaccb067c19931d9e765b1.tar.gz busybox-w32-786ca197ad1305607efaccb067c19931d9e765b1.tar.bz2 busybox-w32-786ca197ad1305607efaccb067c19931d9e765b1.zip |
awk: make builtin definitions more understandable, no code changes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | editors/awk.c | 71 |
1 files changed, 49 insertions, 22 deletions
diff --git a/editors/awk.c b/editors/awk.c index a3dda6959..fb841687e 100644 --- a/editors/awk.c +++ b/editors/awk.c | |||
@@ -331,8 +331,7 @@ if ((n) & TC_NUMBER ) debug_printf_parse(" NUMBER" ); \ | |||
331 | #define OPNMASK 0x007F | 331 | #define OPNMASK 0x007F |
332 | 332 | ||
333 | /* operator priority is a highest byte (even: r->l, odd: l->r grouping) | 333 | /* operator priority is a highest byte (even: r->l, odd: l->r grouping) |
334 | * For builtins it has different meaning: n n s3 s2 s1 v3 v2 v1, | 334 | * (for builtins it has different meaning) |
335 | * n - min. number of args, vN - resolve Nth arg to var, sN - resolve to string | ||
336 | */ | 335 | */ |
337 | #undef P | 336 | #undef P |
338 | #undef PRIMASK | 337 | #undef PRIMASK |
@@ -430,8 +429,6 @@ static const char tokenlist[] ALIGN1 = | |||
430 | /* compiler adds trailing "\0" */ | 429 | /* compiler adds trailing "\0" */ |
431 | ; | 430 | ; |
432 | 431 | ||
433 | #define OC_B OC_BUILTIN | ||
434 | |||
435 | static const uint32_t tokeninfo[] ALIGN4 = { | 432 | static const uint32_t tokeninfo[] ALIGN4 = { |
436 | 0, | 433 | 0, |
437 | 0, | 434 | 0, |
@@ -464,20 +461,43 @@ static const uint32_t tokeninfo[] ALIGN4 = { | |||
464 | OC_RETURN|Vx, OC_EXIT|Nx, | 461 | OC_RETURN|Vx, OC_EXIT|Nx, |
465 | ST_WHILE, | 462 | ST_WHILE, |
466 | 0, /* else */ | 463 | 0, /* else */ |
467 | OC_B|B_an|P(0x83), OC_B|B_co|P(0x41), OC_B|B_ls|P(0x83), OC_B|B_or|P(0x83), | 464 | // OC_B's are builtins with enforced minimum number of arguments (two upper bits). |
468 | OC_B|B_rs|P(0x83), OC_B|B_xo|P(0x83), | 465 | // Highest byte bit pattern: nn s3s2s1 v3v2v1 |
469 | OC_FBLTIN|Sx|F_cl, OC_FBLTIN|Sx|F_sy, OC_FBLTIN|Sx|F_ff, OC_B|B_a2|P(0x83), | 466 | // nn - min. number of args, sN - resolve Nth arg to string, vN - resolve to var |
470 | OC_FBLTIN|Nx|F_co, OC_FBLTIN|Nx|F_ex, OC_FBLTIN|Nx|F_in, OC_FBLTIN|Nx|F_lg, | 467 | // OC_FBLTIN's are builtins with one optional argument, |
471 | OC_FBLTIN|F_rn, OC_FBLTIN|Nx|F_si, OC_FBLTIN|Nx|F_sq, OC_FBLTIN|Nx|F_sr, | 468 | // TODO: enforce exactly one arg for: system, close, cos, sin, exp, int, log, sqrt |
472 | 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 */ | 469 | // zero args for: rand systime |
473 | OC_B|B_ma|P(0x89), OC_B|B_sp|P(0x8b), OC_SPRINTF, OC_B|B_su|P(0xb6), | 470 | // Do have one optional arg: fflush, srand, length |
474 | OC_B|B_ss|P(0x8f), OC_FBLTIN|F_ti, OC_B|B_ti|P(0x0b), OC_B|B_mt|P(0x0b), | 471 | #define OC_B OC_BUILTIN |
475 | OC_B|B_lo|P(0x49), OC_B|B_up|P(0x49), | 472 | #define A1 P(0x40) /*one arg*/ |
476 | OC_FBLTIN|Sx|F_le, /* TC_LENGTH */ | 473 | #define A2 P(0x80) /*two args*/ |
477 | OC_GETLINE|SV|P(0), | 474 | #define A3 P(0xc0) /*three args*/ |
478 | 0, 0, | 475 | #define __v P(1) |
479 | 0, | 476 | #define _vv P(3) |
480 | 0 /* TC_END */ | 477 | #define __s__v P(9) |
478 | #define __s_vv P(0x0b) | ||
479 | #define __svvv P(0x0f) | ||
480 | #define _ss_vv P(0x1b) | ||
481 | #define _s_vv_ P(0x16) | ||
482 | #define ss_vv_ P(0x36) | ||
483 | 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 | ||
484 | OC_B|B_rs|_vv|A2, OC_B|B_xo|_vv|A2, // rshift xor | ||
485 | 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 | ||
486 | OC_FBLTIN|Nx|F_co, OC_FBLTIN|Nx|F_ex, OC_FBLTIN|Nx|F_in, OC_FBLTIN|Nx|F_lg, // cos exp int log | ||
487 | OC_FBLTIN|F_rn, OC_FBLTIN|Nx|F_si, OC_FBLTIN|Nx|F_sq, OC_FBLTIN|Nx|F_sr, // rand sin sqrt srand | ||
488 | 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*/ | ||
489 | 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 | ||
490 | 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 | ||
491 | OC_B|B_lo|__s__v|A1, OC_B|B_up|__s__v|A1, // tolower toupper | ||
492 | OC_FBLTIN|Sx|F_le, // length | ||
493 | OC_GETLINE|SV, // getline | ||
494 | 0, 0, // func function | ||
495 | 0, // BEGIN | ||
496 | 0 // END | ||
497 | #undef A1 | ||
498 | #undef A2 | ||
499 | #undef A3 | ||
500 | #undef OC_B | ||
481 | }; | 501 | }; |
482 | 502 | ||
483 | /* internal variable names and their initial values */ | 503 | /* internal variable names and their initial values */ |
@@ -1630,6 +1650,7 @@ static void chain_group(void) | |||
1630 | debug_printf_parse("%s: OC_BREAK\n", __func__); | 1650 | debug_printf_parse("%s: OC_BREAK\n", __func__); |
1631 | n = chain_node(OC_EXEC); | 1651 | n = chain_node(OC_EXEC); |
1632 | n->a.n = break_ptr; | 1652 | n->a.n = break_ptr; |
1653 | //TODO: if break_ptr is NULL, syntax error (not in the loop)? | ||
1633 | chain_expr(t_info); | 1654 | chain_expr(t_info); |
1634 | break; | 1655 | break; |
1635 | 1656 | ||
@@ -1637,6 +1658,7 @@ static void chain_group(void) | |||
1637 | debug_printf_parse("%s: OC_CONTINUE\n", __func__); | 1658 | debug_printf_parse("%s: OC_CONTINUE\n", __func__); |
1638 | n = chain_node(OC_EXEC); | 1659 | n = chain_node(OC_EXEC); |
1639 | n->a.n = continue_ptr; | 1660 | n->a.n = continue_ptr; |
1661 | //TODO: if continue_ptr is NULL, syntax error (not in the loop)? | ||
1640 | chain_expr(t_info); | 1662 | chain_expr(t_info); |
1641 | break; | 1663 | break; |
1642 | 1664 | ||
@@ -1799,8 +1821,8 @@ static regex_t *as_regex(node *op, regex_t *preg) | |||
1799 | return icase ? op->r.ire : op->l.re; | 1821 | return icase ? op->r.ire : op->l.re; |
1800 | } | 1822 | } |
1801 | 1823 | ||
1802 | #define TMPVAR (&G.as_regex__tmpvar) | ||
1803 | //tmpvar = nvalloc(1); | 1824 | //tmpvar = nvalloc(1); |
1825 | #define TMPVAR (&G.as_regex__tmpvar) | ||
1804 | // We use a single "static" tmpvar (instead of on-stack or malloced one) | 1826 | // We use a single "static" tmpvar (instead of on-stack or malloced one) |
1805 | // to decrease memory consumption in deeply-recursive awk programs. | 1827 | // to decrease memory consumption in deeply-recursive awk programs. |
1806 | // The rule to work safely is to never call evaluate() while our static | 1828 | // The rule to work safely is to never call evaluate() while our static |
@@ -2720,8 +2742,6 @@ static var *evaluate(node *op, var *res) | |||
2720 | #define sreg (G.evaluate__sreg) | 2742 | #define sreg (G.evaluate__sreg) |
2721 | 2743 | ||
2722 | var *tmpvars; | 2744 | var *tmpvars; |
2723 | #define TMPVAR0 (tmpvars) | ||
2724 | #define TMPVAR1 (tmpvars + 1) | ||
2725 | 2745 | ||
2726 | if (!op) | 2746 | if (!op) |
2727 | return setvar_s(res, NULL); | 2747 | return setvar_s(res, NULL); |
@@ -2729,6 +2749,8 @@ static var *evaluate(node *op, var *res) | |||
2729 | debug_printf_eval("entered %s()\n", __func__); | 2749 | debug_printf_eval("entered %s()\n", __func__); |
2730 | 2750 | ||
2731 | tmpvars = nvalloc(2); | 2751 | tmpvars = nvalloc(2); |
2752 | #define TMPVAR0 (tmpvars) | ||
2753 | #define TMPVAR1 (tmpvars + 1) | ||
2732 | 2754 | ||
2733 | while (op) { | 2755 | while (op) { |
2734 | struct { | 2756 | struct { |
@@ -3166,7 +3188,7 @@ static var *evaluate(node *op, var *res) | |||
3166 | rstream *rsm; | 3188 | rstream *rsm; |
3167 | int err = 0; | 3189 | int err = 0; |
3168 | rsm = (rstream *)hash_search(fdhash, L.s); | 3190 | rsm = (rstream *)hash_search(fdhash, L.s); |
3169 | debug_printf_eval("OC_FBLTIN F_cl rsm:%p\n", rsm); | 3191 | debug_printf_eval("OC_FBLTIN close: op1:%p s:'%s' rsm:%p\n", op1, L.s, rsm); |
3170 | if (rsm) { | 3192 | if (rsm) { |
3171 | debug_printf_eval("OC_FBLTIN F_cl " | 3193 | debug_printf_eval("OC_FBLTIN F_cl " |
3172 | "rsm->is_pipe:%d, ->F:%p\n", | 3194 | "rsm->is_pipe:%d, ->F:%p\n", |
@@ -3177,6 +3199,11 @@ static var *evaluate(node *op, var *res) | |||
3177 | */ | 3199 | */ |
3178 | if (rsm->F) | 3200 | if (rsm->F) |
3179 | err = rsm->is_pipe ? pclose(rsm->F) : fclose(rsm->F); | 3201 | err = rsm->is_pipe ? pclose(rsm->F) : fclose(rsm->F); |
3202 | //TODO: fix this case: | ||
3203 | // $ awk 'BEGIN { print close(""); print ERRNO }' | ||
3204 | // -1 | ||
3205 | // close of redirection that was never opened | ||
3206 | // (we print 0, 0) | ||
3180 | free(rsm->buffer); | 3207 | free(rsm->buffer); |
3181 | hash_remove(fdhash, L.s); | 3208 | hash_remove(fdhash, L.s); |
3182 | } | 3209 | } |