commit bash-20160520 snapshot

This commit is contained in:
Chet Ramey
2016-05-23 09:57:30 -04:00
parent 0fcb334438
commit bddda3d2e1
32 changed files with 625 additions and 113 deletions
+156
View File
@@ -10941,3 +10941,159 @@ 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>
5/16
----
general.c
- valid_nameref_value: explicitly handle name == 0 and *name == 0 right
away to save calls to legal_identifier
builtins/declare.def
- declare_internal: if trying to set nameref attribute on a variable with
a null value, flag as invalid assignment, just as if running
`declare -n r=""'. Fixes bug report from Grisha Levit
<grishalevit@gmail.com>
- declare_internal: when creating a variable with a temporary value (""),
use ASS_FORCE in the assignment flags to bypass name validity checks on
nameref variable names
variables.c
- bind_variable_internal: don't call valid_nameref_value if we're forcing
assignment with (flags & ASS_FORCE)
builtins/read.def
- read_builtin: handle bind_variable returning NULL when setting REPLY.
Report and fix from Grisha Levit <grishalevit@gmail.com>
builtins/setattr.def
- set_var_attribute: handle bind_variable returning NULL
lib/sh/tmpfile.c
- sh_seedrand(): call srandom() to seed the random number generator
- sh_mktmpname, sh_mktmpfd: if we have random(), assume we have srandom()
and seed the random number generator. Still looking for better value to
see random number generator with
variables.c
- check_unbind_variable: use internal_error instead of builtin_error
{execute_cmd,variables}.c
- fix some places where bind_variable could return NULL and it was not
checked. Fix from Piotr Grzybowski <narsil.pl@gmail.com>
5/17
----
arrayfunc.c
- convert_var_to_{array,assoc}: make sure to turn off nameref attribute,
since namerefs can't be arrays
execute_cmd.c
- coproc_setvars: if the coproc name names a nameref, resolve the nameref
and use it as the name of the coproc. Suggested by Grisha Levit
<grishalevit@gmail.com>
subst.c
- command_substitute: don't bother calling QUIT after calling
reset_signal_handlers in the child, kill the child with SIGINT in
case we just reset the signal handler to SIG_DFL and we should just
exit instead of throwing to top level. Fixes bug reported by
Grisha Levit <grishalevit@gmail.com>
5/18
----
variables.c
- find_variable_nameref_for_create: find a nameref variable whose value
doesn't resolve to an existing variable and see whether or not that
value is appropriate for a new variable to be created
- find_variable_nameref_for_assignment: find a nameref variable whose value
doesn't resolve to an existing variable and see whether or not that
value is appropriate for a new variable to be created. Difference
between _assignment and _create is that _assignment allows the nameref
value to be a subscripted array reference
builtins/setattr.def
- set_var_attribute: if variable lookup doesn't return anything, check
for a nameref and make sure that any reference value is something we
should be working on here, using find_variable_nameref_for_create().
If it fails, error out and return, otherwise it's probably a reference
to a variable that hasn't been set yet, so let bind_variable take care
of that. Report from Grisha Levit <grishalevit@gmail.com>
arrayfunc.c
- bind_array_variable: if find_shell_variable returns NULL, check for a
nameref using find_variable_nameref_for_create and create a new array
variable with the value if it returns a valid nameref variable.
Makes `unset var; declare -n ref=var ; ref[0]=foo' work right.
Report from Grisha Levit <grishalevit@gmail.com>
5/19
----
variables.[ch]
- unbind_variable_noref: unset a variable NAME without following any
nameref chain. If the first instance of the variable with that name
is a nameref, just unset that nameref variable.
builtins/getopts.def
- getopts_unbind_variable: if OPTARG is going to be unbound, use
unbind_variable_noref to unbind that name even if it is a nameref
variable. Issue raised by Grisha Levit <grishalevit@gmail.com>
execute_cmd.c
- coproc_unsetvars: use unbind_variable_noref in case someone sets the
coproc _PID variable as a nameref pointing to something read-only or
strange. Issue raised by Grisha Levit <grishalevit@gmail.com>
builtins/set.def
- set_ignoreeof: use unbind_variable_noref to unset "IGNOREEOF" and
"ignoreeof"
- set_posix_mode: use unbind_variable_noref to unset "POSIXLY_CORRECT"
variables.c
- make_vers_array: use unbind_variable_noref to unset "BASH_VERSINFO"
lib/sh/shmatch.c
- sh_regmatch: use unbind_variable_noref to unset "BASH_REMATCH"
bashline.c
- bash_execute_unix_command: use check_unbind_variable to unset
READLINE_LINE and READLINE_POINT
pcomplete.c
- unbind_compfunc_variables: use unbind_variable_noref to unset COMP_LINE,
COMP_POINT, COMP_WORDS, COMP_CWORD, COMP_TYPE, COMP_KEY
- gen_shell_function_matches: use unbind_variable_noref to unset COMPREPLY
config-top.h
- USE_MKTEMP/USE_MKSTEMP: define by default to use libc version of mktemp
and mkstemp in lib/sh/tmpfile.c. Recommended by by Mike Frysinger
<vapier@gentoo.org> to fix a FreeBSD problem
configure.ac,config.h.in
- mkstemp: check for mkstemp, define HAVE_MKSTEMP if available
config-bot.h
- USE_MKSTEMP: #undef if HAVE_MKSTEMP not defined
5/22
----
variables.c
- assign_in_env: if appending to a variable's value, make sure we call
make_variable_value with the empty string if expand_assignment_string_to_string
returns NULL, as do_assignment_internal does. Fixes bug with
`str=''; val=foo ; val+=str printenv val' reported by Grisha Levit
<grishalevit@gmail.com>
- assign_in_env: if assigning to a nameref variable in the temporary
environment, and the nameref has a valid value for assignment (even
if the target variable is not set), resolve the nameref and create
a variable in the temporary environment named by the nameref's value.
If the nameref variable is invisible or isn't set to a valid value
for assignment, just create a regular temporary variable with the
nameref's name. This provides a degree of ksh93 compatibility.
Suggested by Grisha Levit <grishalevit@gmail.com>
- find_variable_nameref_context,find_variable_last_nameref_context:
instead of returning NULL when detecting a loop, return a distinguished
value: &nameref_maxloop_value
- bind_variable: catch nameref_maxloop_value so we can do different
things based on whether or not we get it. Right now we don't do
anything different, but we could
+2
View File
@@ -1008,6 +1008,7 @@ tests/getopts6.sub f
tests/getopts7.sub f
tests/getopts8.sub f
tests/getopts9.sub f
tests/getopts10.sub f
tests/glob.tests f
tests/glob1.sub f
tests/glob.right f
@@ -1083,6 +1084,7 @@ tests/nameref10.sub f
tests/nameref11.sub f
tests/nameref12.sub f
tests/nameref13.sub f
tests/nameref14.sub f
tests/nameref.right f
tests/new-exp.tests f
tests/new-exp1.sub f
+16 -1
View File
@@ -90,6 +90,9 @@ convert_var_to_array (var)
/* Make sure it's not marked as an associative array any more */
VUNSETATTR (var, att_assoc);
/* Since namerefs can't be array variables, turn off nameref attribute */
VUNSETATTR (var, att_nameref);
return var;
}
@@ -124,6 +127,9 @@ convert_var_to_assoc (var)
/* Make sure it's not marked as an indexed array any more */
VUNSETATTR (var, att_array);
/* Since namerefs can't be array variables, turn off nameref attribute */
VUNSETATTR (var, att_nameref);
return var;
}
@@ -210,6 +216,15 @@ bind_array_variable (name, ind, value, flags)
entry = find_shell_variable (name);
if (entry == (SHELL_VAR *) 0)
{
/* Is NAME a nameref variable that points to an unset variable? */
entry = find_variable_nameref_for_create (name, 0);
if (entry == INVALID_NAMEREF_VALUE)
return ((SHELL_VAR *)0);
if (entry && nameref_p (entry))
entry = make_new_array_variable (nameref_cell (entry));
}
if (entry == (SHELL_VAR *) 0)
entry = make_new_array_variable (name);
else if ((readonly_p (entry) && (flags&ASS_FORCE) == 0) || noassign_p (entry))
@@ -984,7 +999,7 @@ array_variable_part (s, subp, lenp)
t = array_variable_name (s, subp, lenp);
if (t == 0)
return ((SHELL_VAR *)NULL);
var = find_variable (t);
var = find_variable (t); /* XXX - handle namerefs here? */
free (t);
return var; /* now return invisible variables; caller must handle */
+2 -2
View File
@@ -4135,8 +4135,8 @@ bash_execute_unix_command (count, key)
}
}
unbind_variable ("READLINE_LINE");
unbind_variable ("READLINE_POINT");
check_unbind_variable ("READLINE_LINE");
check_unbind_variable ("READLINE_POINT");
array_needs_making = 1;
/* and restore the readline buffer and display after command execution. */
+6 -5
View File
@@ -344,7 +344,7 @@ declare_internal (list, local_var)
#if 1
if (value && *value && valid_nameref_value (value, 0) == 0)
{
builtin_error (_("%s: invalid variable name for name reference"), value);
builtin_error (_("`%s': invalid variable name for name reference"), value);
assign_error++;
NEXT_VARIABLE ();
}
@@ -570,7 +570,8 @@ declare_internal (list, local_var)
else
#endif
if (offset)
var = mkglobal ? bind_global_variable (name, "", 0) : bind_variable (name, "", 0);
/* We're just setting a temporary value here, so force assignment */
var = mkglobal ? bind_global_variable (name, (char *)NULL, ASS_FORCE) : bind_variable (name, (char *)NULL, ASS_FORCE);
else
{
var = mkglobal ? bind_global_variable (name, (char *)NULL, 0) : bind_variable (name, (char *)NULL, 0);
@@ -592,7 +593,7 @@ declare_internal (list, local_var)
}
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);
builtin_error (_("`%s': invalid variable name for name reference"), value);
any_failed++;
NEXT_VARIABLE ();
}
@@ -601,9 +602,9 @@ declare_internal (list, local_var)
#if 1
/* 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)
if (nameref_p (var) == 0 && var_isset (var) && offset == 0 && valid_nameref_value (value_cell (var), 0) == 0)
{
builtin_error (_("%s: invalid variable name for name reference"), value_cell (var));
builtin_error (_("`%s': invalid variable name for name reference"), value_cell (var));
any_failed++;
NEXT_VARIABLE ();
}
+3 -9
View File
@@ -106,16 +106,10 @@ getopts_unbind_variable (name)
char *name;
{
#if 0
SHELL_VAR *v;
v = find_variable (name);
if (v && readonly_p (v))
{
builtin_error (_("%s: cannot unset: readonly %s"), name, "variable");
return -1;
}
#endif
return (unbind_variable (name));
#else
return (unbind_variable_noref (name));
#endif
}
static int
+3 -2
View File
@@ -797,9 +797,10 @@ assign_vars:
}
else
var = bind_variable ("REPLY", input_string, 0);
VUNSETATTR (var, att_invisible);
if (readonly_p (var) || noassign_p (var))
if (var == 0 || readonly_p (var) || noassign_p (var))
retval = EXECUTION_FAILURE;
else
VUNSETATTR (var, att_invisible);
xfree (input_string);
return (retval);
+3 -3
View File
@@ -367,11 +367,11 @@ set_ignoreeof (on_or_off, option_name)
char *option_name;
{
ignoreeof = on_or_off == FLAG_ON;
unbind_variable ("ignoreeof");
unbind_variable_noref ("ignoreeof");
if (ignoreeof)
bind_variable ("IGNOREEOF", "10", 0);
else
unbind_variable ("IGNOREEOF");
unbind_variable_noref ("IGNOREEOF");
sv_ignoreeof ("IGNOREEOF");
return 0;
}
@@ -383,7 +383,7 @@ set_posix_mode (on_or_off, option_name)
{
posixly_correct = on_or_off == FLAG_ON;
if (posixly_correct == 0)
unbind_variable ("POSIXLY_CORRECT");
unbind_variable_noref ("POSIXLY_CORRECT");
else
bind_variable ("POSIXLY_CORRECT", "y", 0);
sv_strict_posix ("POSIXLY_CORRECT");
+20 -3
View File
@@ -538,8 +538,8 @@ set_var_attribute (name, attribute, undo)
char *name;
int attribute, undo;
{
SHELL_VAR *var, *tv, *v;
char *tvalue;
SHELL_VAR *var, *tv, *v, *refvar;
char *tvalue, *refname;
if (undo)
var = find_variable (name);
@@ -554,6 +554,11 @@ set_var_attribute (name, attribute, undo)
tvalue = var_isset (tv) ? savestring (value_cell (tv)) : savestring ("");
var = bind_variable (tv->name, tvalue, 0);
if (var == 0)
{
free (tvalue);
return; /* XXX - no error message here */
}
var->attributes |= tv->attributes & ~att_tempvar;
/* This avoids an error message when propagating a read-only var
later on. */
@@ -578,10 +583,22 @@ set_var_attribute (name, attribute, undo)
else
{
var = find_variable_notempenv (name);
if (var == 0)
{
/* We might have a nameref pointing to something that we can't
resolve to a shell variable. If we do, skip it. We do a little
checking just so we can print an error message. */
refvar = find_variable_nameref_for_create (name, 0);
if (refvar == INVALID_NAMEREF_VALUE)
return;
/* Otherwise we probably have a nameref pointing to a variable
that hasn't been created yet. bind_variable will take care
of that. */
}
if (var == 0)
{
var = bind_variable (name, (char *)NULL, 0);
if (no_invisible_vars == 0)
if (var && no_invisible_vars == 0)
VSETATTR (var, att_invisible);
}
else if (var->context != 0)
+4
View File
@@ -94,6 +94,10 @@
# undef COND_REGEXP
#endif
#if !HAVE_MKSTEMP
# undef USE_MKSTEMP
#endif
/* If the shell is called by this name, it will become restricted. */
#if defined (RESTRICTED_SHELL)
# define RESTRICTED_SHELL_NAME "rbash"
+4
View File
@@ -156,3 +156,7 @@
/* Define to the maximum level of recursion you want for the source/. builtin.
0 means the limit is not active. */
#define SOURCENEST_MAX 0
/* Define to use libc mktemp/mkstemp instead of replacements in lib/sh/tmpfile.c */
#define USE_MKTEMP
#define USE_MKSTEMP
+3
View File
@@ -736,6 +736,9 @@
/* Define if you have the mkfifo function. */
#undef HAVE_MKFIFO
/* Define if you have the mkstemp function. */
#undef HAVE_MKSTEMP
/* Define if you have the pathconf function. */
#undef HAVE_PATHCONF
Vendored
+12 -1
View File
@@ -1,5 +1,5 @@
#! /bin/sh
# From configure.ac for Bash 4.4, version 4.078.
# From configure.ac for Bash 4.4, version 4.079.
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for bash 4.4-rc2.
#
@@ -9884,6 +9884,17 @@ _ACEOF
fi
done
for ac_func in mkstemp
do :
ac_fn_c_check_func "$LINENO" "mkstemp" "ac_cv_func_mkstemp"
if test "x$ac_cv_func_mkstemp" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_MKSTEMP 1
_ACEOF
fi
done
ac_fn_c_check_func "$LINENO" "getcwd" "ac_cv_func_getcwd"
if test "x$ac_cv_func_getcwd" = xyes; then :
$as_echo "#define HAVE_GETCWD 1" >>confdefs.h
+2 -1
View File
@@ -21,7 +21,7 @@ dnl Process this file with autoconf to produce a configure script.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
AC_REVISION([for Bash 4.4, version 4.078])dnl
AC_REVISION([for Bash 4.4, version 4.079])dnl
define(bashvers, 4.4)
define(relstatus, rc2)
@@ -783,6 +783,7 @@ AC_CHECK_FUNCS(bcopy bzero confstr faccessat fnmatch \
AC_CHECK_FUNCS(vasprintf asprintf)
AC_CHECK_FUNCS(isascii isblank isgraph isprint isspace isxdigit)
AC_CHECK_FUNCS(getpwent getpwnam getpwuid)
AC_CHECK_FUNCS(mkstemp)
AC_REPLACE_FUNCS(getcwd memset)
AC_REPLACE_FUNCS(strcasecmp strcasestr strerror strftime strnlen strpbrk strstr)
AC_REPLACE_FUNCS(strtod strtol strtoul strtoll strtoull strtoimax strtoumax)
+5 -2
View File
@@ -23,8 +23,11 @@
#define INIT_DYNAMIC_VAR(var, val, gfunc, afunc) \
do \
{ SHELL_VAR *v = bind_variable (var, (val), 0); \
v->dynamic_value = gfunc; \
v->assign_func = afunc; \
if (v) \
{ \
v->dynamic_value = gfunc; \
v->assign_func = afunc; \
} \
} \
while (0)
+9 -13
View File
@@ -2175,19 +2175,14 @@ coproc_setvars (cp)
/* 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);
}
v = find_variable_nameref_for_create (cp->c_name, 1);
if (v == INVALID_NAMEREF_VALUE)
return;
if (v && nameref_p (v))
{
if (valid_nameref_value (cp->c_name, 1) == 0)
{
sh_invalidid (cp->c_name);
return;
}
free (cp->c_name);
cp->c_name = savestring (nameref_cell (v));
v = make_new_array_variable (cp->c_name);
}
}
@@ -2244,7 +2239,7 @@ coproc_unsetvars (cp)
namevar = xmalloc (l + 16);
sprintf (namevar, "%s_PID", cp->c_name);
unbind_variable (namevar);
unbind_variable_noref (namevar);
#if defined (ARRAY_VARS)
check_unbind_variable (cp->c_name);
@@ -3812,7 +3807,8 @@ bind_lastarg (arg)
if (arg == 0)
arg = "";
var = bind_variable ("_", arg, 0);
VUNSETATTR (var, att_exported);
if (var)
VUNSETATTR (var, att_exported);
}
/* Execute a null command. Fork a subshell if the command uses pipes or is
+4 -4
View File
@@ -238,16 +238,16 @@ valid_nameref_value (name, for_assignment)
{
intmax_t r;
if (name == 0 || *name == 0)
return 0;
#if defined (ARRAY_VARS)
if (legal_identifier (name) || valid_array_reference (name, 0))
#else
if (legal_identifier (name))
#endif
return 1;
#if 0
if (for_assignment == 0 && legal_number (name, &r))
return 1;
#endif
return 0;
}
+1 -1
View File
@@ -92,7 +92,7 @@ sh_regmatch (string, pattern, flags)
/* Store the parenthesized subexpressions in the array BASH_REMATCH.
Element 0 is the portion that matched the entire regexp. Element 1
is the part that matched the first subexpression, and so on. */
unbind_variable ("BASH_REMATCH");
unbind_variable_noref ("BASH_REMATCH");
rematch = make_new_array_variable ("BASH_REMATCH");
amatch = array_cell (rematch);
+21 -1
View File
@@ -114,6 +114,23 @@ get_tmpdir (flags)
return tdir;
}
static void
sh_seedrand ()
{
#if HAVE_RANDOM
int d;
static int seeded = 0;
if (seeded == 0)
{
struct timeval tv;
gettimeofday (&tv, NULL);
srandom (tv.tv_sec ^ tv.tv_usec ^ (getpid () << 16) ^ (unsigned int)&d);
seeded = 1;
}
#endif
}
char *
sh_mktmpname (nameroot, flags)
char *nameroot;
@@ -122,6 +139,7 @@ sh_mktmpname (nameroot, flags)
char *filename, *tdir, *lroot;
struct stat sb;
int r, tdlen;
static int seeded = 0;
filename = (char *)xmalloc (PATH_MAX + 1);
tdir = get_tmpdir (flags);
@@ -137,6 +155,7 @@ sh_mktmpname (nameroot, flags)
filename = NULL;
}
#else /* !USE_MKTEMP */
sh_seedrand ();
while (1)
{
filenum = (filenum << 1) ^
@@ -167,7 +186,7 @@ sh_mktmpfd (nameroot, flags, namep)
{
char *filename, *tdir, *lroot;
int fd, tdlen;
filename = (char *)xmalloc (PATH_MAX + 1);
tdir = get_tmpdir (flags);
tdlen = strlen (tdir);
@@ -186,6 +205,7 @@ sh_mktmpfd (nameroot, flags, namep)
*namep = filename;
return fd;
#else /* !USE_MKSTEMP */
sh_seedrand ();
do
{
filenum = (filenum << 1) ^
+7 -7
View File
@@ -1025,13 +1025,13 @@ static void
unbind_compfunc_variables (exported)
int exported;
{
unbind_variable ("COMP_LINE");
unbind_variable ("COMP_POINT");
unbind_variable ("COMP_TYPE");
unbind_variable ("COMP_KEY");
unbind_variable_noref ("COMP_LINE");
unbind_variable_noref ("COMP_POINT");
unbind_variable_noref ("COMP_TYPE");
unbind_variable_noref ("COMP_KEY");
#ifdef ARRAY_VARS
unbind_variable ("COMP_WORDS");
unbind_variable ("COMP_CWORD");
unbind_variable_noref ("COMP_WORDS");
unbind_variable_noref ("COMP_CWORD");
#endif
if (exported)
array_needs_making = 1;
@@ -1183,7 +1183,7 @@ gen_shell_function_matches (cs, cmd, text, line, ind, lwords, nw, cw, foundp)
}
/* XXX - should we unbind COMPREPLY here? */
unbind_variable ("COMPREPLY");
unbind_variable_noref ("COMPREPLY");
return (sl);
#endif
+8 -3
View File
@@ -6011,6 +6011,11 @@ command_substitute (string, quoted)
trap strings. Set a flag noting that we have to free the
trap strings if we run trap to change a signal disposition. */
reset_signal_handlers ();
if (ISINTERRUPT)
{
kill (getpid (), SIGINT);
CLRINTERRUPT; /* if we're ignoring SIGINT somehow */
}
QUIT; /* catch any interrupts we got post-fork */
subshell_environment |= SUBSHELL_RESETTRAP;
}
@@ -6040,6 +6045,9 @@ command_substitute (string, quoted)
if (pid == 0)
{
/* The currently executing shell is not interactive. */
interactive = 0;
set_sigint_handler (); /* XXX */
free_pushed_string_input ();
@@ -6077,9 +6085,6 @@ command_substitute (string, quoted)
sh_setlinebuf (stdout);
#endif /* __CYGWIN__ */
/* The currently executing shell is not interactive. */
interactive = 0;
/* This is a subshell environment. */
subshell_environment |= SUBSHELL_COMSUB;
+1 -1
View File
@@ -1,4 +1,4 @@
BUILD_DIR=/usr/local/build/chet/bash/bash-current
BUILD_DIR=/usr/local/build/bash/bash-current
THIS_SH=$BUILD_DIR/bash
PATH=$PATH:$BUILD_DIR
+5
View File
@@ -61,3 +61,8 @@ opt: b
opt: c
opt: z
$1 = a
./getopts10.sub: line 3: OPTARG: readonly variable
OPTARG = x = ?
unset x = ?
declare -r RO="foo"
declare -r RO="foo"
+2
View File
@@ -39,3 +39,5 @@ ${THIS_SH} ./getopts7.sub -a
${THIS_SH} ./getopts8.sub
${THIS_SH} ./getopts9.sub
${THIS_SH} ./getopts10.sub
+17
View File
@@ -0,0 +1,17 @@
set -- -a bb
readonly OPTARG
getopts :x x
echo OPTARG = $OPTARG x = $x
getopts x x
echo ${OPTARG-unset} x = $x
typeset -r RO=foo
typeset -n OPTARG=RO
getopts :x x
typeset -p RO
getopts x x
typeset -p RO
+69 -20
View File
@@ -166,8 +166,8 @@ 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 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
@@ -176,29 +176,48 @@ declare -n foo="bar"
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 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 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
./nameref11.sub: line 14: warning: 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 16: declare: `/': invalid variable name for name reference
/
./nameref11.sub: line 17: 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
./nameref11.sub: line 23: `': not a valid identifier
./nameref11.sub: line 24: declare: `': not a valid identifier
./nameref11.sub: line 25: `': not a valid identifier
./nameref11.sub: line 26: printf: `': not a valid identifier
./nameref11.sub: line 27: declare: `': invalid variable name for name reference
declare -r ROVAR="42"
./nameref11.sub: line 32: ROVAR: readonly variable
./nameref11.sub: line 32: ROVAR: cannot unset: readonly variable
declare -r ROVAR="42"
./nameref11.sub
./nameref11.sub: line 34: `@': not a valid identifier
./nameref11.sub
declare -n ref="x"
./nameref11.sub: line 39: RO: readonly variable
declare -r RO_PID
./nameref11.sub: line 39: RO: cannot unset: readonly variable
declare -r RO="x"
./nameref11.sub: line 39: declare: RO_PID: not found
./nameref11.sub: line 41: ref_PID: readonly variable
declare -r RO2="a"
./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
@@ -206,15 +225,23 @@ 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
/
./nameref12.sub: line 45: declare: `7*6': not a valid identifier
./nameref12.sub: line 45: declare: foo: not found
./nameref12.sub: line 47: `7*6': not a valid identifier
declare -n ref="var"
declare -n ref="var"
./nameref12.sub: line 74: readonly: `var[0]': not a valid identifier
declare -- var="foo"
declare -r var2="foo"
declare -n ref="var"
declare -a var=([0]="foo")
./nameref12.sub: line 91: `': not a valid identifier
declare -n ref
declare -- ref="global"
declare -a var=([0]="foo2")
./nameref12.sub: line 100: declare: global: not found
declare -- a
declare -n r="a"
declare -- a
@@ -227,7 +254,29 @@ declare -n r="a"
0
declare -n r
declare -n r
./nameref13.sub: line 88: typeset: 12345: invalid variable name for name reference
./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
./nameref13.sub: line 97: typeset: `12345': invalid variable name for name reference
declare -n foo
declare -nx ref="var"
var
var
var
var
foo
foo
foo
foo
before
declare -n ref="var"
./nameref14.sub: line 23: typeset: var: not found
first
declare -n ref="var"
declare -x var="xxx"
invalid
declare -n ref="var"
declare -x var="5"
after
declare -n ref="var"
./nameref14.sub: line 32: typeset: var: not found
declare -n ref="var"
+1
View File
@@ -128,3 +128,4 @@ ${THIS_SH} ./nameref10.sub
${THIS_SH} ./nameref11.sub
${THIS_SH} ./nameref12.sub
${THIS_SH} ./nameref13.sub
${THIS_SH} ./nameref14.sub
+21 -1
View File
@@ -18,4 +18,24 @@ 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 /
declare -n r; printf -v r / ; unset -n r
declare -n r; r="" ; unset -n r
declare -n r="" ; unset -n r
declare -n r; : ${r=} ; unset -n r
declare -n r; printf -v r '' ; unset -n r
r=""; declare -n r ; unset -n r
export r
# coproc tests, since coproc sets and unsets variables
declare -r ROVAR=42
declare -p ROVAR; coproc ROVAR { :; }; wait; declare -p ROVAR
echo ${@:0}; coproc @ { :; }; wait ; echo ${@:0}
declare -n ref=x; coproc ref { :; }; wait ; declare -p ref
unset -n ref ; unset ref
declare -r RO RO_PID; coproc RO { :; }; declare -p RO_PID; wait; declare -p RO RO_PID
declare -r RO2=a; declare -n ref_PID=RO2; coproc ref { :; }; wait; declare -p RO2
+35
View File
@@ -31,6 +31,8 @@ declare -p RO
unset -n r; unset r
# the details of this may change; currently we put namerefs and values into
# the tempenv if the nameref value is an invalid variable name
f() { echo $r; }
declare -n r
@@ -63,3 +65,36 @@ f()
declare -p ref
}
f
unset ref; unset -n ref
unset var
var=foo
typeset -n ref=var[0]
readonly ref
typeset -p var
var2=foo
typeset -n ref2=var2
readonly ref2
typeset -p var2
unset var
unset -n ref ref2
unset var; typeset -n ref=var
ref[0]=foo
typeset -p ref var
unset -n ref
unset var; typeset -n ref
ref[0]=foo
typeset -p ref
unset -n ref
ref=global
f() { declare -n ref=var; ref[0]=foo1; }; f
f() { declare -n ref=var; ref[0]=foo2; }; f
declare -p ref var
declare -p global
+43
View File
@@ -0,0 +1,43 @@
# exporting namerefs and putting namerefs in temp env post bash-4.3
typeset -nx ref=var;
typeset -p ref
var=foo; str=''
printenv ref # var
ref+=$str printenv ref # var
ref+="$str" printenv ref # var
ref=$ref$str printenv ref # var
export ref # follows nameref and exports var
printenv var # foo
ref+=$str printenv var # foo
ref+="$str" printenv var # foo
ref=$ref$str printenv var # foo
# none of these should change ref; should follow the nameref and export var
unset var; unset -n ref; typeset -n ref=var
echo before
typeset -p ref var
echo first
ref=xxx typeset -p ref var
echo invalid
var= ref=5 typeset -p ref var
echo after
typeset -p ref var
# ref isn't exported, so none of the printenvs should print anything
unset var ; unset -n ref
typeset -n ref=var;
typeset -p ref
var=foo; str=''
printenv ref
ref+=$str printenv ref
ref+="$str" printenv ref
ref=$ref$str printenv ref
+133 -33
View File
@@ -176,6 +176,9 @@ static int export_env_size;
static int winsize_assignment; /* currently assigning to LINES or COLUMNS */
#endif
SHELL_VAR nameref_invalid_value;
static SHELL_VAR nameref_maxloop_value;
static HASH_TABLE *last_table_searched; /* hash_lookup sets this */
/* Some forward declarations. */
@@ -485,7 +488,8 @@ initialize_shell_variables (env, privmode)
qnx_nidtostr (getnid (), node_name, sizeof (node_name));
# endif
temp_var = bind_variable ("NODE", node_name, 0);
set_auto_export (temp_var);
if (temp_var)
set_auto_export (temp_var);
}
#endif
@@ -948,7 +952,7 @@ make_vers_array ()
ARRAY *av;
char *s, d[32], b[INT_STRLEN_BOUND(int) + 1];
unbind_variable ("BASH_VERSINFO");
unbind_variable_noref ("BASH_VERSINFO");
vv = make_new_array_variable ("BASH_VERSINFO");
av = array_cell (vv);
@@ -1898,7 +1902,7 @@ find_variable_nameref (v)
SHELL_VAR *v;
{
int level, flags;
char *newname;
char *newname, *t;
SHELL_VAR *orig, *oldv;
level = 0;
@@ -1915,6 +1919,7 @@ find_variable_nameref (v)
flags = 0;
if (expanding_redir == 0 && (assigning_in_environment || executing_builtin))
flags |= FV_FORCETEMPENV;
/* We don't handle array subscripts here. */
v = find_variable_internal (newname, flags);
if (v == orig || v == oldv)
{
@@ -1944,15 +1949,12 @@ find_variable_last_nameref (name, vflags)
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))
flags |= FV_FORCETEMPENV;
/* We don't accommodate array subscripts here. */
v = find_variable_internal (newname, flags);
}
return nv;
@@ -1977,12 +1979,9 @@ find_global_variable_last_nameref (name, vflags)
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;
/* We don't accommodate array subscripts here. */
v = find_global_variable_noref (newname);
}
return nv;
@@ -2004,7 +2003,7 @@ find_nameref_at_context (v, vc)
{
level++;
if (level > NAMEREF_MAX)
return ((SHELL_VAR *)NULL);
return (&nameref_maxloop_value);
newname = nameref_cell (nv);
if (newname == 0 || *newname == '\0')
return ((SHELL_VAR *)NULL);
@@ -2034,6 +2033,8 @@ find_variable_nameref_context (v, vc, nvcp)
for (nv = v, nvc = vc; nvc; nvc = nvc->down)
{
nv2 = find_nameref_at_context (nv, nvc);
if (nv2 == &nameref_maxloop_value)
return (nv2); /* XXX */
if (nv2 == 0)
continue;
nv = nv2;
@@ -2063,6 +2064,8 @@ find_variable_last_nameref_context (v, vc, nvcp)
for (nv = v, nvc = vc; nvc; nvc = nvc->down)
{
nv2 = find_nameref_at_context (nv, nvc);
if (nv2 == &nameref_maxloop_value)
return (nv2); /* XXX */
if (nv2 == 0)
continue;
nv = nv2;
@@ -2072,6 +2075,58 @@ find_variable_last_nameref_context (v, vc, nvcp)
return (nameref_p (nv) ? nv : (SHELL_VAR *)NULL);
}
SHELL_VAR *
find_variable_nameref_for_create (name, flags)
const char *name;
int flags;
{
SHELL_VAR *var;
/* See if we have a nameref pointing to a variable that hasn't been
created yet. */
var = find_variable_last_nameref (name, 1);
if ((flags&1) && var && nameref_p (var) && invisible_p (var))
{
internal_warning (_("%s: removing nameref attribute"), name);
VUNSETATTR (var, att_nameref);
}
if (var && nameref_p (var))
{
if (legal_identifier (nameref_cell (var)) == 0)
{
sh_invalidid (nameref_cell (var) ? nameref_cell (var) : "");
return ((SHELL_VAR *)INVALID_NAMEREF_VALUE);
}
}
return (var);
}
SHELL_VAR *
find_variable_nameref_for_assignment (name, flags)
const char *name;
int flags;
{
SHELL_VAR *var;
/* See if we have a nameref pointing to a variable that hasn't been
created yet. */
var = find_variable_last_nameref (name, 1);
if (var && nameref_p (var) && invisible_p (var)) /* XXX - flags */
{
internal_warning (_("%s: removing nameref attribute"), name);
VUNSETATTR (var, att_nameref);
}
if (var && nameref_p (var))
{
if (valid_nameref_value (nameref_cell (var), 1) == 0)
{
sh_invalidid (nameref_cell (var) ? nameref_cell (var) : "");
return ((SHELL_VAR *)INVALID_NAMEREF_VALUE);
}
}
return (var);
}
/* Find a variable, forcing a search of the temporary environment first */
SHELL_VAR *
find_variable_tempenv (name)
@@ -2652,7 +2707,7 @@ bind_variable_internal (name, value, table, hflags, aflags)
declare -n ref' */
if (entry && invisible_p (entry) && nameref_p (entry))
{
if (value && *value && valid_nameref_value (value, 0) == 0)
if ((aflags & ASS_FORCE) == 0 && value && valid_nameref_value (value, 0) == 0)
{
sh_invalidid (value);
return ((SHELL_VAR *)NULL);
@@ -2814,9 +2869,27 @@ bind_variable (name, value, flags)
#endif
return (bind_variable_internal (nameref_cell (nv), value, nvc->table, 0, flags));
}
else if (nv == &nameref_maxloop_value)
{
internal_warning (_("%s: circular name reference"), v->name);
#if 0
return (bind_variable_value (v, value, flags|ASS_NAMEREF));
#else
return (bind_variable_internal (v->name, value, nvc->table, 0, flags));
#endif
}
else
v = nv;
}
else if (nv == &nameref_maxloop_value)
{
internal_warning (_("%s: circular name reference"), v->name);
#if 0
return (bind_variable_value (v, value, flags|ASS_NAMEREF));
#else
return (bind_variable_internal (v->name, value, nvc->table, 0, flags));
#endif
}
else
v = nv;
}
@@ -3054,7 +3127,7 @@ assign_in_env (word, flags)
int flags;
{
int offset, aflags;
char *name, *temp, *value;
char *name, *temp, *value, *newname;
SHELL_VAR *var;
const char *string;
@@ -3062,7 +3135,7 @@ assign_in_env (word, flags)
aflags = 0;
offset = assignment (string, 0);
name = savestring (string);
newname = name = savestring (string);
value = (char *)NULL;
if (name[offset] == '=')
@@ -3078,7 +3151,21 @@ assign_in_env (word, flags)
var = find_variable (name);
if (var == 0)
var = find_variable_last_nameref (name, 1);
{
var = find_variable_last_nameref (name, 1);
/* If we're assigning a value to a nameref variable in the temp
environment, and the value of the nameref is valid for assignment,
but the variable does not already exist, assign to the nameref
target and add the target to the temporary environment. This is
what ksh93 does */
if (var && nameref_p (var) && valid_nameref_value (nameref_cell (var), 1))
{
newname = nameref_cell (var);
var = 0; /* don't use it for append */
}
}
else
newname = name_cell (var); /* no-op if not nameref */
if (var && (readonly_p (var) || noassign_p (var)))
{
@@ -3088,19 +3175,16 @@ assign_in_env (word, flags)
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))
{
if (value == 0)
{
value = (char *)xmalloc (1); /* like do_assignment_internal */
value[0] = '\0';
}
temp = make_variable_value (var, value, aflags);
FREE (value);
value = temp;
@@ -3110,15 +3194,15 @@ assign_in_env (word, flags)
if (temporary_env == 0)
temporary_env = hash_create (TEMPENV_HASH_BUCKETS);
var = hash_lookup (name, temporary_env);
var = hash_lookup (newname, temporary_env);
if (var == 0)
var = make_new_variable (name, temporary_env);
var = make_new_variable (newname, temporary_env);
else
FREE (value_cell (var));
if (value == 0)
{
value = (char *)xmalloc (1); /* like do_assignment_internal */
value = (char *)xmalloc (1); /* see above */
value[0] = '\0';
}
@@ -3127,12 +3211,12 @@ assign_in_env (word, flags)
var->context = variable_context; /* XXX */
INVALIDATE_EXPORTSTR (var);
var->exportstr = mk_env_string (name, value, 0);
var->exportstr = mk_env_string (newname, value, 0);
array_needs_making = 1;
if (flags)
stupidly_hack_special_variables (name);
stupidly_hack_special_variables (newname);
if (echo_command_at_execute)
/* The Korn shell prints the `+ ' in front of assignment statements,
@@ -3264,6 +3348,19 @@ unbind_nameref (name)
return 0;
}
/* Unbind the first instance of NAME, whether it's a nameref or not */
int
unbind_variable_noref (name)
const char *name;
{
SHELL_VAR *v;
v = var_lookup (name, shell_variables);
if (v)
return makunbound (name, shell_variables);
return 0;
}
int
check_unbind_variable (name)
const char *name;
@@ -3273,7 +3370,7 @@ check_unbind_variable (name)
v = find_variable (name);
if (v && readonly_p (v))
{
builtin_error (_("%s: cannot unset: readonly %s"), name, "variable");
internal_error (_("%s: cannot unset: readonly %s"), name, "variable");
return -1;
}
return (unbind_variable (name));
@@ -3954,7 +4051,8 @@ push_temp_var (data)
if (binding_table == shell_variables->table)
shell_variables->flags |= VC_HASTMPVAR;
}
v->attributes |= var->attributes;
if (v)
v->attributes |= var->attributes;
if (find_special_var (var->name) >= 0)
tempvar_list[tvlist_ind++] = savestring (var->name);
@@ -4548,7 +4646,8 @@ push_func_var (data)
var->attributes &= ~(att_tempvar|att_propagate);
else
shell_variables->flags |= VC_HASTMPVAR;
v->attributes |= var->attributes;
if (v)
v->attributes |= var->attributes;
}
else
stupidly_hack_special_variables (var->name); /* XXX */
@@ -4636,7 +4735,8 @@ push_exported_var (data)
v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0);
if (shell_variables == global_variables)
var->attributes &= ~att_propagate;
v->attributes |= var->attributes;
if (v)
v->attributes |= var->attributes;
}
else
stupidly_hack_special_variables (var->name); /* XXX */
+7
View File
@@ -217,6 +217,10 @@ typedef struct _vlist {
} while (0)
#define ifsname(s) ((s)[0] == 'I' && (s)[1] == 'F' && (s)[2] == 'S' && (s)[3] == '\0')
/* Special value for nameref with invalid value for creation or assignment */
extern SHELL_VAR nameref_invalid_value;
#define INVALID_NAMEREF_VALUE (void *)&nameref_invalid_value
/* Stuff for hacking variables. */
typedef int sh_var_map_func_t __P((SHELL_VAR *));
@@ -249,6 +253,8 @@ extern SHELL_VAR *find_variable_noref __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_nameref_for_create __P((const char *, int));
extern SHELL_VAR *find_variable_nameref_for_assignment __P((const char *, int));
extern SHELL_VAR *find_variable_internal __P((const char *, int));
extern SHELL_VAR *find_variable_tempenv __P((const char *));
extern SHELL_VAR *find_variable_notempenv __P((const char *));
@@ -298,6 +304,7 @@ extern int assign_in_env __P((WORD_DESC *, int));
extern int unbind_variable __P((const char *));
extern int check_unbind_variable __P((const char *));
extern int unbind_nameref __P((const char *));
extern int unbind_variable_noref __P((const char *));
extern int unbind_func __P((const char *));
extern int unbind_function_def __P((const char *));
extern int delete_var __P((const char *, VAR_CONTEXT *));