diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-05-21 23:30:54 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-05-21 23:30:54 +0000 |
commit | 06810339189c1372d3defb8e3dcdb58a07ade7a7 (patch) | |
tree | 7d8ab749ab33dfbdcd8115013b75e0852e926293 /shell/hush.c | |
parent | 8805eeb44a291b830e9eb1a430d112913ffa9a24 (diff) | |
download | busybox-w32-06810339189c1372d3defb8e3dcdb58a07ade7a7.tar.gz busybox-w32-06810339189c1372d3defb8e3dcdb58a07ade7a7.tar.bz2 busybox-w32-06810339189c1372d3defb8e3dcdb58a07ade7a7.zip |
hush: add 3 CONFIG_xxx, allowing for smaller and less capable hush.
Minimal hush is ~9k now (lash is ~7k).
Diffstat (limited to 'shell/hush.c')
-rw-r--r-- | shell/hush.c | 129 |
1 files changed, 91 insertions, 38 deletions
diff --git a/shell/hush.c b/shell/hush.c index 90c89fba2..61c03f703 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -175,33 +175,41 @@ typedef enum { | |||
175 | /* might eventually control execution */ | 175 | /* might eventually control execution */ |
176 | typedef enum { | 176 | typedef enum { |
177 | RES_NONE = 0, | 177 | RES_NONE = 0, |
178 | #if ENABLE_HUSH_IF | ||
178 | RES_IF = 1, | 179 | RES_IF = 1, |
179 | RES_THEN = 2, | 180 | RES_THEN = 2, |
180 | RES_ELIF = 3, | 181 | RES_ELIF = 3, |
181 | RES_ELSE = 4, | 182 | RES_ELSE = 4, |
182 | RES_FI = 5, | 183 | RES_FI = 5, |
184 | #endif | ||
185 | #if ENABLE_HUSH_LOOPS | ||
183 | RES_FOR = 6, | 186 | RES_FOR = 6, |
184 | RES_WHILE = 7, | 187 | RES_WHILE = 7, |
185 | RES_UNTIL = 8, | 188 | RES_UNTIL = 8, |
186 | RES_DO = 9, | 189 | RES_DO = 9, |
187 | RES_DONE = 10, | 190 | RES_DONE = 10, |
188 | RES_XXXX = 11, | 191 | RES_IN = 11, |
189 | RES_IN = 12, | 192 | #endif |
193 | RES_XXXX = 12, | ||
190 | RES_SNTX = 13 | 194 | RES_SNTX = 13 |
191 | } reserved_style; | 195 | } reserved_style; |
192 | enum { | 196 | enum { |
193 | FLAG_END = (1 << RES_NONE ), | 197 | FLAG_END = (1 << RES_NONE ), |
198 | #if ENABLE_HUSH_IF | ||
194 | FLAG_IF = (1 << RES_IF ), | 199 | FLAG_IF = (1 << RES_IF ), |
195 | FLAG_THEN = (1 << RES_THEN ), | 200 | FLAG_THEN = (1 << RES_THEN ), |
196 | FLAG_ELIF = (1 << RES_ELIF ), | 201 | FLAG_ELIF = (1 << RES_ELIF ), |
197 | FLAG_ELSE = (1 << RES_ELSE ), | 202 | FLAG_ELSE = (1 << RES_ELSE ), |
198 | FLAG_FI = (1 << RES_FI ), | 203 | FLAG_FI = (1 << RES_FI ), |
204 | #endif | ||
205 | #if ENABLE_HUSH_LOOPS | ||
199 | FLAG_FOR = (1 << RES_FOR ), | 206 | FLAG_FOR = (1 << RES_FOR ), |
200 | FLAG_WHILE = (1 << RES_WHILE), | 207 | FLAG_WHILE = (1 << RES_WHILE), |
201 | FLAG_UNTIL = (1 << RES_UNTIL), | 208 | FLAG_UNTIL = (1 << RES_UNTIL), |
202 | FLAG_DO = (1 << RES_DO ), | 209 | FLAG_DO = (1 << RES_DO ), |
203 | FLAG_DONE = (1 << RES_DONE ), | 210 | FLAG_DONE = (1 << RES_DONE ), |
204 | FLAG_IN = (1 << RES_IN ), | 211 | FLAG_IN = (1 << RES_IN ), |
212 | #endif | ||
205 | FLAG_START = (1 << RES_XXXX ), | 213 | FLAG_START = (1 << RES_XXXX ), |
206 | }; | 214 | }; |
207 | 215 | ||
@@ -429,7 +437,9 @@ static int builtin_export(char **argv); | |||
429 | static int builtin_fg_bg(char **argv); | 437 | static int builtin_fg_bg(char **argv); |
430 | static int builtin_jobs(char **argv); | 438 | static int builtin_jobs(char **argv); |
431 | #endif | 439 | #endif |
440 | #if ENABLE_HUSH_HELP | ||
432 | static int builtin_help(char **argv); | 441 | static int builtin_help(char **argv); |
442 | #endif | ||
433 | static int builtin_pwd(char **argv); | 443 | static int builtin_pwd(char **argv); |
434 | static int builtin_read(char **argv); | 444 | static int builtin_read(char **argv); |
435 | static int builtin_set(char **argv); | 445 | static int builtin_set(char **argv); |
@@ -437,7 +447,7 @@ static int builtin_shift(char **argv); | |||
437 | static int builtin_source(char **argv); | 447 | static int builtin_source(char **argv); |
438 | static int builtin_umask(char **argv); | 448 | static int builtin_umask(char **argv); |
439 | static int builtin_unset(char **argv); | 449 | static int builtin_unset(char **argv); |
440 | static int builtin_not_written(char **argv); | 450 | //static int builtin_not_written(char **argv); |
441 | /* o_string manipulation: */ | 451 | /* o_string manipulation: */ |
442 | static int b_check_space(o_string *o, int len); | 452 | static int b_check_space(o_string *o, int len); |
443 | static int b_addchr(o_string *o, int ch); | 453 | static int b_addchr(o_string *o, int ch); |
@@ -520,38 +530,45 @@ static void unset_local_var(const char *name); | |||
520 | * still be set at the end. */ | 530 | * still be set at the end. */ |
521 | struct built_in_command { | 531 | struct built_in_command { |
522 | const char *cmd; /* name */ | 532 | const char *cmd; /* name */ |
523 | const char *descr; /* description */ | ||
524 | int (*function) (char **argv); /* function ptr */ | 533 | int (*function) (char **argv); /* function ptr */ |
534 | #if ENABLE_HUSH_HELP | ||
535 | const char *descr; /* description */ | ||
536 | #define BLTIN(cmd, func, help) { cmd, func, help } | ||
537 | #else | ||
538 | #define BLTIN(cmd, func, help) { cmd, func } | ||
539 | #endif | ||
525 | }; | 540 | }; |
526 | 541 | ||
527 | static const struct built_in_command bltins[] = { | 542 | static const struct built_in_command bltins[] = { |
528 | #if ENABLE_HUSH_JOB | 543 | #if ENABLE_HUSH_JOB |
529 | { "bg", "Resume a job in the background", builtin_fg_bg }, | 544 | BLTIN("bg" , builtin_fg_bg, "Resume a job in the background"), |
530 | #endif | 545 | #endif |
531 | { "break", "Exit for, while or until loop", builtin_not_written }, | 546 | // BLTIN("break" , builtin_not_written, "Exit for, while or until loop"), |
532 | { "cd", "Change working directory", builtin_cd }, | 547 | BLTIN("cd" , builtin_cd, "Change working directory"), |
533 | { "continue", "Continue for, while or until loop", builtin_not_written }, | 548 | // BLTIN("continue", builtin_not_written, "Continue for, while or until loop"), |
534 | { "eval", "Construct and run shell command", builtin_eval }, | 549 | BLTIN("eval" , builtin_eval, "Construct and run shell command"), |
535 | { "exec", "Exec command, replacing this shell with the exec'd process", | 550 | BLTIN("exec" , builtin_exec, "Exec command, replacing this shell with the exec'd process"), |
536 | builtin_exec }, | 551 | BLTIN("exit" , builtin_exit, "Exit from shell"), |
537 | { "exit", "Exit from shell()", builtin_exit }, | 552 | BLTIN("export", builtin_export, "Set environment variable"), |
538 | { "export", "Set environment variable", builtin_export }, | ||
539 | #if ENABLE_HUSH_JOB | 553 | #if ENABLE_HUSH_JOB |
540 | { "fg", "Bring job into the foreground", builtin_fg_bg }, | 554 | BLTIN("fg" , builtin_fg_bg, "Bring job into the foreground"), |
541 | { "jobs", "Lists the active jobs", builtin_jobs }, | 555 | BLTIN("jobs" , builtin_jobs, "Lists the active jobs"), |
542 | #endif | 556 | #endif |
543 | { "pwd", "Print current directory", builtin_pwd }, | 557 | // TODO: remove pwd? we have it as an applet... |
544 | { "read", "Input environment variable", builtin_read }, | 558 | BLTIN("pwd" , builtin_pwd, "Print current directory"), |
545 | { "return", "Return from a function", builtin_not_written }, | 559 | BLTIN("read" , builtin_read, "Input environment variable"), |
546 | { "set", "Set/unset shell local variables", builtin_set }, | 560 | // BLTIN("return", builtin_not_written, "Return from a function"), |
547 | { "shift", "Shift positional parameters", builtin_shift }, | 561 | BLTIN("set" , builtin_set, "Set/unset shell local variables"), |
548 | { "trap", "Trap signals", builtin_not_written }, | 562 | BLTIN("shift" , builtin_shift, "Shift positional parameters"), |
549 | { "ulimit","Controls resource limits", builtin_not_written }, | 563 | // BLTIN("trap" , builtin_not_written, "Trap signals"), |
550 | { "umask","Sets file creation mask", builtin_umask }, | 564 | // BLTIN("ulimit", builtin_not_written, "Controls resource limits"), |
551 | { "unset", "Unset environment variable", builtin_unset }, | 565 | BLTIN("umask" , builtin_umask, "Sets file creation mask"), |
552 | { ".", "Source-in and run commands in a file", builtin_source }, | 566 | BLTIN("unset" , builtin_unset, "Unset environment variable"), |
553 | { "help", "List shell built-in commands", builtin_help }, | 567 | BLTIN("." , builtin_source, "Source-in and run commands in a file"), |
554 | { NULL, NULL, NULL } | 568 | #if ENABLE_HUSH_HELP |
569 | BLTIN("help" , builtin_help, "List shell built-in commands"), | ||
570 | #endif | ||
571 | BLTIN(NULL, NULL, NULL) | ||
555 | }; | 572 | }; |
556 | 573 | ||
557 | #if ENABLE_HUSH_JOB | 574 | #if ENABLE_HUSH_JOB |
@@ -868,6 +885,7 @@ static int builtin_fg_bg(char **argv) | |||
868 | #endif | 885 | #endif |
869 | 886 | ||
870 | /* built-in 'help' handler */ | 887 | /* built-in 'help' handler */ |
888 | #if ENABLE_HUSH_HELP | ||
871 | static int builtin_help(char **argv ATTRIBUTE_UNUSED) | 889 | static int builtin_help(char **argv ATTRIBUTE_UNUSED) |
872 | { | 890 | { |
873 | const struct built_in_command *x; | 891 | const struct built_in_command *x; |
@@ -875,13 +893,12 @@ static int builtin_help(char **argv ATTRIBUTE_UNUSED) | |||
875 | printf("\nBuilt-in commands:\n"); | 893 | printf("\nBuilt-in commands:\n"); |
876 | printf("-------------------\n"); | 894 | printf("-------------------\n"); |
877 | for (x = bltins; x->cmd; x++) { | 895 | for (x = bltins; x->cmd; x++) { |
878 | if (x->descr == NULL) | ||
879 | continue; | ||
880 | printf("%s\t%s\n", x->cmd, x->descr); | 896 | printf("%s\t%s\n", x->cmd, x->descr); |
881 | } | 897 | } |
882 | printf("\n\n"); | 898 | printf("\n\n"); |
883 | return EXIT_SUCCESS; | 899 | return EXIT_SUCCESS; |
884 | } | 900 | } |
901 | #endif | ||
885 | 902 | ||
886 | #if ENABLE_HUSH_JOB | 903 | #if ENABLE_HUSH_JOB |
887 | /* built-in 'jobs' handler */ | 904 | /* built-in 'jobs' handler */ |
@@ -1014,11 +1031,11 @@ static int builtin_unset(char **argv) | |||
1014 | return EXIT_SUCCESS; | 1031 | return EXIT_SUCCESS; |
1015 | } | 1032 | } |
1016 | 1033 | ||
1017 | static int builtin_not_written(char **argv) | 1034 | //static int builtin_not_written(char **argv) |
1018 | { | 1035 | //{ |
1019 | printf("builtin_%s not written\n", argv[0]); | 1036 | // printf("builtin_%s not written\n", argv[0]); |
1020 | return EXIT_FAILURE; | 1037 | // return EXIT_FAILURE; |
1021 | } | 1038 | //} |
1022 | 1039 | ||
1023 | static int b_check_space(o_string *o, int len) | 1040 | static int b_check_space(o_string *o, int len) |
1024 | { | 1041 | { |
@@ -1882,18 +1899,22 @@ static void debug_print_tree(struct pipe *pi, int lvl) | |||
1882 | }; | 1899 | }; |
1883 | static const char *RES[] = { | 1900 | static const char *RES[] = { |
1884 | [RES_NONE ] = "NONE" , | 1901 | [RES_NONE ] = "NONE" , |
1902 | #if ENABLE_HUSH_IF | ||
1885 | [RES_IF ] = "IF" , | 1903 | [RES_IF ] = "IF" , |
1886 | [RES_THEN ] = "THEN" , | 1904 | [RES_THEN ] = "THEN" , |
1887 | [RES_ELIF ] = "ELIF" , | 1905 | [RES_ELIF ] = "ELIF" , |
1888 | [RES_ELSE ] = "ELSE" , | 1906 | [RES_ELSE ] = "ELSE" , |
1889 | [RES_FI ] = "FI" , | 1907 | [RES_FI ] = "FI" , |
1908 | #endif | ||
1909 | #if ENABLE_HUSH_LOOPS | ||
1890 | [RES_FOR ] = "FOR" , | 1910 | [RES_FOR ] = "FOR" , |
1891 | [RES_WHILE] = "WHILE", | 1911 | [RES_WHILE] = "WHILE", |
1892 | [RES_UNTIL] = "UNTIL", | 1912 | [RES_UNTIL] = "UNTIL", |
1893 | [RES_DO ] = "DO" , | 1913 | [RES_DO ] = "DO" , |
1894 | [RES_DONE ] = "DONE" , | 1914 | [RES_DONE ] = "DONE" , |
1895 | [RES_XXXX ] = "XXXX" , | ||
1896 | [RES_IN ] = "IN" , | 1915 | [RES_IN ] = "IN" , |
1916 | #endif | ||
1917 | [RES_XXXX ] = "XXXX" , | ||
1897 | [RES_SNTX ] = "SNTX" , | 1918 | [RES_SNTX ] = "SNTX" , |
1898 | }; | 1919 | }; |
1899 | 1920 | ||
@@ -1934,21 +1955,28 @@ static void debug_print_tree(struct pipe *pi, int lvl) | |||
1934 | * global data until exec/_exit (we can be a child after vfork!) */ | 1955 | * global data until exec/_exit (we can be a child after vfork!) */ |
1935 | static int run_list_real(struct pipe *pi) | 1956 | static int run_list_real(struct pipe *pi) |
1936 | { | 1957 | { |
1958 | struct pipe *rpipe; | ||
1959 | #if ENABLE_HUSH_LOOPS | ||
1937 | char *for_varname = NULL; | 1960 | char *for_varname = NULL; |
1938 | char **for_lcur = NULL; | 1961 | char **for_lcur = NULL; |
1939 | char **for_list = NULL; | 1962 | char **for_list = NULL; |
1940 | struct pipe *rpipe; | ||
1941 | int flag_rep = 0; | 1963 | int flag_rep = 0; |
1964 | #endif | ||
1942 | int save_num_progs; | 1965 | int save_num_progs; |
1943 | int flag_skip = 1; | 1966 | int flag_skip = 1; |
1944 | int rcode = 0; /* probably for gcc only */ | 1967 | int rcode = 0; /* probably for gcc only */ |
1945 | int flag_restore = 0; | 1968 | int flag_restore = 0; |
1969 | #if ENABLE_HUSH_IF | ||
1946 | int if_code = 0, next_if_code = 0; /* need double-buffer to handle elif */ | 1970 | int if_code = 0, next_if_code = 0; /* need double-buffer to handle elif */ |
1971 | #else | ||
1972 | enum { if_code = 0, next_if_code = 0 }; | ||
1973 | #endif | ||
1947 | reserved_style rword; | 1974 | reserved_style rword; |
1948 | reserved_style skip_more_for_this_rword = RES_XXXX; | 1975 | reserved_style skip_more_for_this_rword = RES_XXXX; |
1949 | 1976 | ||
1950 | debug_printf_exec("run_list_real start lvl %d\n", run_list_level + 1); | 1977 | debug_printf_exec("run_list_real start lvl %d\n", run_list_level + 1); |
1951 | 1978 | ||
1979 | #if ENABLE_HUSH_LOOPS | ||
1952 | /* check syntax for "for" */ | 1980 | /* check syntax for "for" */ |
1953 | for (rpipe = pi; rpipe; rpipe = rpipe->next) { | 1981 | for (rpipe = pi; rpipe; rpipe = rpipe->next) { |
1954 | if ((rpipe->res_word == RES_IN || rpipe->res_word == RES_FOR) | 1982 | if ((rpipe->res_word == RES_IN || rpipe->res_word == RES_FOR) |
@@ -1967,6 +1995,9 @@ static int run_list_real(struct pipe *pi) | |||
1967 | return 1; | 1995 | return 1; |
1968 | } | 1996 | } |
1969 | } | 1997 | } |
1998 | #else | ||
1999 | rpipe = NULL; | ||
2000 | #endif | ||
1970 | 2001 | ||
1971 | #if ENABLE_HUSH_JOB | 2002 | #if ENABLE_HUSH_JOB |
1972 | /* Example of nested list: "while true; do { sleep 1 | exit 2; } done". | 2003 | /* Example of nested list: "while true; do { sleep 1 | exit 2; } done". |
@@ -2012,6 +2043,7 @@ static int run_list_real(struct pipe *pi) | |||
2012 | 2043 | ||
2013 | for (; pi; pi = flag_restore ? rpipe : pi->next) { | 2044 | for (; pi; pi = flag_restore ? rpipe : pi->next) { |
2014 | rword = pi->res_word; | 2045 | rword = pi->res_word; |
2046 | #if ENABLE_HUSH_LOOPS | ||
2015 | if (rword == RES_WHILE || rword == RES_UNTIL || rword == RES_FOR) { | 2047 | if (rword == RES_WHILE || rword == RES_UNTIL || rword == RES_FOR) { |
2016 | flag_restore = 0; | 2048 | flag_restore = 0; |
2017 | if (!rpipe) { | 2049 | if (!rpipe) { |
@@ -2019,6 +2051,7 @@ static int run_list_real(struct pipe *pi) | |||
2019 | rpipe = pi; | 2051 | rpipe = pi; |
2020 | } | 2052 | } |
2021 | } | 2053 | } |
2054 | #endif | ||
2022 | debug_printf_exec(": rword=%d if_code=%d next_if_code=%d skip_more=%d\n", | 2055 | debug_printf_exec(": rword=%d if_code=%d next_if_code=%d skip_more=%d\n", |
2023 | rword, if_code, next_if_code, skip_more_for_this_rword); | 2056 | rword, if_code, next_if_code, skip_more_for_this_rword); |
2024 | if (rword == skip_more_for_this_rword && flag_skip) { | 2057 | if (rword == skip_more_for_this_rword && flag_skip) { |
@@ -2028,6 +2061,7 @@ static int run_list_real(struct pipe *pi) | |||
2028 | } | 2061 | } |
2029 | flag_skip = 1; | 2062 | flag_skip = 1; |
2030 | skip_more_for_this_rword = RES_XXXX; | 2063 | skip_more_for_this_rword = RES_XXXX; |
2064 | #if ENABLE_HUSH_IF | ||
2031 | if (rword == RES_THEN || rword == RES_ELSE) | 2065 | if (rword == RES_THEN || rword == RES_ELSE) |
2032 | if_code = next_if_code; | 2066 | if_code = next_if_code; |
2033 | if (rword == RES_THEN && if_code) | 2067 | if (rword == RES_THEN && if_code) |
@@ -2036,6 +2070,8 @@ static int run_list_real(struct pipe *pi) | |||
2036 | continue; | 2070 | continue; |
2037 | if (rword == RES_ELIF && !if_code) | 2071 | if (rword == RES_ELIF && !if_code) |
2038 | break; | 2072 | break; |
2073 | #endif | ||
2074 | #if ENABLE_HUSH_LOOPS | ||
2039 | if (rword == RES_FOR && pi->num_progs) { | 2075 | if (rword == RES_FOR && pi->num_progs) { |
2040 | if (!for_lcur) { | 2076 | if (!for_lcur) { |
2041 | /* if no variable values after "in" we skip "for" */ | 2077 | /* if no variable values after "in" we skip "for" */ |
@@ -2075,6 +2111,7 @@ static int run_list_real(struct pipe *pi) | |||
2075 | rpipe = NULL; | 2111 | rpipe = NULL; |
2076 | } | 2112 | } |
2077 | } | 2113 | } |
2114 | #endif | ||
2078 | if (pi->num_progs == 0) | 2115 | if (pi->num_progs == 0) |
2079 | continue; | 2116 | continue; |
2080 | save_num_progs = pi->num_progs; /* save number of programs */ | 2117 | save_num_progs = pi->num_progs; /* save number of programs */ |
@@ -2110,12 +2147,16 @@ static int run_list_real(struct pipe *pi) | |||
2110 | debug_printf_exec(": setting last_return_code=%d\n", rcode); | 2147 | debug_printf_exec(": setting last_return_code=%d\n", rcode); |
2111 | last_return_code = rcode; | 2148 | last_return_code = rcode; |
2112 | pi->num_progs = save_num_progs; /* restore number of programs */ | 2149 | pi->num_progs = save_num_progs; /* restore number of programs */ |
2150 | #if ENABLE_HUSH_IF | ||
2113 | if (rword == RES_IF || rword == RES_ELIF) | 2151 | if (rword == RES_IF || rword == RES_ELIF) |
2114 | next_if_code = rcode; /* can be overwritten a number of times */ | 2152 | next_if_code = rcode; /* can be overwritten a number of times */ |
2153 | #endif | ||
2154 | #if ENABLE_HUSH_LOOPS | ||
2115 | if (rword == RES_WHILE) | 2155 | if (rword == RES_WHILE) |
2116 | flag_rep = !last_return_code; | 2156 | flag_rep = !last_return_code; |
2117 | if (rword == RES_UNTIL) | 2157 | if (rword == RES_UNTIL) |
2118 | flag_rep = last_return_code; | 2158 | flag_rep = last_return_code; |
2159 | #endif | ||
2119 | if ((rcode == EXIT_SUCCESS && pi->followup == PIPE_OR) | 2160 | if ((rcode == EXIT_SUCCESS && pi->followup == PIPE_OR) |
2120 | || (rcode != EXIT_SUCCESS && pi->followup == PIPE_AND) | 2161 | || (rcode != EXIT_SUCCESS && pi->followup == PIPE_AND) |
2121 | ) { | 2162 | ) { |
@@ -2811,6 +2852,7 @@ static void initialize_context(struct p_context *ctx) | |||
2811 | * should handle if, then, elif, else, fi, for, while, until, do, done. | 2852 | * should handle if, then, elif, else, fi, for, while, until, do, done. |
2812 | * case, function, and select are obnoxious, save those for later. | 2853 | * case, function, and select are obnoxious, save those for later. |
2813 | */ | 2854 | */ |
2855 | #if ENABLE_HUSH_IF || ENABLE_HUSH_LOOPS | ||
2814 | static int reserved_word(o_string *dest, struct p_context *ctx) | 2856 | static int reserved_word(o_string *dest, struct p_context *ctx) |
2815 | { | 2857 | { |
2816 | struct reserved_combo { | 2858 | struct reserved_combo { |
@@ -2824,17 +2866,21 @@ static int reserved_word(o_string *dest, struct p_context *ctx) | |||
2824 | * FLAG_START means the word must start a new compound list. | 2866 | * FLAG_START means the word must start a new compound list. |
2825 | */ | 2867 | */ |
2826 | static const struct reserved_combo reserved_list[] = { | 2868 | static const struct reserved_combo reserved_list[] = { |
2869 | #if ENABLE_HUSH_IF | ||
2827 | { "if", RES_IF, FLAG_THEN | FLAG_START }, | 2870 | { "if", RES_IF, FLAG_THEN | FLAG_START }, |
2828 | { "then", RES_THEN, FLAG_ELIF | FLAG_ELSE | FLAG_FI }, | 2871 | { "then", RES_THEN, FLAG_ELIF | FLAG_ELSE | FLAG_FI }, |
2829 | { "elif", RES_ELIF, FLAG_THEN }, | 2872 | { "elif", RES_ELIF, FLAG_THEN }, |
2830 | { "else", RES_ELSE, FLAG_FI }, | 2873 | { "else", RES_ELSE, FLAG_FI }, |
2831 | { "fi", RES_FI, FLAG_END }, | 2874 | { "fi", RES_FI, FLAG_END }, |
2875 | #endif | ||
2876 | #if ENABLE_HUSH_LOOPS | ||
2832 | { "for", RES_FOR, FLAG_IN | FLAG_START }, | 2877 | { "for", RES_FOR, FLAG_IN | FLAG_START }, |
2833 | { "while", RES_WHILE, FLAG_DO | FLAG_START }, | 2878 | { "while", RES_WHILE, FLAG_DO | FLAG_START }, |
2834 | { "until", RES_UNTIL, FLAG_DO | FLAG_START }, | 2879 | { "until", RES_UNTIL, FLAG_DO | FLAG_START }, |
2835 | { "in", RES_IN, FLAG_DO }, | 2880 | { "in", RES_IN, FLAG_DO }, |
2836 | { "do", RES_DO, FLAG_DONE }, | 2881 | { "do", RES_DO, FLAG_DONE }, |
2837 | { "done", RES_DONE, FLAG_END } | 2882 | { "done", RES_DONE, FLAG_END } |
2883 | #endif | ||
2838 | }; | 2884 | }; |
2839 | enum { NRES = sizeof(reserved_list)/sizeof(reserved_list[0]) }; | 2885 | enum { NRES = sizeof(reserved_list)/sizeof(reserved_list[0]) }; |
2840 | const struct reserved_combo *r; | 2886 | const struct reserved_combo *r; |
@@ -2845,6 +2891,7 @@ static int reserved_word(o_string *dest, struct p_context *ctx) | |||
2845 | if (r->flag & FLAG_START) { | 2891 | if (r->flag & FLAG_START) { |
2846 | struct p_context *new = xmalloc(sizeof(struct p_context)); | 2892 | struct p_context *new = xmalloc(sizeof(struct p_context)); |
2847 | debug_printf("push stack\n"); | 2893 | debug_printf("push stack\n"); |
2894 | #if ENABLE_HUSH_LOOPS | ||
2848 | if (ctx->res_w == RES_IN || ctx->res_w == RES_FOR) { | 2895 | if (ctx->res_w == RES_IN || ctx->res_w == RES_FOR) { |
2849 | syntax(); | 2896 | syntax(); |
2850 | free(new); | 2897 | free(new); |
@@ -2852,6 +2899,7 @@ static int reserved_word(o_string *dest, struct p_context *ctx) | |||
2852 | b_reset(dest); | 2899 | b_reset(dest); |
2853 | return 1; | 2900 | return 1; |
2854 | } | 2901 | } |
2902 | #endif | ||
2855 | *new = *ctx; /* physical copy */ | 2903 | *new = *ctx; /* physical copy */ |
2856 | initialize_context(ctx); | 2904 | initialize_context(ctx); |
2857 | ctx->stack = new; | 2905 | ctx->stack = new; |
@@ -2879,6 +2927,9 @@ static int reserved_word(o_string *dest, struct p_context *ctx) | |||
2879 | } | 2927 | } |
2880 | return 0; | 2928 | return 0; |
2881 | } | 2929 | } |
2930 | #else | ||
2931 | #define reserved_word(dest, ctx) ((int)0) | ||
2932 | #endif | ||
2882 | 2933 | ||
2883 | /* Normal return is 0. | 2934 | /* Normal return is 0. |
2884 | * Syntax or xglob errors return 1. */ | 2935 | * Syntax or xglob errors return 1. */ |
@@ -2929,10 +2980,12 @@ static int done_word(o_string *dest, struct p_context *ctx) | |||
2929 | } else { | 2980 | } else { |
2930 | child->argv = glob_target->gl_pathv; | 2981 | child->argv = glob_target->gl_pathv; |
2931 | } | 2982 | } |
2983 | #if ENABLE_HUSH_LOOPS | ||
2932 | if (ctx->res_w == RES_FOR) { | 2984 | if (ctx->res_w == RES_FOR) { |
2933 | done_word(dest, ctx); | 2985 | done_word(dest, ctx); |
2934 | done_pipe(ctx, PIPE_SEQ); | 2986 | done_pipe(ctx, PIPE_SEQ); |
2935 | } | 2987 | } |
2988 | #endif | ||
2936 | debug_printf_parse("done_word return 0\n"); | 2989 | debug_printf_parse("done_word return 0\n"); |
2937 | return 0; | 2990 | return 0; |
2938 | } | 2991 | } |