aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-10-14 12:43:13 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-10-14 12:43:13 +0000
commit371de4acf7eb345bf8c92f257f9a14342603e59a (patch)
treed6286600ded22783a7b08801f52b024178c39f61
parentded6ad34edaa03dcd4b899787c2bbdc2ee3e7988 (diff)
downloadbusybox-w32-371de4acf7eb345bf8c92f257f9a14342603e59a.tar.gz
busybox-w32-371de4acf7eb345bf8c92f257f9a14342603e59a.tar.bz2
busybox-w32-371de4acf7eb345bf8c92f257f9a14342603e59a.zip
hush: next small step towards functions
-rw-r--r--shell/hush.c72
1 files changed, 53 insertions, 19 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 377f13aa4..6efc3073b 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -96,6 +96,12 @@
96#endif 96#endif
97 97
98 98
99/* Keep unconditionally on for now */
100#define HUSH_DEBUG 1
101/* In progress... */
102#define ENABLE_HUSH_FUNCTIONS 0
103
104
99/* If you comment out one of these below, it will be #defined later 105/* If you comment out one of these below, it will be #defined later
100 * to perform debug printfs to stderr: */ 106 * to perform debug printfs to stderr: */
101#define debug_printf(...) do {} while (0) 107#define debug_printf(...) do {} while (0)
@@ -218,8 +224,6 @@ void xxfree(void *ptr)
218#endif 224#endif
219 225
220 226
221/* Keep unconditionally on for now */
222#define HUSH_DEBUG 1
223/* Do we support ANY keywords? */ 227/* Do we support ANY keywords? */
224#if ENABLE_HUSH_IF || ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE 228#if ENABLE_HUSH_IF || ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE
225#define HAS_KEYWORDS 1 229#define HAS_KEYWORDS 1
@@ -307,7 +311,7 @@ struct command {
307 pid_t pid; /* 0 if exited */ 311 pid_t pid; /* 0 if exited */
308 int assignment_cnt; /* how many argv[i] are assignments? */ 312 int assignment_cnt; /* how many argv[i] are assignments? */
309 smallint is_stopped; /* is the command currently running? */ 313 smallint is_stopped; /* is the command currently running? */
310 smallint subshell; /* flag, non-zero if group must be forked */ 314 smallint grp_type;
311 struct pipe *group; /* if non-NULL, this "prog" is {} group, 315 struct pipe *group; /* if non-NULL, this "prog" is {} group,
312 * subshell, or a compound statement */ 316 * subshell, or a compound statement */
313 char **argv; /* command name and arguments */ 317 char **argv; /* command name and arguments */
@@ -319,6 +323,11 @@ struct command {
319 * Example: argv[0]=='.^C*^C.' here: echo .$*. 323 * Example: argv[0]=='.^C*^C.' here: echo .$*.
320 * References of the form ^C`cmd arg^C are `cmd arg` substitutions. 324 * References of the form ^C`cmd arg^C are `cmd arg` substitutions.
321 */ 325 */
326#define GRP_NORMAL 0
327#define GRP_SUBSHELL 1
328#if ENABLE_HUSH_FUNCTIONS
329#define GRP_FUNCTION 2
330#endif
322 331
323struct pipe { 332struct pipe {
324 struct pipe *next; 333 struct pipe *next;
@@ -1016,12 +1025,14 @@ static void o_addstr_duplicate_backslash(o_string *o, const char *str, int len)
1016static void o_addqchr(o_string *o, int ch) 1025static void o_addqchr(o_string *o, int ch)
1017{ 1026{
1018 int sz = 1; 1027 int sz = 1;
1019 if (strchr("*?[\\", ch)) { 1028 char *found = strchr("*?[\\", ch);
1029 if (found)
1020 sz++; 1030 sz++;
1031 o_grow_by(o, sz);
1032 if (found) {
1021 o->data[o->length] = '\\'; 1033 o->data[o->length] = '\\';
1022 o->length++; 1034 o->length++;
1023 } 1035 }
1024 o_grow_by(o, sz);
1025 o->data[o->length] = ch; 1036 o->data[o->length] = ch;
1026 o->length++; 1037 o->length++;
1027 o->data[o->length] = '\0'; 1038 o->data[o->length] = '\0';
@@ -1834,7 +1845,15 @@ static int run_pipe(struct pipe *pi)
1834 */ 1845 */
1835 command = &(pi->cmds[0]); 1846 command = &(pi->cmds[0]);
1836 1847
1837 if (single_and_fg && command->group && command->subshell == 0) { 1848#if ENABLE_HUSH_FUNCTIONS
1849 if (single_and_fg && command->group && command->grp_type == GRP_FUNCTION) {
1850 /* We "execute" function definition */
1851 bb_error_msg("here we ought to remember function definition, and go on");
1852 return EXIT_SUCCESS;
1853 }
1854#endif
1855
1856 if (single_and_fg && command->group && command->grp_type == GRP_NORMAL) {
1838 debug_printf("non-subshell grouping\n"); 1857 debug_printf("non-subshell grouping\n");
1839 setup_redirects(command, squirrel); 1858 setup_redirects(command, squirrel);
1840 debug_printf_exec(": run_list\n"); 1859 debug_printf_exec(": run_list\n");
@@ -2023,7 +2042,7 @@ static int run_pipe(struct pipe *pi)
2023#ifndef debug_print_tree 2042#ifndef debug_print_tree
2024static void debug_print_tree(struct pipe *pi, int lvl) 2043static void debug_print_tree(struct pipe *pi, int lvl)
2025{ 2044{
2026 static const char *PIPE[] = { 2045 static const char *const PIPE[] = {
2027 [PIPE_SEQ] = "SEQ", 2046 [PIPE_SEQ] = "SEQ",
2028 [PIPE_AND] = "AND", 2047 [PIPE_AND] = "AND",
2029 [PIPE_OR ] = "OR" , 2048 [PIPE_OR ] = "OR" ,
@@ -2057,6 +2076,13 @@ static void debug_print_tree(struct pipe *pi, int lvl)
2057 [RES_XXXX ] = "XXXX" , 2076 [RES_XXXX ] = "XXXX" ,
2058 [RES_SNTX ] = "SNTX" , 2077 [RES_SNTX ] = "SNTX" ,
2059 }; 2078 };
2079 static const char *const GRPTYPE[] = {
2080 "()",
2081 "{}",
2082#if ENABLE_HUSH_FUNCTIONS
2083 "func()",
2084#endif
2085 };
2060 2086
2061 int pin, prn; 2087 int pin, prn;
2062 2088
@@ -2072,7 +2098,7 @@ static void debug_print_tree(struct pipe *pi, int lvl)
2072 fprintf(stderr, "%*s prog %d assignment_cnt:%d", lvl*2, "", prn, command->assignment_cnt); 2098 fprintf(stderr, "%*s prog %d assignment_cnt:%d", lvl*2, "", prn, command->assignment_cnt);
2073 if (command->group) { 2099 if (command->group) {
2074 fprintf(stderr, " group %s: (argv=%p)\n", 2100 fprintf(stderr, " group %s: (argv=%p)\n",
2075 (command->subshell ? "()" : "{}"), 2101 GRPTYPE[command->grp_type],
2076 argv); 2102 argv);
2077 debug_print_tree(command->group, lvl+1); 2103 debug_print_tree(command->group, lvl+1);
2078 prn++; 2104 prn++;
@@ -2443,7 +2469,7 @@ static int free_pipe(struct pipe *pi, int indent)
2443 free_strings(command->argv); 2469 free_strings(command->argv);
2444 command->argv = NULL; 2470 command->argv = NULL;
2445 } else if (command->group) { 2471 } else if (command->group) {
2446 debug_printf_clean("%s begin group (subshell:%d)\n", indenter(indent), command->subshell); 2472 debug_printf_clean("%s begin group (grp_type:%d)\n", indenter(indent), command->grp_type);
2447 ret_code = free_pipe_list(command->group, indent+3); 2473 ret_code = free_pipe_list(command->group, indent+3);
2448 debug_printf_clean("%s end group\n", indenter(indent)); 2474 debug_printf_clean("%s end group\n", indenter(indent));
2449 } else { 2475 } else {
@@ -2572,7 +2598,6 @@ static int expand_vars_to_list(o_string *output, int n, char *arg, char or_mask)
2572#if ENABLE_HUSH_TICK 2598#if ENABLE_HUSH_TICK
2573 o_string subst_result = NULL_O_STRING; 2599 o_string subst_result = NULL_O_STRING;
2574#endif 2600#endif
2575
2576 o_addstr(output, arg, p - arg); 2601 o_addstr(output, arg, p - arg);
2577 debug_print_list("expand_vars_to_list[1]", output, n); 2602 debug_print_list("expand_vars_to_list[1]", output, n);
2578 arg = ++p; 2603 arg = ++p;
@@ -3100,7 +3125,7 @@ static int reserved_word(o_string *word, struct parse_context *ctx)
3100 done_pipe(ctx, PIPE_SEQ); 3125 done_pipe(ctx, PIPE_SEQ);
3101 old = ctx->stack; 3126 old = ctx->stack;
3102 old->command->group = ctx->list_head; 3127 old->command->group = ctx->list_head;
3103 old->command->subshell = 0; 3128 old->command->grp_type = GRP_NORMAL;
3104 *ctx = *old; /* physical copy */ 3129 *ctx = *old; /* physical copy */
3105 free(old); 3130 free(old);
3106 } 3131 }
@@ -3461,15 +3486,24 @@ static int process_command_subs(o_string *dest,
3461static int parse_group(o_string *dest, struct parse_context *ctx, 3486static int parse_group(o_string *dest, struct parse_context *ctx,
3462 struct in_str *input, int ch) 3487 struct in_str *input, int ch)
3463{ 3488{
3464 /* NB: parse_group may create and use its own o_string, 3489 /* dest contains characters seen prior to ( or {.
3465 * without any code changes. It just so happens that code is smaller 3490 * Typically it's empty, but for functions defs,
3466 * if we (ab)use caller's one. */ 3491 * it contains function name (without '()'). */
3467 int rcode; 3492 int rcode;
3468 const char *endch = NULL; 3493 const char *endch = NULL;
3469 struct parse_context sub; 3494 struct parse_context sub;
3470 struct command *command = ctx->command; 3495 struct command *command = ctx->command;
3471 3496
3472 debug_printf_parse("parse_group entered\n"); 3497 debug_printf_parse("parse_group entered\n");
3498#if ENABLE_HUSH_FUNCTIONS
3499 if (ch == 'F') { /* function definition? */
3500 bb_error_msg("aha '%s' is a function, parsing it...", dest->data);
3501 //command->fname = dest->data;
3502 command->grp_type = GRP_FUNCTION;
3503//TODO: review every o_reset() location... do they handle all o_string fields correctly?
3504 memset(dest, 0, sizeof(*dest));
3505 }
3506#endif
3473 if (command->argv /* word [word](... */ 3507 if (command->argv /* word [word](... */
3474 || dest->length /* word(... */ 3508 || dest->length /* word(... */
3475 || dest->nonnull /* ""(... */ 3509 || dest->nonnull /* ""(... */
@@ -3482,11 +3516,8 @@ static int parse_group(o_string *dest, struct parse_context *ctx,
3482 endch = "}"; 3516 endch = "}";
3483 if (ch == '(') { 3517 if (ch == '(') {
3484 endch = ")"; 3518 endch = ")";
3485 command->subshell = 1; 3519 command->grp_type = GRP_SUBSHELL;
3486 } 3520 }
3487//TODO if (ch == 'F') { /* function definition */
3488// command->subshell = 2;
3489// }
3490 rcode = parse_stream(dest, &sub, input, endch); 3521 rcode = parse_stream(dest, &sub, input, endch);
3491 if (rcode == 0) { 3522 if (rcode == 0) {
3492 done_word(dest, &sub); /* finish off the final word in the subcontext */ 3523 done_word(dest, &sub); /* finish off the final word in the subcontext */
@@ -3988,16 +4019,18 @@ static int parse_stream(o_string *dest, struct parse_context *ctx,
3988 continue; 4019 continue;
3989 } 4020 }
3990#endif 4021#endif
3991#if 0 /* TODO: implement functions */ 4022#if ENABLE_HUSH_FUNCTIONS
3992 if (dest->length != 0 /* not just () but word() */ 4023 if (dest->length != 0 /* not just () but word() */
3993 && dest->nonnull == 0 /* not a"b"c() */ 4024 && dest->nonnull == 0 /* not a"b"c() */
3994 && ctx->command->argv == NULL /* it's the first word */ 4025 && ctx->command->argv == NULL /* it's the first word */
4026//TODO: "func ( ) {...}" - note spaces - is valid format too in bash
3995 && i_peek(input) == ')' 4027 && i_peek(input) == ')'
3996 && !match_reserved_word(dest) 4028 && !match_reserved_word(dest)
3997 ) { 4029 ) {
3998 bb_error_msg("seems like a function definition"); 4030 bb_error_msg("seems like a function definition");
3999 i_getch(input); 4031 i_getch(input);
4000 do { 4032 do {
4033//TODO: do it properly.
4001 ch = i_getch(input); 4034 ch = i_getch(input);
4002 } while (ch == ' ' || ch == '\n'); 4035 } while (ch == ' ' || ch == '\n');
4003 if (ch != '{') { 4036 if (ch != '{') {
@@ -4005,6 +4038,7 @@ static int parse_stream(o_string *dest, struct parse_context *ctx,
4005 debug_printf_parse("parse_stream return 1\n"); 4038 debug_printf_parse("parse_stream return 1\n");
4006 return 1; 4039 return 1;
4007 } 4040 }
4041 ch = 'F'; /* magic value */
4008 } 4042 }
4009#endif 4043#endif
4010 case '{': 4044 case '{':