diff options
-rw-r--r-- | editors/awk.c | 70 |
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 | ||
45 | typedef 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 */ |
36 | typedef struct var_s { | 53 | typedef 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 | ||
1725 | static void hashwalk_init(var *v, xhash *array) | 1749 | static 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 | ||
1749 | static int hashwalk_next(var *v) | 1778 | static 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 | ||