awk: fix the case where nested "for" loops with the same variable misbehave
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
eae697fb93
commit
3cb60c3973
@ -912,8 +912,10 @@ static void nvfree(var *v)
|
|||||||
free(p->x.array->items);
|
free(p->x.array->items);
|
||||||
free(p->x.array);
|
free(p->x.array);
|
||||||
}
|
}
|
||||||
if (p->type & VF_WALK)
|
if (p->type & VF_WALK) {
|
||||||
|
//bb_error_msg("free(walker@%p:%p) #1", &p->x.walker, p->x.walker);
|
||||||
free(p->x.walker);
|
free(p->x.walker);
|
||||||
|
}
|
||||||
|
|
||||||
clrvar(p);
|
clrvar(p);
|
||||||
}
|
}
|
||||||
@ -1724,18 +1726,20 @@ static void hashwalk_init(var *v, xhash *array)
|
|||||||
char **w;
|
char **w;
|
||||||
hash_item *hi;
|
hash_item *hi;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
char **prev_walker = (v->type & VF_WALK) ? v->x.walker : NULL;
|
||||||
if (v->type & VF_WALK)
|
|
||||||
free(v->x.walker);
|
|
||||||
|
|
||||||
v->type |= VF_WALK;
|
v->type |= VF_WALK;
|
||||||
w = v->x.walker = xzalloc(2 + 2*sizeof(char *) + array->glen);
|
|
||||||
w[0] = w[1] = (char *)(w + 2);
|
/* walker structure is: "[ptr2end][ptr2start][prev]<word1>NUL<word2>NUL" */
|
||||||
|
w = v->x.walker = xzalloc(2 + 3*sizeof(char *) + array->glen);
|
||||||
|
//bb_error_msg("walker@%p=%p", &v->x.walker, v->x.walker);
|
||||||
|
w[0] = w[1] = (char *)(w + 3);
|
||||||
|
w[2] = (char *)prev_walker;
|
||||||
for (i = 0; i < array->csize; i++) {
|
for (i = 0; i < array->csize; i++) {
|
||||||
hi = array->items[i];
|
hi = array->items[i];
|
||||||
while (hi) {
|
while (hi) {
|
||||||
strcpy(*w, hi->name);
|
strcpy(w[0], hi->name);
|
||||||
nextword(w);
|
nextword(&w[0]);
|
||||||
hi = hi->next;
|
hi = hi->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1746,10 +1750,16 @@ static int hashwalk_next(var *v)
|
|||||||
char **w;
|
char **w;
|
||||||
|
|
||||||
w = v->x.walker;
|
w = v->x.walker;
|
||||||
if (w[1] == w[0])
|
if (w[1] == w[0]) {
|
||||||
return FALSE;
|
char **prev_walker = (char**)w[2];
|
||||||
|
|
||||||
setvar_s(v, nextword(w+1));
|
//bb_error_msg("free(walker@%p:%p) #3, restoring to %p", &v->x.walker, v->x.walker, prev_walker);
|
||||||
|
free(v->x.walker);
|
||||||
|
v->x.walker = prev_walker;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
setvar_s(v, nextword(&w[1]));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,4 +67,42 @@ testing "awk string cast (bug 725)" \
|
|||||||
testing "awk handles whitespace before array subscript" \
|
testing "awk handles whitespace before array subscript" \
|
||||||
"awk 'BEGIN { arr [3] = 1; print arr [3] }'" "1\n" "" ""
|
"awk 'BEGIN { arr [3] = 1; print arr [3] }'" "1\n" "" ""
|
||||||
|
|
||||||
|
prg='
|
||||||
|
BEGIN {
|
||||||
|
v["q"]=1
|
||||||
|
v["w"]=1
|
||||||
|
v["e"]=1
|
||||||
|
for (l in v) {
|
||||||
|
print "outer1", l;
|
||||||
|
for (l in v) {
|
||||||
|
print " inner", l;
|
||||||
|
}
|
||||||
|
print "outer2", l;
|
||||||
|
}
|
||||||
|
print "end", l;
|
||||||
|
l="a"
|
||||||
|
exit;
|
||||||
|
}'
|
||||||
|
testing "awk nested loops with the same variable" \
|
||||||
|
"awk '$prg'" \
|
||||||
|
"\
|
||||||
|
outer1 e
|
||||||
|
inner e
|
||||||
|
inner q
|
||||||
|
inner w
|
||||||
|
outer2 w
|
||||||
|
outer1 q
|
||||||
|
inner e
|
||||||
|
inner q
|
||||||
|
inner w
|
||||||
|
outer2 w
|
||||||
|
outer1 w
|
||||||
|
inner e
|
||||||
|
inner q
|
||||||
|
inner w
|
||||||
|
outer2 w
|
||||||
|
end w
|
||||||
|
" \
|
||||||
|
"" ""
|
||||||
|
|
||||||
exit $FAILCOUNT
|
exit $FAILCOUNT
|
||||||
|
Loading…
Reference in New Issue
Block a user