From 6f4a785bd1bd0e6973b5c27b34b86655b1d7a602 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 7 Jan 2018 01:19:08 +0100 Subject: awk: fix 'delete array[var--]' decrementing var twice function old new delta evaluate 3395 3390 -5 Signed-off-by: Denys Vlasenko --- editors/awk.c | 54 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 23 deletions(-) (limited to 'editors/awk.c') diff --git a/editors/awk.c b/editors/awk.c index d40c781..8f523ea 100644 --- a/editors/awk.c +++ b/editors/awk.c @@ -2514,6 +2514,32 @@ static var *evaluate(node *op, var *res) op1 = op->l.n; debug_printf_eval("opinfo:%08x opn:%08x\n", opinfo, opn); + /* "delete" is special: + * "delete array[var--]" must evaluate index expr only once, + * must not evaluate it in "execute inevitable things" part. + */ + if (XC(opinfo & OPCLSMASK) == XC(OC_DELETE)) { + uint32_t info = op1->info & OPCLSMASK; + var *v; + + debug_printf_eval("DELETE\n"); + if (info == OC_VAR) { + v = op1->l.v; + } else if (info == OC_FNARG) { + v = &fnargs[op1->l.aidx]; + } else { + syntax_error(EMSG_NOT_ARRAY); + } + if (op1->r.n) { /* array ref? */ + const char *s; + s = getvar_s(evaluate(op1->r.n, v1)); + hash_remove(iamarray(v), s); + } else { + clear_array(iamarray(v)); + } + goto next; + } + /* execute inevitable things */ if (opinfo & OF_RES1) L.v = evaluate(op1, v1); @@ -2621,28 +2647,7 @@ static var *evaluate(node *op, var *res) break; } - case XC( OC_DELETE ): { - uint32_t info = op1->info & OPCLSMASK; - var *v; - - if (info == OC_VAR) { - v = op1->l.v; - } else if (info == OC_FNARG) { - v = &fnargs[op1->l.aidx]; - } else { - syntax_error(EMSG_NOT_ARRAY); - } - - if (op1->r.n) { - const char *s; - clrvar(L.v); - s = getvar_s(evaluate(op1->r.n, v1)); - hash_remove(iamarray(v), s); - } else { - clear_array(iamarray(v)); - } - break; - } + /* case XC( OC_DELETE ): - moved to happen before arg evaluation */ case XC( OC_NEWSOURCE ): g_progname = op->l.new_progname; @@ -2666,12 +2671,14 @@ static var *evaluate(node *op, var *res) /* -- recursive node type -- */ case XC( OC_VAR ): + debug_printf_eval("VAR\n"); L.v = op->l.v; if (L.v == intvar[NF]) split_f0(); goto v_cont; case XC( OC_FNARG ): + debug_printf_eval("FNARG[%d]\n", op->l.aidx); L.v = &fnargs[op->l.aidx]; v_cont: res = op->r.n ? findvar(iamarray(L.v), R.s) : L.v; @@ -3035,7 +3042,8 @@ static var *evaluate(node *op, var *res) default: syntax_error(EMSG_POSSIBLE_ERROR); - } + } /* switch */ + next: if ((opinfo & OPCLSMASK) <= SHIFT_TIL_THIS) op = op->a.n; if ((opinfo & OPCLSMASK) >= RECUR_FROM_THIS) -- cgit v1.1