command with make_local_declare, meaning we have an array or assoc
compound assignment. (Slighty unsatisfactory, but ok for now) Fix
for bug report from Kevin Locke <kevin@kevinlocke.name>,
- https://savannah.gnu.org/support/index.php?109669
+ https://savannah.gnu.org/support/index.php?109669
3/18
----
of a shell started to run a command or process substitution (after
forking a child to run one command, but before forking another, for
instance). Reported by Rob Landley <rob@landley.net>
+
+ 4/27
+ ----
+parse.y
+ - function_def: break the productions starting with `function' without
+ `()' into two productions to avoid a shift-reduce conflict. Report
+ and patch from Dale R. Worley <worley@alum.mit.edu>
+
+variables.h
+ - localvar_inherit: add extern declaration here
+
+subst.c
+ - shell_expand_word_list: take out change from 3/17 to pass -I to
+ make_internal_declare; it generates errors the user will find
+ confusing if there is a variable with the same name but a different
+ type at a previous scope
+ - shell_expand_word_list: check for and note whether or not -I is
+ supplied to the declaration command, since it changes the default
+ behavior of a compound assignment without -a or -A
+ - shell_expand_word_list: if we have a compound assignment that is an
+ argument to a declaration command, but there are no options supplied
+ to the command that determine the type of the array, make sure we
+ call make_internal_declare with either -a (no localvar_inherit or -I)
+ or at least -- (if we are inheriting), because we don't want the
+ declare to get skipped before we perform the word assignment. Fixes
+ bug reported by Ross Goldberg <ross.goldberg@gmail.com>
This file is declare.def, from which is created declare.c.
It implements the builtins "declare" and "local" in Bash.
-Copyright (C) 1987-2016 Free Software Foundation, Inc.
+Copyright (C) 1987-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
$BUILTIN declare
$FUNCTION declare_builtin
-$SHORT_DOC declare [-aAfFgilnrtux] [-p] [name[=value] ...]
+$SHORT_DOC declare [-aAfFgiIlnrtux] [-p] [name[=value] ...]
Set variable values and attributes.
Declare variables and give them attributes. If no NAMEs are given,
$BUILTIN typeset
$FUNCTION declare_builtin
-$SHORT_DOC typeset [-aAfFgilnrtux] [-p] name[=value] ...
+$SHORT_DOC typeset [-aAfFgiIlnrtux] [-p] name[=value] ...
Set variable values and attributes.
A synonym for `declare'. See `help declare'.
function_def: WORD '(' ')' newline_list function_body
{ $$ = make_function_def ($1, $5, function_dstart, function_bstart); }
-
| FUNCTION WORD '(' ')' newline_list function_body
{ $$ = make_function_def ($2, $6, function_dstart, function_bstart); }
-
- | FUNCTION WORD newline_list function_body
- { $$ = make_function_def ($2, $4, function_dstart, function_bstart); }
+ | FUNCTION WORD function_body
+ { $$ = make_function_def ($2, $3, function_dstart, function_bstart); }
+ | FUNCTION WORD '\n' newline_list function_body
+ { $$ = make_function_def ($2, $5, function_dstart, function_bstart); }
;
function_body: shell_command
#endif
#if defined (ARRAY_VARS)
-/* Take WORD, a compound associative array assignment, and internally run
- 'declare -A w', where W is the variable name portion of WORD. */
+/* Take WORD, a compound array assignment, and internally run (for example),
+ 'declare -A w', where W is the variable name portion of WORD. OPTION is
+ the list of options to supply to `declare'. CMD is the declaration command
+ we are expanding right now; it's unused currently. */
static int
make_internal_declare (word, option, cmd)
char *word;
{
int t;
char opts[16];
- int opti, skip;
+ int opti, skip, inheriting, array;
+ inheriting = localvar_inherit;
opti = 0;
if (tlist->word->flags & (W_ASSIGNASSOC|W_ASSNGLOBAL|W_CHKLOCAL|W_ASSIGNARRAY))
opts[opti++] = '-';
else if (tlist->word->flags & W_ASSIGNASSOC)
{
opts[opti++] = 'A';
- opts[opti++] = 'I';
+ /* This doesn't work right if a variable with the same name but
+ a different type exists at a previous scope; it generates
+ errors that a user would find confusing. */
+/* opts[opti++] = 'I'; */
}
else if ((tlist->word->flags & (W_ASSIGNARRAY|W_ASSNGLOBAL)) == (W_ASSIGNARRAY|W_ASSNGLOBAL))
{
else if (tlist->word->flags & W_ASSIGNARRAY)
{
opts[opti++] = 'a';
- opts[opti++] = 'I';
+/* opts[opti++] = 'I'; */
}
else if (tlist->word->flags & W_ASSNGLOBAL)
opts[opti++] = 'g';
for (oind = 1; l->word->word[oind]; oind++)
switch (l->word->word[oind])
{
+ case 'I':
+ inheriting = 1;
case 'i':
case 'l':
case 'u':
opts[opti++] = oind;
}
+ /* If there are no -a/-A options, but we have a compound assignment,
+ we have a choice: we can set opts[0]='-', opt[1]='a', since the
+ default is to create an indexed array, and call
+ make_internal_declare, or we can just skip it and let
+ declare_builtin deal with it. Once we're here, we're better set
+ up for the former. We don't do this if we're inheriting local
+ variables' attributes and values here, since that makes `-a' no
+ longer the default; we pass `--' instead if we don't have any
+ options at all, and just leave off the -a if we have some. */
+ if ((tlist->word->flags & (W_ASSIGNASSOC|W_ASSIGNARRAY)) == 0)
+ {
+ if (opti == 0)
+ {
+ opts[opti++] = '-';
+ opts[opti++] = inheriting ? '-' : 'a';
+ }
+ else if (inheriting == 0)
+ opts[opti++] = 'a';
+ }
+
opts[opti] = '\0';
skip = 0;
if (opti > 0)
./errors.tests: line 62: unset: XPATH: cannot unset: readonly variable
./errors.tests: line 68: unset: cannot simultaneously unset a function and a variable
./errors.tests: line 71: declare: -z: invalid option
-declare: usage: declare [-aAfFgilnrtux] [-p] [name[=value] ...]
+declare: usage: declare [-aAfFgiIlnrtux] [-p] [name[=value] ...]
./errors.tests: line 73: declare: `-z': not a valid identifier
./errors.tests: line 74: declare: `/bin/sh': not a valid identifier
./errors.tests: line 78: declare: cannot use `-f' to make functions
after func: x = outside
./varenv11.sub: line 17: local: qux: readonly variable
./varenv11.sub: line 18: qux: readonly variable
+./varenv11.sub: line 18: local: qux: readonly variable
declare -A foo=([zero]="zero" [one]="one" )
declare -a bar=([0]="zero" [1]="one")
declare -A foo=([one]="one" [zero]="zero" )
help
./varenv13.sub: line 34: `var[0]': not a valid identifier
1
-./varenv14.sub: line 19: warning: var: cannot inherit value from incompatible type
-declare -a var=([0]="X")
-./varenv14.sub: line 22: warning: var: cannot inherit value from incompatible type
-declare -a var=([0]="Y")
-./varenv14.sub: line 23: warning: var: cannot inherit value from incompatible type
-declare -a var=([0]="Y")
-./varenv14.sub: line 24: warning: var: cannot inherit value from incompatible type
-declare -a var=()
-./varenv14.sub: line 25: warning: var: cannot inherit value from incompatible type
-declare -a var=()
+declare -A var=([0]="X" )
+declare -A var=([Y]="Y" )
+declare -A var=([Y]="Y" )
+declare -A var=()
+declare -A var=()
./varenv14.sub: line 31: f: var: cannot convert indexed to associative array
./varenv14.sub: line 31: declare: var: cannot convert indexed to associative array
declare -a var=([0]="12")
declare -- var="local"
declare -- var="f1"
declare -- var="local"
-declare -a arr=([0]="zero" [1]="one" [2]="two")
+declare -a arr=()
declare -a arr=([0]="three" [1]="four" [2]="five")
-declare -a arr=([0]="zero" [1]="one" [2]="two")
+./varenv18.sub: line 39: !name: unbound variable
a=z
a=b
a=z
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-# this uses value inheritance internally so that the self-reference in the
-# local variable declaration works right
+# THIS DOESN'T WORK RIGHT YET
arr=(zero one two)
four=four
extern int posparam_count;
extern pid_t dollar_dollar_pid;
+extern int localvar_inherit; /* declared in variables.c */
+
extern void initialize_shell_variables PARAMS((char **, int));
extern int validate_inherited_value PARAMS((SHELL_VAR *, int));