bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: declare a="$b" if $a previously set as array


From: konsolebox
Subject: Re: declare a="$b" if $a previously set as array
Date: Wed, 17 Dec 2014 16:58:14 +0800

On Mon, Dec 15, 2014 at 4:34 AM, Chet Ramey <chet.ramey@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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]