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
This commit is contained in:
parent
8d523cbcd7
commit
be709c24d4
@ -178,9 +178,11 @@ config HUSH
|
|||||||
hush is a very small shell (just 18k) and it has fairly complete
|
hush is a very small shell (just 18k) and it has fairly complete
|
||||||
Bourne shell grammar. It even handles all the normal flow control
|
Bourne shell grammar. It even handles all the normal flow control
|
||||||
options such as if/then/elif/else/fi, for/in/do/done, while loops,
|
options such as if/then/elif/else/fi, for/in/do/done, while loops,
|
||||||
etc.
|
case/esac.
|
||||||
|
|
||||||
It does not handle case/esac, select, function, here documents ( <<
|
It uses only vfork, so it can be used on uClinux systems.
|
||||||
|
|
||||||
|
It does not handle select, functions, here documents ( <<
|
||||||
word ), arithmetic expansion, aliases, brace expansion, tilde
|
word ), arithmetic expansion, aliases, brace expansion, tilde
|
||||||
expansion, &> and >& redirection of stdout+stderr, etc.
|
expansion, &> and >& redirection of stdout+stderr, etc.
|
||||||
|
|
||||||
@ -232,6 +234,14 @@ config HUSH_LOOPS
|
|||||||
depends on HUSH
|
depends on HUSH
|
||||||
help
|
help
|
||||||
Enable for, while and until loops in hush.
|
Enable for, while and until loops in hush.
|
||||||
|
As of 2008-07, break and continue statements are not supported.
|
||||||
|
|
||||||
|
config HUSH_CASE
|
||||||
|
bool "Support case ... esac statement"
|
||||||
|
default n
|
||||||
|
depends on HUSH
|
||||||
|
help
|
||||||
|
Enable case ... esac statement in hush. +400 bytes.
|
||||||
|
|
||||||
config LASH
|
config LASH
|
||||||
bool "lash"
|
bool "lash"
|
||||||
@ -249,7 +259,7 @@ config MSH
|
|||||||
shell to do. It is not always pedantically correct about Bourne
|
shell to do. It is not always pedantically correct about Bourne
|
||||||
shell grammar (try running the shell testscript "tests/sh.testcases"
|
shell grammar (try running the shell testscript "tests/sh.testcases"
|
||||||
on it and compare vs bash) but for most things it works quite well.
|
on it and compare vs bash) but for most things it works quite well.
|
||||||
It also uses only vfork, so it can be used on uClinux systems.
|
It uses only vfork, so it can be used on uClinux systems.
|
||||||
|
|
||||||
comment "Bourne Shell Options"
|
comment "Bourne Shell Options"
|
||||||
depends on MSH || LASH || HUSH || ASH
|
depends on MSH || LASH || HUSH || ASH
|
||||||
|
36
shell/hush.c
36
shell/hush.c
@ -67,14 +67,12 @@
|
|||||||
* Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
|
* Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <glob.h> /* glob, of course */
|
|
||||||
/* #include <dmalloc.h> */
|
|
||||||
|
|
||||||
#include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */
|
#include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */
|
||||||
|
#include <glob.h>
|
||||||
// TEMP
|
/* #include <dmalloc.h> */
|
||||||
#define ENABLE_HUSH_CASE 0
|
#if ENABLE_HUSH_CASE
|
||||||
|
#include <fnmatch.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if !BB_MMU && ENABLE_HUSH_TICK
|
#if !BB_MMU && ENABLE_HUSH_TICK
|
||||||
@ -2064,6 +2062,10 @@ static int run_list(struct pipe *pi)
|
|||||||
rpipe = NULL;
|
rpipe = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Past this point, all code paths should jump to ret: label
|
||||||
|
* in order to return, no direct "return" statements.
|
||||||
|
* This helps to ensure that no memory is leaked */
|
||||||
|
|
||||||
#if ENABLE_HUSH_JOB
|
#if ENABLE_HUSH_JOB
|
||||||
/* Example of nested list: "while true; do { sleep 1 | exit 2; } done".
|
/* Example of nested list: "while true; do { sleep 1 | exit 2; } done".
|
||||||
* We are saving state before entering outermost list ("while...done")
|
* We are saving state before entering outermost list ("while...done")
|
||||||
@ -2170,6 +2172,7 @@ static int run_list(struct pipe *pi)
|
|||||||
if (!*for_lcur) {
|
if (!*for_lcur) {
|
||||||
/* for loop is over, clean up */
|
/* for loop is over, clean up */
|
||||||
free(for_list);
|
free(for_list);
|
||||||
|
for_list = NULL;
|
||||||
for_lcur = NULL;
|
for_lcur = NULL;
|
||||||
flag_rep = 0;
|
flag_rep = 0;
|
||||||
pi->progs->argv[0] = for_varname;
|
pi->progs->argv[0] = for_varname;
|
||||||
@ -2195,14 +2198,21 @@ static int run_list(struct pipe *pi)
|
|||||||
#endif
|
#endif
|
||||||
#if ENABLE_HUSH_CASE
|
#if ENABLE_HUSH_CASE
|
||||||
if (rword == RES_CASE) {
|
if (rword == RES_CASE) {
|
||||||
case_word = pi->progs->argv[0];
|
case_word = expand_strvec_to_string(pi->progs->argv);
|
||||||
|
//bb_error_msg("case: arg:'%s' case_word:'%s'", pi->progs->argv[0], case_word);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (rword == RES_MATCH) {
|
if (rword == RES_MATCH) {
|
||||||
if (case_word) {
|
if (case_word) {
|
||||||
next_if_code = strcmp(case_word, pi->progs->argv[0]);
|
char *pattern = expand_strvec_to_string(pi->progs->argv);
|
||||||
if (next_if_code == 0)
|
/* TODO: which FNM_xxx flags to use? */
|
||||||
|
next_if_code = fnmatch(pattern, case_word, /*flags:*/ 0);
|
||||||
|
//bb_error_msg("fnmatch('%s','%s'):%d", pattern, case_word, next_if_code);
|
||||||
|
free(pattern);
|
||||||
|
if (next_if_code == 0) {
|
||||||
|
free(case_word);
|
||||||
case_word = NULL;
|
case_word = NULL;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -2276,6 +2286,12 @@ static int run_list(struct pipe *pi)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
debug_printf_exec("run_list lvl %d return %d\n", run_list_level + 1, rcode);
|
debug_printf_exec("run_list lvl %d return %d\n", run_list_level + 1, rcode);
|
||||||
|
#if ENABLE_HUSH_LOOPS
|
||||||
|
free(for_list);
|
||||||
|
#endif
|
||||||
|
#if ENABLE_HUSH_CASE
|
||||||
|
free(case_word);
|
||||||
|
#endif
|
||||||
return rcode;
|
return rcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
13
shell/hush_test/hush-misc/case1.right
Normal file
13
shell/hush_test/hush-misc/case1.right
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
OK_1
|
||||||
|
OK_21
|
||||||
|
OK_22
|
||||||
|
OK_23
|
||||||
|
OK_31
|
||||||
|
OK_32
|
||||||
|
OK_41
|
||||||
|
OK_42
|
||||||
|
OK_43
|
||||||
|
OK_44
|
||||||
|
OK_51
|
||||||
|
OK_52
|
||||||
|
OK_53
|
17
shell/hush_test/hush-misc/case1.tests
Executable file
17
shell/hush_test/hush-misc/case1.tests
Executable file
@ -0,0 +1,17 @@
|
|||||||
|
case w in a) echo SKIP;; w) echo OK_1;; w) echo WRONG;; esac
|
||||||
|
|
||||||
|
t=w
|
||||||
|
case $t in a) echo SKIP;; w) echo OK_21;; w) echo WRONG;; esac;
|
||||||
|
case "$t" in a) echo SKIP;; w) echo OK_22;; w) echo WRONG;; esac;
|
||||||
|
case w in a) echo SKIP;; $t) echo OK_23;; "$t") echo WRONG;; esac;
|
||||||
|
|
||||||
|
case '' in a) echo SKIP;; w) echo WRONG;; *) echo OK_31;; esac;
|
||||||
|
case '' in a) echo SKIP;; '') echo OK_32;; *) echo WRONG;; esac;
|
||||||
|
|
||||||
|
case `echo w` in a) echo SKIP;; w) echo OK_41;; w) echo WRONG;; esac;
|
||||||
|
case "`echo w`" in a) echo SKIP;; w) echo OK_42;; w) echo WRONG;; esac;
|
||||||
|
case `echo w w` in a) echo SKIP;; w) echo WRONG;; 'w w') echo OK_43;; esac;
|
||||||
|
case `echo w w` in a) echo SKIP;; w) echo WRONG;; w*) echo OK_44;; esac;
|
||||||
|
|
||||||
|
case w in `echo w`) echo OK_51;; `echo WRONG >&2`w) echo WRONG;; esac;
|
||||||
|
case w in `echo OK_52 >&2`) echo SKIP;; `echo`w) echo OK_53;; esac;
|
Loading…
Reference in New Issue
Block a user