diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-01-07 01:19:08 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-01-07 01:19:08 +0100 |
commit | 6f4a785bd1bd0e6973b5c27b34b86655b1d7a602 (patch) | |
tree | f7c5acf0f2f844883e5e183b45d85ba0ee5471df | |
parent | 7367a949a6a81d71d524f0635a212371120df4e0 (diff) | |
download | busybox-w32-6f4a785bd1bd0e6973b5c27b34b86655b1d7a602.tar.gz busybox-w32-6f4a785bd1bd0e6973b5c27b34b86655b1d7a602.tar.bz2 busybox-w32-6f4a785bd1bd0e6973b5c27b34b86655b1d7a602.zip |
awk: fix 'delete array[var--]' decrementing var twice
function old new delta
evaluate 3395 3390 -5
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | editors/awk.c | 54 | ||||
-rwxr-xr-x | testsuite/awk.tests | 19 |
2 files changed, 50 insertions, 23 deletions
diff --git a/editors/awk.c b/editors/awk.c index d40c7816a..8f523ea28 100644 --- a/editors/awk.c +++ b/editors/awk.c | |||
@@ -2514,6 +2514,32 @@ static var *evaluate(node *op, var *res) | |||
2514 | op1 = op->l.n; | 2514 | op1 = op->l.n; |
2515 | debug_printf_eval("opinfo:%08x opn:%08x\n", opinfo, opn); | 2515 | debug_printf_eval("opinfo:%08x opn:%08x\n", opinfo, opn); |
2516 | 2516 | ||
2517 | /* "delete" is special: | ||
2518 | * "delete array[var--]" must evaluate index expr only once, | ||
2519 | * must not evaluate it in "execute inevitable things" part. | ||
2520 | */ | ||
2521 | if (XC(opinfo & OPCLSMASK) == XC(OC_DELETE)) { | ||
2522 | uint32_t info = op1->info & OPCLSMASK; | ||
2523 | var *v; | ||
2524 | |||
2525 | debug_printf_eval("DELETE\n"); | ||
2526 | if (info == OC_VAR) { | ||
2527 | v = op1->l.v; | ||
2528 | } else if (info == OC_FNARG) { | ||
2529 | v = &fnargs[op1->l.aidx]; | ||
2530 | } else { | ||
2531 | syntax_error(EMSG_NOT_ARRAY); | ||
2532 | } | ||
2533 | if (op1->r.n) { /* array ref? */ | ||
2534 | const char *s; | ||
2535 | s = getvar_s(evaluate(op1->r.n, v1)); | ||
2536 | hash_remove(iamarray(v), s); | ||
2537 | } else { | ||
2538 | clear_array(iamarray(v)); | ||
2539 | } | ||
2540 | goto next; | ||
2541 | } | ||
2542 | |||
2517 | /* execute inevitable things */ | 2543 | /* execute inevitable things */ |
2518 | if (opinfo & OF_RES1) | 2544 | if (opinfo & OF_RES1) |
2519 | L.v = evaluate(op1, v1); | 2545 | L.v = evaluate(op1, v1); |
@@ -2621,28 +2647,7 @@ static var *evaluate(node *op, var *res) | |||
2621 | break; | 2647 | break; |
2622 | } | 2648 | } |
2623 | 2649 | ||
2624 | case XC( OC_DELETE ): { | 2650 | /* case XC( OC_DELETE ): - moved to happen before arg evaluation */ |
2625 | uint32_t info = op1->info & OPCLSMASK; | ||
2626 | var *v; | ||
2627 | |||
2628 | if (info == OC_VAR) { | ||
2629 | v = op1->l.v; | ||
2630 | } else if (info == OC_FNARG) { | ||
2631 | v = &fnargs[op1->l.aidx]; | ||
2632 | } else { | ||
2633 | syntax_error(EMSG_NOT_ARRAY); | ||
2634 | } | ||
2635 | |||
2636 | if (op1->r.n) { | ||
2637 | const char *s; | ||
2638 | clrvar(L.v); | ||
2639 | s = getvar_s(evaluate(op1->r.n, v1)); | ||
2640 | hash_remove(iamarray(v), s); | ||
2641 | } else { | ||
2642 | clear_array(iamarray(v)); | ||
2643 | } | ||
2644 | break; | ||
2645 | } | ||
2646 | 2651 | ||
2647 | case XC( OC_NEWSOURCE ): | 2652 | case XC( OC_NEWSOURCE ): |
2648 | g_progname = op->l.new_progname; | 2653 | g_progname = op->l.new_progname; |
@@ -2666,12 +2671,14 @@ static var *evaluate(node *op, var *res) | |||
2666 | /* -- recursive node type -- */ | 2671 | /* -- recursive node type -- */ |
2667 | 2672 | ||
2668 | case XC( OC_VAR ): | 2673 | case XC( OC_VAR ): |
2674 | debug_printf_eval("VAR\n"); | ||
2669 | L.v = op->l.v; | 2675 | L.v = op->l.v; |
2670 | if (L.v == intvar[NF]) | 2676 | if (L.v == intvar[NF]) |
2671 | split_f0(); | 2677 | split_f0(); |
2672 | goto v_cont; | 2678 | goto v_cont; |
2673 | 2679 | ||
2674 | case XC( OC_FNARG ): | 2680 | case XC( OC_FNARG ): |
2681 | debug_printf_eval("FNARG[%d]\n", op->l.aidx); | ||
2675 | L.v = &fnargs[op->l.aidx]; | 2682 | L.v = &fnargs[op->l.aidx]; |
2676 | v_cont: | 2683 | v_cont: |
2677 | res = op->r.n ? findvar(iamarray(L.v), R.s) : L.v; | 2684 | res = op->r.n ? findvar(iamarray(L.v), R.s) : L.v; |
@@ -3035,7 +3042,8 @@ static var *evaluate(node *op, var *res) | |||
3035 | 3042 | ||
3036 | default: | 3043 | default: |
3037 | syntax_error(EMSG_POSSIBLE_ERROR); | 3044 | syntax_error(EMSG_POSSIBLE_ERROR); |
3038 | } | 3045 | } /* switch */ |
3046 | next: | ||
3039 | if ((opinfo & OPCLSMASK) <= SHIFT_TIL_THIS) | 3047 | if ((opinfo & OPCLSMASK) <= SHIFT_TIL_THIS) |
3040 | op = op->a.n; | 3048 | op = op->a.n; |
3041 | if ((opinfo & OPCLSMASK) >= RECUR_FROM_THIS) | 3049 | if ((opinfo & OPCLSMASK) >= RECUR_FROM_THIS) |
diff --git a/testsuite/awk.tests b/testsuite/awk.tests index 82937bc10..ad0583afb 100755 --- a/testsuite/awk.tests +++ b/testsuite/awk.tests | |||
@@ -261,6 +261,25 @@ end d | |||
261 | " \ | 261 | " \ |
262 | "" "" | 262 | "" "" |
263 | 263 | ||
264 | prg=' | ||
265 | BEGIN{ | ||
266 | cnt = 0 | ||
267 | a[cnt] = "zeroth" | ||
268 | a[++cnt] = "first" | ||
269 | delete a[cnt--] | ||
270 | print cnt | ||
271 | print "[0]:" a[0] | ||
272 | print "[1]:" a[1] | ||
273 | }' | ||
274 | testing "awk 'delete a[v--]' evaluates v-- once" \ | ||
275 | "awk '$prg'" \ | ||
276 | "\ | ||
277 | 0 | ||
278 | [0]:zeroth | ||
279 | [1]: | ||
280 | " \ | ||
281 | "" "" | ||
282 | |||
264 | testing "awk handles empty ()" \ | 283 | testing "awk handles empty ()" \ |
265 | "awk 'BEGIN {print()}' 2>&1" "awk: cmd. line:1: Empty sequence\n" "" "" | 284 | "awk 'BEGIN {print()}' 2>&1" "awk: cmd. line:1: Empty sequence\n" "" "" |
266 | 285 | ||