aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shell/hush.c203
-rw-r--r--shell/hush_test/hush-misc/syntax_err_negate.right2
-rwxr-xr-xshell/hush_test/hush-misc/syntax_err_negate.tests2
-rw-r--r--shell/hush_test/hush-parsing/negate.right35
-rwxr-xr-xshell/hush_test/hush-parsing/negate.tests16
-rwxr-xr-xshell/hush_test/run-all4
6 files changed, 172 insertions, 90 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 8b218aba9..222fd9fb5 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -20,10 +20,10 @@
20 * rewrites. 20 * rewrites.
21 * 21 *
22 * Other credits: 22 * Other credits:
23 * o_addchr() derived from similar w_addchar function in glibc-2.2 23 * o_addchr() derived from similar w_addchar function in glibc-2.2.
24 * setup_redirect(), redirect_opt_num(), and big chunks of main() 24 * setup_redirect(), redirect_opt_num(), and big chunks of main()
25 * and many builtins derived from contributions by Erik Andersen 25 * and many builtins derived from contributions by Erik Andersen
26 * miscellaneous bugfixes from Matt Kraai 26 * miscellaneous bugfixes from Matt Kraai.
27 * 27 *
28 * There are two big (and related) architecture differences between 28 * There are two big (and related) architecture differences between
29 * this parser and the lash parser. One is that this version is 29 * this parser and the lash parser. One is that this version is
@@ -38,7 +38,6 @@
38 * 38 *
39 * Bash grammar not implemented: (how many of these were in original sh?) 39 * Bash grammar not implemented: (how many of these were in original sh?)
40 * $_ 40 * $_
41 * ! negation operator for pipes
42 * &> and >& redirection of stdout+stderr 41 * &> and >& redirection of stdout+stderr
43 * Brace Expansion 42 * Brace Expansion
44 * Tilde Expansion 43 * Tilde Expansion
@@ -54,24 +53,16 @@
54 * reserved word execution woefully incomplete and buggy 53 * reserved word execution woefully incomplete and buggy
55 * to-do: 54 * to-do:
56 * port selected bugfixes from post-0.49 busybox lash - done? 55 * port selected bugfixes from post-0.49 busybox lash - done?
57 * finish implementing reserved words: for, while, until, do, done
58 * change { and } from special chars to reserved words 56 * change { and } from special chars to reserved words
59 * builtins: break, continue, eval, return, set, trap, ulimit 57 * builtins: break, continue, eval, return, set, trap, ulimit
60 * test magic exec 58 * test magic exec
61 * handle children going into background
62 * clean up recognition of null pipes
63 * check setting of global_argc and global_argv 59 * check setting of global_argc and global_argv
64 * control-C handling, probably with longjmp
65 * follow IFS rules more precisely, including update semantics 60 * follow IFS rules more precisely, including update semantics
66 * figure out what to do with backslash-newline 61 * figure out what to do with backslash-newline
67 * explain why we use signal instead of sigaction
68 * propagate syntax errors, die on resource errors? 62 * propagate syntax errors, die on resource errors?
69 * continuation lines, both explicit and implicit - done? 63 * continuation lines, both explicit and implicit - done?
70 * memory leak finding and plugging - done? 64 * memory leak finding and plugging - done?
71 * more testing, especially quoting rules and redirection
72 * document how quoting rules not precisely followed for variable assignments
73 * maybe change charmap[] to use 2-bit entries 65 * maybe change charmap[] to use 2-bit entries
74 * (eventually) remove all the printf's
75 * 66 *
76 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. 67 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
77 */ 68 */
@@ -244,26 +235,6 @@ typedef enum {
244 RES_XXXX = 12, 235 RES_XXXX = 12,
245 RES_SNTX = 13 236 RES_SNTX = 13
246} reserved_style; 237} reserved_style;
247enum {
248 FLAG_END = (1 << RES_NONE ),
249#if ENABLE_HUSH_IF
250 FLAG_IF = (1 << RES_IF ),
251 FLAG_THEN = (1 << RES_THEN ),
252 FLAG_ELIF = (1 << RES_ELIF ),
253 FLAG_ELSE = (1 << RES_ELSE ),
254 FLAG_FI = (1 << RES_FI ),
255#endif
256#if ENABLE_HUSH_LOOPS
257 FLAG_FOR = (1 << RES_FOR ),
258 FLAG_WHILE = (1 << RES_WHILE),
259 FLAG_UNTIL = (1 << RES_UNTIL),
260 FLAG_DO = (1 << RES_DO ),
261 FLAG_DONE = (1 << RES_DONE ),
262 FLAG_IN = (1 << RES_IN ),
263#endif
264 FLAG_START = (1 << RES_XXXX ),
265};
266
267/* This holds pointers to the various results of parsing */ 238/* This holds pointers to the various results of parsing */
268struct p_context { 239struct p_context {
269 struct child_prog *child; 240 struct child_prog *child;
@@ -271,7 +242,8 @@ struct p_context {
271 struct pipe *pipe; 242 struct pipe *pipe;
272 struct redir_struct *pending_redirect; 243 struct redir_struct *pending_redirect;
273 smallint res_w; 244 smallint res_w;
274 smallint parse_type; /* bitmask of PARSEFLAG_xxx, defines type of parser : ";$" common or special symbol */ 245 smallint parse_type; /* bitmask of PARSEFLAG_xxx, defines type of parser: ";$" common or special symbol */
246 smallint ctx_inverted; /* "! cmd | cmd" */
275 int old_flag; /* bitmask of FLAG_xxx, for figuring out valid reserved words */ 247 int old_flag; /* bitmask of FLAG_xxx, for figuring out valid reserved words */
276 struct p_context *stack; 248 struct p_context *stack;
277 /* How about quoting status? */ 249 /* How about quoting status? */
@@ -313,6 +285,7 @@ struct pipe {
313 char *cmdbuf; /* buffer various argv's point into */ 285 char *cmdbuf; /* buffer various argv's point into */
314 struct child_prog *progs; /* array of commands in pipe */ 286 struct child_prog *progs; /* array of commands in pipe */
315 int job_context; /* bitmask defining current context */ 287 int job_context; /* bitmask defining current context */
288 smallint pi_inverted; /* "! cmd | cmd" */
316 smallint followup; /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */ 289 smallint followup; /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */
317 smallint res_word; /* needed for if, for, while, until... */ 290 smallint res_word; /* needed for if, for, while, until... */
318}; 291};
@@ -524,7 +497,7 @@ static int setup_redirect(struct p_context *ctx, int fd, redir_type style, struc
524static void initialize_context(struct p_context *ctx); 497static void initialize_context(struct p_context *ctx);
525static int done_word(o_string *dest, struct p_context *ctx); 498static int done_word(o_string *dest, struct p_context *ctx);
526static int done_command(struct p_context *ctx); 499static int done_command(struct p_context *ctx);
527static int done_pipe(struct p_context *ctx, pipe_style type); 500static void done_pipe(struct p_context *ctx, pipe_style type);
528/* primary string parsing: */ 501/* primary string parsing: */
529static int redirect_dup_num(struct in_str *input); 502static int redirect_dup_num(struct in_str *input);
530static int redirect_opt_num(o_string *o); 503static int redirect_opt_num(o_string *o);
@@ -1648,9 +1621,6 @@ static void pseudo_exec_argv(char **ptrs2free, char **argv)
1648 */ 1621 */
1649static void pseudo_exec(char **ptrs2free, struct child_prog *child) 1622static void pseudo_exec(char **ptrs2free, struct child_prog *child)
1650{ 1623{
1651// FIXME: buggy wrt NOMMU! Must not modify any global data
1652// until it does exec/_exit, but currently it does
1653// (puts malloc'ed stuff into environment)
1654 if (child->argv) 1624 if (child->argv)
1655 pseudo_exec_argv(ptrs2free, child->argv); 1625 pseudo_exec_argv(ptrs2free, child->argv);
1656 1626
@@ -1691,8 +1661,10 @@ static const char *get_cmdtext(struct pipe *pi)
1691 if (pi->cmdtext) 1661 if (pi->cmdtext)
1692 return pi->cmdtext; 1662 return pi->cmdtext;
1693 argv = pi->progs[0].argv; 1663 argv = pi->progs[0].argv;
1694 if (!argv || !argv[0]) 1664 if (!argv || !argv[0]) {
1695 return (pi->cmdtext = xzalloc(1)); 1665 pi->cmdtext = xzalloc(1);
1666 return pi->cmdtext;
1667 }
1696 1668
1697 len = 0; 1669 len = 0;
1698 do len += strlen(*argv) + 1; while (*++argv); 1670 do len += strlen(*argv) + 1; while (*++argv);
@@ -1833,9 +1805,12 @@ static int checkjobs(struct pipe* fg_pipe)
1833 if (dead) { 1805 if (dead) {
1834 fg_pipe->progs[i].pid = 0; 1806 fg_pipe->progs[i].pid = 0;
1835 fg_pipe->running_progs--; 1807 fg_pipe->running_progs--;
1836 if (i == fg_pipe->num_progs - 1) 1808 if (i == fg_pipe->num_progs - 1) {
1837 /* last process gives overall exitstatus */ 1809 /* last process gives overall exitstatus */
1838 rcode = WEXITSTATUS(status); 1810 rcode = WEXITSTATUS(status);
1811 if (fg_pipe->pi_inverted)
1812 rcode = !rcode;
1813 }
1839 } else { 1814 } else {
1840 fg_pipe->progs[i].is_stopped = 1; 1815 fg_pipe->progs[i].is_stopped = 1;
1841 fg_pipe->stopped_progs++; 1816 fg_pipe->stopped_progs++;
@@ -1966,6 +1941,8 @@ static int run_pipe(struct pipe *pi)
1966 rcode = run_list(child->group) & 0xff; 1941 rcode = run_list(child->group) & 0xff;
1967 restore_redirects(squirrel); 1942 restore_redirects(squirrel);
1968 debug_printf_exec("run_pipe return %d\n", rcode); 1943 debug_printf_exec("run_pipe return %d\n", rcode);
1944 if (pi->pi_inverted)
1945 rcode = !rcode;
1969 return rcode; 1946 return rcode;
1970 } 1947 }
1971 1948
@@ -2007,6 +1984,8 @@ static int run_pipe(struct pipe *pi)
2007 free(argv_expanded); 1984 free(argv_expanded);
2008 restore_redirects(squirrel); 1985 restore_redirects(squirrel);
2009 debug_printf_exec("run_pipe return %d\n", rcode); 1986 debug_printf_exec("run_pipe return %d\n", rcode);
1987 if (pi->pi_inverted)
1988 rcode = !rcode;
2010 return rcode; 1989 return rcode;
2011 } 1990 }
2012 } 1991 }
@@ -2023,6 +2002,8 @@ static int run_pipe(struct pipe *pi)
2023 free(argv_expanded); 2002 free(argv_expanded);
2024 restore_redirects(squirrel); 2003 restore_redirects(squirrel);
2025 debug_printf_exec("run_pipe return %d\n", rcode); 2004 debug_printf_exec("run_pipe return %d\n", rcode);
2005 if (pi->pi_inverted)
2006 rcode = !rcode;
2026 return rcode; 2007 return rcode;
2027 } 2008 }
2028 } 2009 }
@@ -2985,7 +2966,8 @@ static int setup_redirect(struct p_context *ctx, int fd, redir_type style,
2985 2966
2986 /* Check for a '2>&1' type redirect */ 2967 /* Check for a '2>&1' type redirect */
2987 redir->dup = redirect_dup_num(input); 2968 redir->dup = redirect_dup_num(input);
2988 if (redir->dup == -2) return 1; /* syntax error */ 2969 if (redir->dup == -2)
2970 return 1; /* syntax error */
2989 if (redir->dup != -1) { 2971 if (redir->dup != -1) {
2990 /* Erik had a check here that the file descriptor in question 2972 /* Erik had a check here that the file descriptor in question
2991 * is legit; I postpone that to "run time" 2973 * is legit; I postpone that to "run time"
@@ -3005,10 +2987,7 @@ static struct pipe *new_pipe(void)
3005{ 2987{
3006 struct pipe *pi; 2988 struct pipe *pi;
3007 pi = xzalloc(sizeof(struct pipe)); 2989 pi = xzalloc(sizeof(struct pipe));
3008 /*pi->num_progs = 0;*/ 2990 /*pi->followup = 0; - deliberately invalid value */
3009 /*pi->progs = NULL;*/
3010 /*pi->next = NULL;*/
3011 /*pi->followup = 0; invalid */
3012 if (RES_NONE) 2991 if (RES_NONE)
3013 pi->res_word = RES_NONE; 2992 pi->res_word = RES_NONE;
3014 return pi; 2993 return pi;
@@ -3016,29 +2995,50 @@ static struct pipe *new_pipe(void)
3016 2995
3017static void initialize_context(struct p_context *ctx) 2996static void initialize_context(struct p_context *ctx)
3018{ 2997{
3019 ctx->child = NULL; 2998 smallint sv = ctx->parse_type;
2999 memset(ctx, 0, sizeof(*ctx));
3000 ctx->parse_type = sv;
3020 ctx->pipe = ctx->list_head = new_pipe(); 3001 ctx->pipe = ctx->list_head = new_pipe();
3021 ctx->pending_redirect = NULL; 3002 /* Create the memory for child, roughly:
3022 ctx->res_w = RES_NONE; 3003 * ctx->pipe->progs = new struct child_prog;
3023 //only ctx->parse_type is not touched... is this intentional? 3004 * ctx->pipe->progs[0].family = ctx->pipe;
3024 ctx->old_flag = 0; 3005 * ctx->child = &ctx->pipe->progs[0];
3025 ctx->stack = NULL; 3006 */
3026 done_command(ctx); /* creates the memory for working child */ 3007 done_command(ctx);
3027} 3008}
3028 3009
3029/* normal return is 0 3010/* If a reserved word is found and processed, parse context is modified
3030 * if a reserved word is found, and processed, return 1 3011 * and 1 is returned.
3031 * should handle if, then, elif, else, fi, for, while, until, do, done. 3012 * Handles if, then, elif, else, fi, for, while, until, do, done.
3032 * case, function, and select are obnoxious, save those for later. 3013 * case, function, and select are obnoxious, save those for later.
3033 */ 3014 */
3034#if ENABLE_HUSH_IF || ENABLE_HUSH_LOOPS 3015#if ENABLE_HUSH_IF || ENABLE_HUSH_LOOPS
3035static int reserved_word(o_string *dest, struct p_context *ctx) 3016static int reserved_word(const o_string *word, struct p_context *ctx)
3036{ 3017{
3037 struct reserved_combo { 3018 struct reserved_combo {
3038 char literal[7]; 3019 char literal[7];
3039 unsigned char code; 3020 unsigned char res;
3040 int flag; 3021 int flag;
3041 }; 3022 };
3023 enum {
3024 FLAG_END = (1 << RES_NONE ),
3025#if ENABLE_HUSH_IF
3026 FLAG_IF = (1 << RES_IF ),
3027 FLAG_THEN = (1 << RES_THEN ),
3028 FLAG_ELIF = (1 << RES_ELIF ),
3029 FLAG_ELSE = (1 << RES_ELSE ),
3030 FLAG_FI = (1 << RES_FI ),
3031#endif
3032#if ENABLE_HUSH_LOOPS
3033 FLAG_FOR = (1 << RES_FOR ),
3034 FLAG_WHILE = (1 << RES_WHILE),
3035 FLAG_UNTIL = (1 << RES_UNTIL),
3036 FLAG_DO = (1 << RES_DO ),
3037 FLAG_DONE = (1 << RES_DONE ),
3038 FLAG_IN = (1 << RES_IN ),
3039#endif
3040 FLAG_START = (1 << RES_XXXX ),
3041 };
3042 /* Mostly a list of accepted follow-up reserved words. 3042 /* Mostly a list of accepted follow-up reserved words.
3043 * FLAG_END means we are done with the sequence, and are ready 3043 * FLAG_END means we are done with the sequence, and are ready
3044 * to turn the compound list into a command. 3044 * to turn the compound list into a command.
@@ -3046,6 +3046,7 @@ static int reserved_word(o_string *dest, struct p_context *ctx)
3046 */ 3046 */
3047 static const struct reserved_combo reserved_list[] = { 3047 static const struct reserved_combo reserved_list[] = {
3048#if ENABLE_HUSH_IF 3048#if ENABLE_HUSH_IF
3049 { "!", RES_NONE, 0 },
3049 { "if", RES_IF, FLAG_THEN | FLAG_START }, 3050 { "if", RES_IF, FLAG_THEN | FLAG_START },
3050 { "then", RES_THEN, FLAG_ELIF | FLAG_ELSE | FLAG_FI }, 3051 { "then", RES_THEN, FLAG_ELIF | FLAG_ELSE | FLAG_FI },
3051 { "elif", RES_ELIF, FLAG_THEN }, 3052 { "elif", RES_ELIF, FLAG_THEN },
@@ -3053,9 +3054,9 @@ static int reserved_word(o_string *dest, struct p_context *ctx)
3053 { "fi", RES_FI, FLAG_END }, 3054 { "fi", RES_FI, FLAG_END },
3054#endif 3055#endif
3055#if ENABLE_HUSH_LOOPS 3056#if ENABLE_HUSH_LOOPS
3056 { "for", RES_FOR, FLAG_IN | FLAG_START }, 3057 { "for", RES_FOR, FLAG_IN | FLAG_START },
3057 { "while", RES_WHILE, FLAG_DO | FLAG_START }, 3058 { "while", RES_WHILE, FLAG_DO | FLAG_START },
3058 { "until", RES_UNTIL, FLAG_DO | FLAG_START }, 3059 { "until", RES_UNTIL, FLAG_DO | FLAG_START },
3059 { "in", RES_IN, FLAG_DO }, 3060 { "in", RES_IN, FLAG_DO },
3060 { "do", RES_DO, FLAG_DONE }, 3061 { "do", RES_DO, FLAG_DONE },
3061 { "done", RES_DONE, FLAG_END } 3062 { "done", RES_DONE, FLAG_END }
@@ -3065,9 +3066,23 @@ static int reserved_word(o_string *dest, struct p_context *ctx)
3065 const struct reserved_combo *r; 3066 const struct reserved_combo *r;
3066 3067
3067 for (r = reserved_list; r < reserved_list + ARRAY_SIZE(reserved_list); r++) { 3068 for (r = reserved_list; r < reserved_list + ARRAY_SIZE(reserved_list); r++) {
3068 if (strcmp(dest->data, r->literal) != 0) 3069 if (strcmp(word->data, r->literal) != 0)
3069 continue; 3070 continue;
3070 debug_printf("found reserved word %s, code %d\n", r->literal, r->code); 3071 debug_printf("found reserved word %s, res %d\n", r->literal, r->res);
3072 if (r->flag == 0) { /* '!' */
3073 if (ctx->res_w == RES_IN) {
3074 /* 'for a in ! a b c; ...' - ! isn't a keyword here */
3075 break;
3076 }
3077 if (ctx->res_w == RES_FOR /* example: 'for ! a' */
3078 || ctx->ctx_inverted /* bash doesn't accept '! ! true' */
3079 ) {
3080 syntax(NULL);
3081 ctx->res_w = RES_SNTX;
3082 }
3083 ctx->ctx_inverted = 1;
3084 return 1;
3085 }
3071 if (r->flag & FLAG_START) { 3086 if (r->flag & FLAG_START) {
3072 struct p_context *new; 3087 struct p_context *new;
3073 debug_printf("push stack\n"); 3088 debug_printf("push stack\n");
@@ -3075,7 +3090,6 @@ static int reserved_word(o_string *dest, struct p_context *ctx)
3075 if (ctx->res_w == RES_IN || ctx->res_w == RES_FOR) { 3090 if (ctx->res_w == RES_IN || ctx->res_w == RES_FOR) {
3076 syntax("malformed for"); /* example: 'for if' */ 3091 syntax("malformed for"); /* example: 'for if' */
3077 ctx->res_w = RES_SNTX; 3092 ctx->res_w = RES_SNTX;
3078 o_reset(dest);
3079 return 1; 3093 return 1;
3080 } 3094 }
3081#endif 3095#endif
@@ -3083,13 +3097,12 @@ static int reserved_word(o_string *dest, struct p_context *ctx)
3083 *new = *ctx; /* physical copy */ 3097 *new = *ctx; /* physical copy */
3084 initialize_context(ctx); 3098 initialize_context(ctx);
3085 ctx->stack = new; 3099 ctx->stack = new;
3086 } else if (ctx->res_w == RES_NONE || !(ctx->old_flag & (1 << r->code))) { 3100 } else if (ctx->res_w == RES_NONE || !(ctx->old_flag & (1 << r->res))) {
3087 syntax(NULL); 3101 syntax(NULL);
3088 ctx->res_w = RES_SNTX; 3102 ctx->res_w = RES_SNTX;
3089 o_reset(dest);
3090 return 1; 3103 return 1;
3091 } 3104 }
3092 ctx->res_w = r->code; 3105 ctx->res_w = r->res;
3093 ctx->old_flag = r->flag; 3106 ctx->old_flag = r->flag;
3094 if (ctx->old_flag & FLAG_END) { 3107 if (ctx->old_flag & FLAG_END) {
3095 struct p_context *old; 3108 struct p_context *old;
@@ -3101,52 +3114,55 @@ static int reserved_word(o_string *dest, struct p_context *ctx)
3101 *ctx = *old; /* physical copy */ 3114 *ctx = *old; /* physical copy */
3102 free(old); 3115 free(old);
3103 } 3116 }
3104 o_reset(dest);
3105 return 1; 3117 return 1;
3106 } 3118 }
3107 return 0; 3119 return 0;
3108} 3120}
3109#else 3121#else
3110#define reserved_word(dest, ctx) ((int)0) 3122#define reserved_word(word, ctx) ((int)0)
3111#endif 3123#endif
3112 3124
3113/* Normal return is 0. 3125/* Word is complete, look at it and update parsing context.
3126 * Normal return is 0.
3114 * Syntax or xglob errors return 1. */ 3127 * Syntax or xglob errors return 1. */
3115static int done_word(o_string *dest, struct p_context *ctx) 3128static int done_word(o_string *word, struct p_context *ctx)
3116{ 3129{
3117 struct child_prog *child = ctx->child; 3130 struct child_prog *child = ctx->child;
3118 char ***glob_target; 3131 char ***glob_target;
3119 int gr; 3132 int gr;
3120 3133
3121 debug_printf_parse("done_word entered: '%s' %p\n", dest->data, child); 3134 debug_printf_parse("done_word entered: '%s' %p\n", word->data, child);
3122 if (dest->length == 0 && !dest->nonnull) { 3135 if (word->length == 0 && !word->nonnull) {
3123 debug_printf_parse("done_word return 0: true null, ignored\n"); 3136 debug_printf_parse("done_word return 0: true null, ignored\n");
3124 return 0; 3137 return 0;
3125 } 3138 }
3126 if (ctx->pending_redirect) { 3139 if (ctx->pending_redirect) {
3127 glob_target = &ctx->pending_redirect->glob_word; 3140 glob_target = &ctx->pending_redirect->glob_word;
3128 } else { 3141 } else {
3129 if (child->group) { 3142 if (child->group) { /* TODO: example how to trigger? */
3130 syntax(NULL); 3143 syntax(NULL);
3131 debug_printf_parse("done_word return 1: syntax error, groups and arglists don't mix\n"); 3144 debug_printf_parse("done_word return 1: syntax error, groups and arglists don't mix\n");
3132 return 1; 3145 return 1;
3133 } 3146 }
3134 if (!child->argv && (ctx->parse_type & PARSEFLAG_SEMICOLON)) { 3147 if (!child->argv && (ctx->parse_type & PARSEFLAG_SEMICOLON)) {
3135 debug_printf_parse(": checking '%s' for reserved-ness\n", dest->data); 3148 debug_printf_parse(": checking '%s' for reserved-ness\n", word->data);
3136 if (reserved_word(dest, ctx)) { 3149 if (reserved_word(word, ctx)) {
3150 o_reset(word);
3137 debug_printf_parse("done_word return %d\n", (ctx->res_w == RES_SNTX)); 3151 debug_printf_parse("done_word return %d\n", (ctx->res_w == RES_SNTX));
3138 return (ctx->res_w == RES_SNTX); 3152 return (ctx->res_w == RES_SNTX);
3139 } 3153 }
3140 } 3154 }
3141 glob_target = &child->argv; 3155 glob_target = &child->argv;
3142 } 3156 }
3143 gr = xglob(dest, glob_target); 3157//BUG! globbing should be done after variable expansion!
3158//See glob_and_vars testcase
3159 gr = xglob(word, glob_target);
3144 if (gr != 0) { 3160 if (gr != 0) {
3145 debug_printf_parse("done_word return 1: xglob returned %d\n", gr); 3161 debug_printf_parse("done_word return 1: xglob returned %d\n", gr);
3146 return 1; 3162 return 1;
3147 } 3163 }
3148 3164
3149 o_reset(dest); 3165 o_reset(word);
3150 if (ctx->pending_redirect) { 3166 if (ctx->pending_redirect) {
3151 /* NB: don't free_strings(ctx->pending_redirect->glob_word) here */ 3167 /* NB: don't free_strings(ctx->pending_redirect->glob_word) here */
3152 if (ctx->pending_redirect->glob_word 3168 if (ctx->pending_redirect->glob_word
@@ -3162,8 +3178,11 @@ static int done_word(o_string *dest, struct p_context *ctx)
3162 ctx->pending_redirect = NULL; 3178 ctx->pending_redirect = NULL;
3163 } 3179 }
3164#if ENABLE_HUSH_LOOPS 3180#if ENABLE_HUSH_LOOPS
3165 if (ctx->res_w == RES_FOR) { 3181 if (ctx->res_w == RES_FOR) { /* comment? */
3166 done_word(dest, ctx); 3182//TESTING
3183//looks like (word->length == 0 && !word->nonnull) is true here, always
3184//(due to o_reset). done_word would return at once. Why then?
3185// done_word(word, ctx);
3167 done_pipe(ctx, PIPE_SEQ); 3186 done_pipe(ctx, PIPE_SEQ);
3168 } 3187 }
3169#endif 3188#endif
@@ -3200,10 +3219,6 @@ static int done_command(struct p_context *ctx)
3200 child = &pi->progs[pi->num_progs]; 3219 child = &pi->progs[pi->num_progs];
3201 3220
3202 memset(child, 0, sizeof(*child)); 3221 memset(child, 0, sizeof(*child));
3203 /*child->redirects = NULL;*/
3204 /*child->argv = NULL;*/
3205 /*child->is_stopped = 0;*/
3206 /*child->group = NULL;*/
3207 child->family = pi; 3222 child->family = pi;
3208 3223
3209 ctx->child = child; 3224 ctx->child = child;
@@ -3212,7 +3227,7 @@ static int done_command(struct p_context *ctx)
3212 return pi->num_progs; /* used only for 0/nonzero check */ 3227 return pi->num_progs; /* used only for 0/nonzero check */
3213} 3228}
3214 3229
3215static int done_pipe(struct p_context *ctx, pipe_style type) 3230static void done_pipe(struct p_context *ctx, pipe_style type)
3216{ 3231{
3217 struct pipe *new_p; 3232 struct pipe *new_p;
3218 int not_null; 3233 int not_null;
@@ -3221,6 +3236,8 @@ static int done_pipe(struct p_context *ctx, pipe_style type)
3221 not_null = done_command(ctx); /* implicit closure of previous command */ 3236 not_null = done_command(ctx); /* implicit closure of previous command */
3222 ctx->pipe->followup = type; 3237 ctx->pipe->followup = type;
3223 ctx->pipe->res_word = ctx->res_w; 3238 ctx->pipe->res_word = ctx->res_w;
3239 ctx->pipe->pi_inverted = ctx->ctx_inverted;
3240 ctx->ctx_inverted = 0;
3224 /* Without this check, even just <enter> on command line generates 3241 /* Without this check, even just <enter> on command line generates
3225 * tree of three NOPs (!). Which is harmless but annoying. 3242 * tree of three NOPs (!). Which is harmless but annoying.
3226 * IOW: it is safe to do it unconditionally. */ 3243 * IOW: it is safe to do it unconditionally. */
@@ -3228,11 +3245,15 @@ static int done_pipe(struct p_context *ctx, pipe_style type)
3228 new_p = new_pipe(); 3245 new_p = new_pipe();
3229 ctx->pipe->next = new_p; 3246 ctx->pipe->next = new_p;
3230 ctx->pipe = new_p; 3247 ctx->pipe = new_p;
3231 ctx->child = NULL; 3248 ctx->child = NULL; /* needed! */
3232 done_command(ctx); /* set up new pipe to accept commands */ 3249 /* Create the memory for child, roughly:
3250 * ctx->pipe->progs = new struct child_prog;
3251 * ctx->pipe->progs[0].family = ctx->pipe;
3252 * ctx->child = &ctx->pipe->progs[0];
3253 */
3254 done_command(ctx);
3233 } 3255 }
3234 debug_printf_parse("done_pipe return 0\n"); 3256 debug_printf_parse("done_pipe return\n");
3235 return 0;
3236} 3257}
3237 3258
3238/* peek ahead in the in_str to find out if we have a "&n" construct, 3259/* peek ahead in the in_str to find out if we have a "&n" construct,
@@ -3826,7 +3847,8 @@ static int parse_stream(o_string *dest, struct p_context *ctx,
3826 break; 3847 break;
3827 case ')': 3848 case ')':
3828 case '}': 3849 case '}':
3829 syntax("unexpected }"); /* Proper use of this character is caught by end_trigger */ 3850 /* proper use of this character is caught by end_trigger */
3851 syntax("unexpected } or )");
3830 debug_printf_parse("parse_stream return 1: unexpected '}'\n"); 3852 debug_printf_parse("parse_stream return 1: unexpected '}'\n");
3831 return 1; 3853 return 1;
3832 default: 3854 default:
@@ -3880,10 +3902,14 @@ static void update_charmap(void)
3880 * from builtin_source() and builtin_eval() */ 3902 * from builtin_source() and builtin_eval() */
3881static int parse_and_run_stream(struct in_str *inp, int parse_flag) 3903static int parse_and_run_stream(struct in_str *inp, int parse_flag)
3882{ 3904{
3905//TODO: PARSEFLAG_SEMICOLON bit is always set in parse_flag. fishy
3906//TODO: PARSEFLAG_REPARSING bit is never set (grep for it). wow
3883 struct p_context ctx; 3907 struct p_context ctx;
3884 o_string temp = NULL_O_STRING; 3908 o_string temp = NULL_O_STRING;
3885 int rcode; 3909 int rcode;
3886 do { 3910 do {
3911// It always has PARSEFLAG_SEMICOLON, can we remove all checks for this bit?
3912// After that, the whole parse_type fiels is not needed.
3887 ctx.parse_type = parse_flag; 3913 ctx.parse_type = parse_flag;
3888 initialize_context(&ctx); 3914 initialize_context(&ctx);
3889 update_charmap(); 3915 update_charmap();
@@ -3922,6 +3948,7 @@ static int parse_and_run_stream(struct in_str *inp, int parse_flag)
3922 3948
3923static int parse_and_run_string(const char *s, int parse_flag) 3949static int parse_and_run_string(const char *s, int parse_flag)
3924{ 3950{
3951//TODO: PARSEFLAG_SEMICOLON bit is always set in parse_flag. fishy
3925 struct in_str input; 3952 struct in_str input;
3926 setup_string_in_str(&input, s); 3953 setup_string_in_str(&input, s);
3927 return parse_and_run_stream(&input, parse_flag); 3954 return parse_and_run_stream(&input, parse_flag);
diff --git a/shell/hush_test/hush-misc/syntax_err_negate.right b/shell/hush_test/hush-misc/syntax_err_negate.right
new file mode 100644
index 000000000..d1e7654f5
--- /dev/null
+++ b/shell/hush_test/hush-misc/syntax_err_negate.right
@@ -0,0 +1,2 @@
1bash 3.2 fails this
2hush: syntax error
diff --git a/shell/hush_test/hush-misc/syntax_err_negate.tests b/shell/hush_test/hush-misc/syntax_err_negate.tests
new file mode 100755
index 000000000..d61b1b09f
--- /dev/null
+++ b/shell/hush_test/hush-misc/syntax_err_negate.tests
@@ -0,0 +1,2 @@
1echo bash 3.2 fails this
2! ! true
diff --git a/shell/hush_test/hush-parsing/negate.right b/shell/hush_test/hush-parsing/negate.right
new file mode 100644
index 000000000..01166012e
--- /dev/null
+++ b/shell/hush_test/hush-parsing/negate.right
@@ -0,0 +1,35 @@
1! printing !
20
31
41
50
60
70
8!
9a
10b
11c
12! 1
13a 1
14b 1
15c 1
16! 1
17a 1
18b 1
19c 1
200
210
220
230
241
251
261
271
280
290
300
310
321
331
341
351
diff --git a/shell/hush_test/hush-parsing/negate.tests b/shell/hush_test/hush-parsing/negate.tests
new file mode 100755
index 000000000..72e731fe9
--- /dev/null
+++ b/shell/hush_test/hush-parsing/negate.tests
@@ -0,0 +1,16 @@
1echo ! printing !
2! false
3echo $?
4! true
5echo $?
6if ! false; then false; echo $?; fi
7echo $?
8if ! false; then ! false; echo $?; fi
9echo $?
10for a in ! a b c; do echo $a; done
11for a in ! a b c; do ! echo -n "$a "; echo $?; done
12for a in ! a b c; do ! /bin/echo -n "$a "; echo $?; done
13for a in ! a b c; do ! echo -n "$a " | false; echo $?; done
14for a in ! a b c; do ! echo -n "$a " | true; echo $?; done
15for a in ! a b c; do ! { echo -n "$a " | false; }; echo $?; done
16for a in ! a b c; do ! { echo -n "$a " | true; }; echo $?; done
diff --git a/shell/hush_test/run-all b/shell/hush_test/run-all
index 805f75ad5..5cec85af6 100755
--- a/shell/hush_test/run-all
+++ b/shell/hush_test/run-all
@@ -1,8 +1,8 @@
1#!/bin/sh 1#!/bin/sh
2 2
3test -x hush || { 3test -x hush || {
4 echo "No ./hush?! Perhaps you want to run 'ln -s ../../busybox hush'" 4 echo "No ./hush - creating a link to ../../busybox"
5 exit 5 ln -s ../../busybox hush
6} 6}
7 7
8PATH="$PWD:$PATH" # for hush and recho/zecho/printenv 8PATH="$PWD:$PATH" # for hush and recho/zecho/printenv