diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-03-10 19:20:32 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-03-10 19:20:32 +0100 |
commit | 3cb60c39737208ca073842f4f0386d5e5c278705 (patch) | |
tree | 7e96890a5016885d75dea187edd1c63cbbf05f6a /editors/awk.c | |
parent | eae697fb93362dd51365fdd5283128cb339b91c2 (diff) |
awk: fix the case where nested "for" loops with the same variable misbehave
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'editors/awk.c')
-rw-r--r-- | editors/awk.c | 30 |
1 files changed, 20 insertions, 10 deletions
diff --git a/editors/awk.c b/editors/awk.c index b9bc01f16..5cc4adce7 100644 --- a/editors/awk.c +++ b/editors/awk.c @@ -912,8 +912,10 @@ static void nvfree(var *v) free(p->x.array->items); 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); + } clrvar(p); } @@ -1724,18 +1726,20 @@ static void hashwalk_init(var *v, xhash *array) char **w; hash_item *hi; unsigned i; - - if (v->type & VF_WALK) - free(v->x.walker); + char **prev_walker = (v->type & VF_WALK) ? v->x.walker : NULL; 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++) { hi = array->items[i]; while (hi) { - strcpy(*w, hi->name); - nextword(w); + strcpy(w[0], hi->name); + nextword(&w[0]); hi = hi->next; } } @@ -1746,10 +1750,16 @@ static int hashwalk_next(var *v) char **w; w = v->x.walker; - if (w[1] == w[0]) + if (w[1] == w[0]) { + char **prev_walker = (char**)w[2]; + + //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)); + setvar_s(v, nextword(&w[1])); return TRUE; } |