diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 8e8ea670..eb7c8d6f 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -4094,3 +4094,18 @@ subst.c - word_list_split: if a word expands to nothing after expansion and splitting, but we saw a quoted null during the expansion (W_SAWQUOTEDNULL), return an empty word + + 7/25 + ---- + +subst.c + - do_compound_assignment: if creating a local variable, make sure to + set `newname' to the name of the variable returned from find_variable, + since that follows namerefs. Fixes issue raised by Grisha Levit + + + 7/29 + ---- +subst.c + - get_var_and_type: if VALUE is NULL, check before calling dequote_string. + Report and fix from Grisha Levit diff --git a/execute_cmd.c b/execute_cmd.c index 7834c15d..58d32c03 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -4068,9 +4068,13 @@ fix_assignment_words (words) /* If we have an assignment builtin that does not create local variables, make sure we create global variables even if we internally call `declare'. The CHKLOCAL flag means to set attributes or values on - an existing local variable */ + an existing local variable, if there is one. */ if (b && ((b->flags & (ASSIGNMENT_BUILTIN|LOCALVAR_BUILTIN)) == ASSIGNMENT_BUILTIN)) w->word->flags |= W_ASSNGLOBAL|W_CHKLOCAL; +#if 0 + else if (b && (b->flags & ASSIGNMENT_BUILTIN) && (b->flags & LOCALVAR_BUILTIN)) + w->word->flags |= W_CHKLOCAL; +#endif } #if defined (ARRAY_VARS) /* Note that we saw an associative array option to a builtin that takes diff --git a/subst.c b/subst.c index dbb38fae..59ba900d 100644 --- a/subst.c +++ b/subst.c @@ -3071,8 +3071,8 @@ do_compound_assignment (name, value, flags) if (mklocal && variable_context) { - v = find_variable (name); - newname = (v == 0) ? nameref_transform_name (name, flags) : name; + v = find_variable (name); /* follows namerefs */ + newname = (v == 0) ? nameref_transform_name (name, flags) : v->name; if (v && ((readonly_p (v) && (flags & ASS_FORCE) == 0) || noassign_p (v))) { if (readonly_p (v)) @@ -7320,9 +7320,9 @@ get_var_and_type (varname, value, ind, quoted, flags, varp, valp) vtype = VT_VARIABLE; *varp = v; if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) - *valp = dequote_string (value); + *valp = value ? dequote_string (value) : savestring (""); else - *valp = dequote_escapes (value); + *valp = value ? dequote_escapes (value) : (char *)NULL; } else { diff --git a/tests/RUN-ONE-TEST b/tests/RUN-ONE-TEST index 554f3d6e..58c375b7 100755 --- a/tests/RUN-ONE-TEST +++ b/tests/RUN-ONE-TEST @@ -1,4 +1,4 @@ -BUILD_DIR=/usr/local/build/bash/bash-current +BUILD_DIR=/usr/local/build/chet/bash/bash-current THIS_SH=$BUILD_DIR/bash PATH=$PATH:$BUILD_DIR diff --git a/tests/intl.right b/tests/intl.right index 006318e5..7da99192 100644 --- a/tests/intl.right +++ b/tests/intl.right @@ -50,7 +50,8 @@ Passed all 1378 Unicode tests 0000003 0000000 101 040 302 243 040 305 222 012 0000010 -./unicode3.sub: line 3: $'5\247@3\231+\306S8\237\242\352\263': command not found -./unicode3.sub: line 5: cd: $'5\247@3\231+\306S8\237\242\352\263': No such file or directory +./unicode3.sub: line 5: $'5\247@3\231+\306S8\237\242\352\263': command not found +./unicode3.sub: line 7: cd: $'5\247@3\231+\306S8\237\242\352\263': No such file or directory $'5\247@3\231+\306S8\237\242\352\263' + : $'5\247@3\231+\306S8\237\242\352\263' ++ set +x diff --git a/tests/nameref.right b/tests/nameref.right index 02bd2c27..233a31cf 100644 --- a/tests/nameref.right +++ b/tests/nameref.right @@ -461,3 +461,5 @@ declare -- var="X" outside: ./nameref20.sub: line 45: declare: ref: not found ./nameref20.sub: line 45: declare: var: not found +declare -n ref="var" +declare -a var=([0]="Y") diff --git a/tests/nameref20.sub b/tests/nameref20.sub index c440db5e..7416233d 100644 --- a/tests/nameref20.sub +++ b/tests/nameref20.sub @@ -45,3 +45,12 @@ echo outside: declare -p ref var unset -f f + +unset -n ref; unset var + +f() +{ + declare var=X; declare -n ref=var; declare ref=(Y) + declare -p ref var +} +f diff --git a/tests/unicode3.sub b/tests/unicode3.sub index b39f1d3c..cb1b8732 100644 --- a/tests/unicode3.sub +++ b/tests/unicode3.sub @@ -1,4 +1,6 @@ export LANG=en_US.UTF-8 # make sure + +cd $TMPDIR # try to avoid NFS artifacts payload=$'\065\247\100\063\231\053\306\123\070\237\242\352\263' "$payload" @@ -6,4 +8,5 @@ cd "$payload" printf %q "$payload" echo -set -x ; : "$payload" +set -x ; : "$payload" ; set +x +cd $OLDPWD diff --git a/variables.c b/variables.c index 21d3735f..cf6822d9 100644 --- a/variables.c +++ b/variables.c @@ -251,6 +251,8 @@ static void initialize_dynamic_variables __P((void)); static SHELL_VAR *bind_invalid_envvar __P((const char *, char *, int)); +static int var_sametype __P((SHELL_VAR *, SHELL_VAR *)); + static SHELL_VAR *hash_lookup __P((const char *, HASH_TABLE *)); static SHELL_VAR *new_shell_variable __P((const char *)); static SHELL_VAR *make_new_variable __P((const char *, HASH_TABLE *)); @@ -2501,6 +2503,42 @@ sh_get_env_value (v) /* */ /* **************************************************************** */ +static int +var_sametype (v1, v2) + SHELL_VAR *v1; + SHELL_VAR *v2; +{ + if (v1 == 0 || v2 == 0) + return 0; +#if defined (ARRAY_VARS) + else if (assoc_p (v1) && assoc_p (v2)) + return 1; + else if (array_p (v1) && array_p (v2)) + return 1; + else if (array_p (v1) || array_p (v2)) + return 0; + else if (assoc_p (v1) || assoc_p (v2)) + return 0; +#endif + else + return 1; +} + +int +validate_inherited_value (var, type) + SHELL_VAR *var; + int type; +{ +#if defined (ARRAY_VARS) + if (type == att_array && assoc_p (var)) + return 0; + else if (type == att_assoc && array_p (var)) + return 0; + else +#endif + return 1; /* should we run convert_var_to_array here or let the caller? */ +} + /* Set NAME to VALUE if NAME has no value. */ SHELL_VAR * set_if_not (name, value) @@ -2741,6 +2779,9 @@ make_local_array_variable (name, assoc_ok) if (var == 0 || array_p (var) || (assoc_ok && assoc_p (var))) return var; + /* Validate any value we inherited from a variable instance at a previous + scope and disard anything that's invalid. */ + array = array_create (); dispose_variable_value (var); @@ -2779,6 +2820,9 @@ make_local_assoc_variable (name, array_ok) if (var == 0 || assoc_p (var) || (array_ok && array_p (var))) return var; + /* Validate any value we inherited from a variable instance at a previous + scope and disard anything that's invalid. */ + dispose_variable_value (var); hash = assoc_create (0); @@ -5042,7 +5086,7 @@ push_func_var (data) functions no longer behave like assignment statements preceding special builtins, and do not persist in the current shell environment. This is austin group interp #654, though nobody implements it yet. */ - posix_var_behavior = posixly_correct && (shell_compatibility_level < 50 || vc_isfuncenv (shell_variables) == 0); + posix_var_behavior = posixly_correct; if (local_p (var) && STREQ (var->name, "-")) set_current_options (value_cell (var)); diff --git a/variables.h b/variables.h index 613e94f9..2f6e3546 100644 --- a/variables.h +++ b/variables.h @@ -251,6 +251,9 @@ extern WORD_LIST *rest_of_args; extern pid_t dollar_dollar_pid; extern void initialize_shell_variables __P((char **, int)); + +extern int validate_inherited_value __P((SHELL_VAR *, int)); + extern SHELL_VAR *set_if_not __P((char *, char *)); extern void sh_set_lines_and_columns __P((int, int));