diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog
index 9995e616..570502c0 100644
--- a/CWRU/CWRU.chlog
+++ b/CWRU/CWRU.chlog
@@ -2640,3 +2640,25 @@ variables.c
doc/Makefile.in
- changes to allow man pages that include others (.so FN) to be built
outside the source tree
+
+ 12/13
+ -----
+arrayfunc.c
+ - assign_array_element_internal: take an additional argument: char **NVALP.
+ If non-null, it gets the value eventually assigned to the array
+ element
+ - assign_array_element: take an additional NVALP argument; pass it to
+ assign_array_element_internal
+
+arrayfunc.h
+ - assign_array_element: new extern function declaration
+
+{subst,variables}.c,builtins/{common.c,declare.def}
+ - assign_array_element: change callers
+
+subst.c
+ - parameter_brace_expand_rhs: for the ${param:=value}, use the value
+ returned by assign_array_element in NVALP as the return value, since
+ it's the value ultimately assigned to the variable after possible
+ modification (e.g., arithmetic evaluation). Reported by
+ oguzismailuysal@gmail.com after flawed fix applied 11/16
diff --git a/MANIFEST b/MANIFEST
index 8755145b..0e1bd571 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -933,6 +933,7 @@ tests/array26.sub f
tests/array27.sub f
tests/array28.sub f
tests/array29.sub f
+tests/array30.sub f
tests/array-at-star f
tests/array2.right f
tests/assoc.tests f
diff --git a/array.h b/array.h
index 24d2b632..4214e8b4 100644
--- a/array.h
+++ b/array.h
@@ -27,8 +27,6 @@
typedef intmax_t arrayind_t;
-enum atype {array_indexed, array_assoc}; /* not used */
-
typedef struct array {
arrayind_t max_index;
arrayind_t num_elements;
diff --git a/arrayfunc.c b/arrayfunc.c
index 81656052..420547cf 100644
--- a/arrayfunc.c
+++ b/arrayfunc.c
@@ -53,7 +53,7 @@ int assoc_expand_once = 0;
int array_expand_once = 0;
static SHELL_VAR *bind_array_var_internal PARAMS((SHELL_VAR *, arrayind_t, char *, char *, int));
-static SHELL_VAR *assign_array_element_internal PARAMS((SHELL_VAR *, char *, char *, char *, int, char *, int));
+static SHELL_VAR *assign_array_element_internal PARAMS((SHELL_VAR *, char *, char *, char *, int, char *, int, char **));
static void assign_assoc_from_kvlist PARAMS((SHELL_VAR *, WORD_LIST *, HASH_TABLE *, int));
@@ -322,9 +322,10 @@ bind_assoc_variable (entry, name, key, value, flags)
assign VALUE to that array element by calling bind_array_variable().
Flags are ASS_ assignment flags */
SHELL_VAR *
-assign_array_element (name, value, flags)
+assign_array_element (name, value, flags, nvalp)
char *name, *value;
int flags;
+ char **nvalp;
{
char *sub, *vname;
int sublen, isassoc;
@@ -352,14 +353,14 @@ assign_array_element (name, value, flags)
return ((SHELL_VAR *)NULL);
}
- entry = assign_array_element_internal (entry, name, vname, sub, sublen, value, flags);
+ entry = assign_array_element_internal (entry, name, vname, sub, sublen, value, flags, nvalp);
free (vname);
return entry;
}
static SHELL_VAR *
-assign_array_element_internal (entry, name, vname, sub, sublen, value, flags)
+assign_array_element_internal (entry, name, vname, sub, sublen, value, flags, nvalp)
SHELL_VAR *entry;
char *name; /* only used for error messages */
char *vname;
@@ -367,9 +368,11 @@ assign_array_element_internal (entry, name, vname, sub, sublen, value, flags)
int sublen;
char *value;
int flags;
+ char **nvalp;
{
char *akey;
arrayind_t ind;
+ char *newval;
if (entry && assoc_p (entry))
{
@@ -386,6 +389,7 @@ assign_array_element_internal (entry, name, vname, sub, sublen, value, flags)
return ((SHELL_VAR *)NULL);
}
entry = bind_assoc_variable (entry, vname, akey, value, flags);
+ newval = entry ? assoc_reference (assoc_cell (entry), akey) : 0;
}
else
{
@@ -399,8 +403,14 @@ assign_array_element_internal (entry, name, vname, sub, sublen, value, flags)
return ((SHELL_VAR *)NULL);
}
entry = bind_array_variable (vname, ind, value, flags);
+ newval = entry ? array_reference (array_cell (entry), ind) : 0;
}
+ /* If the caller asks, return the (possibly modified) final value assigned.
+ This saves subseqent lookups. */
+ if (nvalp)
+ *nvalp = newval;
+
return (entry);
}
diff --git a/arrayfunc.h b/arrayfunc.h
index 87569e43..136313d1 100644
--- a/arrayfunc.h
+++ b/arrayfunc.h
@@ -56,7 +56,7 @@ extern char *make_array_variable_value PARAMS((SHELL_VAR *, arrayind_t, char *,
extern SHELL_VAR *bind_array_variable PARAMS((char *, arrayind_t, char *, int));
extern SHELL_VAR *bind_array_element PARAMS((SHELL_VAR *, arrayind_t, char *, int));
-extern SHELL_VAR *assign_array_element PARAMS((char *, char *, int));
+extern SHELL_VAR *assign_array_element PARAMS((char *, char *, int, char **));
extern SHELL_VAR *bind_assoc_variable PARAMS((SHELL_VAR *, char *, char *, char *, int));
diff --git a/builtins/common.c b/builtins/common.c
index 563a0626..ad97874d 100644
--- a/builtins/common.c
+++ b/builtins/common.c
@@ -1004,7 +1004,7 @@ builtin_bind_variable (name, value, flags)
if (valid_array_reference (name, vflags) == 0)
v = bind_variable (name, value, flags);
else
- v = assign_array_element (name, value, bindflags);
+ v = assign_array_element (name, value, bindflags, (char **)0);
#else /* !ARRAY_VARS */
v = bind_variable (name, value, flags);
#endif /* !ARRAY_VARS */
diff --git a/builtins/declare.def b/builtins/declare.def
index 58413853..c8535ab0 100644
--- a/builtins/declare.def
+++ b/builtins/declare.def
@@ -949,7 +949,7 @@ restart_new_var_name:
local_aflags = aflags&ASS_APPEND;
local_aflags |= assoc_noexpand ? ASS_NOEXPAND : 0;
local_aflags |= ASS_ALLOWALLSUB; /* allow declare a[@]=at */
- var = assign_array_element (name, value, local_aflags); /* XXX - not aflags */
+ var = assign_array_element (name, value, local_aflags, (char **)0); /* XXX - not aflags */
*subscript_start = '\0';
if (var == 0) /* some kind of assignment error */
{
diff --git a/doc/bash.1 b/doc/bash.1
index 1cf056cc..43fc4530 100644
--- a/doc/bash.1
+++ b/doc/bash.1
@@ -281,7 +281,7 @@ An \fIinteractive\fP shell is one started without non-option arguments
(unless \fB\-s\fP is specified)
and without the
.B \-c
-option
+option,
whose standard input and error are
both connected to terminals (as determined by
.IR isatty (3)),
diff --git a/doc/bashref.texi b/doc/bashref.texi
index ec538a38..f831ff04 100644
--- a/doc/bashref.texi
+++ b/doc/bashref.texi
@@ -7091,8 +7091,9 @@ the same, but the effective user id is not reset.
@subsection What is an Interactive Shell?
An interactive shell
-is one started without non-option arguments, unless @option{-s} is
-specified, without specifying the @option{-c} option, and
+is one started without non-option arguments
+(unless @option{-s} is specified)
+and without specifying the @option{-c} option,
whose input and error output are both
connected to terminals (as determined by @code{isatty(3)}),
or one started with the @option{-i} option.
diff --git a/subst.c b/subst.c
index 20755b6f..7ba7ede3 100644
--- a/subst.c
+++ b/subst.c
@@ -3308,7 +3308,7 @@ do_assignment_internal (word, expand)
ASSIGN_RETURN (0);
}
aflags |= ASS_ALLOWALLSUB; /* allow a[@]=value for existing associative arrays */
- entry = assign_array_element (name, value, aflags);
+ entry = assign_array_element (name, value, aflags, (char **)0);
if (entry == 0)
ASSIGN_RETURN (0);
}
@@ -7227,8 +7227,8 @@ parameter_brace_expand_rhs (name, value, op, quoted, pflags, qdollaratp, hasdoll
{
WORD_DESC *w;
WORD_LIST *l, *tl;
- char *t, *t1, *temp, *vname;
- int l_hasdollat, sindex;
+ char *t, *t1, *temp, *vname, *newval;
+ int l_hasdollat, sindex, arrayref;
SHELL_VAR *v;
/*itrace("parameter_brace_expand_rhs: %s:%s pflags = %d", name, value, pflags);*/
@@ -7374,9 +7374,13 @@ parameter_brace_expand_rhs (name, value, op, quoted, pflags, qdollaratp, hasdoll
}
}
+ arrayref = 0;
#if defined (ARRAY_VARS)
if (valid_array_reference (vname, 0))
- v = assign_array_element (vname, t1, 0);
+ {
+ v = assign_array_element (vname, t1, ASS_ALLOWALLSUB, &newval);
+ arrayref = 1;
+ }
else
#endif /* ARRAY_VARS */
v = bind_variable (vname, t1, 0);
@@ -7399,16 +7403,20 @@ parameter_brace_expand_rhs (name, value, op, quoted, pflags, qdollaratp, hasdoll
stupidly_hack_special_variables (vname);
- if (vname != name)
- free (vname);
-
/* "In all cases, the final value of parameter shall be substituted." */
if (shell_compatibility_level > 51)
{
FREE (t1);
+#if defined (ARRAY_VARS)
+ t1 = arrayref ? newval : get_variable_value (v);
+#else
t1 = value_cell (v);
+#endif
}
+ if (vname != name)
+ free (vname);
+
/* From Posix group discussion Feb-March 2010. Issue 7 0000221 */
/* If we are double-quoted or if we are not going to be performing word
diff --git a/tests/array.right b/tests/array.right
index 939d6a2a..62278852 100644
--- a/tests/array.right
+++ b/tests/array.right
@@ -773,3 +773,15 @@ declare -A foo=([v]=$'\001\001\001\001' )
declare -A foo=([v]=$'\001\001\001\001' )
declare -A foo=([$'\001']=$'ab\001c' )
declare -A foo=([$'\001']=$'ab\001c' )
+foo
+declare -a a=([42]="foo")
+foo
+declare -a a=([42]="foo")
+7
+declare -ai a=([42]="7")
+42
+declare -ai a=([42]="42")
+FOO
+declare -Au A=([Darwin]="FOO" )
+FOO
+declare -Au A=(["@"]="FOO" )
diff --git a/tests/array.tests b/tests/array.tests
index 74d14821..d0bb08b7 100644
--- a/tests/array.tests
+++ b/tests/array.tests
@@ -426,3 +426,4 @@ ${THIS_SH} ./array26.sub
${THIS_SH} ./array27.sub
${THIS_SH} ./array28.sub
${THIS_SH} ./array29.sub
+${THIS_SH} ./array30.sub
diff --git a/tests/array30.sub b/tests/array30.sub
new file mode 100644
index 00000000..14f97980
--- /dev/null
+++ b/tests/array30.sub
@@ -0,0 +1,46 @@
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+declare -a a
+a=()
+
+echo ${a[42]=foo}
+declare -p a
+
+a=()
+echo ${a[$(echo 42)]=foo}
+declare -p a
+
+unset a
+
+declare -ai a
+a=()
+echo ${a[42]=4+3}
+declare -p a
+
+a=()
+echo ${a[$(echo 42)]=42}
+declare -p a
+
+unset a
+
+declare -A A
+declare -u A
+A=()
+echo ${A[$(echo Darwin)]=foo}
+
+declare -p A
+A=()
+
+echo ${A[@]:=foo}
+declare -p A
diff --git a/tests/exp.right b/tests/exp.right
index b6b3747d..60241a1d 100644
--- a/tests/exp.right
+++ b/tests/exp.right
@@ -409,3 +409,11 @@ cdefg
abcdefg
abcde
abcdefg
+foo
+declare -- a="foo"
+7
+declare -i a="7"
+42
+declare -- a="42"
+FOO
+declare -u A="FOO"
diff --git a/tests/exp.tests b/tests/exp.tests
index 3e69db4f..61a39d3b 100644
--- a/tests/exp.tests
+++ b/tests/exp.tests
@@ -423,3 +423,4 @@ ${THIS_SH} ./exp9.sub
${THIS_SH} ./exp10.sub
${THIS_SH} ./exp11.sub
${THIS_SH} ./exp12.sub
+${THIS_SH} ./exp13.sub
diff --git a/tests/exp13.sub b/tests/exp13.sub
new file mode 100644
index 00000000..80e14635
--- /dev/null
+++ b/tests/exp13.sub
@@ -0,0 +1,34 @@
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+unset a
+
+echo ${a:=foo}
+declare -p a
+
+unset a
+
+declare -i a
+echo ${a:=4+3}
+declare -p a
+
+unset a
+echo ${a:=42}
+declare -p a
+
+unset a
+declare -u A
+A=
+echo ${A:=foo}
+
+declare -p A
diff --git a/variables.c b/variables.c
index b5bdec20..65f5ce54 100644
--- a/variables.c
+++ b/variables.c
@@ -2495,7 +2495,7 @@ get_variable_value (var)
/* Return the string value of a variable. Return NULL if the variable
doesn't exist. Don't cons a new string. This is a potential memory
leak if the variable is found in the temporary environment, but doesn't
- leak in practice. Since functions and variables have separate name
+ leak in practice. Since functions and variables have separate name
spaces, returns NULL if var_name is a shell function only. */
char *
get_string_value (var_name)
@@ -3111,7 +3111,7 @@ bind_variable_internal (name, value, table, hflags, aflags)
assign_array_element will eventually do it itself based on
newval and aflags. */
- entry = assign_array_element (newval, value, aflags|ASS_NAMEREF);
+ entry = assign_array_element (newval, value, aflags|ASS_NAMEREF, (char **)0);
if (entry == 0)
return entry;
}
@@ -3268,7 +3268,7 @@ bind_variable (name, value, flags)
return (bind_variable_internal (nv->name, value, nvc->table, 0, flags));
#if defined (ARRAY_VARS)
else if (valid_array_reference (nameref_cell (nv), 0))
- return (assign_array_element (nameref_cell (nv), value, flags));
+ return (assign_array_element (nameref_cell (nv), value, flags, (char **)0));
else
#endif
return (bind_variable_internal (nameref_cell (nv), value, nvc->table, 0, flags));
@@ -3433,7 +3433,7 @@ bind_int_variable (lhs, rhs, flags)
#if defined (ARRAY_VARS)
if (isarr)
- v = assign_array_element (lhs, rhs, flags);
+ v = assign_array_element (lhs, rhs, flags, (char **)0);
else if (implicitarray)
v = bind_array_variable (lhs, 0, rhs, 0); /* XXX - check on flags */
else