aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2021-07-02 17:32:08 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2021-07-02 17:32:08 +0200
commit786ca197ad1305607efaccb067c19931d9e765b1 (patch)
tree3844aa19ef61498d8c7ad25a33a5914671bed526
parent640212ae0ea8a1b47cd73a080d77b25b9f3ccd40 (diff)
downloadbusybox-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.c71
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
435static const uint32_t tokeninfo[] ALIGN4 = { 432static 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 }