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>
This commit is contained in:
parent
7367a949a6
commit
6f4a785bd1
@ -2514,6 +2514,32 @@ static var *evaluate(node *op, var *res)
|
|||||||
op1 = op->l.n;
|
op1 = op->l.n;
|
||||||
debug_printf_eval("opinfo:%08x opn:%08x\n", opinfo, opn);
|
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 */
|
/* execute inevitable things */
|
||||||
if (opinfo & OF_RES1)
|
if (opinfo & OF_RES1)
|
||||||
L.v = evaluate(op1, v1);
|
L.v = evaluate(op1, v1);
|
||||||
@ -2621,28 +2647,7 @@ static var *evaluate(node *op, var *res)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case XC( OC_DELETE ): {
|
/* case XC( OC_DELETE ): - moved to happen before arg evaluation */
|
||||||
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_NEWSOURCE ):
|
case XC( OC_NEWSOURCE ):
|
||||||
g_progname = op->l.new_progname;
|
g_progname = op->l.new_progname;
|
||||||
@ -2666,12 +2671,14 @@ static var *evaluate(node *op, var *res)
|
|||||||
/* -- recursive node type -- */
|
/* -- recursive node type -- */
|
||||||
|
|
||||||
case XC( OC_VAR ):
|
case XC( OC_VAR ):
|
||||||
|
debug_printf_eval("VAR\n");
|
||||||
L.v = op->l.v;
|
L.v = op->l.v;
|
||||||
if (L.v == intvar[NF])
|
if (L.v == intvar[NF])
|
||||||
split_f0();
|
split_f0();
|
||||||
goto v_cont;
|
goto v_cont;
|
||||||
|
|
||||||
case XC( OC_FNARG ):
|
case XC( OC_FNARG ):
|
||||||
|
debug_printf_eval("FNARG[%d]\n", op->l.aidx);
|
||||||
L.v = &fnargs[op->l.aidx];
|
L.v = &fnargs[op->l.aidx];
|
||||||
v_cont:
|
v_cont:
|
||||||
res = op->r.n ? findvar(iamarray(L.v), R.s) : L.v;
|
res = op->r.n ? findvar(iamarray(L.v), R.s) : L.v;
|
||||||
@ -3035,7 +3042,8 @@ static var *evaluate(node *op, var *res)
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
syntax_error(EMSG_POSSIBLE_ERROR);
|
syntax_error(EMSG_POSSIBLE_ERROR);
|
||||||
}
|
} /* switch */
|
||||||
|
next:
|
||||||
if ((opinfo & OPCLSMASK) <= SHIFT_TIL_THIS)
|
if ((opinfo & OPCLSMASK) <= SHIFT_TIL_THIS)
|
||||||
op = op->a.n;
|
op = op->a.n;
|
||||||
if ((opinfo & OPCLSMASK) >= RECUR_FROM_THIS)
|
if ((opinfo & OPCLSMASK) >= RECUR_FROM_THIS)
|
||||||
|
@ -261,6 +261,25 @@ end d
|
|||||||
" \
|
" \
|
||||||
"" ""
|
"" ""
|
||||||
|
|
||||||
|
prg='
|
||||||
|
BEGIN{
|
||||||
|
cnt = 0
|
||||||
|
a[cnt] = "zeroth"
|
||||||
|
a[++cnt] = "first"
|
||||||
|
delete a[cnt--]
|
||||||
|
print cnt
|
||||||
|
print "[0]:" a[0]
|
||||||
|
print "[1]:" a[1]
|
||||||
|
}'
|
||||||
|
testing "awk 'delete a[v--]' evaluates v-- once" \
|
||||||
|
"awk '$prg'" \
|
||||||
|
"\
|
||||||
|
0
|
||||||
|
[0]:zeroth
|
||||||
|
[1]:
|
||||||
|
" \
|
||||||
|
"" ""
|
||||||
|
|
||||||
testing "awk handles empty ()" \
|
testing "awk handles empty ()" \
|
||||||
"awk 'BEGIN {print()}' 2>&1" "awk: cmd. line:1: Empty sequence\n" "" ""
|
"awk 'BEGIN {print()}' 2>&1" "awk: cmd. line:1: Empty sequence\n" "" ""
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user