diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-07-14 06:29:38 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-07-14 06:29:38 +0000 |
commit | 395ae452165a607c6b5bc4623225516044619616 (patch) | |
tree | 00ceff4dcd3fc4604d9252003cf45dfb6cfbedc1 /shell/hush.c | |
parent | 17f02e79f407ff2311255981c191a1bf8b3a7ae0 (diff) | |
download | busybox-w32-395ae452165a607c6b5bc4623225516044619616.tar.gz busybox-w32-395ae452165a607c6b5bc4623225516044619616.tar.bz2 busybox-w32-395ae452165a607c6b5bc4623225516044619616.zip |
hush: delete unused field in struct child.
reinstate needed check for invalid syntax.
document command parsing in hush_doc.txt.
Diffstat (limited to 'shell/hush.c')
-rw-r--r-- | shell/hush.c | 34 |
1 files changed, 18 insertions, 16 deletions
diff --git a/shell/hush.c b/shell/hush.c index 47e53f8c1..db608018c 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -322,7 +322,6 @@ struct child_prog { | |||
322 | char **argv; /* program name and arguments */ | 322 | char **argv; /* program name and arguments */ |
323 | struct pipe *group; /* if non-NULL, first in group or subshell */ | 323 | struct pipe *group; /* if non-NULL, first in group or subshell */ |
324 | struct redir_struct *redirects; /* I/O redirections */ | 324 | struct redir_struct *redirects; /* I/O redirections */ |
325 | struct pipe *family; /* pointer back to the child's parent pipe */ | ||
326 | }; | 325 | }; |
327 | /* argv vector may contain variable references (^Cvar^C, ^C0^C etc) | 326 | /* argv vector may contain variable references (^Cvar^C, ^C0^C etc) |
328 | * and on execution these are substituted with their values. | 327 | * and on execution these are substituted with their values. |
@@ -2830,7 +2829,6 @@ static void initialize_context(struct p_context *ctx) | |||
2830 | ctx->pipe = ctx->list_head = new_pipe(); | 2829 | ctx->pipe = ctx->list_head = new_pipe(); |
2831 | /* Create the memory for child, roughly: | 2830 | /* Create the memory for child, roughly: |
2832 | * ctx->pipe->progs = new struct child_prog; | 2831 | * ctx->pipe->progs = new struct child_prog; |
2833 | * ctx->pipe->progs[0].family = ctx->pipe; | ||
2834 | * ctx->child = &ctx->pipe->progs[0]; | 2832 | * ctx->child = &ctx->pipe->progs[0]; |
2835 | */ | 2833 | */ |
2836 | done_command(ctx); | 2834 | done_command(ctx); |
@@ -2960,6 +2958,7 @@ static int done_word(o_string *word, struct p_context *ctx) | |||
2960 | { | 2958 | { |
2961 | struct child_prog *child = ctx->child; | 2959 | struct child_prog *child = ctx->child; |
2962 | 2960 | ||
2961 | debug_printf_parse("done_word entered: '%s' %p\n", word->data, child); | ||
2963 | /* If this word wasn't an assignment, next ones definitely | 2962 | /* If this word wasn't an assignment, next ones definitely |
2964 | * can't be assignments. Even if they look like ones. */ | 2963 | * can't be assignments. Even if they look like ones. */ |
2965 | if (word->o_assignment != DEFINITELY_ASSIGNMENT) { | 2964 | if (word->o_assignment != DEFINITELY_ASSIGNMENT) { |
@@ -2967,8 +2966,6 @@ static int done_word(o_string *word, struct p_context *ctx) | |||
2967 | } else { | 2966 | } else { |
2968 | word->o_assignment = MAYBE_ASSIGNMENT; | 2967 | word->o_assignment = MAYBE_ASSIGNMENT; |
2969 | } | 2968 | } |
2970 | |||
2971 | debug_printf_parse("done_word entered: '%s' %p\n", word->data, child); | ||
2972 | if (word->length == 0 && word->nonnull == 0) { | 2969 | if (word->length == 0 && word->nonnull == 0) { |
2973 | debug_printf_parse("done_word return 0: true null, ignored\n"); | 2970 | debug_printf_parse("done_word return 0: true null, ignored\n"); |
2974 | return 0; | 2971 | return 0; |
@@ -2980,15 +2977,17 @@ static int done_word(o_string *word, struct p_context *ctx) | |||
2980 | word->o_assignment = NOT_ASSIGNMENT; | 2977 | word->o_assignment = NOT_ASSIGNMENT; |
2981 | debug_printf("word stored in rd_filename: '%s'\n", word->data); | 2978 | debug_printf("word stored in rd_filename: '%s'\n", word->data); |
2982 | } else { | 2979 | } else { |
2983 | // if (child->group) { /* TODO: example how to trigger? */ | 2980 | /* "{ echo foo; } echo bar" - bad */ |
2984 | // syntax(NULL); | 2981 | /* NB: bash allows e.g. "if true; then { echo foo; } fi". TODO? */ |
2985 | // debug_printf_parse("done_word return 1: syntax error, groups and arglists don't mix\n"); | 2982 | if (child->group) { |
2986 | // return 1; | 2983 | syntax(NULL); |
2987 | // } | 2984 | debug_printf_parse("done_word return 1: syntax error, groups and arglists don't mix\n"); |
2985 | return 1; | ||
2986 | } | ||
2988 | #if HAS_KEYWORDS | 2987 | #if HAS_KEYWORDS |
2989 | #if ENABLE_HUSH_CASE | 2988 | #if ENABLE_HUSH_CASE |
2990 | if (ctx->ctx_dsemicolon) { | 2989 | if (ctx->ctx_dsemicolon) { |
2991 | /* already done when ctx_dsemicolon was set to 1 */ | 2990 | /* already done when ctx_dsemicolon was set to 1: */ |
2992 | /* ctx->ctx_res_w = RES_MATCH; */ | 2991 | /* ctx->ctx_res_w = RES_MATCH; */ |
2993 | ctx->ctx_dsemicolon = 0; | 2992 | ctx->ctx_dsemicolon = 0; |
2994 | } else | 2993 | } else |
@@ -3085,9 +3084,7 @@ static int done_command(struct p_context *ctx) | |||
3085 | * child structure is not counted in pi->num_progs. */ | 3084 | * child structure is not counted in pi->num_progs. */ |
3086 | pi->progs = xrealloc(pi->progs, sizeof(*pi->progs) * (pi->num_progs+1)); | 3085 | pi->progs = xrealloc(pi->progs, sizeof(*pi->progs) * (pi->num_progs+1)); |
3087 | child = &pi->progs[pi->num_progs]; | 3086 | child = &pi->progs[pi->num_progs]; |
3088 | |||
3089 | memset(child, 0, sizeof(*child)); | 3087 | memset(child, 0, sizeof(*child)); |
3090 | child->family = pi; | ||
3091 | 3088 | ||
3092 | ctx->child = child; | 3089 | ctx->child = child; |
3093 | /* but ctx->pipe and ctx->list_head remain unchanged */ | 3090 | /* but ctx->pipe and ctx->list_head remain unchanged */ |
@@ -3100,22 +3097,28 @@ static void done_pipe(struct p_context *ctx, pipe_style type) | |||
3100 | int not_null; | 3097 | int not_null; |
3101 | 3098 | ||
3102 | debug_printf_parse("done_pipe entered, followup %d\n", type); | 3099 | debug_printf_parse("done_pipe entered, followup %d\n", type); |
3103 | not_null = done_command(ctx); /* implicit closure of previous command */ | 3100 | /* Close previous command */ |
3101 | not_null = done_command(ctx); | ||
3104 | ctx->pipe->followup = type; | 3102 | ctx->pipe->followup = type; |
3105 | IF_HAS_KEYWORDS(ctx->pipe->pi_inverted = ctx->ctx_inverted;) | 3103 | IF_HAS_KEYWORDS(ctx->pipe->pi_inverted = ctx->ctx_inverted;) |
3106 | IF_HAS_KEYWORDS(ctx->ctx_inverted = 0;) | 3104 | IF_HAS_KEYWORDS(ctx->ctx_inverted = 0;) |
3107 | IF_HAS_KEYWORDS(ctx->pipe->res_word = ctx->ctx_res_w;) | 3105 | IF_HAS_KEYWORDS(ctx->pipe->res_word = ctx->ctx_res_w;) |
3106 | |||
3108 | /* Without this check, even just <enter> on command line generates | 3107 | /* Without this check, even just <enter> on command line generates |
3109 | * tree of three NOPs (!). Which is harmless but annoying. | 3108 | * tree of three NOPs (!). Which is harmless but annoying. |
3110 | * IOW: it is safe to do it unconditionally. | 3109 | * IOW: it is safe to do it unconditionally. |
3111 | * RES_NONE case is for "for a in; do ..." (empty IN set) | 3110 | * RES_NONE case is for "for a in; do ..." (empty IN set) |
3112 | * to work, possibly other cases too. */ | 3111 | * to work, possibly other cases too. */ |
3113 | if (not_null IF_HAS_KEYWORDS(|| ctx->ctx_res_w != RES_NONE)) { | 3112 | if (not_null IF_HAS_KEYWORDS(|| ctx->ctx_res_w != RES_NONE)) { |
3114 | struct pipe *new_p = new_pipe(); | 3113 | struct pipe *new_p; |
3114 | debug_printf_parse("done_pipe: adding new pipe: " | ||
3115 | " not_null:%d ctx->ctx_res_w:%d\n", | ||
3116 | not_null, ctx->ctx_res_w); | ||
3117 | new_p = new_pipe(); | ||
3115 | ctx->pipe->next = new_p; | 3118 | ctx->pipe->next = new_p; |
3116 | ctx->pipe = new_p; | 3119 | ctx->pipe = new_p; |
3117 | ctx->child = NULL; /* needed! */ | 3120 | ctx->child = NULL; /* needed! */ |
3118 | /* RES_IF, RES_WHILE etc are "sticky" - | 3121 | /* RES_THEN, RES_DO etc are "sticky" - |
3119 | * they remain set for commands inside if/while. | 3122 | * they remain set for commands inside if/while. |
3120 | * This is used to control execution. | 3123 | * This is used to control execution. |
3121 | * RES_FOR and RES_IN are NOT sticky (needed to support | 3124 | * RES_FOR and RES_IN are NOT sticky (needed to support |
@@ -3132,7 +3135,6 @@ static void done_pipe(struct p_context *ctx, pipe_style type) | |||
3132 | #endif | 3135 | #endif |
3133 | /* Create the memory for child, roughly: | 3136 | /* Create the memory for child, roughly: |
3134 | * ctx->pipe->progs = new struct child_prog; | 3137 | * ctx->pipe->progs = new struct child_prog; |
3135 | * ctx->pipe->progs[0].family = ctx->pipe; | ||
3136 | * ctx->child = &ctx->pipe->progs[0]; | 3138 | * ctx->child = &ctx->pipe->progs[0]; |
3137 | */ | 3139 | */ |
3138 | done_command(ctx); | 3140 | done_command(ctx); |