mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-27 15:43:18 +02:00
commit bash-20160506 snapshot
This commit is contained in:
+143
@@ -10798,3 +10798,146 @@ variables.c
|
||||
variable, throw an error if valid_nameref_value fails (with a second
|
||||
argument of 1). More fixes for bug reported by Grisha Levit
|
||||
<grishalevit@gmail.com>
|
||||
|
||||
5/2
|
||||
---
|
||||
builtins/declare.def
|
||||
- declare_internal: don't allow nameref attribute to be applied to an
|
||||
existing readonly variable; it can be used to circumvent readonly
|
||||
value. Fix for bug reported by Grisha Levit <grishalevit@gmail.com>
|
||||
|
||||
variables.[ch]
|
||||
- find_variable_last_nameref, find_global_variable_last_nameref: takes a
|
||||
new flags argument. If flags is non-zero, and we find a nameref
|
||||
variable that is unset (has no value), return that variable instead
|
||||
of NULL.
|
||||
|
||||
{variables,execute_cmd,arrayfunc,subst}.c,builtins/{declare,set}.def
|
||||
- find_variable_last_nameref, find_global_variable_last_nameref: change
|
||||
callers to add flags argument (initially 0)
|
||||
|
||||
5/3
|
||||
---
|
||||
variables.c
|
||||
- bind_variable_internal: make sure we run the value of a namref variable
|
||||
through valid_nameref_value before doing the assignment. This can go
|
||||
away if we stop allowing namerefs to refer to positional parameters
|
||||
|
||||
execute_cmd.c
|
||||
- execute_select_command: if bind_variable returns NULL, handle it as an
|
||||
error, as if attempting assignment to a readonly variable
|
||||
- execute_for_command: use 1 as second argument to
|
||||
find_variable_last_nameref, so it will return an invisible nameref
|
||||
to assign for each variable in the list
|
||||
- execute_for_command: if the current word in the list is an invalid
|
||||
identifier and the loop variable is a nameref, handle it as an error,
|
||||
as if attempting assignment to a readonly variable
|
||||
|
||||
5/4
|
||||
---
|
||||
variables.c
|
||||
- bind_int_variable: add warning if assigning an int to a nameref
|
||||
variable
|
||||
- assign_in_env: if assigning a variable in the temporary environment
|
||||
that is a namref, throw an error if trying to assign an invalid
|
||||
value
|
||||
- bind_variable_value: use valid_nameref_value instead of calls to
|
||||
legal_identifier and valid_array_reference
|
||||
|
||||
execute_cmd.c
|
||||
- coproc_setvars: if we have a nameref variable as the coproc name, but
|
||||
it can't be assigned to for some reason, remove the nameref attribute
|
||||
and issue a warning that we are doing so
|
||||
- coproc_setvars: don't allow assignment to a nameref variable with an
|
||||
invalid variable name, using same code as find_or_make_array_variable
|
||||
|
||||
general.c
|
||||
- valid_nameref_value: disallow values consisting solely of digits,
|
||||
like the positional parameters
|
||||
|
||||
builtins/declare.def
|
||||
- declare_internal: don't call valid_nameref_value on the existing value
|
||||
of a variable that's being converted to a nameref -- that value is
|
||||
going to be thrown away and we've already checked the new value
|
||||
- declare_internal: call bind_variable_value with the ASS_NAMEREF flag
|
||||
if we're assigning to an existing nameref variable (for instance,
|
||||
`declare -n x ; declare x=42')
|
||||
|
||||
5/5
|
||||
---
|
||||
variables.c
|
||||
- make_local_variable: if we are being asked to create a local copy of
|
||||
a nameref variable from a prior scope (checked by looking up
|
||||
using find_variable_noref), use the nameref variable, not the variable
|
||||
it references (which we find using find_variable). Bug report from
|
||||
Grisha Levit <grishalevit@gmail.com> ; fix by Piotr Grzybowski
|
||||
<narsil.pl@gmail.com>
|
||||
|
||||
builtins/declare.def
|
||||
- declare_internal: if asked to do the same thing as above (difference
|
||||
is declare -n r=foo in previous case; declare -n r in this one),
|
||||
don't follow reference var from a previous context. Create a new
|
||||
local variable (using make_local_variable) and inherit attributes
|
||||
from previous scope's nameref as above
|
||||
|
||||
5/6
|
||||
---
|
||||
builtins/declare.def
|
||||
- declare_internal: if we are assigning a value to an existing
|
||||
invisible nameref variable, validate value early so we don't end up
|
||||
removing the variable after the assignment fails
|
||||
|
||||
builtins/shopt.def
|
||||
- toggle_shopts: don't call set_bashopts here unless $BASHOPTS exists,
|
||||
since we don't want to set it up before it gets read from the
|
||||
environment. Keeping BASHOPTS read-only should keep users from
|
||||
unsetting it. Fix from Grisha Levit <grishalevit@gmail.com>
|
||||
- shopt_set_debug_mode: make sure error_trace_mode reflects the setting
|
||||
of extdebug. This one is tentative. Fix from Grisha Levit
|
||||
<grishalevit@gmail.com>
|
||||
- shopt_set_debug_mode: call set_shellopts after setting error_trace_mode
|
||||
or function_trace_mode. Fix from Grisha Levit <grishalevit@gmail.com>
|
||||
|
||||
shell.c
|
||||
- start_debugger: make sure that function_trace_mode and error_trace_mode
|
||||
reflect the value of debugging_mode, so they are both disabled if we
|
||||
disable debugging mode because we can't find the debugger start file.
|
||||
Fix from Grisha Levit <grishalevit@gmail.com>
|
||||
- start_debugger: set $SHELLOPTS and $BASHOPTS to the option values are
|
||||
reflected if we change or set them here. Fix from Grisha Levit
|
||||
<grishalevit@gmail.com>
|
||||
|
||||
builtins/set.def
|
||||
- reset_shell_options: add reset values for: posix, nolog, pipefail.
|
||||
Fix from Grisha Levit <grishalevit@gmail.com>
|
||||
|
||||
builtins/shopt.def
|
||||
- reset_shopt_options: add reset values for: autocd, checkjobs,
|
||||
complete_fullquote, dirspell, failglob, globstar, gnu_errfmt,
|
||||
huponexit, inherit_errexit, interactive_comments, lastpipe,
|
||||
no_empty_cmd_completion, progcomp. Fix from Grisha Levit
|
||||
<grishalevit@gmail.com>
|
||||
- reset_shopt_options: make sure the following options have the right
|
||||
defaults based on #defines: checkjobs, checkwinsize, direxpand,
|
||||
extglob, globasciiranges. Fix from Grisha Levit
|
||||
<grishalevit@gmail.com>
|
||||
|
||||
flags.c
|
||||
- reset_shell_flags: add missing flags, re-initialize history_expansion
|
||||
based on STRICT_POSIX
|
||||
|
||||
5/8
|
||||
---
|
||||
lib/readline/histexpand.c
|
||||
- history_expand: if any expansion returns 1 from history_expand_internal,
|
||||
indicating that :p was supplied, make it apply to the entire line
|
||||
like tcsh and csh. Fixes bug reported by Dean Stanton
|
||||
<dstanton@tintri.com>
|
||||
|
||||
variables.[ch]
|
||||
- ifsname: move define to variables.h
|
||||
|
||||
execute_cmd.c
|
||||
- execute_for_command: check whether or not the word in the for command
|
||||
is IFS; call setifs every time the variable is assigned a value.
|
||||
Fixes bug report from Grisha Levit <grishalevit@gmail.com>
|
||||
|
||||
@@ -1080,6 +1080,9 @@ tests/nameref7.sub f
|
||||
tests/nameref8.sub f
|
||||
tests/nameref9.sub f
|
||||
tests/nameref10.sub f
|
||||
tests/nameref11.sub f
|
||||
tests/nameref12.sub f
|
||||
tests/nameref13.sub f
|
||||
tests/nameref.right f
|
||||
tests/new-exp.tests f
|
||||
tests/new-exp1.sub f
|
||||
|
||||
+14
-2
@@ -347,9 +347,21 @@ find_or_make_array_variable (name, flags)
|
||||
{
|
||||
/* See if we have a nameref pointing to a variable that hasn't been
|
||||
created yet. */
|
||||
var = find_variable_last_nameref (name);
|
||||
var = find_variable_last_nameref (name, 1);
|
||||
if (var && nameref_p (var) && invisible_p (var))
|
||||
{
|
||||
internal_warning (_("%s: removing nameref attribute"), name);
|
||||
VUNSETATTR (var, att_nameref);
|
||||
}
|
||||
if (var && nameref_p (var))
|
||||
var = (flags & 2) ? make_new_assoc_variable (nameref_cell (var)) : make_new_array_variable (nameref_cell (var));
|
||||
{
|
||||
if (valid_nameref_value (nameref_cell (var), 1) == 0)
|
||||
{
|
||||
sh_invalidid (nameref_cell (var));
|
||||
return ((SHELL_VAR *)NULL);
|
||||
}
|
||||
var = (flags & 2) ? make_new_assoc_variable (nameref_cell (var)) : make_new_array_variable (nameref_cell (var));
|
||||
}
|
||||
}
|
||||
|
||||
if (var == 0)
|
||||
|
||||
+39
-9
@@ -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-2015 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987-2016 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -404,8 +404,24 @@ declare_internal (list, local_var)
|
||||
#endif
|
||||
if (offset == 0 && (flags_on & att_nameref))
|
||||
{
|
||||
refvar = mkglobal ? find_global_variable_last_nameref (name) : find_variable_last_nameref (name);
|
||||
var = 0;
|
||||
/* First look for refvar at current scope */
|
||||
refvar = find_variable_last_nameref (name, 1);
|
||||
var = find_variable (name);
|
||||
/* VARIABLE_CONTEXT != 0, so we are attempting to create or modify
|
||||
the attributes for a local variable at the same scope. If we've
|
||||
used a reference from a previous context to resolve VAR, we
|
||||
want to throw REFVAR and VAR away and create a new local var. */
|
||||
if (refvar && refvar->context != variable_context)
|
||||
{
|
||||
refvar = 0;
|
||||
var = make_local_variable (name);
|
||||
}
|
||||
else if (refvar && refvar->context == variable_context)
|
||||
var = refvar;
|
||||
/* Maybe we just want to create a new local variable */
|
||||
else if (var == 0 || var->context != variable_context)
|
||||
var = make_local_variable (name);
|
||||
/* otherwise we have a var at the right context */
|
||||
}
|
||||
else
|
||||
var = make_local_variable (name); /* sets att_invisible for new vars */
|
||||
@@ -488,7 +504,7 @@ declare_internal (list, local_var)
|
||||
if (var == 0 && (flags_on & att_nameref))
|
||||
{
|
||||
/* See if we are trying to modify an existing nameref variable */
|
||||
var = mkglobal ? find_global_variable_last_nameref (name) : find_variable_last_nameref (name);
|
||||
var = mkglobal ? find_global_variable_last_nameref (name, 1) : find_variable_last_nameref (name, 1);
|
||||
if (var && nameref_p (var) == 0)
|
||||
var = 0;
|
||||
}
|
||||
@@ -500,7 +516,7 @@ declare_internal (list, local_var)
|
||||
else if (var == 0 && (flags_off & att_nameref))
|
||||
{
|
||||
/* See if we are trying to modify an existing nameref variable */
|
||||
refvar = mkglobal ? find_global_variable_last_nameref (name) : find_variable_last_nameref (name);
|
||||
refvar = mkglobal ? find_global_variable_last_nameref (name, 0) : find_variable_last_nameref (name, 0);
|
||||
if (refvar && nameref_p (refvar) == 0)
|
||||
refvar = 0;
|
||||
if (refvar)
|
||||
@@ -516,7 +532,7 @@ declare_internal (list, local_var)
|
||||
declare -p foo */
|
||||
if (var == 0 && (flags_on || flags_off || offset))
|
||||
{
|
||||
refvar = mkglobal ? find_global_variable_last_nameref (name) : find_variable_last_nameref (name);
|
||||
refvar = mkglobal ? find_global_variable_last_nameref (name, 0) : find_variable_last_nameref (name, 0);
|
||||
if (refvar && nameref_p (refvar) == 0)
|
||||
refvar = 0;
|
||||
if (refvar)
|
||||
@@ -574,16 +590,30 @@ declare_internal (list, local_var)
|
||||
assign_error++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
else if (nameref_p (var) && (flags_on & att_nameref) == 0 && (flags_off & att_nameref) == 0 && offset && valid_nameref_value (value, 1) == 0)
|
||||
{
|
||||
builtin_error (_("%s: invalid variable name for name reference"), value);
|
||||
any_failed++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
else if (flags_on & att_nameref)
|
||||
{
|
||||
#if 1
|
||||
if (nameref_p (var) == 0 && var_isset (var) && var_isnull (var) == 0 && valid_nameref_value (value_cell (var), 0) == 0)
|
||||
/* Check of offset is to allow an assignment to a nameref var as
|
||||
part of the declare word to override existing value */
|
||||
if (nameref_p (var) == 0 && var_isset (var) && var_isnull (var) == 0 && offset == 0 && valid_nameref_value (value_cell (var), 0) == 0)
|
||||
{
|
||||
builtin_error (_("%s: invalid variable name for name reference"), value_cell (var));
|
||||
any_failed++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
#endif
|
||||
if (readonly_p (var))
|
||||
{
|
||||
sh_readonly (name);
|
||||
any_failed++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
/* ksh93 compat: turning on nameref attribute turns off -ilu */
|
||||
VUNSETATTR (var, att_integer|att_uppercase|att_lowercase|att_capcase);
|
||||
}
|
||||
@@ -722,10 +752,10 @@ declare_internal (list, local_var)
|
||||
bind_variable() */
|
||||
if (offset)
|
||||
{
|
||||
if (onref)
|
||||
if (onref || nameref_p (var))
|
||||
aflags |= ASS_NAMEREF;
|
||||
v = bind_variable_value (var, value, aflags);
|
||||
if (v == 0 && onref)
|
||||
if (v == 0 && (onref || nameref_p (var)))
|
||||
{
|
||||
sh_invalidid (value);
|
||||
assign_error++;
|
||||
|
||||
@@ -2,7 +2,7 @@ This file is mapfile.def, from which is created mapfile.c.
|
||||
It implements the builtin "mapfile" in Bash.
|
||||
|
||||
Copyright (C) 2005-2006 Rocky Bernstein for Free Software Foundation, Inc.
|
||||
Copyright (C) 2008-2015 Free Software Foundation, Inc.
|
||||
Copyright (C) 2008-2016 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
|
||||
+14
-4
@@ -183,7 +183,9 @@ static int previous_option_value;
|
||||
|
||||
/* A struct used to match long options for set -o to the corresponding
|
||||
option letter or internal variable. The functions can be called to
|
||||
dynamically generate values. */
|
||||
dynamically generate values. If you add a new variable name here
|
||||
that doesn't have a corresponding single-character option letter, make
|
||||
sure to set the value appropriately in reset_shell_options. */
|
||||
const struct {
|
||||
char *name;
|
||||
int letter;
|
||||
@@ -623,10 +625,18 @@ initialize_shell_options (no_shellopts)
|
||||
void
|
||||
reset_shell_options ()
|
||||
{
|
||||
pipefail_opt = 0;
|
||||
ignoreeof = 0;
|
||||
|
||||
#if defined (STRICT_POSIX)
|
||||
posixly_correct = 1;
|
||||
#else
|
||||
posixly_correct = 0;
|
||||
#endif
|
||||
#if defined (HISTORY)
|
||||
dont_save_function_defs = 0;
|
||||
remember_on_history = enable_history_list = 1;
|
||||
#endif
|
||||
ignoreeof = 0;
|
||||
}
|
||||
|
||||
/* Set some flags from the word values in the input list. If LIST is empty,
|
||||
@@ -870,7 +880,7 @@ unset_builtin (list)
|
||||
|
||||
/* Only search for functions here if -f supplied. */
|
||||
var = unset_function ? find_function (name)
|
||||
: (nameref ? find_variable_last_nameref (name) : find_variable (name));
|
||||
: (nameref ? find_variable_last_nameref (name, 0) : find_variable (name));
|
||||
|
||||
/* Some variables (but not functions yet) cannot be unset, period. */
|
||||
if (var && unset_function == 0 && non_unsettable_p (var))
|
||||
@@ -921,7 +931,7 @@ unset_builtin (list)
|
||||
variable, make sure we still try to unset the nameref's value */
|
||||
if (var == 0 && nameref == 0 && unset_function == 0)
|
||||
{
|
||||
var = find_variable_last_nameref (name);
|
||||
var = find_variable_last_nameref (name, 0);
|
||||
tem = (var && nameref_p (var)) ? unbind_variable (nameref_cell (var)) : unbind_variable (name);
|
||||
}
|
||||
else
|
||||
|
||||
+53
-11
@@ -1,7 +1,7 @@
|
||||
This file is shopt.def, from which is created shopt.c.
|
||||
It implements the Bash `shopt' builtin.
|
||||
|
||||
Copyright (C) 1994-2015 Free Software Foundation, Inc.
|
||||
Copyright (C) 1994-2016 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -144,6 +144,9 @@ static int shopt_compat43;
|
||||
|
||||
typedef int shopt_set_func_t __P((char *, int));
|
||||
|
||||
/* If you add a new variable name here, make sure to set the default value
|
||||
appropriately in reset_shopt_options. */
|
||||
|
||||
static struct {
|
||||
char *name;
|
||||
int *value;
|
||||
@@ -304,32 +307,67 @@ shopt_builtin (list)
|
||||
}
|
||||
|
||||
/* Reset the options managed by `shopt' to the values they would have at
|
||||
shell startup. */
|
||||
shell startup. Variables from shopt_vars. */
|
||||
void
|
||||
reset_shopt_options ()
|
||||
{
|
||||
autocd = cdable_vars = cdspelling = 0;
|
||||
check_hashed_filenames = CHECKHASH_DEFAULT;
|
||||
check_window_size = CHECKWINSIZE_DEFAULT;
|
||||
allow_null_glob_expansion = glob_dot_filenames = 0;
|
||||
cdable_vars = mail_warning = 0;
|
||||
no_exit_on_failed_exec = print_shift_error = 0;
|
||||
check_hashed_filenames = cdspelling = expand_aliases = 0;
|
||||
|
||||
no_exit_on_failed_exec = 0;
|
||||
expand_aliases = 0;
|
||||
extended_quote = 1;
|
||||
fail_glob_expansion = 0;
|
||||
glob_asciirange = GLOBASCII_DEFAULT;
|
||||
glob_star = 0;
|
||||
gnu_error_format = 0;
|
||||
hup_on_exit = 0;
|
||||
inherit_errexit = 0;
|
||||
interactive_comments = 1;
|
||||
lastpipe_opt = 0;
|
||||
mail_warning = 0;
|
||||
glob_ignore_case = match_ignore_case = 0;
|
||||
print_shift_error = 0;
|
||||
source_uses_path = promptvars = 1;
|
||||
|
||||
check_window_size = CHECKWINSIZE_DEFAULT;
|
||||
#if defined (JOB_CONTROL)
|
||||
check_jobs_at_exit = 0;
|
||||
#endif
|
||||
|
||||
#if defined (EXTENDED_GLOB)
|
||||
extended_glob = 0;
|
||||
extended_glob = EXTGLOB_DEFAULT;
|
||||
#endif
|
||||
|
||||
#if defined (HISTORY)
|
||||
literal_history = force_append_history = 0;
|
||||
literal_history = 0;
|
||||
force_append_history = 0;
|
||||
command_oriented_history = 1;
|
||||
#endif
|
||||
|
||||
#if defined (READLINE)
|
||||
complete_fullquote = 1;
|
||||
force_fignore = 1;
|
||||
hist_verify = history_reediting = 0;
|
||||
perform_hostname_completion = 1;
|
||||
# if DIRCOMPLETE_EXPAND_DEFAULT
|
||||
dircomplete_expand = 1;
|
||||
# else
|
||||
dircomplete_expand = 0;
|
||||
#endif
|
||||
dircomplete_spelling = 0;
|
||||
no_empty_command_completion = 0;
|
||||
#endif
|
||||
|
||||
#if defined (PROGRAMMABLE_COMPLETION)
|
||||
prog_completion_enabled = 1;
|
||||
#endif
|
||||
|
||||
#if defined (DEFAULT_ECHO_TO_XPG) || defined (STRICT_POSIX)
|
||||
xpg_echo = 1;
|
||||
#else
|
||||
xpg_echo = 0;
|
||||
#endif /* DEFAULT_ECHO_TO_XPG */
|
||||
|
||||
shopt_login_shell = login_shell;
|
||||
}
|
||||
@@ -361,6 +399,7 @@ toggle_shopts (mode, list, quiet)
|
||||
{
|
||||
WORD_LIST *l;
|
||||
int ind, rval;
|
||||
SHELL_VAR *v;
|
||||
|
||||
for (l = list, rval = EXECUTION_SUCCESS; l; l = l->next)
|
||||
{
|
||||
@@ -378,7 +417,9 @@ toggle_shopts (mode, list, quiet)
|
||||
}
|
||||
}
|
||||
|
||||
set_bashopts ();
|
||||
/* Don't set $BASHOPTS here if it hasn't already been initialized */
|
||||
if (v = find_variable ("BASHOPTS"))
|
||||
set_bashopts ();
|
||||
return (rval);
|
||||
}
|
||||
|
||||
@@ -529,7 +570,8 @@ shopt_set_debug_mode (option_name, mode)
|
||||
int mode;
|
||||
{
|
||||
#if defined (DEBUGGER)
|
||||
function_trace_mode = debugging_mode;
|
||||
error_trace_mode = function_trace_mode = debugging_mode;
|
||||
set_shellopts ();
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
+40
-11
@@ -2172,13 +2172,31 @@ coproc_setvars (cp)
|
||||
#if defined (ARRAY_VARS)
|
||||
v = find_variable (cp->c_name);
|
||||
|
||||
/* This is the same code as in find_or_make_array_variable */
|
||||
if (v == 0)
|
||||
{
|
||||
v = find_variable_last_nameref (cp->c_name, 1);
|
||||
if (v && nameref_p (v) && invisible_p (v))
|
||||
{
|
||||
internal_warning (_("coproc: %s: removing nameref attribute"), cp->c_name);
|
||||
VUNSETATTR (v, att_nameref);
|
||||
}
|
||||
if (v && nameref_p (v))
|
||||
{
|
||||
if (valid_nameref_value (cp->c_name, 1) == 0)
|
||||
{
|
||||
sh_invalidid (cp->c_name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (v && (readonly_p (v) || noassign_p (v)))
|
||||
{
|
||||
if (readonly_p (v))
|
||||
err_readonly (cp->c_name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (v == 0)
|
||||
v = make_new_array_variable (cp->c_name);
|
||||
if (array_p (v) == 0)
|
||||
@@ -2255,7 +2273,7 @@ execute_coproc (command, pipe_in, pipe_out, fds_to_close)
|
||||
/* XXX -- can be removed after changes to handle multiple coprocs */
|
||||
#if !MULTIPLE_COPROCS
|
||||
if (sh_coproc.c_pid != NO_PID)
|
||||
internal_warning ("execute_coproc: coproc [%d:%s] still exists", sh_coproc.c_pid, sh_coproc.c_name);
|
||||
internal_warning (_("execute_coproc: coproc [%d:%s] still exists"), sh_coproc.c_pid, sh_coproc.c_name);
|
||||
coproc_init (&sh_coproc);
|
||||
#endif
|
||||
|
||||
@@ -2750,17 +2768,24 @@ execute_for_command (for_command)
|
||||
|
||||
this_command_name = (char *)NULL;
|
||||
/* XXX - special ksh93 for command index variable handling */
|
||||
v = find_variable_last_nameref (identifier);
|
||||
v = find_variable_last_nameref (identifier, 1);
|
||||
if (v && nameref_p (v))
|
||||
{
|
||||
v = bind_variable_value (v, list->word->word, 0);
|
||||
}
|
||||
{
|
||||
if (valid_nameref_value (list->word->word, 1) == 0)
|
||||
{
|
||||
sh_invalidid (list->word->word);
|
||||
v = 0;
|
||||
}
|
||||
else
|
||||
v = bind_variable_value (v, list->word->word, 0);
|
||||
}
|
||||
else
|
||||
v = bind_variable (identifier, list->word->word, 0);
|
||||
if (readonly_p (v) || noassign_p (v))
|
||||
v = bind_variable (identifier, list->word->word, 0);
|
||||
|
||||
if (v == 0 || readonly_p (v) || noassign_p (v))
|
||||
{
|
||||
line_number = save_line_number;
|
||||
if (readonly_p (v) && interactive_shell == 0 && posixly_correct)
|
||||
if (v && readonly_p (v) && interactive_shell == 0 && posixly_correct)
|
||||
{
|
||||
last_command_exit_value = EXECUTION_FAILURE;
|
||||
jump_to_top_level (FORCE_EOF);
|
||||
@@ -2773,6 +2798,10 @@ execute_for_command (for_command)
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (ifsname (identifier))
|
||||
setifs (v);
|
||||
|
||||
retval = execute_command (for_command->action);
|
||||
REAP ();
|
||||
QUIT;
|
||||
@@ -3250,9 +3279,9 @@ execute_select_command (select_command)
|
||||
}
|
||||
|
||||
v = bind_variable (identifier, selection, 0);
|
||||
if (readonly_p (v) || noassign_p (v))
|
||||
if (v == 0 || readonly_p (v) || noassign_p (v))
|
||||
{
|
||||
if (readonly_p (v) && interactive_shell == 0 && posixly_correct)
|
||||
if (v && readonly_p (v) && interactive_shell == 0 && posixly_correct)
|
||||
{
|
||||
last_command_exit_value = EXECUTION_FAILURE;
|
||||
jump_to_top_level (FORCE_EOF);
|
||||
|
||||
@@ -356,11 +356,17 @@ set_current_flags (bitmap)
|
||||
void
|
||||
reset_shell_flags ()
|
||||
{
|
||||
mark_modified_vars = exit_immediately_on_error = disallow_filename_globbing = 0;
|
||||
mark_modified_vars = disallow_filename_globbing = 0;
|
||||
place_keywords_in_env = read_but_dont_execute = just_one_command = 0;
|
||||
noclobber = unbound_vars_is_error = echo_input_at_read = verbose_flag = 0;
|
||||
noclobber = unbound_vars_is_error = 0;
|
||||
echo_command_at_execute = jobs_m_flag = forced_interactive = 0;
|
||||
no_symbolic_links = no_invisible_vars = privileged_mode = pipefail_opt = 0;
|
||||
no_symbolic_links = no_invisible_vars = 0;
|
||||
privileged_mode = pipefail_opt = 0;
|
||||
|
||||
error_trace_mode = function_trace_mode = 0;
|
||||
|
||||
exit_immediately_on_error = errexit_flag = 0;
|
||||
echo_input_at_read = verbose_flag = 0;
|
||||
|
||||
hashing_enabled = interactive_comments = 1;
|
||||
|
||||
@@ -369,7 +375,11 @@ reset_shell_flags ()
|
||||
#endif
|
||||
|
||||
#if defined (BANG_HISTORY)
|
||||
# if defined (STRICT_POSIX)
|
||||
history_expansion = 0;
|
||||
# else
|
||||
history_expansion = 1;
|
||||
# endif /* STRICT_POSIX */
|
||||
#endif
|
||||
|
||||
#if defined (BRACE_EXPANSION)
|
||||
|
||||
@@ -227,6 +227,10 @@ legal_identifier (name)
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Return 1 if NAME is a valid value that can be assigned to a nameref
|
||||
variable. The FOR_ASSIGNMENT flag is currently unused, but it could
|
||||
be used to allow values to be stored and indirectly referenced, but
|
||||
not used in assignments. */
|
||||
int
|
||||
valid_nameref_value (name, for_assignment)
|
||||
char *name;
|
||||
@@ -240,8 +244,10 @@ valid_nameref_value (name, for_assignment)
|
||||
if (legal_identifier (name))
|
||||
#endif
|
||||
return 1;
|
||||
#if 0
|
||||
if (for_assignment == 0 && legal_number (name, &r))
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1220,7 +1220,7 @@ history_expand (hstring, output)
|
||||
ADD_STRING (temp);
|
||||
xfree (temp);
|
||||
}
|
||||
only_printing = r == 1;
|
||||
only_printing += r == 1;
|
||||
i = eindex;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2314,7 +2314,7 @@ shell_getc (remove_quoted_newline)
|
||||
if (n <= 2) /* we have to save 1 for the newline added below */
|
||||
{
|
||||
if (truncating == 0)
|
||||
internal_warning("shell_getc: shell_input_line_size (%zu) exceeds SIZE_MAX (%lu): line truncated", shell_input_line_size, (unsigned long)SIZE_MAX);
|
||||
internal_warning(_("shell_getc: shell_input_line_size (%zu) exceeds SIZE_MAX (%lu): line truncated"), shell_input_line_size, (unsigned long)SIZE_MAX);
|
||||
shell_input_line[i] = '\0';
|
||||
truncating = 1;
|
||||
}
|
||||
|
||||
+1
-1
@@ -1643,7 +1643,7 @@ programmable_completions (cmd, word, start, end, foundp)
|
||||
|
||||
if (count > 32)
|
||||
{
|
||||
internal_warning ("programmable_completion: %s: possible retry loop", cmd);
|
||||
internal_warning (_("programmable_completion: %s: possible retry loop"), cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1455,11 +1455,13 @@ start_debugger ()
|
||||
r = force_execute_file (DEBUGGER_START_FILE, 1);
|
||||
if (r < 0)
|
||||
{
|
||||
internal_warning ("cannot start debugger; debugging mode disabled");
|
||||
debugging_mode = function_trace_mode = 0;
|
||||
internal_warning (_("cannot start debugger; debugging mode disabled"));
|
||||
debugging_mode = 0;
|
||||
}
|
||||
else
|
||||
function_trace_mode = 1;
|
||||
error_trace_mode = function_trace_mode = debugging_mode;
|
||||
|
||||
set_shellopts ();
|
||||
set_bashopts ();
|
||||
|
||||
exit_immediately_on_error += old_errexit;
|
||||
#endif
|
||||
|
||||
@@ -5645,7 +5645,7 @@ process_substitute (string, open_for_read_in_child)
|
||||
#else /* HAVE_DEV_FD */
|
||||
if (pipe (fildes) < 0)
|
||||
{
|
||||
sys_error (_("cannot make pipe for process substitution"));
|
||||
sys_error ("%s", _("cannot make pipe for process substitution"));
|
||||
return ((char *)NULL);
|
||||
}
|
||||
/* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
|
||||
@@ -5661,7 +5661,7 @@ process_substitute (string, open_for_read_in_child)
|
||||
|
||||
if (pathname == 0)
|
||||
{
|
||||
sys_error (_("cannot make pipe for process substitution"));
|
||||
sys_error ("%s", _("cannot make pipe for process substitution"));
|
||||
return ((char *)NULL);
|
||||
}
|
||||
|
||||
@@ -5703,7 +5703,7 @@ process_substitute (string, open_for_read_in_child)
|
||||
|
||||
if (pid < 0)
|
||||
{
|
||||
sys_error (_("cannot make child for process substitution"));
|
||||
sys_error ("%s", _("cannot make child for process substitution"));
|
||||
free (pathname);
|
||||
#if defined (HAVE_DEV_FD)
|
||||
close (parent_pipe_fd);
|
||||
@@ -5864,7 +5864,7 @@ read_comsub (fd, quoted, rflag)
|
||||
if (c == 0)
|
||||
{
|
||||
#if 1
|
||||
internal_warning ("command substitution: ignored null byte in input");
|
||||
internal_warning ("%s", _("command substitution: ignored null byte in input"));
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
@@ -5988,7 +5988,7 @@ command_substitute (string, quoted)
|
||||
/* Pipe the output of executing STRING into the current shell. */
|
||||
if (pipe (fildes) < 0)
|
||||
{
|
||||
sys_error (_("cannot make pipe for command substitution"));
|
||||
sys_error ("%s", _("cannot make pipe for command substitution"));
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
@@ -6050,7 +6050,7 @@ command_substitute (string, quoted)
|
||||
|
||||
if (dup2 (fildes[1], 1) < 0)
|
||||
{
|
||||
sys_error (_("command_substitute: cannot duplicate pipe as fd 1"));
|
||||
sys_error ("%s", _("command_substitute: cannot duplicate pipe as fd 1"));
|
||||
exit (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
@@ -6463,7 +6463,7 @@ expand_arrayref:
|
||||
else
|
||||
temp = (char *)NULL;
|
||||
}
|
||||
else if (var = find_variable_last_nameref (name))
|
||||
else if (var = find_variable_last_nameref (name, 0))
|
||||
{
|
||||
temp = nameref_cell (var);
|
||||
#if defined (ARRAY_VARS)
|
||||
@@ -6506,7 +6506,7 @@ parameter_brace_find_indir (name, var_is_special, quoted, find_nameref)
|
||||
WORD_DESC *w;
|
||||
SHELL_VAR *v;
|
||||
|
||||
if (find_nameref && var_is_special == 0 && (v = find_variable_last_nameref (name)) &&
|
||||
if (find_nameref && var_is_special == 0 && (v = find_variable_last_nameref (name, 0)) &&
|
||||
nameref_p (v) && (t = nameref_cell (v)) && *t)
|
||||
return (savestring (t));
|
||||
|
||||
@@ -6546,7 +6546,7 @@ parameter_brace_expand_indir (name, var_is_special, quoted, quoted_dollar_atp, c
|
||||
bash performs an indirect lookup on foo[0] and expands the result;
|
||||
ksh93 expands bar[0]. We could do that here -- there are enough usable
|
||||
primitives to do that -- but do not at this point. */
|
||||
if (var_is_special == 0 && (v = find_variable_last_nameref (name)))
|
||||
if (var_is_special == 0 && (v = find_variable_last_nameref (name, 0)))
|
||||
{
|
||||
if (nameref_p (v) && (t = nameref_cell (v)) && *t)
|
||||
{
|
||||
@@ -8798,7 +8798,7 @@ comsub:
|
||||
}
|
||||
else if (var && (invisible_p (var) || var_isset (var) == 0))
|
||||
temp = (char *)NULL;
|
||||
else if ((var = find_variable_last_nameref (temp1)) && var_isset (var) && invisible_p (var) == 0)
|
||||
else if ((var = find_variable_last_nameref (temp1, 0)) && var_isset (var) && invisible_p (var) == 0)
|
||||
{
|
||||
temp = nameref_cell (var);
|
||||
#if defined (ARRAY_VARS)
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
|
||||
@@ -166,3 +166,68 @@ declare -i bar="8"
|
||||
8
|
||||
declare -n foo="bar"
|
||||
./nameref10.sub: line 64: typeset: bar: not found
|
||||
./nameref11.sub: line 1: declare: /: invalid variable name for name reference
|
||||
./nameref11.sub: line 2: declare: /: invalid variable name for name reference
|
||||
./nameref11.sub: line 3: `/': not a valid identifier
|
||||
./nameref11.sub: line 4: declare: `/': not a valid identifier
|
||||
./nameref11.sub: line 5: `/': not a valid identifier
|
||||
1) /
|
||||
#? ./nameref11.sub: line 6: `/': not a valid identifier
|
||||
x
|
||||
|
||||
./nameref11.sub: line 7: ((: `0': not a valid identifier
|
||||
./nameref11.sub: line 8: declare: 0: invalid variable name for name reference
|
||||
./nameref11.sub: line 9: declare: /: invalid variable name for name reference
|
||||
./nameref11.sub: line 10: declare: /: invalid variable name for name reference
|
||||
./nameref11.sub: line 11: `/': not a valid identifier
|
||||
|
||||
./nameref11.sub: line 12: `/': not a valid identifier
|
||||
./nameref11.sub: line 13: exec: `10': not a valid identifier
|
||||
./nameref11.sub: line 13: r: cannot assign fd to variable
|
||||
./nameref11.sub: line 14: warning: coproc: r: removing nameref attribute
|
||||
63
|
||||
./nameref11.sub: line 15: declare: RO: readonly variable
|
||||
./nameref11.sub: line 15: RO: readonly variable
|
||||
./nameref11.sub: line 16: declare: /: invalid variable name for name reference
|
||||
/
|
||||
./nameref11.sub: line 17: declare: /: invalid variable name for name reference
|
||||
./nameref11.sub: illegal option -- h
|
||||
./nameref11.sub: line 18: getopts: `?': not a valid identifier
|
||||
./nameref11.sub: line 19: warning: r: removing nameref attribute
|
||||
declare -a r=()
|
||||
./nameref11.sub: line 20: declare: r: reference variable cannot be an array
|
||||
./nameref11.sub: line 21: printf: `/': not a valid identifier
|
||||
./nameref12.sub: line 6: declare: /: invalid variable name for name reference
|
||||
./nameref12.sub: line 9: declare: %: invalid variable name for name reference
|
||||
./nameref12.sub: line 13: `^': not a valid identifier
|
||||
declare -n r
|
||||
declare -a foo
|
||||
declare -a foo=([0]="7")
|
||||
./nameref12.sub: line 26: declare: `42': not a valid identifier
|
||||
./nameref12.sub: line 27: declare: x: not found
|
||||
declare -nr RO="foo"
|
||||
./nameref12.sub: line 37: `/': not a valid identifier
|
||||
0 0
|
||||
./nameref12.sub: line 38: `/': not a valid identifier
|
||||
|
||||
./nameref12.sub: line 43: declare: `7*6': not a valid identifier
|
||||
./nameref12.sub: line 43: declare: foo: not found
|
||||
./nameref12.sub: line 45: `7*6': not a valid identifier
|
||||
declare -n ref="var"
|
||||
declare -n ref="var"
|
||||
declare -- a
|
||||
declare -n r="a"
|
||||
declare -- a
|
||||
declare -n r="a"
|
||||
0
|
||||
declare -n r="P"
|
||||
declare -n ref="var"
|
||||
declare -- a
|
||||
declare -n r="a"
|
||||
0
|
||||
declare -n r
|
||||
declare -n r
|
||||
./nameref13.sub: line 88: typeset: 12345: invalid variable name for name reference
|
||||
declare -n foo
|
||||
./nameref13.sub: line 97: typeset: 12345: invalid variable name for name reference
|
||||
declare -n foo
|
||||
|
||||
@@ -125,3 +125,6 @@ ${THIS_SH} ./nameref7.sub
|
||||
${THIS_SH} ./nameref8.sub
|
||||
${THIS_SH} ./nameref9.sub
|
||||
${THIS_SH} ./nameref10.sub
|
||||
${THIS_SH} ./nameref11.sub
|
||||
${THIS_SH} ./nameref12.sub
|
||||
${THIS_SH} ./nameref13.sub
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
r=/; declare -n r ; unset r
|
||||
declare -n r=/ ; unset -n r
|
||||
declare -n r; r=/ ; unset -n r
|
||||
declare -n r; declare r=/ ; unset -n r
|
||||
declare -n r; for r in /; do :; done ; unset -n r
|
||||
declare -n r; select r in /; do :; done <<< 1; echo x; echo $r ; unset -n r
|
||||
declare -n r; ((r=0)) ; unset -n r
|
||||
((r=0)); declare -n r ; unset -n r
|
||||
r=/ declare -n r ; unset -n r
|
||||
f() { declare -n r; }; r=/ f ; unset r
|
||||
f() { echo $r; }; declare -n r; r=/ f ; unset -n r
|
||||
declare -n r; : ${r:=/} ; unset -n r
|
||||
declare -n r; exec {r}>/dev/null ; unset -n r
|
||||
declare -n r; coproc r { :; }; echo $r ; unset r
|
||||
declare -r RO=x; r=$RO; declare -n r; x=y; declare -n RO; RO=z; declare -p RO; echo "$RO"
|
||||
s=/; declare -n r=s; declare -n s; echo $r ; unset -n r ; unset -n s
|
||||
declare -n r=s; declare -n s; s=/ ; unset -n r; unset -n s
|
||||
declare -n r; getopts x r -h ; unset r; unset -n r
|
||||
declare -n r; mapfile r < /dev/null ; declare -p r; unset r ; unset -n r
|
||||
mapfile r < /dev/null; declare -n r ; unset r ; unset -n r
|
||||
declare -n r; printf -v r /
|
||||
@@ -0,0 +1,65 @@
|
||||
declare -n r
|
||||
declare -n r
|
||||
unset -n r
|
||||
|
||||
r=foo
|
||||
declare -n r=/
|
||||
|
||||
r=%
|
||||
declare -n r
|
||||
unset r
|
||||
|
||||
declare -n r
|
||||
r=^
|
||||
declare -p r
|
||||
|
||||
unset -n r
|
||||
|
||||
declare -n foo
|
||||
declare -a foo
|
||||
declare -p foo
|
||||
foo[0]=7
|
||||
declare -p foo
|
||||
unset foo
|
||||
|
||||
declare -n x
|
||||
declare x=42
|
||||
declare -p x
|
||||
|
||||
declare -n -r RO=foo
|
||||
declare -p RO
|
||||
|
||||
unset -n r; unset r
|
||||
|
||||
f() { echo $r; }
|
||||
|
||||
declare -n r
|
||||
r=/ /usr/bin/sum < /dev/null
|
||||
r=/ f
|
||||
|
||||
unset -f f
|
||||
|
||||
# the details of this may change; this will tell me when they do
|
||||
declare -n foo ; declare -i foo=7*6 ; declare -p foo
|
||||
unset -n foo
|
||||
declare -n foo ; declare -i foo ; foo=7*6 ; declare -p foo
|
||||
|
||||
# used to be buggy
|
||||
f()
|
||||
{
|
||||
unset var
|
||||
declare -n ref=var
|
||||
declare -n ref
|
||||
declare -p ref
|
||||
}
|
||||
f
|
||||
|
||||
unset -f f
|
||||
f()
|
||||
{
|
||||
local var
|
||||
declare -n ref=var
|
||||
declare -n ref
|
||||
declare -p ref
|
||||
}
|
||||
f
|
||||
@@ -0,0 +1,102 @@
|
||||
declare -nt r=a
|
||||
|
||||
f()
|
||||
{
|
||||
declare a
|
||||
declare -n r=a
|
||||
declare -p a r
|
||||
}
|
||||
|
||||
f
|
||||
unset -f f
|
||||
|
||||
f()
|
||||
{
|
||||
declare a
|
||||
declare -n r
|
||||
r=a
|
||||
declare -p a r
|
||||
}
|
||||
f
|
||||
echo $?
|
||||
|
||||
unset -f f
|
||||
|
||||
P=12345
|
||||
function foo
|
||||
{
|
||||
typeset -n r
|
||||
typeset -n r=P
|
||||
typeset -p r
|
||||
}
|
||||
|
||||
foo
|
||||
unset P foo
|
||||
|
||||
ref=outside
|
||||
|
||||
f()
|
||||
{
|
||||
unset var
|
||||
declare -n ref=var
|
||||
declare -n ref;
|
||||
declare -p ref;
|
||||
}
|
||||
f
|
||||
|
||||
unset ref foo
|
||||
|
||||
typeset -n r=a
|
||||
|
||||
f()
|
||||
{
|
||||
typeset a
|
||||
typeset -n r
|
||||
typeset -n r
|
||||
r=a
|
||||
|
||||
typeset -p a r
|
||||
}
|
||||
f
|
||||
echo $?
|
||||
unset -n r
|
||||
unset -f f
|
||||
|
||||
function foo
|
||||
{
|
||||
typeset -n r
|
||||
typeset -n r
|
||||
typeset -p r
|
||||
}
|
||||
|
||||
foo
|
||||
unset -f foo
|
||||
|
||||
|
||||
function foo
|
||||
{
|
||||
typeset r
|
||||
typeset -n r
|
||||
typeset -p r
|
||||
}
|
||||
foo
|
||||
unset -f foo
|
||||
|
||||
foo()
|
||||
{
|
||||
typeset -n foo
|
||||
typeset foo=12345
|
||||
typeset -p foo
|
||||
}
|
||||
foo
|
||||
unset -f foo
|
||||
|
||||
foo()
|
||||
{
|
||||
typeset -n foo
|
||||
typeset -n foo=12345
|
||||
typeset -p foo
|
||||
}
|
||||
foo
|
||||
unset -f foo
|
||||
|
||||
+57
-16
@@ -1,6 +1,6 @@
|
||||
/* variables.c -- Functions for hacking shell variables. */
|
||||
|
||||
/* Copyright (C) 1987-2015 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2016 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -83,8 +83,6 @@
|
||||
#define FUNCTIONS_HASH_BUCKETS 512
|
||||
#define TEMPENV_HASH_BUCKETS 4 /* must be power of two */
|
||||
|
||||
#define ifsname(s) ((s)[0] == 'I' && (s)[1] == 'F' && (s)[2] == 'S' && (s)[3] == '\0')
|
||||
|
||||
#define BASHFUNC_PREFIX "BASH_FUNC_"
|
||||
#define BASHFUNC_PREFLEN 10 /* == strlen(BASHFUNC_PREFIX */
|
||||
#define BASHFUNC_SUFFIX "%%"
|
||||
@@ -1929,8 +1927,9 @@ find_variable_nameref (v)
|
||||
|
||||
/* Resolve the chain of nameref variables for NAME. XXX - could change later */
|
||||
SHELL_VAR *
|
||||
find_variable_last_nameref (name)
|
||||
find_variable_last_nameref (name, vflags)
|
||||
const char *name;
|
||||
int vflags;
|
||||
{
|
||||
SHELL_VAR *v, *nv;
|
||||
char *newname;
|
||||
@@ -1945,7 +1944,11 @@ find_variable_last_nameref (name)
|
||||
return ((SHELL_VAR *)0); /* error message here? */
|
||||
newname = nameref_cell (v);
|
||||
if (newname == 0 || *newname == '\0')
|
||||
#if 0
|
||||
return ((SHELL_VAR *)0);
|
||||
#else
|
||||
return ((vflags && invisible_p (v)) ? v : (SHELL_VAR *)0);
|
||||
#endif
|
||||
nv = v;
|
||||
flags = 0;
|
||||
if (expanding_redir == 0 && (assigning_in_environment || executing_builtin))
|
||||
@@ -1957,8 +1960,9 @@ find_variable_last_nameref (name)
|
||||
|
||||
/* Resolve the chain of nameref variables for NAME. XXX - could change later */
|
||||
SHELL_VAR *
|
||||
find_global_variable_last_nameref (name)
|
||||
find_global_variable_last_nameref (name, vflags)
|
||||
const char *name;
|
||||
int vflags;
|
||||
{
|
||||
SHELL_VAR *v, *nv;
|
||||
char *newname;
|
||||
@@ -1973,7 +1977,11 @@ find_global_variable_last_nameref (name)
|
||||
return ((SHELL_VAR *)0); /* error message here? */
|
||||
newname = nameref_cell (v);
|
||||
if (newname == 0 || *newname == '\0')
|
||||
#if 0
|
||||
return ((SHELL_VAR *)0);
|
||||
#else
|
||||
return ((vflags && invisible_p (v)) ? v : (SHELL_VAR *)0);
|
||||
#endif
|
||||
nv = v;
|
||||
v = find_global_variable_noref (newname);
|
||||
}
|
||||
@@ -2297,16 +2305,29 @@ SHELL_VAR *
|
||||
make_local_variable (name)
|
||||
const char *name;
|
||||
{
|
||||
SHELL_VAR *new_var, *old_var;
|
||||
SHELL_VAR *new_var, *old_var, *old_ref;
|
||||
VAR_CONTEXT *vc;
|
||||
int was_tmpvar;
|
||||
char *tmp_value;
|
||||
|
||||
/* We don't want to follow the nameref chain when making local variables; we
|
||||
just want to create them. */
|
||||
old_ref = find_variable_noref (name);
|
||||
if (old_ref && nameref_p (old_ref) == 0)
|
||||
old_ref = 0;
|
||||
/* local foo; local foo; is a no-op. */
|
||||
old_var = find_variable (name);
|
||||
if (old_var && local_p (old_var) && old_var->context == variable_context)
|
||||
if (old_ref == 0 && old_var && local_p (old_var) && old_var->context == variable_context)
|
||||
return (old_var);
|
||||
|
||||
/* local -n foo; local -n foo; is a no-op. */
|
||||
if (old_ref && local_p (old_ref) && old_ref->context == variable_context)
|
||||
return (old_ref);
|
||||
|
||||
/* From here on, we want to use the refvar, not the variable it references */
|
||||
if (old_ref)
|
||||
old_var = old_ref;
|
||||
|
||||
was_tmpvar = old_var && tempvar_p (old_var);
|
||||
/* If we're making a local variable in a shell function, the temporary env
|
||||
has already been merged into the function's variable context stack. We
|
||||
@@ -2622,15 +2643,16 @@ bind_variable_internal (name, value, table, hflags, aflags)
|
||||
/* Let's see if we have a nameref referencing a variable that hasn't yet
|
||||
been created. */
|
||||
if (entry == 0)
|
||||
entry = find_variable_last_nameref (name); /* XXX */
|
||||
entry = find_variable_last_nameref (name, 0); /* XXX */
|
||||
if (entry == 0) /* just in case */
|
||||
return (entry);
|
||||
}
|
||||
|
||||
/* The first clause handles `declare -n ref; ref=x;' */
|
||||
/* The first clause handles `declare -n ref; ref=x;' or `declare -n ref;
|
||||
declare -n ref' */
|
||||
if (entry && invisible_p (entry) && nameref_p (entry))
|
||||
{
|
||||
if (valid_nameref_value (value, 1) == 0)
|
||||
if (value && *value && valid_nameref_value (value, 0) == 0)
|
||||
{
|
||||
sh_invalidid (value);
|
||||
return ((SHELL_VAR *)NULL);
|
||||
@@ -2640,6 +2662,15 @@ bind_variable_internal (name, value, table, hflags, aflags)
|
||||
else if (entry && nameref_p (entry))
|
||||
{
|
||||
newval = nameref_cell (entry);
|
||||
#if 0
|
||||
/* This check can go away if we stop allowing all-digit values for
|
||||
nameref variables. */
|
||||
if (newval && *newval && valid_nameref_value (newval, 1) == 0)
|
||||
{
|
||||
sh_invalidid (newval);
|
||||
return ((SHELL_VAR *)NULL);
|
||||
}
|
||||
#endif
|
||||
#if defined (ARRAY_VARS)
|
||||
/* declare -n foo=x[2] */
|
||||
if (valid_array_reference (newval, 0))
|
||||
@@ -2843,11 +2874,7 @@ bind_variable_value (var, value, aflags)
|
||||
else
|
||||
{
|
||||
t = make_variable_value (var, value, aflags);
|
||||
#if defined (ARRAY_VARS)
|
||||
if ((aflags & ASS_NAMEREF) && (t == 0 || *t == 0 || (legal_identifier (t) == 0 && valid_array_reference (t, 0) == 0)))
|
||||
#else
|
||||
if ((aflags & ASS_NAMEREF) && (t == 0 || *t == 0 || legal_identifier (t) == 0))
|
||||
#endif
|
||||
if ((aflags & ASS_NAMEREF) && (t == 0 || *t == 0 || valid_nameref_value (t, 0) == 0))
|
||||
{
|
||||
free (t);
|
||||
if (invis)
|
||||
@@ -2923,6 +2950,9 @@ bind_int_variable (lhs, rhs)
|
||||
VUNSETATTR (v, att_invisible);
|
||||
}
|
||||
|
||||
if (v && nameref_p (v))
|
||||
internal_warning (_("%s: assigning integer to name reference"), lhs);
|
||||
|
||||
return (v);
|
||||
}
|
||||
|
||||
@@ -3047,6 +3077,9 @@ assign_in_env (word, flags)
|
||||
}
|
||||
|
||||
var = find_variable (name);
|
||||
if (var == 0)
|
||||
var = find_variable_last_nameref (name, 1);
|
||||
|
||||
if (var && (readonly_p (var) || noassign_p (var)))
|
||||
{
|
||||
if (readonly_p (var))
|
||||
@@ -3054,8 +3087,16 @@ assign_in_env (word, flags)
|
||||
free (name);
|
||||
return (0);
|
||||
}
|
||||
|
||||
temp = name + offset + 1;
|
||||
if (var && nameref_p (var) && valid_nameref_value (temp, 0) == 0)
|
||||
{
|
||||
/* If we're assigning a value to a nameref variable in the temp
|
||||
environment that's an invalid name, flag an error. */
|
||||
sh_invalidid (temp);
|
||||
free (name);
|
||||
return (0);
|
||||
}
|
||||
|
||||
value = expand_assignment_string_to_string (temp, 0);
|
||||
|
||||
if (var && (aflags & ASS_APPEND))
|
||||
|
||||
+4
-2
@@ -215,6 +215,8 @@ typedef struct _vlist {
|
||||
(var)->exportstr = (char *)NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ifsname(s) ((s)[0] == 'I' && (s)[1] == 'F' && (s)[2] == 'S' && (s)[3] == '\0')
|
||||
|
||||
/* Stuff for hacking variables. */
|
||||
typedef int sh_var_map_func_t __P((SHELL_VAR *));
|
||||
@@ -244,8 +246,8 @@ extern SHELL_VAR *find_function __P((const char *));
|
||||
extern FUNCTION_DEF *find_function_def __P((const char *));
|
||||
extern SHELL_VAR *find_variable __P((const char *));
|
||||
extern SHELL_VAR *find_variable_noref __P((const char *));
|
||||
extern SHELL_VAR *find_variable_last_nameref __P((const char *));
|
||||
extern SHELL_VAR *find_global_variable_last_nameref __P((const char *));
|
||||
extern SHELL_VAR *find_variable_last_nameref __P((const char *, int));
|
||||
extern SHELL_VAR *find_global_variable_last_nameref __P((const char *, int));
|
||||
extern SHELL_VAR *find_variable_nameref __P((SHELL_VAR *));
|
||||
extern SHELL_VAR *find_variable_internal __P((const char *, int));
|
||||
extern SHELL_VAR *find_variable_tempenv __P((const char *));
|
||||
|
||||
Reference in New Issue
Block a user