aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--editors/awk.c70
1 files changed, 49 insertions, 21 deletions
diff --git a/editors/awk.c b/editors/awk.c
index 1d704e87c..397d70f4c 100644
--- a/editors/awk.c
+++ b/editors/awk.c
@@ -14,6 +14,16 @@
14/* This is a NOEXEC applet. Be very careful! */ 14/* This is a NOEXEC applet. Be very careful! */
15 15
16 16
17/* If you comment out one of these below, it will be #defined later
18 * to perform debug printfs to stderr: */
19#define debug_printf_walker(...) do {} while (0)
20
21#ifndef debug_printf_walker
22# define debug_printf_walker(...) (fprintf(stderr, __VA_ARGS__))
23#endif
24
25
26
17#define MAXVARFMT 240 27#define MAXVARFMT 240
18#define MINNVBLOCK 64 28#define MINNVBLOCK 64
19 29
@@ -32,6 +42,13 @@
32/* these flags are static, don't change them when value is changed */ 42/* these flags are static, don't change them when value is changed */
33#define VF_DONTTOUCH (VF_ARRAY | VF_SPECIAL | VF_WALK | VF_CHILD | VF_DIRTY) 43#define VF_DONTTOUCH (VF_ARRAY | VF_SPECIAL | VF_WALK | VF_CHILD | VF_DIRTY)
34 44
45typedef struct walker_list {
46 char *end;
47 char *cur;
48 struct walker_list *prev;
49 char wbuf[1];
50} walker_list;
51
35/* Variable */ 52/* Variable */
36typedef struct var_s { 53typedef struct var_s {
37 unsigned type; /* flags */ 54 unsigned type; /* flags */
@@ -41,7 +58,7 @@ typedef struct var_s {
41 int aidx; /* func arg idx (for compilation stage) */ 58 int aidx; /* func arg idx (for compilation stage) */
42 struct xhash_s *array; /* array ptr */ 59 struct xhash_s *array; /* array ptr */
43 struct var_s *parent; /* for func args, ptr to actual parameter */ 60 struct var_s *parent; /* for func args, ptr to actual parameter */
44 char **walker; /* list of array elements (for..in) */ 61 walker_list *walker; /* list of array elements (for..in) */
45 } x; 62 } x;
46} var; 63} var;
47 64
@@ -913,10 +930,17 @@ static void nvfree(var *v)
913 free(p->x.array); 930 free(p->x.array);
914 } 931 }
915 if (p->type & VF_WALK) { 932 if (p->type & VF_WALK) {
916 //bb_error_msg("free(walker@%p:%p) #1", &p->x.walker, p->x.walker); 933 walker_list *n;
917 free(p->x.walker); 934 walker_list *w = p->x.walker;
935 debug_printf_walker("nvfree: freeing walker @%p\n", &p->x.walker);
936 p->x.walker = NULL;
937 while (w) {
938 n = w->prev;
939 debug_printf_walker(" free(%p)\n", w);
940 free(w);
941 w = n;
942 }
918 } 943 }
919
920 clrvar(p); 944 clrvar(p);
921 } 945 }
922 946
@@ -1724,23 +1748,28 @@ static node *nextarg(node **pn)
1724 1748
1725static void hashwalk_init(var *v, xhash *array) 1749static void hashwalk_init(var *v, xhash *array)
1726{ 1750{
1727 char **w;
1728 hash_item *hi; 1751 hash_item *hi;
1729 unsigned i; 1752 unsigned i;
1730 char **prev_walker = (v->type & VF_WALK) ? v->x.walker : NULL; 1753 walker_list *w;
1754 walker_list *prev_walker;
1731 1755
1732 v->type |= VF_WALK; 1756 if (v->type & VF_WALK) {
1757 prev_walker = v->x.walker;
1758 } else {
1759 v->type |= VF_WALK;
1760 prev_walker = NULL;
1761 }
1762 debug_printf_walker("hashwalk_init: prev_walker:%p\n", prev_walker);
1733 1763
1734 /* walker structure is: "[ptr2end][ptr2start][prev]<word1>NUL<word2>NUL" */ 1764 w = v->x.walker = xzalloc(sizeof(*w) + array->glen + 1); /* why + 1? */
1735 w = v->x.walker = xzalloc(2 + 3*sizeof(char *) + array->glen); 1765 debug_printf_walker(" walker@%p=%p\n", &v->x.walker, w);
1736 //bb_error_msg("walker@%p=%p", &v->x.walker, v->x.walker); 1766 w->cur = w->end = w->wbuf;
1737 w[0] = w[1] = (char *)(w + 3); 1767 w->prev = prev_walker;
1738 w[2] = (char *)prev_walker;
1739 for (i = 0; i < array->csize; i++) { 1768 for (i = 0; i < array->csize; i++) {
1740 hi = array->items[i]; 1769 hi = array->items[i];
1741 while (hi) { 1770 while (hi) {
1742 strcpy(w[0], hi->name); 1771 strcpy(w->end, hi->name);
1743 nextword(&w[0]); 1772 nextword(&w->end);
1744 hi = hi->next; 1773 hi = hi->next;
1745 } 1774 }
1746 } 1775 }
@@ -1748,19 +1777,18 @@ static void hashwalk_init(var *v, xhash *array)
1748 1777
1749static int hashwalk_next(var *v) 1778static int hashwalk_next(var *v)
1750{ 1779{
1751 char **w; 1780 walker_list *w = v->x.walker;
1752 1781
1753 w = v->x.walker; 1782 if (w->cur >= w->end) {
1754 if (w[1] == w[0]) { 1783 walker_list *prev_walker = w->prev;
1755 char **prev_walker = (char**)w[2];
1756 1784
1757 //bb_error_msg("free(walker@%p:%p) #3, restoring to %p", &v->x.walker, v->x.walker, prev_walker); 1785 debug_printf_walker("end of iteration, free(walker@%p:%p), prev_walker:%p\n", &v->x.walker, w, prev_walker);
1758 free(v->x.walker); 1786 free(w);
1759 v->x.walker = prev_walker; 1787 v->x.walker = prev_walker;
1760 return FALSE; 1788 return FALSE;
1761 } 1789 }
1762 1790
1763 setvar_s(v, nextword(&w[1])); 1791 setvar_s(v, nextword(&w->cur));
1764 return TRUE; 1792 return TRUE;
1765} 1793}
1766 1794