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 | |
parent | eae697fb93362dd51365fdd5283128cb339b91c2 (diff) | |
download | busybox-w32-3cb60c39737208ca073842f4f0386d5e5c278705.tar.gz busybox-w32-3cb60c39737208ca073842f4f0386d5e5c278705.tar.bz2 busybox-w32-3cb60c39737208ca073842f4f0386d5e5c278705.zip |
awk: fix the case where nested "for" loops with the same variable misbehave
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | editors/awk.c | 30 | ||||
-rwxr-xr-x | testsuite/awk.tests | 38 |
2 files changed, 58 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) | |||
912 | free(p->x.array->items); | 912 | free(p->x.array->items); |
913 | free(p->x.array); | 913 | free(p->x.array); |
914 | } | 914 | } |
915 | if (p->type & VF_WALK) | 915 | if (p->type & VF_WALK) { |
916 | //bb_error_msg("free(walker@%p:%p) #1", &p->x.walker, p->x.walker); | ||
916 | free(p->x.walker); | 917 | free(p->x.walker); |
918 | } | ||
917 | 919 | ||
918 | clrvar(p); | 920 | clrvar(p); |
919 | } | 921 | } |
@@ -1724,18 +1726,20 @@ static void hashwalk_init(var *v, xhash *array) | |||
1724 | char **w; | 1726 | char **w; |
1725 | hash_item *hi; | 1727 | hash_item *hi; |
1726 | unsigned i; | 1728 | unsigned i; |
1727 | 1729 | char **prev_walker = (v->type & VF_WALK) ? v->x.walker : NULL; | |
1728 | if (v->type & VF_WALK) | ||
1729 | free(v->x.walker); | ||
1730 | 1730 | ||
1731 | v->type |= VF_WALK; | 1731 | v->type |= VF_WALK; |
1732 | w = v->x.walker = xzalloc(2 + 2*sizeof(char *) + array->glen); | 1732 | |
1733 | w[0] = w[1] = (char *)(w + 2); | 1733 | /* walker structure is: "[ptr2end][ptr2start][prev]<word1>NUL<word2>NUL" */ |
1734 | w = v->x.walker = xzalloc(2 + 3*sizeof(char *) + array->glen); | ||
1735 | //bb_error_msg("walker@%p=%p", &v->x.walker, v->x.walker); | ||
1736 | w[0] = w[1] = (char *)(w + 3); | ||
1737 | w[2] = (char *)prev_walker; | ||
1734 | for (i = 0; i < array->csize; i++) { | 1738 | for (i = 0; i < array->csize; i++) { |
1735 | hi = array->items[i]; | 1739 | hi = array->items[i]; |
1736 | while (hi) { | 1740 | while (hi) { |
1737 | strcpy(*w, hi->name); | 1741 | strcpy(w[0], hi->name); |
1738 | nextword(w); | 1742 | nextword(&w[0]); |
1739 | hi = hi->next; | 1743 | hi = hi->next; |
1740 | } | 1744 | } |
1741 | } | 1745 | } |
@@ -1746,10 +1750,16 @@ static int hashwalk_next(var *v) | |||
1746 | char **w; | 1750 | char **w; |
1747 | 1751 | ||
1748 | w = v->x.walker; | 1752 | w = v->x.walker; |
1749 | if (w[1] == w[0]) | 1753 | if (w[1] == w[0]) { |
1754 | char **prev_walker = (char**)w[2]; | ||
1755 | |||
1756 | //bb_error_msg("free(walker@%p:%p) #3, restoring to %p", &v->x.walker, v->x.walker, prev_walker); | ||
1757 | free(v->x.walker); | ||
1758 | v->x.walker = prev_walker; | ||
1750 | return FALSE; | 1759 | return FALSE; |
1760 | } | ||
1751 | 1761 | ||
1752 | setvar_s(v, nextword(w+1)); | 1762 | setvar_s(v, nextword(&w[1])); |
1753 | return TRUE; | 1763 | return TRUE; |
1754 | } | 1764 | } |
1755 | 1765 | ||
diff --git a/testsuite/awk.tests b/testsuite/awk.tests index 03d464969..78f9f0b98 100755 --- a/testsuite/awk.tests +++ b/testsuite/awk.tests | |||
@@ -67,4 +67,42 @@ testing "awk string cast (bug 725)" \ | |||
67 | testing "awk handles whitespace before array subscript" \ | 67 | testing "awk handles whitespace before array subscript" \ |
68 | "awk 'BEGIN { arr [3] = 1; print arr [3] }'" "1\n" "" "" | 68 | "awk 'BEGIN { arr [3] = 1; print arr [3] }'" "1\n" "" "" |
69 | 69 | ||
70 | prg=' | ||
71 | BEGIN { | ||
72 | v["q"]=1 | ||
73 | v["w"]=1 | ||
74 | v["e"]=1 | ||
75 | for (l in v) { | ||
76 | print "outer1", l; | ||
77 | for (l in v) { | ||
78 | print " inner", l; | ||
79 | } | ||
80 | print "outer2", l; | ||
81 | } | ||
82 | print "end", l; | ||
83 | l="a" | ||
84 | exit; | ||
85 | }' | ||
86 | testing "awk nested loops with the same variable" \ | ||
87 | "awk '$prg'" \ | ||
88 | "\ | ||
89 | outer1 e | ||
90 | inner e | ||
91 | inner q | ||
92 | inner w | ||
93 | outer2 w | ||
94 | outer1 q | ||
95 | inner e | ||
96 | inner q | ||
97 | inner w | ||
98 | outer2 w | ||
99 | outer1 w | ||
100 | inner e | ||
101 | inner q | ||
102 | inner w | ||
103 | outer2 w | ||
104 | end w | ||
105 | " \ | ||
106 | "" "" | ||
107 | |||
70 | exit $FAILCOUNT | 108 | exit $FAILCOUNT |