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;
|
||||
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)
|
||||
|
@ -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 ()" \
|
||||
"awk 'BEGIN {print()}' 2>&1" "awk: cmd. line:1: Empty sequence\n" "" ""
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user