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
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
typedef intmax_t arrayind_t;
-enum atype {array_indexed, array_assoc}; /* not used */
-
typedef struct array {
arrayind_t max_index;
arrayind_t num_elements;
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));
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;
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;
int sublen;
char *value;
int flags;
+ char **nvalp;
{
char *akey;
arrayind_t ind;
+ char *newval;
if (entry && assoc_p (entry))
{
return ((SHELL_VAR *)NULL);
}
entry = bind_assoc_variable (entry, vname, akey, value, flags);
+ newval = entry ? assoc_reference (assoc_cell (entry), akey) : 0;
}
else
{
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);
}
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));
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 */
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 */
{
(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)),
@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.
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);
}
{
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);*/
}
}
+ 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);
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
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" )
${THIS_SH} ./array27.sub
${THIS_SH} ./array28.sub
${THIS_SH} ./array29.sub
+${THIS_SH} ./array30.sub
--- /dev/null
+# 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 <http://www.gnu.org/licenses/>.
+#
+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
abcdefg
abcde
abcdefg
+foo
+declare -- a="foo"
+7
+declare -i a="7"
+42
+declare -- a="42"
+FOO
+declare -u A="FOO"
${THIS_SH} ./exp10.sub
${THIS_SH} ./exp11.sub
${THIS_SH} ./exp12.sub
+${THIS_SH} ./exp13.sub
--- /dev/null
+# 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 <http://www.gnu.org/licenses/>.
+#
+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
/* 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)
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;
}
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));
#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