diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-07-28 00:01:16 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-07-28 00:01:16 +0000 |
commit | be709c24d40c2fb52d3f57faa25b9134c7d25270 (patch) | |
tree | 8a2d3d0281ab92d0d961c7a783e01ba501e8a418 | |
parent | 8d523cbcd79c5428f1ea5bcbec6b7d9fd3756dc3 (diff) | |
download | busybox-w32-be709c24d40c2fb52d3f57faa25b9134c7d25270.tar.gz busybox-w32-be709c24d40c2fb52d3f57faa25b9134c7d25270.tar.bz2 busybox-w32-be709c24d40c2fb52d3f57faa25b9134c7d25270.zip |
hush: finish and enable optional case...esac support. Code size cost:
function old new delta
run_list 1891 2075 +184
parse_stream 1764 1847 +83
expand_strvec_to_string - 83 +83
done_word 647 715 +68
static.reserved_list 144 168 +24
static.reserved_match - 12 +12
done_pipe 95 105 +10
builtin_exit 48 46 -2
builtin_eval 127 54 -73
------------------------------------------------------------------------------
(add/remove: 2/0 grow/shrink: 5/2 up/down: 464/-75) Total: 389 bytes
-rw-r--r-- | shell/Config.in | 16 | ||||
-rw-r--r-- | shell/hush.c | 36 | ||||
-rw-r--r-- | shell/hush_test/hush-misc/case1.right | 13 | ||||
-rwxr-xr-x | shell/hush_test/hush-misc/case1.tests | 17 |
4 files changed, 69 insertions, 13 deletions
diff --git a/shell/Config.in b/shell/Config.in index f4a9e7b1c..ee2f832fa 100644 --- a/shell/Config.in +++ b/shell/Config.in | |||
@@ -178,9 +178,11 @@ config HUSH | |||
178 | hush is a very small shell (just 18k) and it has fairly complete | 178 | hush is a very small shell (just 18k) and it has fairly complete |
179 | Bourne shell grammar. It even handles all the normal flow control | 179 | Bourne shell grammar. It even handles all the normal flow control |
180 | options such as if/then/elif/else/fi, for/in/do/done, while loops, | 180 | options such as if/then/elif/else/fi, for/in/do/done, while loops, |
181 | etc. | 181 | case/esac. |
182 | 182 | ||
183 | It does not handle case/esac, select, function, here documents ( << | 183 | It uses only vfork, so it can be used on uClinux systems. |
184 | |||
185 | It does not handle select, functions, here documents ( << | ||
184 | word ), arithmetic expansion, aliases, brace expansion, tilde | 186 | word ), arithmetic expansion, aliases, brace expansion, tilde |
185 | expansion, &> and >& redirection of stdout+stderr, etc. | 187 | expansion, &> and >& redirection of stdout+stderr, etc. |
186 | 188 | ||
@@ -232,6 +234,14 @@ config HUSH_LOOPS | |||
232 | depends on HUSH | 234 | depends on HUSH |
233 | help | 235 | help |
234 | Enable for, while and until loops in hush. | 236 | Enable for, while and until loops in hush. |
237 | As of 2008-07, break and continue statements are not supported. | ||
238 | |||
239 | config HUSH_CASE | ||
240 | bool "Support case ... esac statement" | ||
241 | default n | ||
242 | depends on HUSH | ||
243 | help | ||
244 | Enable case ... esac statement in hush. +400 bytes. | ||
235 | 245 | ||
236 | config LASH | 246 | config LASH |
237 | bool "lash" | 247 | bool "lash" |
@@ -249,7 +259,7 @@ config MSH | |||
249 | shell to do. It is not always pedantically correct about Bourne | 259 | shell to do. It is not always pedantically correct about Bourne |
250 | shell grammar (try running the shell testscript "tests/sh.testcases" | 260 | shell grammar (try running the shell testscript "tests/sh.testcases" |
251 | on it and compare vs bash) but for most things it works quite well. | 261 | on it and compare vs bash) but for most things it works quite well. |
252 | It also uses only vfork, so it can be used on uClinux systems. | 262 | It uses only vfork, so it can be used on uClinux systems. |
253 | 263 | ||
254 | comment "Bourne Shell Options" | 264 | comment "Bourne Shell Options" |
255 | depends on MSH || LASH || HUSH || ASH | 265 | depends on MSH || LASH || HUSH || ASH |
diff --git a/shell/hush.c b/shell/hush.c index cf6a18f86..5a565b392 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -67,14 +67,12 @@ | |||
67 | * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. | 67 | * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. |
68 | */ | 68 | */ |
69 | 69 | ||
70 | |||
71 | #include <glob.h> /* glob, of course */ | ||
72 | /* #include <dmalloc.h> */ | ||
73 | |||
74 | #include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */ | 70 | #include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */ |
75 | 71 | #include <glob.h> | |
76 | // TEMP | 72 | /* #include <dmalloc.h> */ |
77 | #define ENABLE_HUSH_CASE 0 | 73 | #if ENABLE_HUSH_CASE |
74 | #include <fnmatch.h> | ||
75 | #endif | ||
78 | 76 | ||
79 | 77 | ||
80 | #if !BB_MMU && ENABLE_HUSH_TICK | 78 | #if !BB_MMU && ENABLE_HUSH_TICK |
@@ -2064,6 +2062,10 @@ static int run_list(struct pipe *pi) | |||
2064 | rpipe = NULL; | 2062 | rpipe = NULL; |
2065 | #endif | 2063 | #endif |
2066 | 2064 | ||
2065 | /* Past this point, all code paths should jump to ret: label | ||
2066 | * in order to return, no direct "return" statements. | ||
2067 | * This helps to ensure that no memory is leaked */ | ||
2068 | |||
2067 | #if ENABLE_HUSH_JOB | 2069 | #if ENABLE_HUSH_JOB |
2068 | /* Example of nested list: "while true; do { sleep 1 | exit 2; } done". | 2070 | /* Example of nested list: "while true; do { sleep 1 | exit 2; } done". |
2069 | * We are saving state before entering outermost list ("while...done") | 2071 | * We are saving state before entering outermost list ("while...done") |
@@ -2170,6 +2172,7 @@ static int run_list(struct pipe *pi) | |||
2170 | if (!*for_lcur) { | 2172 | if (!*for_lcur) { |
2171 | /* for loop is over, clean up */ | 2173 | /* for loop is over, clean up */ |
2172 | free(for_list); | 2174 | free(for_list); |
2175 | for_list = NULL; | ||
2173 | for_lcur = NULL; | 2176 | for_lcur = NULL; |
2174 | flag_rep = 0; | 2177 | flag_rep = 0; |
2175 | pi->progs->argv[0] = for_varname; | 2178 | pi->progs->argv[0] = for_varname; |
@@ -2195,14 +2198,21 @@ static int run_list(struct pipe *pi) | |||
2195 | #endif | 2198 | #endif |
2196 | #if ENABLE_HUSH_CASE | 2199 | #if ENABLE_HUSH_CASE |
2197 | if (rword == RES_CASE) { | 2200 | if (rword == RES_CASE) { |
2198 | case_word = pi->progs->argv[0]; | 2201 | case_word = expand_strvec_to_string(pi->progs->argv); |
2202 | //bb_error_msg("case: arg:'%s' case_word:'%s'", pi->progs->argv[0], case_word); | ||
2199 | continue; | 2203 | continue; |
2200 | } | 2204 | } |
2201 | if (rword == RES_MATCH) { | 2205 | if (rword == RES_MATCH) { |
2202 | if (case_word) { | 2206 | if (case_word) { |
2203 | next_if_code = strcmp(case_word, pi->progs->argv[0]); | 2207 | char *pattern = expand_strvec_to_string(pi->progs->argv); |
2204 | if (next_if_code == 0) | 2208 | /* TODO: which FNM_xxx flags to use? */ |
2209 | next_if_code = fnmatch(pattern, case_word, /*flags:*/ 0); | ||
2210 | //bb_error_msg("fnmatch('%s','%s'):%d", pattern, case_word, next_if_code); | ||
2211 | free(pattern); | ||
2212 | if (next_if_code == 0) { | ||
2213 | free(case_word); | ||
2205 | case_word = NULL; | 2214 | case_word = NULL; |
2215 | } | ||
2206 | continue; | 2216 | continue; |
2207 | } | 2217 | } |
2208 | break; | 2218 | break; |
@@ -2276,6 +2286,12 @@ static int run_list(struct pipe *pi) | |||
2276 | } | 2286 | } |
2277 | #endif | 2287 | #endif |
2278 | debug_printf_exec("run_list lvl %d return %d\n", run_list_level + 1, rcode); | 2288 | debug_printf_exec("run_list lvl %d return %d\n", run_list_level + 1, rcode); |
2289 | #if ENABLE_HUSH_LOOPS | ||
2290 | free(for_list); | ||
2291 | #endif | ||
2292 | #if ENABLE_HUSH_CASE | ||
2293 | free(case_word); | ||
2294 | #endif | ||
2279 | return rcode; | 2295 | return rcode; |
2280 | } | 2296 | } |
2281 | 2297 | ||
diff --git a/shell/hush_test/hush-misc/case1.right b/shell/hush_test/hush-misc/case1.right new file mode 100644 index 000000000..9b88658af --- /dev/null +++ b/shell/hush_test/hush-misc/case1.right | |||
@@ -0,0 +1,13 @@ | |||
1 | OK_1 | ||
2 | OK_21 | ||
3 | OK_22 | ||
4 | OK_23 | ||
5 | OK_31 | ||
6 | OK_32 | ||
7 | OK_41 | ||
8 | OK_42 | ||
9 | OK_43 | ||
10 | OK_44 | ||
11 | OK_51 | ||
12 | OK_52 | ||
13 | OK_53 | ||
diff --git a/shell/hush_test/hush-misc/case1.tests b/shell/hush_test/hush-misc/case1.tests new file mode 100755 index 000000000..15f60f3a6 --- /dev/null +++ b/shell/hush_test/hush-misc/case1.tests | |||
@@ -0,0 +1,17 @@ | |||
1 | case w in a) echo SKIP;; w) echo OK_1;; w) echo WRONG;; esac | ||
2 | |||
3 | t=w | ||
4 | case $t in a) echo SKIP;; w) echo OK_21;; w) echo WRONG;; esac; | ||
5 | case "$t" in a) echo SKIP;; w) echo OK_22;; w) echo WRONG;; esac; | ||
6 | case w in a) echo SKIP;; $t) echo OK_23;; "$t") echo WRONG;; esac; | ||
7 | |||
8 | case '' in a) echo SKIP;; w) echo WRONG;; *) echo OK_31;; esac; | ||
9 | case '' in a) echo SKIP;; '') echo OK_32;; *) echo WRONG;; esac; | ||
10 | |||
11 | case `echo w` in a) echo SKIP;; w) echo OK_41;; w) echo WRONG;; esac; | ||
12 | case "`echo w`" in a) echo SKIP;; w) echo OK_42;; w) echo WRONG;; esac; | ||
13 | case `echo w w` in a) echo SKIP;; w) echo WRONG;; 'w w') echo OK_43;; esac; | ||
14 | case `echo w w` in a) echo SKIP;; w) echo WRONG;; w*) echo OK_44;; esac; | ||
15 | |||
16 | case w in `echo w`) echo OK_51;; `echo WRONG >&2`w) echo WRONG;; esac; | ||
17 | case w in `echo OK_52 >&2`) echo SKIP;; `echo`w) echo OK_53;; esac; | ||