mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-27 07:43:07 +02:00
commit bash-20160603 snapshot
This commit is contained in:
+109
@@ -11153,3 +11153,112 @@ builtins/declare.def
|
||||
removed from a readonly nameref variable that has a value, even if it
|
||||
doesn't reference an existing variable. This distinction is for ksh93
|
||||
compatibility. Pointed out by Grisha Levit <grishalevit@gmail.com>
|
||||
|
||||
5/31
|
||||
----
|
||||
builtins/declare.def
|
||||
- declare_internal: if the call to bind_variable_value fails for some
|
||||
reason, make sure to restore the nameref attribute to flags_on and
|
||||
flags_off before calling NEXT_VARIABLE
|
||||
|
||||
subst.c
|
||||
- make_internal_declare: handle += append op
|
||||
- shell_expand_word_list: when transforming assignment statement arguments
|
||||
to `declare', make sure to handle += append op to avoid passing invalid
|
||||
identifiers to declare. Report by Grisha Levit <grishalevit@gmail.com>
|
||||
|
||||
6/1
|
||||
---
|
||||
builtins/declare.def
|
||||
- declare_internal: if a nameref assignment fails, only call delete_var to
|
||||
delete the variable if we created it in declare_internal in the first
|
||||
place
|
||||
|
||||
general.c
|
||||
- check_selfref: new function, checks a NAME against a VALUE for nameref
|
||||
self-reference
|
||||
|
||||
general.h
|
||||
- check_selfref: extern declaration
|
||||
|
||||
builtins/declare.def
|
||||
- declare_internal: call check_selfref to determine whether a given NAME
|
||||
and VALUE constitute an invalid nameref variable self-reference
|
||||
|
||||
variables.c
|
||||
- bind_variable_internal: call check_selfref to determine whether a given
|
||||
NAME and VALUE constitute an invalid nameref variable self-reference
|
||||
|
||||
6/2
|
||||
---
|
||||
parse.y
|
||||
- clear_shell_input_line: new function, clears contents of shell_input_line
|
||||
and sets index to 0, but doesn't free it
|
||||
|
||||
externs.h
|
||||
- clear_shell_input_line: extern declaration
|
||||
|
||||
builtins/evalstring.c
|
||||
- parse_and_execute: call clear_shell_input_line after setting input to
|
||||
string to be executed. Fixes problem with command substitution and
|
||||
multi-line aliases reported by Grisha Levit <grishalevit@gmail.com>
|
||||
|
||||
eval.c
|
||||
- parse_command: only execute PROMPT_COMMAND if the shell is not
|
||||
currently expanding an alias; use the same tests as parse.y:SHOULD_PROMPT
|
||||
and parse.y:prompt_again() use to decide whether or not to print a
|
||||
prompt. Fixes problems with PROMPT_COMMAND and multi-line aliases
|
||||
reported by Grisha Levit <grishalevit@gmail.com>
|
||||
|
||||
builtins/set.def
|
||||
- unset_builtin: changes to fix three problems reported by Grisha
|
||||
Levit <grishalevit@gmail.com>:
|
||||
o if -n is supplied, we should not try to unset a function if
|
||||
a variable isn't found
|
||||
o unsetting namerefs whose values are array references does
|
||||
not work
|
||||
o unset -n n[0], where n is a nameref, would unset the referenced
|
||||
variable instead of `n'
|
||||
|
||||
redir.c
|
||||
- redir_varvalue: handle case where nameref var points to subscripted
|
||||
array reference. Reported by Grisha Levit <grishalevit@gmail.com>
|
||||
|
||||
variables.c
|
||||
- bind_variable_value: make sure to call check_selfref only if aflags
|
||||
includes ASS_NAMEREF and not ASS_FORCE. Reported by Grisha Levit
|
||||
<grishalevit@gmail.com>
|
||||
|
||||
general.c
|
||||
- valid_nameref_value: now understands a FLAGS value of 2 to mean that
|
||||
the name will be used to create a variable, so only legal_identifier
|
||||
matters
|
||||
|
||||
arrayfunc.c
|
||||
- find_or_make_array_variable: call valid_nameref_value with FLAGS value
|
||||
of 2 to indicate we will be creating a variable. Fixes mapfile issue
|
||||
reported by Grisha Levit <grishalevit@gmail.com>
|
||||
|
||||
6/5
|
||||
---
|
||||
builtins/declare.def
|
||||
- declare_internal: only pass ASS_FORCE as part of assignment flags to
|
||||
assignments concerning arrays
|
||||
- declare_internal: when at the global scope, if we resolve a nameref
|
||||
and commit to using the new name, go back to to the beginning of the
|
||||
loop and use the new name in the checks and variable references.
|
||||
Make sure we construct the new name as a straight substitution of
|
||||
the nameref value into the old name, including array subscripts and
|
||||
rebuilding the correct values for `offset' and `value', since they
|
||||
are relative to the original value of name.
|
||||
Fixes several issues with checking use of subscripted array variables
|
||||
as nameref values
|
||||
- declare_internal: when calling assign_array_element, make sure to pass
|
||||
ASS_APPEND if aflags includes it, so things like
|
||||
declare -a var; var[1]=1; declare var[1]+=4
|
||||
append to the value appropriately and var[1] ends up being `14'
|
||||
|
||||
arrayfunc.c
|
||||
- valid_array_reference: make sure the array reference is properly
|
||||
terminated after the first subscript; return invalid if there is
|
||||
anything following the closing `]'
|
||||
|
||||
+3
-1
@@ -370,7 +370,7 @@ find_or_make_array_variable (name, flags)
|
||||
}
|
||||
if (var && nameref_p (var))
|
||||
{
|
||||
if (valid_nameref_value (nameref_cell (var), 1) == 0)
|
||||
if (valid_nameref_value (nameref_cell (var), 2) == 0)
|
||||
{
|
||||
sh_invalidid (nameref_cell (var));
|
||||
return ((SHELL_VAR *)NULL);
|
||||
@@ -899,6 +899,8 @@ valid_array_reference (name, flags)
|
||||
len = skipsubscript (t, 0, 0);
|
||||
if (t[len] != ']' || len == 1)
|
||||
return 0;
|
||||
if (t[len+1] != '\0')
|
||||
return 0;
|
||||
for (r = 1; r < len; r++)
|
||||
if (whitespace (t[r]) == 0)
|
||||
return 1;
|
||||
|
||||
+67
-36
@@ -286,8 +286,8 @@ declare_internal (list, local_var)
|
||||
/* There are arguments left, so we are making variables. */
|
||||
while (list) /* declare [-aAfFirx] name [name ...] */
|
||||
{
|
||||
char *value, *name;
|
||||
int offset, aflags, wflags;
|
||||
char *value, *name, *oldname;
|
||||
int offset, aflags, wflags, created_var, namelen;
|
||||
#if defined (ARRAY_VARS)
|
||||
int making_array_special, compound_array_assign, simple_array_assign;
|
||||
int var_exists, array_exists, creating_array, array_subscript_assignment;
|
||||
@@ -297,6 +297,7 @@ declare_internal (list, local_var)
|
||||
wflags = list->word->flags;
|
||||
offset = assignment (name, 0);
|
||||
aflags = 0;
|
||||
created_var = 0;
|
||||
|
||||
if (local_var && variable_context && STREQ (name, "-"))
|
||||
{
|
||||
@@ -332,27 +333,10 @@ declare_internal (list, local_var)
|
||||
assign_error++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
else if (valid_array_reference (value, 0))
|
||||
{
|
||||
t = array_variable_name (value, (int *)NULL, (int *)NULL);
|
||||
if (t && STREQ (name, t))
|
||||
{
|
||||
if (variable_context == 0)
|
||||
{
|
||||
free (t);
|
||||
builtin_error (_("%s: nameref variable self references not allowed"), name);
|
||||
assign_error++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
else
|
||||
builtin_warning (_("%s: circular name reference"), name);
|
||||
}
|
||||
free (t);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
/* disallow self references at global scope, warn at function scope */
|
||||
if (STREQ (name, value))
|
||||
if (check_selfref (name, value, 0))
|
||||
{
|
||||
if (variable_context == 0)
|
||||
{
|
||||
@@ -364,7 +348,7 @@ declare_internal (list, local_var)
|
||||
builtin_warning (_("%s: circular name reference"), name);
|
||||
}
|
||||
#if 1
|
||||
if (value && *value && (aflags & ASS_APPEND) == 0 && valid_nameref_value (value, 0) == 0)
|
||||
if (value && *value && (aflags & ASS_APPEND) == 0 && valid_nameref_value (value, 1) == 0)
|
||||
{
|
||||
builtin_error (_("`%s': invalid variable name for name reference"), value);
|
||||
assign_error++;
|
||||
@@ -374,13 +358,15 @@ declare_internal (list, local_var)
|
||||
}
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
restart_new_var_name:
|
||||
var_exists = array_exists = creating_array = 0;
|
||||
compound_array_assign = simple_array_assign = 0;
|
||||
array_subscript_assignment = 0;
|
||||
subscript_start = (char *)NULL;
|
||||
if (t = strchr (name, '[')) /* ] */
|
||||
{
|
||||
/* If offset != 0 we have already validated any array reference */
|
||||
/* If offset != 0 we have already validated any array reference
|
||||
because assignment() calls skipsubscript() */
|
||||
if (offset == 0 && valid_array_reference (name, 0) == 0)
|
||||
{
|
||||
sh_invalidid (name);
|
||||
@@ -417,6 +403,7 @@ declare_internal (list, local_var)
|
||||
refvar = (SHELL_VAR *)NULL;
|
||||
if (variable_context && mkglobal == 0 && ((flags_on & att_function) == 0))
|
||||
{
|
||||
/* check name for validity here? */
|
||||
#if defined (ARRAY_VARS)
|
||||
if (flags_on & att_assoc)
|
||||
var = make_local_assoc_variable (name);
|
||||
@@ -446,6 +433,7 @@ declare_internal (list, local_var)
|
||||
/* otherwise we have a var at the right context */
|
||||
}
|
||||
else
|
||||
/* XXX - check name for validity here with valid_nameref_value */
|
||||
var = make_local_variable (name); /* sets att_invisible for new vars */
|
||||
if (var == 0)
|
||||
{
|
||||
@@ -592,8 +580,50 @@ declare_internal (list, local_var)
|
||||
var = mkglobal ? find_global_variable (nameref_cell (refvar)) : find_variable (nameref_cell (refvar));
|
||||
if (refvar && var == 0)
|
||||
{
|
||||
free (name);
|
||||
name = savestring (nameref_cell (refvar));
|
||||
oldname = name; /* need to free this */
|
||||
|
||||
namelen = strlen (nameref_cell (refvar));
|
||||
#if defined (ARRAY_VARS)
|
||||
if (subscript_start)
|
||||
{
|
||||
*subscript_start = '['; /*]*/
|
||||
namelen += strlen (subscript_start);
|
||||
}
|
||||
#endif
|
||||
name = xmalloc (namelen + 2 + strlen (value) + 1);
|
||||
strcpy (name, nameref_cell (refvar));
|
||||
#if defined (ARRAY_VARS)
|
||||
if (subscript_start)
|
||||
strcpy (name + strlen (nameref_cell (refvar)), subscript_start);
|
||||
#endif
|
||||
/* We are committed to using the new name, so reset */
|
||||
if (offset)
|
||||
{
|
||||
/* Rebuild assignment and restore offset and value */
|
||||
if (aflags & ASS_APPEND)
|
||||
name[namelen++] = '+';
|
||||
name[namelen++] = '=';
|
||||
if (value && *value)
|
||||
strcpy (name + namelen, value);
|
||||
else
|
||||
name[namelen] = '\0';
|
||||
offset = assignment (name, 0);
|
||||
/* if offset was valid previously, but the substituting
|
||||
of the nameref value results in an invalid assignment,
|
||||
throw an invalid identifier error */
|
||||
if (offset == 0)
|
||||
{
|
||||
free (oldname);
|
||||
sh_invalidid (name);
|
||||
assign_error++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
name[offset] = '\0';
|
||||
value = name + namelen;
|
||||
}
|
||||
free (oldname);
|
||||
goto restart_new_var_name;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
if (var == 0)
|
||||
@@ -622,13 +652,9 @@ declare_internal (list, local_var)
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (offset)
|
||||
/* 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, ASS_FORCE) : bind_variable (name, (char *)NULL, ASS_FORCE);
|
||||
if (var && no_invisible_vars == 0)
|
||||
if (var && offset == 0 && no_invisible_vars == 0)
|
||||
VSETATTR (var, att_invisible);
|
||||
}
|
||||
if (var == 0)
|
||||
@@ -636,6 +662,7 @@ declare_internal (list, local_var)
|
||||
/* Has to appear in brackets */
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
created_var = 1;
|
||||
}
|
||||
/* Can't take an existing array variable and make it a nameref */
|
||||
else if ((array_p (var) || assoc_p (var)) && (flags_on & att_nameref))
|
||||
@@ -775,14 +802,14 @@ declare_internal (list, local_var)
|
||||
VUNSETATTR (var, flags_off);
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
aflags |= ASS_FORCE;
|
||||
if (offset && compound_array_assign)
|
||||
assign_array_var_from_string (var, value, aflags);
|
||||
assign_array_var_from_string (var, value, aflags|ASS_FORCE);
|
||||
else if (simple_array_assign && subscript_start)
|
||||
{
|
||||
/* declare [-aA] name[N]=value */
|
||||
*subscript_start = '['; /* ] */
|
||||
var = assign_array_element (name, value, 0); /* XXX - not aflags */
|
||||
/* XXX - problem here with appending */
|
||||
var = assign_array_element (name, value, aflags&ASS_APPEND); /* XXX - not aflags */
|
||||
*subscript_start = '\0';
|
||||
if (var == 0) /* some kind of assignment error */
|
||||
{
|
||||
@@ -796,12 +823,13 @@ declare_internal (list, local_var)
|
||||
{
|
||||
/* let bind_{array,assoc}_variable take care of this. */
|
||||
if (assoc_p (var))
|
||||
bind_assoc_variable (var, name, savestring ("0"), value, aflags);
|
||||
bind_assoc_variable (var, name, savestring ("0"), value, aflags|ASS_FORCE);
|
||||
else
|
||||
bind_array_variable (name, 0, value, aflags);
|
||||
bind_array_variable (name, 0, value, aflags|ASS_FORCE);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
/* XXX - no ASS_FORCE here */
|
||||
/* bind_variable_value duplicates the essential internals of
|
||||
bind_variable() */
|
||||
if (offset)
|
||||
@@ -811,11 +839,14 @@ declare_internal (list, local_var)
|
||||
v = bind_variable_value (var, value, aflags);
|
||||
if (v == 0 && (onref || nameref_p (var)))
|
||||
{
|
||||
if (valid_nameref_value (value, 0) == 0)
|
||||
if (valid_nameref_value (value, 1) == 0)
|
||||
sh_invalidid (value);
|
||||
assign_error++;
|
||||
/* XXX - unset this variable? or leave it as normal var? */
|
||||
delete_var (var->name, mkglobal ? global_variables : shell_variables);
|
||||
if (created_var)
|
||||
delete_var (var->name, mkglobal ? global_variables : shell_variables);
|
||||
flags_on |= onref; /* undo change from above */
|
||||
flags_off |= offref;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,6 +267,7 @@ parse_and_execute (string, from_file, flags)
|
||||
current_token = '\n'; /* reset_parser() ? */
|
||||
|
||||
with_input_from_string (string, from_file);
|
||||
clear_shell_input_line ();
|
||||
while (*(bash_input.location.string))
|
||||
{
|
||||
command = (COMMAND *)NULL;
|
||||
@@ -497,7 +498,7 @@ parse_string (string, from_file, flags, endp)
|
||||
sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &ps_sigmask);
|
||||
#endif
|
||||
|
||||
/* itrace("parse_string: `%s'", string); */
|
||||
/*itrace("parse_string: `%s'", string);*/
|
||||
/* Reset the line number if the caller wants us to. If we don't reset the
|
||||
line number, we have to subtract one, because we will add one just
|
||||
before executing the next command (resetting the line number sets it to
|
||||
|
||||
+20
-5
@@ -808,7 +808,7 @@ unset_builtin (list)
|
||||
{
|
||||
int unset_function, unset_variable, unset_array, opt, nameref, any_failed;
|
||||
int global_unset_func, global_unset_var;
|
||||
char *name;
|
||||
char *name, *tname;
|
||||
|
||||
unset_function = unset_variable = unset_array = nameref = any_failed = 0;
|
||||
global_unset_func = global_unset_var = 0;
|
||||
@@ -859,7 +859,7 @@ unset_builtin (list)
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
unset_array = 0;
|
||||
if (!unset_function && valid_array_reference (name, 0))
|
||||
if (!unset_function && nameref == 0 && valid_array_reference (name, 0))
|
||||
{
|
||||
t = strchr (name, '[');
|
||||
*t++ = '\0';
|
||||
@@ -897,7 +897,7 @@ unset_builtin (list)
|
||||
find a function after unsuccessfully searching for a variable,
|
||||
note that we're acting on a function now as if -f were
|
||||
supplied. The readonly check below takes care of it. */
|
||||
if (var == 0 && unset_variable == 0 && unset_function == 0)
|
||||
if (var == 0 && nameref == 0 && unset_variable == 0 && unset_function == 0)
|
||||
{
|
||||
if (var = find_function (name))
|
||||
unset_function = 1;
|
||||
@@ -932,7 +932,22 @@ unset_builtin (list)
|
||||
if (var == 0 && nameref == 0 && unset_function == 0)
|
||||
{
|
||||
var = find_variable_last_nameref (name, 0);
|
||||
tem = (var && nameref_p (var)) ? unbind_variable (nameref_cell (var)) : unbind_variable (name);
|
||||
if (var && nameref_p (var))
|
||||
{
|
||||
#if defined (ARRAY_VARS)
|
||||
if (valid_array_reference (nameref_cell (var), 0))
|
||||
{
|
||||
tname = savestring (nameref_cell (var));
|
||||
if (var = array_variable_part (tname, &t, 0))
|
||||
tem = unbind_array_element (var, t);
|
||||
free (tname);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
tem = unbind_variable (nameref_cell (var));
|
||||
}
|
||||
else
|
||||
tem = unbind_variable (name);
|
||||
}
|
||||
else
|
||||
tem = unset_function ? unbind_func (name) : (nameref ? unbind_nameref (name) : unbind_variable (name));
|
||||
@@ -941,7 +956,7 @@ unset_builtin (list)
|
||||
is specified, the name refers to a variable; if a variable by
|
||||
that name does not exist, a function by that name, if any,
|
||||
shall be unset.'' */
|
||||
if (tem == -1 && unset_function == 0 && unset_variable == 0)
|
||||
if (tem == -1 && nameref == 0 && unset_function == 0 && unset_variable == 0)
|
||||
tem = unbind_func (name);
|
||||
|
||||
name = list->word->word; /* reset above for namerefs */
|
||||
|
||||
@@ -244,7 +244,10 @@ parse_command ()
|
||||
/* Allow the execution of a random command just before the printing
|
||||
of each primary prompt. If the shell variable PROMPT_COMMAND
|
||||
is set then the value of it is the command to execute. */
|
||||
if (interactive && bash_input.type != st_string)
|
||||
/* The tests are a combination of SHOULD_PROMPT() and prompt_again()
|
||||
from parse.y, which are the conditions under which the prompt is
|
||||
actually printed. */
|
||||
if (interactive && bash_input.type != st_string && parser_expanding_alias() == 0)
|
||||
{
|
||||
command_to_execute = get_string_value ("PROMPT_COMMAND");
|
||||
if (command_to_execute)
|
||||
|
||||
@@ -116,6 +116,8 @@ extern int parser_expanding_alias __P((void));
|
||||
extern void parser_save_alias __P((void));
|
||||
extern void parser_restore_alias __P((void));
|
||||
|
||||
extern void clear_shell_input_line __P((void));
|
||||
|
||||
extern char *decode_prompt_string __P((char *));
|
||||
|
||||
extern int get_current_prompt_level __P((void));
|
||||
|
||||
@@ -228,21 +228,21 @@ legal_identifier (name)
|
||||
}
|
||||
|
||||
/* 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
|
||||
variable. FLAGS can be 2, in which case the name is going to be used
|
||||
to create a variable. Other values are currently unused, but could
|
||||
be used to allow values to be stored and indirectly referenced, but
|
||||
not used in assignments. */
|
||||
int
|
||||
valid_nameref_value (name, for_assignment)
|
||||
valid_nameref_value (name, flags)
|
||||
char *name;
|
||||
int for_assignment;
|
||||
int flags;
|
||||
{
|
||||
intmax_t r;
|
||||
|
||||
if (name == 0 || *name == 0)
|
||||
return 0;
|
||||
|
||||
/* valid identifier */
|
||||
#if defined (ARRAY_VARS)
|
||||
if (legal_identifier (name) || valid_array_reference (name, 0))
|
||||
if (legal_identifier (name) || (flags != 2 && valid_array_reference (name, 0)))
|
||||
#else
|
||||
if (legal_identifier (name))
|
||||
#endif
|
||||
@@ -251,6 +251,33 @@ valid_nameref_value (name, for_assignment)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
check_selfref (name, value, flags)
|
||||
const char *name;
|
||||
const char *value;
|
||||
int flags;
|
||||
{
|
||||
char *t;
|
||||
|
||||
if (STREQ (name, value))
|
||||
return 1;
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
if (valid_array_reference (value, 0))
|
||||
{
|
||||
t = array_variable_name (value, (int *)NULL, (int *)NULL);
|
||||
if (t && STREQ (name, t))
|
||||
{
|
||||
free (t);
|
||||
return 1;
|
||||
}
|
||||
free (t);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0; /* not a self reference */
|
||||
}
|
||||
|
||||
/* Make sure that WORD is a valid shell identifier, i.e.
|
||||
does not contain a dollar sign, nor is quoted in any way. Nor
|
||||
does it consist of all digits. If CHECK_WORD is non-zero,
|
||||
|
||||
@@ -290,6 +290,7 @@ extern int importable_function_name __P((char *, size_t));
|
||||
extern int exportable_function_name __P((char *));
|
||||
extern int check_identifier __P((WORD_DESC *, int));
|
||||
extern int valid_nameref_value __P((char *, int));
|
||||
extern int check_selfref __P((const char *, const char *, int));
|
||||
extern int legal_alias_name __P((char *, int));
|
||||
extern int assignment __P((const char *, int));
|
||||
|
||||
|
||||
@@ -4687,8 +4687,6 @@ set_maxchild (nchild)
|
||||
{
|
||||
static int lmaxchild = -1;
|
||||
|
||||
itrace("set_maxchild (%d)", nchild);
|
||||
|
||||
if (lmaxchild < 0)
|
||||
lmaxchild = getmaxchild ();
|
||||
if (lmaxchild < 0)
|
||||
|
||||
@@ -1961,6 +1961,13 @@ parser_restore_alias ()
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
clear_shell_input_line ()
|
||||
{
|
||||
if (shell_input_line)
|
||||
shell_input_line[shell_input_line_index = 0] = '\0';
|
||||
}
|
||||
|
||||
/* Return a line of text, taken from wherever yylex () reads input.
|
||||
If there is no more input, then we return NULL. If REMOVE_QUOTED_NEWLINE
|
||||
is non-zero, we remove unquoted \<newline> pairs. This is used by
|
||||
@@ -4696,7 +4703,7 @@ read_token_word (character)
|
||||
|
||||
/* Non-zero means to ignore the value of the next character, and just
|
||||
to add it no matter what. */
|
||||
int pass_next_character;
|
||||
int pass_next_character;
|
||||
|
||||
/* The current delimiting character. */
|
||||
int cd;
|
||||
@@ -4993,7 +5000,6 @@ read_token_word (character)
|
||||
}
|
||||
|
||||
got_character:
|
||||
|
||||
if (character == CTLESC || character == CTLNUL)
|
||||
{
|
||||
RESIZE_MALLOCED_BUFFER (token, token_index, 2, token_buffer_size,
|
||||
|
||||
@@ -1381,10 +1381,29 @@ redir_varvalue (redir)
|
||||
/* XXX - handle set -u here? */
|
||||
#if defined (ARRAY_VARS)
|
||||
if (vr = valid_array_reference (w, 0))
|
||||
v = array_variable_part (w, &sub, &len);
|
||||
{
|
||||
v = array_variable_part (w, &sub, &len);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
v = find_variable (w);
|
||||
{
|
||||
v = find_variable (w);
|
||||
#if defined (ARRAY_VARS)
|
||||
if (v == 0)
|
||||
{
|
||||
v = find_variable_last_nameref (w, 0);
|
||||
if (v && nameref_p (v))
|
||||
{
|
||||
w = nameref_cell (v);
|
||||
if (vr = valid_array_reference (w, 0))
|
||||
v = array_variable_part (w, &sub, &len);
|
||||
else
|
||||
v = find_variable (w);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (v == 0 || invisible_p (v))
|
||||
return -1;
|
||||
|
||||
|
||||
@@ -10294,7 +10294,12 @@ make_internal_declare (word, option, cmd)
|
||||
w = make_word (word);
|
||||
|
||||
t = assignment (w->word, 0);
|
||||
w->word[t] = '\0';
|
||||
if (w->word[t] == '=')
|
||||
{
|
||||
w->word[t] = '\0';
|
||||
if (w->word[t - 1] == '+') /* cut off any append op */
|
||||
w->word[t - 1] = '\0';
|
||||
}
|
||||
|
||||
wl = make_word_list (w, (WORD_LIST *)NULL);
|
||||
wl = make_word_list (make_word (option), wl);
|
||||
@@ -10419,6 +10424,8 @@ shell_expand_word_list (tlist, eflags)
|
||||
/* Now transform the word as ksh93 appears to do and go on */
|
||||
t = assignment (tlist->word->word, 0);
|
||||
tlist->word->word[t] = '\0';
|
||||
if (tlist->word->word[t - 1] == '+')
|
||||
tlist->word->word[t - 1] = '\0'; /* cut off append op */
|
||||
tlist->word->flags &= ~(W_ASSIGNMENT|W_NOSPLIT|W_COMPASSIGN|W_ASSIGNARG|W_ASSIGNASSOC|W_ASSIGNARRAY);
|
||||
}
|
||||
#endif
|
||||
|
||||
+7
-4
@@ -291,6 +291,7 @@ declare -n ref="var"
|
||||
./nameref14.sub: line 32: typeset: var: not found
|
||||
declare -n ref="var"
|
||||
./nameref15.sub: line 1: local: warning: a: circular name reference
|
||||
./nameref15.sub: line 1: warning: a: circular name reference
|
||||
./nameref15.sub: line 1: `a[0]': not a valid identifier
|
||||
declare -a a=([0]="0")
|
||||
./nameref15.sub: line 1: local: warning: a: circular name reference
|
||||
@@ -299,6 +300,7 @@ declare -a a=([0]="0")
|
||||
declare -a a=([0]="X")
|
||||
declare -a b=([0]="X")
|
||||
./nameref15.sub: line 1: local: warning: a: circular name reference
|
||||
./nameref15.sub: line 1: warning: a: circular name reference
|
||||
./nameref15.sub: line 1: `a[0]': not a valid identifier
|
||||
declare -a b=([0]="0")
|
||||
./nameref15.sub: line 19: typeset: warning: ref: circular name reference
|
||||
@@ -309,14 +311,15 @@ inside
|
||||
outside X
|
||||
./nameref15.sub: line 29: typeset: ref: nameref variable self references not allowed
|
||||
./nameref15.sub: line 31: ref: nameref variable self references not allowed
|
||||
./nameref15.sub: line 32: typeset: ref: not found
|
||||
declare -- ref="4"
|
||||
declare -n ref="re"
|
||||
declare -n ref="re"
|
||||
declare -- re="4"
|
||||
4
|
||||
declare -n foo="var[@]"
|
||||
declare -n ref="var[@]"
|
||||
./nameref15.sub: line 47: var[@]: bad array subscript
|
||||
./nameref15.sub: line 48: var[@]: bad array subscript
|
||||
declare -n bar="var[@]"
|
||||
./nameref15.sub: line 52: var[@]: bad array subscript
|
||||
./nameref15.sub: line 53: var[@]: bad array subscript
|
||||
declare -n r1="y"
|
||||
declare -n r2="x"
|
||||
./nameref16.sub: line 12: typeset: x: not found
|
||||
|
||||
+2
-1
@@ -31,10 +31,11 @@ typeset -n ref=ref
|
||||
typeset -n ref=re ref+=f
|
||||
typeset -p ref
|
||||
ref=4
|
||||
typeset -p ref
|
||||
typeset -p ref re
|
||||
|
||||
export ref
|
||||
printenv ref
|
||||
printenv re
|
||||
|
||||
unset ref ; unset -n ref
|
||||
unset foo; unset -n foo
|
||||
|
||||
+1
-10
@@ -2719,15 +2719,6 @@ 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))
|
||||
@@ -2949,7 +2940,7 @@ bind_variable_value (var, value, aflags)
|
||||
else
|
||||
{
|
||||
t = make_variable_value (var, value, aflags);
|
||||
if (STREQ (name_cell (var), t))
|
||||
if ((aflags & (ASS_NAMEREF|ASS_FORCE)) == ASS_NAMEREF && check_selfref (name_cell (var), t, 0))
|
||||
{
|
||||
if (variable_context)
|
||||
internal_warning (_("%s: circular name reference"), name_cell (var));
|
||||
|
||||
Reference in New Issue
Block a user