hush: add HUSH_BASH_COMPAT, make [[ special handling depend on it

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2009-06-10 13:39:35 +02:00
parent 1d77db8459
commit 9ca656b149
2 changed files with 40 additions and 29 deletions

View File

@ -43,9 +43,6 @@ config ASH
shell (by Herbert Xu), which was created by porting the 'ash' shell shell (by Herbert Xu), which was created by porting the 'ash' shell
(written by Kenneth Almquist) from NetBSD. (written by Kenneth Almquist) from NetBSD.
comment "Ash Shell Options"
depends on ASH
config ASH_BASH_COMPAT config ASH_BASH_COMPAT
bool "bash-compatible extensions" bool "bash-compatible extensions"
default y default y
@ -169,6 +166,13 @@ config HUSH
It does not handle select, aliases, brace expansion, It does not handle select, aliases, brace expansion,
tilde expansion, &>file and >&file redirection of stdout+stderr. tilde expansion, &>file and >&file redirection of stdout+stderr.
config HUSH_BASH_COMPAT
bool "bash-compatible extensions"
default y
depends on HUSH
help
Enable bash-compatible extensions.
config HUSH_HELP config HUSH_HELP
bool "help builtin" bool "help builtin"
default n default n
@ -268,9 +272,6 @@ config MSH
# It 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"
depends on MSH || LASH || HUSH || ASH
config SH_MATH_SUPPORT config SH_MATH_SUPPORT
bool "POSIX math support" bool "POSIX math support"
default y default y

View File

@ -42,11 +42,18 @@
* <(list) and >(list) Process Substitution * <(list) and >(list) Process Substitution
* Tilde Expansion * Tilde Expansion
* *
* Bash stuff (maybe optionally enable?): * Bash stuff (optionally enabled):
* &> and >& redirection of stdout+stderr * &> and >& redirection of stdout+stderr
* Brace Expansion * Brace Expansion
* reserved words: [[ ]] function select * reserved words: [[ ]] function select
* substrings ${var:1:5} * substrings ${var:1:5}
* let EXPR [EXPR...]
* Each EXPR is an arithmetic expression (ARITHMETIC EVALUATION)
* If the last arg evaluates to 0, let returns 1; 0 otherwise.
* NB: let `echo 'a=a + 1'` - error (IOW: multi-word expansion is used)
* ((EXPR))
* The EXPR is evaluated according to ARITHMETIC EVALUATION.
* This is exactly equivalent to let "expression".
* *
* TODOs: * TODOs:
* grep for "TODO" and fix (some of them are easy) * grep for "TODO" and fix (some of them are easy)
@ -59,7 +66,7 @@
* $ ls i=`echo 'a b'` # ls has two args: "i=a" and "b" * $ ls i=`echo 'a b'` # ls has two args: "i=a" and "b"
* ls: cannot access i=a: No such file or directory * ls: cannot access i=a: No such file or directory
* ls: cannot access b: No such file or directory * ls: cannot access b: No such file or directory
* Note1: same applies to local builtin when we'll have it. * Note1: same applies to local builtin.
* Note2: bash 3.2.33(1) does this only if export word itself * Note2: bash 3.2.33(1) does this only if export word itself
* is not quoted: * is not quoted:
* $ export i=`echo 'aaa bbb'`; echo "$i" * $ export i=`echo 'aaa bbb'`; echo "$i"
@ -299,28 +306,11 @@ struct command {
smallint cmd_type; /* CMD_xxx */ smallint cmd_type; /* CMD_xxx */
#define CMD_NORMAL 0 #define CMD_NORMAL 0
#define CMD_SUBSHELL 1 #define CMD_SUBSHELL 1
/* used for "[[ EXPR ]]" */ /* used for "[[ EXPR ]]" */
#define CMD_SINGLEWORD_NOGLOB 2 #if ENABLE_HUSH_BASH_COMPAT
/* used for "export noglob=* glob* a=`echo a b`" */ # define CMD_SINGLEWORD_NOGLOB 2
/* #define CMD_SINGLEWORD_NOGLOB_COND 3 */
// It is hard to implement correctly, adds significant amounts of tricky code,
// and all this only useful for really obscure export statements
// almost nobody would use anyway. #ifdef CMD_SINGLEWORD_NOGLOB_COND
// guard the code which implement it, but I have doubts it works
// in all cases (especially with mixed globbed/non-globbed arguments)
#if ENABLE_HUSH_FUNCTIONS
# define CMD_FUNCDEF 4
#endif #endif
//TODO
//#define CMD_ARITH - let EXPR, ((EXPR))
//let EXPR [EXPR...]
// Each EXPR is an arithmetic expression to be evaluated (ARITHMETIC EVALUATION)
// If the last arg evaluates to 0, let returns 1; 0 is returned otherwise.
// NB: let `echo 'a=a + 1'` - error (IOW: multi-word expansion is used)
//((EXPR))
// The EXPR is evaluated according to ARITHMETIC EVALUATION.
// This is exactly equivalent to let "expression".
//[[ EXPR ]]
// Basically, word splitting and pathname expansion should NOT be performed // Basically, word splitting and pathname expansion should NOT be performed
// Examples: // Examples:
// no word splitting: a="a b"; [[ $a = "a b" ]]; echo $? should print "0" // no word splitting: a="a b"; [[ $a = "a b" ]]; echo $? should print "0"
@ -330,6 +320,18 @@ struct command {
// =~ regexp match // =~ regexp match
// Apart from the above, [[ expr ]] should work as [ expr ] // Apart from the above, [[ expr ]] should work as [ expr ]
/* used for "export noglob=* glob* a=`echo a b`" */
/*#define CMD_SINGLEWORD_NOGLOB_COND 3 */
// It is hard to implement correctly, it adds significant amounts of tricky code,
// and all this is only useful for really obscure export statements
// almost nobody would use anyway. #ifdef CMD_SINGLEWORD_NOGLOB_COND
// guards the code which implements it, but I have doubts it works
// in all cases (especially with mixed globbed/non-globbed arguments)
#if ENABLE_HUSH_FUNCTIONS
# define CMD_FUNCDEF 3
#endif
/* if non-NULL, this "command" is { list }, ( list ), or a compound statement */ /* if non-NULL, this "command" is { list }, ( list ), or a compound statement */
struct pipe *group; struct pipe *group;
#if !BB_MMU #if !BB_MMU
@ -2484,10 +2486,12 @@ static char **expand_strvec_to_strvec(char **argv)
return expand_variables(argv, 0x100); return expand_variables(argv, 0x100);
} }
#if ENABLE_HUSH_BASH_COMPAT
static char **expand_strvec_to_strvec_singleword_noglob(char **argv) static char **expand_strvec_to_strvec_singleword_noglob(char **argv)
{ {
return expand_variables(argv, 0x80); return expand_variables(argv, 0x80);
} }
#endif
#ifdef CMD_SINGLEWORD_NOGLOB_COND #ifdef CMD_SINGLEWORD_NOGLOB_COND
static char **expand_strvec_to_strvec_singleword_noglob_cond(char **argv) static char **expand_strvec_to_strvec_singleword_noglob_cond(char **argv)
@ -3838,9 +3842,12 @@ static int run_pipe(struct pipe *pi)
} }
/* Expand the rest into (possibly) many strings each */ /* Expand the rest into (possibly) many strings each */
if (command->cmd_type == CMD_SINGLEWORD_NOGLOB) { if (0) {}
#if ENABLE_HUSH_BASH_COMPAT
else if (command->cmd_type == CMD_SINGLEWORD_NOGLOB) {
argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt); argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt);
} }
#endif
#ifdef CMD_SINGLEWORD_NOGLOB_COND #ifdef CMD_SINGLEWORD_NOGLOB_COND
else if (command->cmd_type == CMD_SINGLEWORD_NOGLOB_COND) { else if (command->cmd_type == CMD_SINGLEWORD_NOGLOB_COND) {
argv_expanded = expand_strvec_to_strvec_singleword_noglob_cond(argv + command->assignment_cnt); argv_expanded = expand_strvec_to_strvec_singleword_noglob_cond(argv + command->assignment_cnt);
@ -4094,6 +4101,7 @@ static void debug_print_tree(struct pipe *pi, int lvl)
static const char *const CMDTYPE[] = { static const char *const CMDTYPE[] = {
"{}", "{}",
"()", "()",
"[noglob]",
#if ENABLE_HUSH_FUNCTIONS #if ENABLE_HUSH_FUNCTIONS
"func()", "func()",
#endif #endif
@ -4833,10 +4841,12 @@ static int done_word(o_string *word, struct parse_context *ctx)
command->cmd_type = CMD_SINGLEWORD_NOGLOB_COND; command->cmd_type = CMD_SINGLEWORD_NOGLOB_COND;
} else } else
# endif # endif
# if ENABLE_HUSH_BASH_COMPAT
if (strcmp(word->data, "[[") == 0) { if (strcmp(word->data, "[[") == 0) {
command->cmd_type = CMD_SINGLEWORD_NOGLOB; command->cmd_type = CMD_SINGLEWORD_NOGLOB;
} }
/* fall through */ /* fall through */
# endif
} }
#endif #endif
if (command->group) { if (command->group) {