diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-10-09 12:58:26 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-10-09 12:58:26 +0000 |
commit | c373527e4fe7d2d46ce25165687463da00ba986c (patch) | |
tree | 3b982f0ca0cb00abeff4af0415f10713d19f2cfe | |
parent | 9af22c762652ff92f3f207a754f71f3c4bf2c078 (diff) | |
download | busybox-w32-c373527e4fe7d2d46ce25165687463da00ba986c.tar.gz busybox-w32-c373527e4fe7d2d46ce25165687463da00ba986c.tar.bz2 busybox-w32-c373527e4fe7d2d46ce25165687463da00ba986c.zip |
hush: preparatory work for implementing functions
-rw-r--r-- | shell/hush.c | 155 |
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 |
2906 | static int reserved_word(o_string *word, struct parse_context *ctx) | 2906 | struct 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; | 2912 | enum { |
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 | |||
2936 | static 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 | } | ||
2973 | static 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; |