aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-10-09 12:58:26 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-10-09 12:58:26 +0000
commitc373527e4fe7d2d46ce25165687463da00ba986c (patch)
tree3b982f0ca0cb00abeff4af0415f10713d19f2cfe
parent9af22c762652ff92f3f207a754f71f3c4bf2c078 (diff)
downloadbusybox-w32-c373527e4fe7d2d46ce25165687463da00ba986c.tar.gz
busybox-w32-c373527e4fe7d2d46ce25165687463da00ba986c.tar.bz2
busybox-w32-c373527e4fe7d2d46ce25165687463da00ba986c.zip
hush: preparatory work for implementing functions
-rw-r--r--shell/hush.c155
1 files changed, 89 insertions, 66 deletions
diff --git a/shell/hush.c b/shell/hush.c
index c26b9e420..d5955dd93 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -2903,37 +2903,38 @@ static void initialize_context(struct parse_context *ctx)
2903 * case, function, and select are obnoxious, save those for later. 2903 * case, function, and select are obnoxious, save those for later.
2904 */ 2904 */
2905#if HAS_KEYWORDS 2905#if HAS_KEYWORDS
2906static int reserved_word(o_string *word, struct parse_context *ctx) 2906struct reserved_combo {
2907{ 2907 char literal[6];
2908 struct reserved_combo { 2908 unsigned char res;
2909 char literal[6]; 2909 unsigned char assignment_flag;
2910 unsigned char res; 2910 int flag;
2911 unsigned char assignment_flag; 2911};
2912 int flag; 2912enum {
2913 }; 2913 FLAG_END = (1 << RES_NONE ),
2914 enum {
2915 FLAG_END = (1 << RES_NONE ),
2916#if ENABLE_HUSH_IF 2914#if ENABLE_HUSH_IF
2917 FLAG_IF = (1 << RES_IF ), 2915 FLAG_IF = (1 << RES_IF ),
2918 FLAG_THEN = (1 << RES_THEN ), 2916 FLAG_THEN = (1 << RES_THEN ),
2919 FLAG_ELIF = (1 << RES_ELIF ), 2917 FLAG_ELIF = (1 << RES_ELIF ),
2920 FLAG_ELSE = (1 << RES_ELSE ), 2918 FLAG_ELSE = (1 << RES_ELSE ),
2921 FLAG_FI = (1 << RES_FI ), 2919 FLAG_FI = (1 << RES_FI ),
2922#endif 2920#endif
2923#if ENABLE_HUSH_LOOPS 2921#if ENABLE_HUSH_LOOPS
2924 FLAG_FOR = (1 << RES_FOR ), 2922 FLAG_FOR = (1 << RES_FOR ),
2925 FLAG_WHILE = (1 << RES_WHILE), 2923 FLAG_WHILE = (1 << RES_WHILE),
2926 FLAG_UNTIL = (1 << RES_UNTIL), 2924 FLAG_UNTIL = (1 << RES_UNTIL),
2927 FLAG_DO = (1 << RES_DO ), 2925 FLAG_DO = (1 << RES_DO ),
2928 FLAG_DONE = (1 << RES_DONE ), 2926 FLAG_DONE = (1 << RES_DONE ),
2929 FLAG_IN = (1 << RES_IN ), 2927 FLAG_IN = (1 << RES_IN ),
2930#endif 2928#endif
2931#if ENABLE_HUSH_CASE 2929#if ENABLE_HUSH_CASE
2932 FLAG_MATCH = (1 << RES_MATCH), 2930 FLAG_MATCH = (1 << RES_MATCH),
2933 FLAG_ESAC = (1 << RES_ESAC ), 2931 FLAG_ESAC = (1 << RES_ESAC ),
2934#endif 2932#endif
2935 FLAG_START = (1 << RES_XXXX ), 2933 FLAG_START = (1 << RES_XXXX ),
2936 }; 2934};
2935
2936static const struct reserved_combo* match_reserved_word(o_string *word)
2937{
2937 /* Mostly a list of accepted follow-up reserved words. 2938 /* Mostly a list of accepted follow-up reserved words.
2938 * FLAG_END means we are done with the sequence, and are ready 2939 * FLAG_END means we are done with the sequence, and are ready
2939 * to turn the compound list into a command. 2940 * to turn the compound list into a command.
@@ -2961,6 +2962,16 @@ static int reserved_word(o_string *word, struct parse_context *ctx)
2961 { "esac", RES_ESAC, NOT_ASSIGNMENT , FLAG_END }, 2962 { "esac", RES_ESAC, NOT_ASSIGNMENT , FLAG_END },
2962#endif 2963#endif
2963 }; 2964 };
2965 const struct reserved_combo *r;
2966
2967 for (r = reserved_list; r < reserved_list + ARRAY_SIZE(reserved_list); r++) {
2968 if (strcmp(word->data, r->literal) == 0)
2969 return r;
2970 }
2971 return NULL;
2972}
2973static int reserved_word(o_string *word, struct parse_context *ctx)
2974{
2964#if ENABLE_HUSH_CASE 2975#if ENABLE_HUSH_CASE
2965 static const struct reserved_combo reserved_match = { 2976 static const struct reserved_combo reserved_match = {
2966 "", RES_MATCH, NOT_ASSIGNMENT , FLAG_MATCH | FLAG_ESAC 2977 "", RES_MATCH, NOT_ASSIGNMENT , FLAG_MATCH | FLAG_ESAC
@@ -2968,52 +2979,51 @@ static int reserved_word(o_string *word, struct parse_context *ctx)
2968#endif 2979#endif
2969 const struct reserved_combo *r; 2980 const struct reserved_combo *r;
2970 2981
2971 for (r = reserved_list; r < reserved_list + ARRAY_SIZE(reserved_list); r++) { 2982 r = match_reserved_word(word);
2972 if (strcmp(word->data, r->literal) != 0) 2983 if (!r)
2973 continue; 2984 return 0;
2974 debug_printf("found reserved word %s, res %d\n", r->literal, r->res); 2985
2986 debug_printf("found reserved word %s, res %d\n", r->literal, r->res);
2975#if ENABLE_HUSH_CASE 2987#if ENABLE_HUSH_CASE
2976 if (r->res == RES_IN && ctx->ctx_res_w == RES_CASE) 2988 if (r->res == RES_IN && ctx->ctx_res_w == RES_CASE)
2977 /* "case word IN ..." - IN part starts first match part */ 2989 /* "case word IN ..." - IN part starts first match part */
2978 r = &reserved_match; 2990 r = &reserved_match;
2979 else 2991 else
2980#endif 2992#endif
2981 if (r->flag == 0) { /* '!' */ 2993 if (r->flag == 0) { /* '!' */
2982 if (ctx->ctx_inverted) { /* bash doesn't accept '! ! true' */ 2994 if (ctx->ctx_inverted) { /* bash doesn't accept '! ! true' */
2983 syntax(NULL);
2984 IF_HAS_KEYWORDS(ctx->ctx_res_w = RES_SNTX;)
2985 }
2986 ctx->ctx_inverted = 1;
2987 return 1;
2988 }
2989 if (r->flag & FLAG_START) {
2990 struct parse_context *new;
2991 debug_printf("push stack\n");
2992 new = xmalloc(sizeof(*new));
2993 *new = *ctx; /* physical copy */
2994 initialize_context(ctx);
2995 ctx->stack = new;
2996 } else if (/*ctx->ctx_res_w == RES_NONE ||*/ !(ctx->old_flag & (1 << r->res))) {
2997 syntax(NULL); 2995 syntax(NULL);
2998 ctx->ctx_res_w = RES_SNTX; 2996 IF_HAS_KEYWORDS(ctx->ctx_res_w = RES_SNTX;)
2999 return 1;
3000 }
3001 ctx->ctx_res_w = r->res;
3002 ctx->old_flag = r->flag;
3003 if (ctx->old_flag & FLAG_END) {
3004 struct parse_context *old;
3005 debug_printf("pop stack\n");
3006 done_pipe(ctx, PIPE_SEQ);
3007 old = ctx->stack;
3008 old->command->group = ctx->list_head;
3009 old->command->subshell = 0;
3010 *ctx = *old; /* physical copy */
3011 free(old);
3012 } 2997 }
3013 word->o_assignment = r->assignment_flag; 2998 ctx->ctx_inverted = 1;
3014 return 1; 2999 return 1;
3015 } 3000 }
3016 return 0; 3001 if (r->flag & FLAG_START) {
3002 struct parse_context *new;
3003 debug_printf("push stack\n");
3004 new = xmalloc(sizeof(*new));
3005 *new = *ctx; /* physical copy */
3006 initialize_context(ctx);
3007 ctx->stack = new;
3008 } else if (/*ctx->ctx_res_w == RES_NONE ||*/ !(ctx->old_flag & (1 << r->res))) {
3009 syntax(NULL);
3010 ctx->ctx_res_w = RES_SNTX;
3011 return 1;
3012 }
3013 ctx->ctx_res_w = r->res;
3014 ctx->old_flag = r->flag;
3015 if (ctx->old_flag & FLAG_END) {
3016 struct parse_context *old;
3017 debug_printf("pop stack\n");
3018 done_pipe(ctx, PIPE_SEQ);
3019 old = ctx->stack;
3020 old->command->group = ctx->list_head;
3021 old->command->subshell = 0;
3022 *ctx = *old; /* physical copy */
3023 free(old);
3024 }
3025 word->o_assignment = r->assignment_flag;
3026 return 1;
3017} 3027}
3018#endif 3028#endif
3019 3029
@@ -3893,6 +3903,17 @@ static int parse_stream(o_string *dest, struct parse_context *ctx,
3893 continue; 3903 continue;
3894 } 3904 }
3895#endif 3905#endif
3906#if 0 /* TODO: implement functions */
3907 if (dest->length != 0 /* not just () but word() */
3908 && dest->nonnull == 0 /* not a"b"c() */
3909 && ctx->command->argv == NULL /* it's the first word */
3910 && i_peek(input) == ')'
3911 ) {
3912 bb_error_msg("seems like a function definition");
3913 if (match_reserved_word(dest))
3914 bb_error_msg("but '%s' is a reserved word!", dest->data);
3915 }
3916#endif
3896 case '{': 3917 case '{':
3897 if (parse_group(dest, ctx, input, ch) != 0) { 3918 if (parse_group(dest, ctx, input, ch) != 0) {
3898 debug_printf_parse("parse_stream return 1: parse_group returned non-0\n"); 3919 debug_printf_parse("parse_stream return 1: parse_group returned non-0\n");
@@ -3905,7 +3926,9 @@ static int parse_stream(o_string *dest, struct parse_context *ctx,
3905 goto case_semi; 3926 goto case_semi;
3906#endif 3927#endif
3907 case '}': 3928 case '}':
3908 /* proper use of this character is caught by end_trigger */ 3929 /* proper use of this character is caught by end_trigger:
3930 * if we see {, we call parse_group(..., end_trigger='}')
3931 * and it will match } earlier (not here). */
3909 syntax("unexpected } or )"); 3932 syntax("unexpected } or )");
3910 debug_printf_parse("parse_stream return 1: unexpected '}'\n"); 3933 debug_printf_parse("parse_stream return 1: unexpected '}'\n");
3911 return 1; 3934 return 1;