On Mon, Dec 15, 2014 at 4:34 AM, Chet Ramey <chet.ra...@case.edu> wrote: > It does implement `emulated behavior of normal assignments'. The question > is whether or not it should do that after having had its arguments undergo > one round of word expansion.
After studying the code I realized that that's actually the only thing we have to consider for changing. It turns out that the solution here is to just not allow expanded arguments to have compound assignments. This may break a little compatibility but I believe it's the only proper solution for it. If we are concerned about compatibility, as suggested we can consider adding another shopt option to allow other people to retain its old behavior - which is to allow expanded arguments to be recognized as possible forms of compound assignments. And I thought that this concept is better proven with some modifications to the code so I went ahead to create some. It turns out that we only need to change one significant line to have it done which is this one: if (value[0] == '(' && value[vlen-1] == ')') I changed it to this: if (delayed_compounds && value[0] == '(' && value[vlen-1] == ')') I named the shopt option delayed_compounds (it can be changed) which if enabled would allow old behavior. I made it disabled by default but this could be enabled with an option on compile time (--enable-delayed-compounds-default). This is my complete patch that's compatible with 4.3.30: -------------------- diff --git a/builtins/declare.def b/builtins/declare.def index a634e7c..8fdf4ae 100644 --- a/builtins/declare.def +++ b/builtins/declare.def @@ -92,6 +92,14 @@ extern int posixly_correct; static int declare_internal __P((register WORD_LIST *, int)); +#if defined (ARRAY_VARS) + #ifdef DELAYED_COMPOUNDS_DEFAULT +int delayed_compounds = 1; + #else +int delayed_compounds = 0; + #endif +#endif + /* Declare or change variable attributes. */ int declare_builtin (list) @@ -540,7 +554,7 @@ declare_internal (list, local_var) int vlen; vlen = STRLEN (value); - if (value[0] == '(' && value[vlen-1] == ')') + if (delayed_compounds && value[0] == '(' && value[vlen-1] == ')') compound_array_assign = 1; else simple_array_assign = 1; diff --git a/builtins/shopt.def b/builtins/shopt.def index 6050a14..abdbaa9 100644 --- a/builtins/shopt.def +++ b/builtins/shopt.def @@ -117,6 +117,10 @@ extern char *shell_name; extern int debugging_mode; #endif +#if defined (ARRAY_VARS) + extern int delayed_compounds; +#endif + static void shopt_error __P((char *)); static int set_shellopts_after_change __P((char *, int)); @@ -163,8 +167,15 @@ static struct { { "compat42", &shopt_compat41, set_compatibility_level }, #if defined (READLINE) { "complete_fullquote", &complete_fullquote, (shopt_set_func_t *)NULL}, + #if defined (ARRAY_VARS) + { "delayed_compounds", &delayed_compounds, (shopt_set_func_t *)NULL }, + #endif { "direxpand", &dircomplete_expand, shopt_set_complete_direxpand }, { "dirspell", &dircomplete_spelling, (shopt_set_func_t *)NULL }, +#else + #if defined (ARRAY_VARS) + { "delayed_compounds", &delayed_compounds, (shopt_set_func_t *)NULL }, + #endif #endif { "dotglob", &glob_dot_filenames, (shopt_set_func_t *)NULL }, { "execfail", &no_exit_on_failed_exec, (shopt_set_func_t *)NULL }, diff --git a/config.h.in b/config.h.in index 08af2ba..720c7f0 100644 --- a/config.h.in +++ b/config.h.in @@ -167,6 +167,9 @@ /* Define for case-modifying word expansions */ #undef CASEMOD_EXPANSIONS +/* Define to make the `delayed_compounds' shopt option enabled by default. */ +#undef DELAYED_COMPOUNDS_DEFAULT + /* Define to make the `direxpand' shopt option enabled by default. */ #undef DIRCOMPLETE_EXPAND_DEFAULT diff --git a/configure b/configure index 98bf890..175935f 100755 --- a/configure +++ b/configure @@ -803,6 +803,7 @@ enable_cond_command enable_cond_regexp enable_coprocesses enable_debugger +enable_delayed_compounds_default enable_direxpand_default enable_directory_stack enable_disabled_builtins @@ -1486,6 +1487,8 @@ Optional Features: --enable-coprocesses enable coprocess support and the coproc reserved word --enable-debugger enable support for bash debugger + --enable-delayed-compounds-default + enable the delayed_compounds shell option by default --enable-direxpand-default enable the direxpand shell option by default --enable-directory-stack @@ -3085,6 +3088,11 @@ if test "${enable_debugger+set}" = set; then : enableval=$enable_debugger; opt_debugger=$enableval fi +# Check whether --enable-delayed-compounds-default was given. +if test "${enable_delayed_compounds_default+set}" = set; then : + enableval=$enable_delayed_compounds_default; opt_delayed_compounds_default=$enableval +fi + # Check whether --enable-direxpand-default was given. if test "${enable_direxpand_default+set}" = set; then : enableval=$enable_direxpand_default; opt_dircomplete_expand_default=$enableval @@ -3331,6 +3339,10 @@ if test $opt_casemod_expansions = yes; then $as_echo "#define CASEMOD_EXPANSIONS 1" >>confdefs.h fi +if test $opt_delayed_compounds_default = yes; then +$as_echo "#define DELAYED_COMPOUNDS_DEFAULT 1" >>confdefs.h + +fi if test $opt_dircomplete_expand_default = yes; then $as_echo "#define DIRCOMPLETE_EXPAND_DEFAULT 1" >>confdefs.h diff --git a/configure.ac b/configure.ac index 97e8e04..a6f1639 100644 --- a/configure.ac +++ b/configure.ac @@ -228,6 +228,7 @@ AC_ARG_ENABLE(cond-command, AC_HELP_STRING([--enable-cond-command], [enable the AC_ARG_ENABLE(cond-regexp, AC_HELP_STRING([--enable-cond-regexp], [enable extended regular expression matching in conditional commands]), opt_cond_regexp=$enableval) AC_ARG_ENABLE(coprocesses, AC_HELP_STRING([--enable-coprocesses], [enable coprocess support and the coproc reserved word]), opt_coproc=$enableval) AC_ARG_ENABLE(debugger, AC_HELP_STRING([--enable-debugger], [enable support for bash debugger]), opt_debugger=$enableval) +AC_ARG_ENABLE(delayed-compounds-default, AC_HELP_STRING([--enable-delayed-compounds-default], [enable the delayed_compounds shell option by default]), opt_delayed_compounds_default=$enableval) AC_ARG_ENABLE(direxpand-default, AC_HELP_STRING([--enable-direxpand-default], [enable the direxpand shell option by default]), opt_dircomplete_expand_default=$enableval) AC_ARG_ENABLE(directory-stack, AC_HELP_STRING([--enable-directory-stack], [enable builtins pushd/popd/dirs]), opt_dirstack=$enableval) AC_ARG_ENABLE(disabled-builtins, AC_HELP_STRING([--enable-disabled-builtins], [allow disabled builtins to still be invoked]), opt_disabled_builtins=$enableval) @@ -349,6 +350,9 @@ fi if test $opt_casemod_expansions = yes; then AC_DEFINE(CASEMOD_EXPANSIONS) fi +if test $opt_delayed_compounds_default = yes; then +AC_DEFINE(DELAYED_COMPOUNDS_DEFAULT) +fi if test $opt_dircomplete_expand_default = yes; then AC_DEFINE(DIRCOMPLETE_EXPAND_DEFAULT) fi diff --git a/doc/bash.1 b/doc/bash.1 index ec41462..d4a5035 100644 --- a/doc/bash.1 +++ b/doc/bash.1 @@ -9316,6 +9316,15 @@ filenames. This variable is set by default, which is the default bash behavior in versions through 4.2. .TP 8 +.B delayed_compounds +If set, +.B bash +would allow expanded arguments to +.B declare +or +.B local +to be recognized as possible forms of assigning compound values to arrays. +.TP 8 .B direxpand If set, .B bash diff --git a/doc/bashref.texi b/doc/bashref.texi index eca3c26..ff77c46 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -4992,6 +4992,11 @@ filenames. This variable is set by default, which is the default Bash behavior in versions through 4.2. +@item delayed_compounds +If set, Bash +would recognize expanded arguments to @code{declare} or @code{local} to be +recognized as possible forms of assigning compound values to arrays. + @item direxpand If set, Bash replaces directory names with the results of word expansion when performing @@ -8077,6 +8082,11 @@ Include support for coprocesses and the @code{coproc} reserved word @item --enable-debugger Include support for the bash debugger (distributed separately). +@item --enable-delayed-compounds-default +Cause the @code{delayed_compounds} shell option (@pxref{The Shopt Builtin}) +to be enabled by default when the shell starts. +It is normally disabled by default. + @item --enable-direxpand-default Cause the @code{direxpand} shell option (@pxref{The Shopt Builtin}) to be enabled by default when the shell starts. -------------------- And here are some tests: -------------------- # b='($(uname))' ./bash -c 'shopt delayed_compounds; declare -a a; declare a="$b"; printf "<%s>\n" "$a" "${a[0]}"' delayed_compounds off <($(uname))> <($(uname))> # external_input='($(echo FOO))' ./bash -c 'a=(); declare -l a="$external_input"; echo "$a"' ($(echo foo)) -------------------- I also uploaded the working tree in https://github.com/konsolebox/bash/tree/delayed_compounds. Cheers, konsolebox