aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-03-10 19:20:32 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2010-03-10 19:20:32 +0100
commit3cb60c39737208ca073842f4f0386d5e5c278705 (patch)
tree7e96890a5016885d75dea187edd1c63cbbf05f6a
parenteae697fb93362dd51365fdd5283128cb339b91c2 (diff)
downloadbusybox-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.c30
-rwxr-xr-xtestsuite/awk.tests38
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)" \
67testing "awk handles whitespace before array subscript" \ 67testing "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
70prg='
71BEGIN {
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}'
86testing "awk nested loops with the same variable" \
87 "awk '$prg'" \
88 "\
89outer1 e
90 inner e
91 inner q
92 inner w
93outer2 w
94outer1 q
95 inner e
96 inner q
97 inner w
98outer2 w
99outer1 w
100 inner e
101 inner q
102 inner w
103outer2 w
104end w
105" \
106 "" ""
107
70exit $FAILCOUNT 108exit $FAILCOUNT