diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-24 00:50:07 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-24 00:50:07 +0000 |
commit | 5ec6132c9884f1f6ccbcc8277cb73220462a2133 (patch) | |
tree | 3944b70fa297304042d48acb52b32359433c5c97 | |
parent | 003f9fb213e034dcfd3bdbd93e4d60315002d473 (diff) | |
download | busybox-w32-5ec6132c9884f1f6ccbcc8277cb73220462a2133.tar.gz busybox-w32-5ec6132c9884f1f6ccbcc8277cb73220462a2133.tar.bz2 busybox-w32-5ec6132c9884f1f6ccbcc8277cb73220462a2133.zip |
hush: ifdef out parts which are not needed
if neither loops nor ifs are supported. Code savings:
function old new delta
parse_stream 1758 1757 -1
checkjobs 335 318 -17
done_pipe 74 52 -22
expand_variables 1437 1407 -30
run_list 1232 1189 -43
parse_and_run_stream 328 267 -61
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/6 up/down: 0/-174) Total: -174 bytes
-rw-r--r-- | shell/hush.c | 105 |
1 files changed, 59 insertions, 46 deletions
diff --git a/shell/hush.c b/shell/hush.c index b59f67942..ace0cdafc 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -150,9 +150,6 @@ | |||
150 | #define debug_printf_subst(...) fprintf(stderr, __VA_ARGS__) | 150 | #define debug_printf_subst(...) fprintf(stderr, __VA_ARGS__) |
151 | #endif | 151 | #endif |
152 | 152 | ||
153 | /* Keep unconditionally on for now */ | ||
154 | #define ENABLE_HUSH_DEBUG 1 | ||
155 | |||
156 | #ifndef debug_printf_clean | 153 | #ifndef debug_printf_clean |
157 | /* broken, of course, but OK for testing */ | 154 | /* broken, of course, but OK for testing */ |
158 | static const char *indenter(int i) | 155 | static const char *indenter(int i) |
@@ -176,7 +173,6 @@ static void debug_print_strings(const char *prefix, char **vv) | |||
176 | #define debug_print_strings(prefix, vv) ((void)0) | 173 | #define debug_print_strings(prefix, vv) ((void)0) |
177 | #endif | 174 | #endif |
178 | 175 | ||
179 | |||
180 | /* | 176 | /* |
181 | * Leak hunting. Use hush_leaktool.sh for post-processing. | 177 | * Leak hunting. Use hush_leaktool.sh for post-processing. |
182 | */ | 178 | */ |
@@ -216,6 +212,20 @@ void xxfree(void *ptr) | |||
216 | #endif | 212 | #endif |
217 | 213 | ||
218 | 214 | ||
215 | /* Keep unconditionally on for now */ | ||
216 | #define HUSH_DEBUG 1 | ||
217 | /* Do we support ANY keywords? */ | ||
218 | #if ENABLE_HUSH_IF || ENABLE_HUSH_LOOPS | ||
219 | #define HAS_KEYWORDS 1 | ||
220 | #define IF_HAS_KEYWORDS(...) __VA_ARGS__ | ||
221 | #define IF_HAS_NO_KEYWORDS(...) | ||
222 | #else | ||
223 | #define HAS_KEYWORDS 0 | ||
224 | #define IF_HAS_KEYWORDS(...) | ||
225 | #define IF_HAS_NO_KEYWORDS(...) __VA_ARGS__ | ||
226 | #endif | ||
227 | |||
228 | |||
219 | #define SPECIAL_VAR_SYMBOL 3 | 229 | #define SPECIAL_VAR_SYMBOL 3 |
220 | #define PARSEFLAG_EXIT_FROM_LOOP 1 | 230 | #define PARSEFLAG_EXIT_FROM_LOOP 1 |
221 | 231 | ||
@@ -276,18 +286,20 @@ struct p_context { | |||
276 | struct pipe *list_head; | 286 | struct pipe *list_head; |
277 | struct pipe *pipe; | 287 | struct pipe *pipe; |
278 | struct redir_struct *pending_redirect; | 288 | struct redir_struct *pending_redirect; |
279 | smallint res_w; | 289 | #if HAS_KEYWORDS |
280 | smallint ctx_inverted; /* "! cmd | cmd" */ | 290 | smallint ctx_res_w; |
281 | int old_flag; /* bitmask of FLAG_xxx, for figuring out valid reserved words */ | 291 | smallint ctx_inverted; /* "! cmd | cmd" */ |
292 | int old_flag; /* bitmask of FLAG_xxx, for figuring out valid reserved words */ | ||
282 | struct p_context *stack; | 293 | struct p_context *stack; |
294 | #endif | ||
283 | }; | 295 | }; |
284 | 296 | ||
285 | struct redir_struct { | 297 | struct redir_struct { |
286 | struct redir_struct *next; | 298 | struct redir_struct *next; |
287 | smallint /*redir_type*/ rd_type; | 299 | char *rd_filename; /* filename */ |
288 | int fd; /* file descriptor being redirected */ | 300 | int fd; /* file descriptor being redirected */ |
289 | int dup; /* -1, or file descriptor being duplicated */ | 301 | int dup; /* -1, or file descriptor being duplicated */ |
290 | char *rd_filename; /* filename */ | 302 | smallint /*enum redir_type*/ rd_type; |
291 | }; | 303 | }; |
292 | 304 | ||
293 | struct child_prog { | 305 | struct child_prog { |
@@ -317,9 +329,9 @@ struct pipe { | |||
317 | char *cmdtext; /* name of job */ | 329 | char *cmdtext; /* name of job */ |
318 | #endif | 330 | #endif |
319 | struct child_prog *progs; /* array of commands in pipe */ | 331 | struct child_prog *progs; /* array of commands in pipe */ |
320 | smallint pi_inverted; /* "! cmd | cmd" */ | ||
321 | smallint followup; /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */ | 332 | smallint followup; /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */ |
322 | smallint res_word; /* needed for if, for, while, until... */ | 333 | IF_HAS_KEYWORDS(smallint pi_inverted;) /* "! cmd | cmd" */ |
334 | IF_HAS_KEYWORDS(smallint res_word;) /* needed for if, for, while, until... */ | ||
323 | }; | 335 | }; |
324 | 336 | ||
325 | /* On program start, environ points to initial environment. | 337 | /* On program start, environ points to initial environment. |
@@ -1629,8 +1641,7 @@ static int checkjobs(struct pipe* fg_pipe) | |||
1629 | if (i == fg_pipe->num_progs - 1) { | 1641 | if (i == fg_pipe->num_progs - 1) { |
1630 | /* last process gives overall exitstatus */ | 1642 | /* last process gives overall exitstatus */ |
1631 | rcode = WEXITSTATUS(status); | 1643 | rcode = WEXITSTATUS(status); |
1632 | if (fg_pipe->pi_inverted) | 1644 | IF_HAS_KEYWORDS(if (fg_pipe->pi_inverted) rcode = !rcode;) |
1633 | rcode = !rcode; | ||
1634 | } | 1645 | } |
1635 | } else { | 1646 | } else { |
1636 | fg_pipe->progs[i].is_stopped = 1; | 1647 | fg_pipe->progs[i].is_stopped = 1; |
@@ -1757,8 +1768,7 @@ static int run_pipe(struct pipe *pi) | |||
1757 | rcode = run_list(child->group) & 0xff; | 1768 | rcode = run_list(child->group) & 0xff; |
1758 | restore_redirects(squirrel); | 1769 | restore_redirects(squirrel); |
1759 | debug_printf_exec("run_pipe return %d\n", rcode); | 1770 | debug_printf_exec("run_pipe return %d\n", rcode); |
1760 | if (pi->pi_inverted) | 1771 | IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;) |
1761 | rcode = !rcode; | ||
1762 | return rcode; | 1772 | return rcode; |
1763 | } | 1773 | } |
1764 | 1774 | ||
@@ -1801,8 +1811,7 @@ static int run_pipe(struct pipe *pi) | |||
1801 | free(argv_expanded); | 1811 | free(argv_expanded); |
1802 | restore_redirects(squirrel); | 1812 | restore_redirects(squirrel); |
1803 | debug_printf_exec("run_pipe return %d\n", rcode); | 1813 | debug_printf_exec("run_pipe return %d\n", rcode); |
1804 | if (pi->pi_inverted) | 1814 | IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;) |
1805 | rcode = !rcode; | ||
1806 | return rcode; | 1815 | return rcode; |
1807 | } | 1816 | } |
1808 | } | 1817 | } |
@@ -1819,8 +1828,7 @@ static int run_pipe(struct pipe *pi) | |||
1819 | free(argv_expanded); | 1828 | free(argv_expanded); |
1820 | restore_redirects(squirrel); | 1829 | restore_redirects(squirrel); |
1821 | debug_printf_exec("run_pipe return %d\n", rcode); | 1830 | debug_printf_exec("run_pipe return %d\n", rcode); |
1822 | if (pi->pi_inverted) | 1831 | IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;) |
1823 | rcode = !rcode; | ||
1824 | return rcode; | 1832 | return rcode; |
1825 | } | 1833 | } |
1826 | } | 1834 | } |
@@ -2003,8 +2011,7 @@ static int run_list(struct pipe *pi) | |||
2003 | #else | 2011 | #else |
2004 | enum { if_code = 0, next_if_code = 0 }; | 2012 | enum { if_code = 0, next_if_code = 0 }; |
2005 | #endif | 2013 | #endif |
2006 | // TODO: rword and ->res_word are not needed if !LOOPS and !IF | 2014 | reserved_style rword IF_HAS_NO_KEYWORDS(= RES_NONE); |
2007 | reserved_style rword; | ||
2008 | reserved_style skip_more_for_this_rword = RES_XXXX; | 2015 | reserved_style skip_more_for_this_rword = RES_XXXX; |
2009 | 2016 | ||
2010 | debug_printf_exec("run_list start lvl %d\n", run_list_level + 1); | 2017 | debug_printf_exec("run_list start lvl %d\n", run_list_level + 1); |
@@ -2075,7 +2082,8 @@ static int run_list(struct pipe *pi) | |||
2075 | #endif /* JOB */ | 2082 | #endif /* JOB */ |
2076 | 2083 | ||
2077 | for (; pi; pi = flag_restore ? rpipe : pi->next) { | 2084 | for (; pi; pi = flag_restore ? rpipe : pi->next) { |
2078 | rword = pi->res_word; | 2085 | IF_HAS_KEYWORDS(rword = pi->res_word;) |
2086 | IF_HAS_NO_KEYWORDS(rword = RES_NONE;) | ||
2079 | #if ENABLE_HUSH_LOOPS | 2087 | #if ENABLE_HUSH_LOOPS |
2080 | if (rword == RES_WHILE || rword == RES_UNTIL || rword == RES_FOR) { | 2088 | if (rword == RES_WHILE || rword == RES_UNTIL || rword == RES_FOR) { |
2081 | flag_restore = 0; | 2089 | flag_restore = 0; |
@@ -2272,7 +2280,9 @@ static int free_pipe_list(struct pipe *head, int indent) | |||
2272 | struct pipe *pi, *next; | 2280 | struct pipe *pi, *next; |
2273 | 2281 | ||
2274 | for (pi = head; pi; pi = next) { | 2282 | for (pi = head; pi; pi = next) { |
2283 | #if HAS_KEYWORDS | ||
2275 | debug_printf_clean("%s pipe reserved mode %d\n", indenter(indent), pi->res_word); | 2284 | debug_printf_clean("%s pipe reserved mode %d\n", indenter(indent), pi->res_word); |
2285 | #endif | ||
2276 | rcode = free_pipe(pi, indent); | 2286 | rcode = free_pipe(pi, indent); |
2277 | debug_printf_clean("%s pipe followup code %d\n", indenter(indent), pi->followup); | 2287 | debug_printf_clean("%s pipe followup code %d\n", indenter(indent), pi->followup); |
2278 | next = pi->next; | 2288 | next = pi->next; |
@@ -2548,7 +2558,7 @@ static char *expand_string_to_string(const char *str) | |||
2548 | argv[0] = (char*)str; | 2558 | argv[0] = (char*)str; |
2549 | argv[1] = NULL; | 2559 | argv[1] = NULL; |
2550 | list = expand_variables(argv, 0x80); /* 0x80: make one-element expansion */ | 2560 | list = expand_variables(argv, 0x80); /* 0x80: make one-element expansion */ |
2551 | if (ENABLE_HUSH_DEBUG) | 2561 | if (HUSH_DEBUG) |
2552 | if (!list[0] || list[1]) | 2562 | if (!list[0] || list[1]) |
2553 | bb_error_msg_and_die("BUG in varexp2"); | 2563 | bb_error_msg_and_die("BUG in varexp2"); |
2554 | /* actually, just move string 2*sizeof(char*) bytes back */ | 2564 | /* actually, just move string 2*sizeof(char*) bytes back */ |
@@ -2567,7 +2577,7 @@ static char* expand_strvec_to_string(char **argv) | |||
2567 | if (list[0]) { | 2577 | if (list[0]) { |
2568 | int n = 1; | 2578 | int n = 1; |
2569 | while (list[n]) { | 2579 | while (list[n]) { |
2570 | if (ENABLE_HUSH_DEBUG) | 2580 | if (HUSH_DEBUG) |
2571 | if (list[n-1] + strlen(list[n-1]) + 1 != list[n]) | 2581 | if (list[n-1] + strlen(list[n-1]) + 1 != list[n]) |
2572 | bb_error_msg_and_die("BUG in varexp3"); | 2582 | bb_error_msg_and_die("BUG in varexp3"); |
2573 | list[n][-1] = ' '; /* TODO: or to ifs[0]? */ | 2583 | list[n][-1] = ' '; /* TODO: or to ifs[0]? */ |
@@ -2747,8 +2757,7 @@ static struct pipe *new_pipe(void) | |||
2747 | struct pipe *pi; | 2757 | struct pipe *pi; |
2748 | pi = xzalloc(sizeof(struct pipe)); | 2758 | pi = xzalloc(sizeof(struct pipe)); |
2749 | /*pi->followup = 0; - deliberately invalid value */ | 2759 | /*pi->followup = 0; - deliberately invalid value */ |
2750 | if (RES_NONE) | 2760 | /*pi->res_word = RES_NONE; - RES_NONE is 0 anyway */ |
2751 | pi->res_word = RES_NONE; | ||
2752 | return pi; | 2761 | return pi; |
2753 | } | 2762 | } |
2754 | 2763 | ||
@@ -2769,7 +2778,7 @@ static void initialize_context(struct p_context *ctx) | |||
2769 | * Handles if, then, elif, else, fi, for, while, until, do, done. | 2778 | * Handles if, then, elif, else, fi, for, while, until, do, done. |
2770 | * case, function, and select are obnoxious, save those for later. | 2779 | * case, function, and select are obnoxious, save those for later. |
2771 | */ | 2780 | */ |
2772 | #if ENABLE_HUSH_IF || ENABLE_HUSH_LOOPS | 2781 | #if HAS_KEYWORDS |
2773 | static int reserved_word(const o_string *word, struct p_context *ctx) | 2782 | static int reserved_word(const o_string *word, struct p_context *ctx) |
2774 | { | 2783 | { |
2775 | struct reserved_combo { | 2784 | struct reserved_combo { |
@@ -2828,18 +2837,18 @@ static int reserved_word(const o_string *word, struct p_context *ctx) | |||
2828 | debug_printf("found reserved word %s, res %d\n", r->literal, r->res); | 2837 | debug_printf("found reserved word %s, res %d\n", r->literal, r->res); |
2829 | if (r->flag == 0) { /* '!' */ | 2838 | if (r->flag == 0) { /* '!' */ |
2830 | #if ENABLE_HUSH_LOOPS | 2839 | #if ENABLE_HUSH_LOOPS |
2831 | if (ctx->res_w == RES_IN) { | 2840 | if (ctx->ctx_res_w == RES_IN) { |
2832 | /* 'for a in ! a b c; ...' - ! isn't a keyword here */ | 2841 | /* 'for a in ! a b c; ...' - ! isn't a keyword here */ |
2833 | break; | 2842 | break; |
2834 | } | 2843 | } |
2835 | #endif | 2844 | #endif |
2836 | if (ctx->ctx_inverted /* bash doesn't accept '! ! true' */ | 2845 | if (ctx->ctx_inverted /* bash doesn't accept '! ! true' */ |
2837 | #if ENABLE_HUSH_LOOPS | 2846 | #if ENABLE_HUSH_LOOPS |
2838 | || ctx->res_w == RES_FOR /* example: 'for ! a' */ | 2847 | || ctx->ctx_res_w == RES_FOR /* example: 'for ! a' */ |
2839 | #endif | 2848 | #endif |
2840 | ) { | 2849 | ) { |
2841 | syntax(NULL); | 2850 | syntax(NULL); |
2842 | ctx->res_w = RES_SNTX; | 2851 | IF_HAS_KEYWORDS(ctx->ctx_res_w = RES_SNTX;) |
2843 | } | 2852 | } |
2844 | ctx->ctx_inverted = 1; | 2853 | ctx->ctx_inverted = 1; |
2845 | return 1; | 2854 | return 1; |
@@ -2848,9 +2857,9 @@ static int reserved_word(const o_string *word, struct p_context *ctx) | |||
2848 | struct p_context *new; | 2857 | struct p_context *new; |
2849 | debug_printf("push stack\n"); | 2858 | debug_printf("push stack\n"); |
2850 | #if ENABLE_HUSH_LOOPS | 2859 | #if ENABLE_HUSH_LOOPS |
2851 | if (ctx->res_w == RES_IN || ctx->res_w == RES_FOR) { | 2860 | if (ctx->ctx_res_w == RES_IN || ctx->ctx_res_w == RES_FOR) { |
2852 | syntax("malformed for"); /* example: 'for if' */ | 2861 | syntax("malformed for"); /* example: 'for if' */ |
2853 | ctx->res_w = RES_SNTX; | 2862 | ctx->ctx_res_w = RES_SNTX; |
2854 | return 1; | 2863 | return 1; |
2855 | } | 2864 | } |
2856 | #endif | 2865 | #endif |
@@ -2858,12 +2867,12 @@ static int reserved_word(const o_string *word, struct p_context *ctx) | |||
2858 | *new = *ctx; /* physical copy */ | 2867 | *new = *ctx; /* physical copy */ |
2859 | initialize_context(ctx); | 2868 | initialize_context(ctx); |
2860 | ctx->stack = new; | 2869 | ctx->stack = new; |
2861 | } else if (ctx->res_w == RES_NONE || !(ctx->old_flag & (1 << r->res))) { | 2870 | } else if (ctx->ctx_res_w == RES_NONE || !(ctx->old_flag & (1 << r->res))) { |
2862 | syntax(NULL); | 2871 | syntax(NULL); |
2863 | ctx->res_w = RES_SNTX; | 2872 | ctx->ctx_res_w = RES_SNTX; |
2864 | return 1; | 2873 | return 1; |
2865 | } | 2874 | } |
2866 | ctx->res_w = r->res; | 2875 | ctx->ctx_res_w = r->res; |
2867 | ctx->old_flag = r->flag; | 2876 | ctx->old_flag = r->flag; |
2868 | if (ctx->old_flag & FLAG_END) { | 2877 | if (ctx->old_flag & FLAG_END) { |
2869 | struct p_context *old; | 2878 | struct p_context *old; |
@@ -2879,8 +2888,6 @@ static int reserved_word(const o_string *word, struct p_context *ctx) | |||
2879 | } | 2888 | } |
2880 | return 0; | 2889 | return 0; |
2881 | } | 2890 | } |
2882 | #else | ||
2883 | #define reserved_word(word, ctx) ((int)0) | ||
2884 | #endif | 2891 | #endif |
2885 | 2892 | ||
2886 | /* Word is complete, look at it and update parsing context. | 2893 | /* Word is complete, look at it and update parsing context. |
@@ -2914,15 +2921,17 @@ static int done_word(o_string *word, struct p_context *ctx) | |||
2914 | debug_printf_parse("done_word return 1: syntax error, groups and arglists don't mix\n"); | 2921 | debug_printf_parse("done_word return 1: syntax error, groups and arglists don't mix\n"); |
2915 | return 1; | 2922 | return 1; |
2916 | } | 2923 | } |
2924 | #if HAS_KEYWORDS | ||
2917 | if (!child->argv) { /* if it's the first word... */ | 2925 | if (!child->argv) { /* if it's the first word... */ |
2918 | debug_printf_parse(": checking '%s' for reserved-ness\n", word->data); | 2926 | debug_printf_parse(": checking '%s' for reserved-ness\n", word->data); |
2919 | if (reserved_word(word, ctx)) { | 2927 | if (reserved_word(word, ctx)) { |
2920 | o_reset(word); | 2928 | o_reset(word); |
2921 | word->o_assignment = NOT_ASSIGNMENT; | 2929 | word->o_assignment = NOT_ASSIGNMENT; |
2922 | debug_printf_parse("done_word return %d\n", (ctx->res_w == RES_SNTX)); | 2930 | debug_printf_parse("done_word return %d\n", (ctx->ctx_res_w == RES_SNTX)); |
2923 | return (ctx->res_w == RES_SNTX); | 2931 | return (ctx->ctx_res_w == RES_SNTX); |
2924 | } | 2932 | } |
2925 | } | 2933 | } |
2934 | #endif | ||
2926 | if (word->nonnull /* we saw "xx" or 'xx' */ | 2935 | if (word->nonnull /* we saw "xx" or 'xx' */ |
2927 | /* optimization: and if it's ("" or '') or ($v... or `cmd`...): */ | 2936 | /* optimization: and if it's ("" or '') or ($v... or `cmd`...): */ |
2928 | && (word->data[0] == '\0' || word->data[0] == SPECIAL_VAR_SYMBOL) | 2937 | && (word->data[0] == '\0' || word->data[0] == SPECIAL_VAR_SYMBOL) |
@@ -2942,7 +2951,7 @@ static int done_word(o_string *word, struct p_context *ctx) | |||
2942 | 2951 | ||
2943 | #if ENABLE_HUSH_LOOPS | 2952 | #if ENABLE_HUSH_LOOPS |
2944 | /* Force FOR to have just one word (variable name) */ | 2953 | /* Force FOR to have just one word (variable name) */ |
2945 | if (ctx->res_w == RES_FOR) | 2954 | if (ctx->ctx_res_w == RES_FOR) |
2946 | done_pipe(ctx, PIPE_SEQ); | 2955 | done_pipe(ctx, PIPE_SEQ); |
2947 | #endif | 2956 | #endif |
2948 | debug_printf_parse("done_word return 0\n"); | 2957 | debug_printf_parse("done_word return 0\n"); |
@@ -2993,9 +3002,9 @@ static void done_pipe(struct p_context *ctx, pipe_style type) | |||
2993 | debug_printf_parse("done_pipe entered, followup %d\n", type); | 3002 | debug_printf_parse("done_pipe entered, followup %d\n", type); |
2994 | not_null = done_command(ctx); /* implicit closure of previous command */ | 3003 | not_null = done_command(ctx); /* implicit closure of previous command */ |
2995 | ctx->pipe->followup = type; | 3004 | ctx->pipe->followup = type; |
2996 | ctx->pipe->res_word = ctx->res_w; | 3005 | IF_HAS_KEYWORDS(ctx->pipe->res_word = ctx->ctx_res_w;) |
2997 | ctx->pipe->pi_inverted = ctx->ctx_inverted; | 3006 | IF_HAS_KEYWORDS(ctx->pipe->pi_inverted = ctx->ctx_inverted;) |
2998 | ctx->ctx_inverted = 0; | 3007 | IF_HAS_KEYWORDS(ctx->ctx_inverted = 0;) |
2999 | /* Without this check, even just <enter> on command line generates | 3008 | /* Without this check, even just <enter> on command line generates |
3000 | * tree of three NOPs (!). Which is harmless but annoying. | 3009 | * tree of three NOPs (!). Which is harmless but annoying. |
3001 | * IOW: it is safe to do it unconditionally. | 3010 | * IOW: it is safe to do it unconditionally. |
@@ -3480,7 +3489,7 @@ static int parse_stream(o_string *dest, struct p_context *ctx, | |||
3480 | //err chk? | 3489 | //err chk? |
3481 | done_pipe(ctx, PIPE_SEQ); | 3490 | done_pipe(ctx, PIPE_SEQ); |
3482 | } | 3491 | } |
3483 | if (ctx->res_w == RES_NONE) { | 3492 | if (!HAS_KEYWORDS IF_HAS_KEYWORDS(|| ctx->ctx_res_w == RES_NONE)) { |
3484 | debug_printf_parse("parse_stream return 0: end_trigger char found\n"); | 3493 | debug_printf_parse("parse_stream return 0: end_trigger char found\n"); |
3485 | return 0; | 3494 | return 0; |
3486 | } | 3495 | } |
@@ -3650,7 +3659,7 @@ static int parse_stream(o_string *dest, struct p_context *ctx, | |||
3650 | debug_printf_parse("parse_stream return 1: unexpected '}'\n"); | 3659 | debug_printf_parse("parse_stream return 1: unexpected '}'\n"); |
3651 | return 1; | 3660 | return 1; |
3652 | default: | 3661 | default: |
3653 | if (ENABLE_HUSH_DEBUG) | 3662 | if (HUSH_DEBUG) |
3654 | bb_error_msg_and_die("BUG: unexpected %c\n", ch); | 3663 | bb_error_msg_and_die("BUG: unexpected %c\n", ch); |
3655 | } | 3664 | } |
3656 | } /* while (1) */ | 3665 | } /* while (1) */ |
@@ -3706,10 +3715,12 @@ static int parse_and_run_stream(struct in_str *inp, int parse_flag) | |||
3706 | * Example: "sleep 9999; echo TEST" + ctrl-C: | 3715 | * Example: "sleep 9999; echo TEST" + ctrl-C: |
3707 | * TEST should be printed */ | 3716 | * TEST should be printed */ |
3708 | rcode = parse_stream(&temp, &ctx, inp, ";\n"); | 3717 | rcode = parse_stream(&temp, &ctx, inp, ";\n"); |
3718 | #if HAS_KEYWORDS | ||
3709 | if (rcode != 1 && ctx.old_flag != 0) { | 3719 | if (rcode != 1 && ctx.old_flag != 0) { |
3710 | syntax(NULL); | 3720 | syntax(NULL); |
3711 | } | 3721 | } |
3712 | if (rcode != 1 && ctx.old_flag == 0) { | 3722 | #endif |
3723 | if (rcode != 1 IF_HAS_KEYWORDS(&& ctx.old_flag == 0)) { | ||
3713 | done_word(&temp, &ctx); | 3724 | done_word(&temp, &ctx); |
3714 | done_pipe(&ctx, PIPE_SEQ); | 3725 | done_pipe(&ctx, PIPE_SEQ); |
3715 | debug_print_tree(ctx.list_head, 0); | 3726 | debug_print_tree(ctx.list_head, 0); |
@@ -3717,10 +3728,12 @@ static int parse_and_run_stream(struct in_str *inp, int parse_flag) | |||
3717 | run_and_free_list(ctx.list_head); | 3728 | run_and_free_list(ctx.list_head); |
3718 | } else { | 3729 | } else { |
3719 | /* We arrive here also if rcode == 1 (error in parse_stream) */ | 3730 | /* We arrive here also if rcode == 1 (error in parse_stream) */ |
3731 | #if HAS_KEYWORDS | ||
3720 | if (ctx.old_flag != 0) { | 3732 | if (ctx.old_flag != 0) { |
3721 | free(ctx.stack); | 3733 | free(ctx.stack); |
3722 | o_reset(&temp); | 3734 | o_reset(&temp); |
3723 | } | 3735 | } |
3736 | #endif | ||
3724 | /*temp.nonnull = 0; - o_free does it below */ | 3737 | /*temp.nonnull = 0; - o_free does it below */ |
3725 | /*temp.o_quote = 0; - o_free does it below */ | 3738 | /*temp.o_quote = 0; - o_free does it below */ |
3726 | free_pipe_list(ctx.list_head, /* indent: */ 0); | 3739 | free_pipe_list(ctx.list_head, /* indent: */ 0); |