mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-22 21:37:58 +02:00
commit bash-20160520 snapshot
This commit is contained in:
+156
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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. */
|
||||
|
||||
@@ -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 ();
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -39,3 +39,5 @@ ${THIS_SH} ./getopts7.sub -a
|
||||
|
||||
${THIS_SH} ./getopts8.sub
|
||||
${THIS_SH} ./getopts9.sub
|
||||
|
||||
${THIS_SH} ./getopts10.sub
|
||||
|
||||
@@ -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
@@ -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"
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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 *));
|
||||
|
||||
Reference in New Issue
Block a user