From 69333f10bbd56ba9f93c87d939569aa12d9b24f1 Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Mon, 27 Apr 2020 17:05:14 -0400 Subject: [PATCH] commit bash-20200424 snapshot --- CWRU/CWRU.chlog | 28 +++++++++++++++++++++++++++- builtins/declare.def | 6 +++--- parse.y | 8 ++++---- subst.c | 38 +++++++++++++++++++++++++++++++++----- tests/errors.right | 2 +- tests/varenv.right | 20 ++++++++------------ tests/varenv18.sub | 3 +-- variables.h | 2 ++ 8 files changed, 79 insertions(+), 28 deletions(-) diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 262763b6e..da7f24c60 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -7579,7 +7579,7 @@ subst.c 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 , - https://savannah.gnu.org/support/index.php?109669 + https://savannah.gnu.org/support/index.php?109669 3/18 ---- @@ -8185,3 +8185,29 @@ jobs.c 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 + + 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 + +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 diff --git a/builtins/declare.def b/builtins/declare.def index 7af62c39b..4b26cb1fc 100644 --- a/builtins/declare.def +++ b/builtins/declare.def @@ -1,7 +1,7 @@ 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. @@ -22,7 +22,7 @@ $PRODUCES declare.c $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, @@ -64,7 +64,7 @@ $END $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'. diff --git a/parse.y b/parse.y index c5d9b93cd..873bd596d 100644 --- a/parse.y +++ b/parse.y @@ -926,12 +926,12 @@ case_command: CASE WORD newline_list IN newline_list ESAC 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 diff --git a/subst.c b/subst.c index 1d91dd5d0..e5e05df22 100644 --- a/subst.c +++ b/subst.c @@ -11472,8 +11472,10 @@ brace_expand_word_list (tlist, eflags) #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; @@ -11533,8 +11535,9 @@ shell_expand_word_list (tlist, eflags) { 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++] = '-'; @@ -11547,7 +11550,10 @@ shell_expand_word_list (tlist, eflags) 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)) { @@ -11557,7 +11563,7 @@ shell_expand_word_list (tlist, eflags) 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'; @@ -11585,6 +11591,8 @@ shell_expand_word_list (tlist, eflags) for (oind = 1; l->word->word[oind]; oind++) switch (l->word->word[oind]) { + case 'I': + inheriting = 1; case 'i': case 'l': case 'u': @@ -11603,6 +11611,26 @@ shell_expand_word_list (tlist, eflags) 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) diff --git a/tests/errors.right b/tests/errors.right index 12eb047ce..25f036e69 100644 --- a/tests/errors.right +++ b/tests/errors.right @@ -14,7 +14,7 @@ unset: usage: unset [-f] [-v] [-n] [name ...] ./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 diff --git a/tests/varenv.right b/tests/varenv.right index b16b4033f..34a130f8f 100644 --- a/tests/varenv.right +++ b/tests/varenv.right @@ -131,6 +131,7 @@ func: null or unset 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" ) @@ -172,16 +173,11 @@ declare -A var=([0]="X" ) 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") @@ -250,9 +246,9 @@ declare -- var 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 diff --git a/tests/varenv18.sub b/tests/varenv18.sub index 4500c39e7..e587a7c75 100644 --- a/tests/varenv18.sub +++ b/tests/varenv18.sub @@ -12,8 +12,7 @@ # along with this program. If not, see . # -# 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 diff --git a/variables.h b/variables.h index 3865d21a0..c73eb4e52 100644 --- a/variables.h +++ b/variables.h @@ -253,6 +253,8 @@ extern WORD_LIST *rest_of_args; 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)); -- 2.47.2