mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-27 15:43:18 +02:00
commit bash-20131213 snapshot
This commit is contained in:
@@ -5380,6 +5380,10 @@ support/shobj-conf
|
||||
- add support for Darwin 13 (Mac OS X 10.9, Mavericks). Based on a
|
||||
report by Ludwig Schwardt <ludwig.schwardt@gmail.com>
|
||||
|
||||
11/20
|
||||
-----
|
||||
[bash-4.3-rc1 frozen]
|
||||
|
||||
11/24
|
||||
-----
|
||||
builtins/printf.def
|
||||
@@ -5405,3 +5409,37 @@ doc/bashref.texi
|
||||
lib/readline/{histexpand.c
|
||||
- get_history_event: account for current_history() possibly returning
|
||||
NULL. Report and fix from Pankaj Sharma <pankaj.s01@samsung.com>
|
||||
|
||||
|
||||
12/11
|
||||
-----
|
||||
|
||||
lib/readline/parse-colors.c
|
||||
- get_funky_string: don't call abort if we see something we can't
|
||||
parse; just return an error
|
||||
- _rl_parse_colors: if we encounter an error while parsing $LS_COLORS
|
||||
we need to leave _rl_color_ext_list as NULL after freeing its
|
||||
elements, then turn off _rl_colored_stats. Report and fix from Martin
|
||||
Wesdorp <mwesdorp@casema.nl>
|
||||
|
||||
12/13
|
||||
-----
|
||||
|
||||
lib/readline/parse-colors.c
|
||||
- _rl_parse_colors: if we encounter an unrecognized prefix, throw an
|
||||
error but try to recover and go on to the next specification
|
||||
|
||||
variables.c
|
||||
- make_local_variable: for new variables this function creates, set
|
||||
the att_invisible attribute. All callers from declare_internal.
|
||||
Indirectly, this is a fix for bug with `declare -n var; var=foo;'
|
||||
reported by Pierre Gaston <pierre.gaston@gmail.com>
|
||||
- bind_variable: if assigning to nameref variable that doesn't have
|
||||
a value yet (e.g., with `declare -n var; var=foo'), don't try to
|
||||
use the unset name. Fixes a segfault reported by Pierre Gaston
|
||||
<pierre.gaston@gmail.com>
|
||||
|
||||
execute_cmd.c
|
||||
- execute_command_internal: make sure last_command_exit_value is set
|
||||
to 0 after any command executed in the background. Fixes bug
|
||||
reported by Martin Kealey <martin@kurahaupo.gen.nz>
|
||||
|
||||
+5441
File diff suppressed because it is too large
Load Diff
@@ -989,6 +989,7 @@ tests/nameref3.sub f
|
||||
tests/nameref4.sub f
|
||||
tests/nameref5.sub f
|
||||
tests/nameref6.sub f
|
||||
tests/nameref7.sub f
|
||||
tests/nameref.right f
|
||||
tests/new-exp.tests f
|
||||
tests/new-exp1.sub f
|
||||
|
||||
@@ -399,7 +399,7 @@ declare_internal (list, local_var)
|
||||
}
|
||||
else
|
||||
#endif
|
||||
var = make_local_variable (name);
|
||||
var = make_local_variable (name); /* sets att_invisible for new vars */
|
||||
if (var == 0)
|
||||
{
|
||||
any_failed++;
|
||||
|
||||
@@ -0,0 +1,713 @@
|
||||
This file is declare.def, from which is created declare.c.
|
||||
It implements the builtins "declare" and "local" in Bash.
|
||||
|
||||
Copyright (C) 1987-2012 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$PRODUCES declare.c
|
||||
|
||||
$BUILTIN declare
|
||||
$FUNCTION declare_builtin
|
||||
$SHORT_DOC declare [-aAfFgilnrtux] [-p] [name[=value] ...]
|
||||
Set variable values and attributes.
|
||||
|
||||
Declare variables and give them attributes. If no NAMEs are given,
|
||||
display the attributes and values of all variables.
|
||||
|
||||
Options:
|
||||
-f restrict action or display to function names and definitions
|
||||
-F restrict display to function names only (plus line number and
|
||||
source file when debugging)
|
||||
-g create global variables when used in a shell function; otherwise
|
||||
ignored
|
||||
-p display the attributes and value of each NAME
|
||||
|
||||
Options which set attributes:
|
||||
-a to make NAMEs indexed arrays (if supported)
|
||||
-A to make NAMEs associative arrays (if supported)
|
||||
-i to make NAMEs have the `integer' attribute
|
||||
-l to convert NAMEs to lower case on assignment
|
||||
-n make NAME a reference to the variable named by its value
|
||||
-r to make NAMEs readonly
|
||||
-t to make NAMEs have the `trace' attribute
|
||||
-u to convert NAMEs to upper case on assignment
|
||||
-x to make NAMEs export
|
||||
|
||||
Using `+' instead of `-' turns off the given attribute.
|
||||
|
||||
Variables with the integer attribute have arithmetic evaluation (see
|
||||
the `let' command) performed when the variable is assigned a value.
|
||||
|
||||
When used in a function, `declare' makes NAMEs local, as with the `local'
|
||||
command. The `-g' option suppresses this behavior.
|
||||
|
||||
Exit Status:
|
||||
Returns success unless an invalid option is supplied or a variable
|
||||
assignment error occurs.
|
||||
$END
|
||||
|
||||
$BUILTIN typeset
|
||||
$FUNCTION declare_builtin
|
||||
$SHORT_DOC typeset [-aAfFgilrtux] [-p] name[=value] ...
|
||||
Set variable values and attributes.
|
||||
|
||||
Obsolete. See `help declare'.
|
||||
$END
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifdef _MINIX
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../bashansi.h"
|
||||
#include "../bashintl.h"
|
||||
|
||||
#include "../shell.h"
|
||||
#include "common.h"
|
||||
#include "builtext.h"
|
||||
#include "bashgetopt.h"
|
||||
|
||||
extern int array_needs_making;
|
||||
extern int posixly_correct;
|
||||
|
||||
static int declare_internal __P((register WORD_LIST *, int));
|
||||
|
||||
/* Declare or change variable attributes. */
|
||||
int
|
||||
declare_builtin (list)
|
||||
register WORD_LIST *list;
|
||||
{
|
||||
return (declare_internal (list, 0));
|
||||
}
|
||||
|
||||
$BUILTIN local
|
||||
$FUNCTION local_builtin
|
||||
$SHORT_DOC local [option] name[=value] ...
|
||||
Define local variables.
|
||||
|
||||
Create a local variable called NAME, and give it VALUE. OPTION can
|
||||
be any option accepted by `declare'.
|
||||
|
||||
Local variables can only be used within a function; they are visible
|
||||
only to the function where they are defined and its children.
|
||||
|
||||
Exit Status:
|
||||
Returns success unless an invalid option is supplied, a variable
|
||||
assignment error occurs, or the shell is not executing a function.
|
||||
$END
|
||||
int
|
||||
local_builtin (list)
|
||||
register WORD_LIST *list;
|
||||
{
|
||||
if (variable_context)
|
||||
return (declare_internal (list, 1));
|
||||
else
|
||||
{
|
||||
builtin_error (_("can only be used in a function"));
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
# define DECLARE_OPTS "+acfgilnprtuxAF"
|
||||
#else
|
||||
# define DECLARE_OPTS "+cfgilnprtuxF"
|
||||
#endif
|
||||
|
||||
/* The workhorse function. */
|
||||
static int
|
||||
declare_internal (list, local_var)
|
||||
register WORD_LIST *list;
|
||||
int local_var;
|
||||
{
|
||||
int flags_on, flags_off, *flags;
|
||||
int any_failed, assign_error, pflag, nodefs, opt, mkglobal, onref, offref;
|
||||
char *t, *subscript_start;
|
||||
SHELL_VAR *var, *v, *refvar;
|
||||
FUNCTION_DEF *shell_fn;
|
||||
|
||||
flags_on = flags_off = any_failed = assign_error = pflag = nodefs = mkglobal = 0;
|
||||
refvar = (SHELL_VAR *)NULL;
|
||||
reset_internal_getopt ();
|
||||
while ((opt = internal_getopt (list, DECLARE_OPTS)) != EOF)
|
||||
{
|
||||
flags = list_opttype == '+' ? &flags_off : &flags_on;
|
||||
|
||||
switch (opt)
|
||||
{
|
||||
case 'a':
|
||||
#if defined (ARRAY_VARS)
|
||||
*flags |= att_array;
|
||||
break;
|
||||
#else
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
#endif
|
||||
case 'A':
|
||||
#if defined (ARRAY_VARS)
|
||||
*flags |= att_assoc;
|
||||
break;
|
||||
#else
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
#endif
|
||||
case 'p':
|
||||
if (local_var == 0)
|
||||
pflag++;
|
||||
break;
|
||||
case 'F':
|
||||
nodefs++;
|
||||
*flags |= att_function;
|
||||
break;
|
||||
case 'f':
|
||||
*flags |= att_function;
|
||||
break;
|
||||
case 'g':
|
||||
if (flags == &flags_on)
|
||||
mkglobal = 1;
|
||||
break;
|
||||
case 'i':
|
||||
*flags |= att_integer;
|
||||
break;
|
||||
case 'n':
|
||||
*flags |= att_nameref;
|
||||
break;
|
||||
case 'r':
|
||||
*flags |= att_readonly;
|
||||
break;
|
||||
case 't':
|
||||
*flags |= att_trace;
|
||||
break;
|
||||
case 'x':
|
||||
*flags |= att_exported;
|
||||
array_needs_making = 1;
|
||||
break;
|
||||
#if defined (CASEMOD_ATTRS)
|
||||
# if defined (CASEMOD_CAPCASE)
|
||||
case 'c':
|
||||
*flags |= att_capcase;
|
||||
if (flags == &flags_on)
|
||||
flags_off |= att_uppercase|att_lowercase;
|
||||
break;
|
||||
# endif
|
||||
case 'l':
|
||||
*flags |= att_lowercase;
|
||||
if (flags == &flags_on)
|
||||
flags_off |= att_capcase|att_uppercase;
|
||||
break;
|
||||
case 'u':
|
||||
*flags |= att_uppercase;
|
||||
if (flags == &flags_on)
|
||||
flags_off |= att_capcase|att_lowercase;
|
||||
break;
|
||||
#endif /* CASEMOD_ATTRS */
|
||||
default:
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
}
|
||||
|
||||
list = loptend;
|
||||
|
||||
/* If there are no more arguments left, then we just want to show
|
||||
some variables. */
|
||||
if (list == 0) /* declare -[aAfFirtx] */
|
||||
{
|
||||
/* Show local variables defined at this context level if this is
|
||||
the `local' builtin. */
|
||||
if (local_var)
|
||||
{
|
||||
register SHELL_VAR **vlist;
|
||||
register int i;
|
||||
|
||||
vlist = all_local_variables ();
|
||||
|
||||
if (vlist)
|
||||
{
|
||||
for (i = 0; vlist[i]; i++)
|
||||
print_assignment (vlist[i]);
|
||||
|
||||
free (vlist);
|
||||
}
|
||||
}
|
||||
else if (pflag && (flags_on == 0 || flags_on == att_function))
|
||||
show_all_var_attributes (flags_on == 0, nodefs);
|
||||
else if (flags_on == 0)
|
||||
return (set_builtin ((WORD_LIST *)NULL));
|
||||
else
|
||||
set_or_show_attributes ((WORD_LIST *)NULL, flags_on, nodefs);
|
||||
|
||||
return (sh_chkwrite (EXECUTION_SUCCESS));
|
||||
}
|
||||
|
||||
if (pflag) /* declare -p [-aAfFirtx] name [name...] */
|
||||
{
|
||||
for (any_failed = 0; list; list = list->next)
|
||||
{
|
||||
if (flags_on & att_function)
|
||||
pflag = show_func_attributes (list->word->word, nodefs);
|
||||
else
|
||||
pflag = show_name_attributes (list->word->word, nodefs);
|
||||
if (pflag)
|
||||
{
|
||||
sh_notfound (list->word->word);
|
||||
any_failed++;
|
||||
}
|
||||
}
|
||||
return (sh_chkwrite (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS));
|
||||
}
|
||||
|
||||
#define NEXT_VARIABLE() free (name); list = list->next; continue
|
||||
|
||||
/* There are arguments left, so we are making variables. */
|
||||
while (list) /* declare [-aAfFirx] name [name ...] */
|
||||
{
|
||||
char *value, *name;
|
||||
int offset, aflags;
|
||||
#if defined (ARRAY_VARS)
|
||||
int making_array_special, compound_array_assign, simple_array_assign;
|
||||
#endif
|
||||
|
||||
name = savestring (list->word->word);
|
||||
offset = assignment (name, 0);
|
||||
aflags = 0;
|
||||
|
||||
if (offset) /* declare [-aAfFirx] name=value */
|
||||
{
|
||||
name[offset] = '\0';
|
||||
value = name + offset + 1;
|
||||
if (name[offset - 1] == '+')
|
||||
{
|
||||
aflags |= ASS_APPEND;
|
||||
name[offset - 1] = '\0';
|
||||
}
|
||||
}
|
||||
else
|
||||
value = "";
|
||||
|
||||
/* Do some lexical error checking on the LHS and RHS of the assignment
|
||||
that is specific to nameref variables. */
|
||||
if (flags_on & att_nameref)
|
||||
{
|
||||
#if defined (ARRAY_VARIABLES)
|
||||
if (valid_array_reference (name))
|
||||
{
|
||||
builtin_error (_("%s: reference variable cannot be an array"), name);
|
||||
assign_error++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
/* disallow self references at global scope */
|
||||
if (STREQ (name, value) && variable_context == 0)
|
||||
{
|
||||
builtin_error (_("%s: nameref variable self references not allowed"), name);
|
||||
assign_error++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
compound_array_assign = simple_array_assign = 0;
|
||||
subscript_start = (char *)NULL;
|
||||
if (t = strchr (name, '[')) /* ] */
|
||||
{
|
||||
/* If offset != 0 we have already validated any array reference */
|
||||
if (offset == 0 && valid_array_reference (name) == 0)
|
||||
{
|
||||
sh_invalidid (name);
|
||||
assign_error++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
subscript_start = t;
|
||||
*t = '\0';
|
||||
making_array_special = 1;
|
||||
}
|
||||
else
|
||||
making_array_special = 0;
|
||||
#endif
|
||||
|
||||
/* If we're in posix mode or not looking for a shell function (since
|
||||
shell function names don't have to be valid identifiers when the
|
||||
shell's not in posix mode), check whether or not the argument is a
|
||||
valid, well-formed shell identifier. */
|
||||
if ((posixly_correct || (flags_on & att_function) == 0) && legal_identifier (name) == 0)
|
||||
{
|
||||
sh_invalidid (name);
|
||||
assign_error++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
|
||||
/* If VARIABLE_CONTEXT has a non-zero value, then we are executing
|
||||
inside of a function. This means we should make local variables,
|
||||
not global ones. */
|
||||
|
||||
/* XXX - this has consequences when we're making a local copy of a
|
||||
variable that was in the temporary environment. Watch out
|
||||
for this. */
|
||||
refvar = (SHELL_VAR *)NULL;
|
||||
if (variable_context && mkglobal == 0 && ((flags_on & att_function) == 0))
|
||||
{
|
||||
/* Is there already a local variable by this name? */
|
||||
v = find_variable (name);
|
||||
if (v == 0 || local_p (v) == 0 || tempvar_p (v) == 0 || v->context != variable_context)
|
||||
v = 0;
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
if (flags_on & att_assoc)
|
||||
var = make_local_assoc_variable (name);
|
||||
else if ((flags_on & att_array) || making_array_special)
|
||||
var = make_local_array_variable (name, making_array_special);
|
||||
else
|
||||
#endif
|
||||
#if 0
|
||||
/* XXX - this doesn't work right yet. */
|
||||
/* See below for rationale for doing this. */
|
||||
if (flags_on & att_nameref)
|
||||
{
|
||||
/* See if we are trying to modify an existing nameref variable */
|
||||
var = find_variable_last_nameref (name);
|
||||
if (var && nameref_p (var) == 0)
|
||||
var = make_local_variable (name);
|
||||
}
|
||||
else if (flags_off & att_nameref)
|
||||
{
|
||||
var = (SHELL_VAR *)NULL;
|
||||
/* See if we are trying to modify an existing nameref variable */
|
||||
refvar = find_variable_last_nameref (name);
|
||||
if (refvar && nameref_p (refvar) == 0)
|
||||
refvar = 0;
|
||||
if (refvar)
|
||||
var = make_local_variable (nameref_cell (refvar));
|
||||
if (var == 0)
|
||||
var = make_local_variable (name);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
var = make_local_variable (name);
|
||||
if (var == 0)
|
||||
{
|
||||
any_failed++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
#if 0
|
||||
/* v != 0 means that this is not a local variable at this context */
|
||||
if (offset == 0 && v)
|
||||
VSETATTR (var, att_invisible);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
var = (SHELL_VAR *)NULL;
|
||||
|
||||
/* If we are declaring a function, then complain about it in some way.
|
||||
We don't let people make functions by saying `typeset -f foo=bar'. */
|
||||
|
||||
/* There should be a way, however, to let people look at a particular
|
||||
function definition by saying `typeset -f foo'. */
|
||||
|
||||
if (flags_on & att_function)
|
||||
{
|
||||
if (offset) /* declare -f [-rix] foo=bar */
|
||||
{
|
||||
builtin_error (_("cannot use `-f' to make functions"));
|
||||
free (name);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
else /* declare -f [-rx] name [name...] */
|
||||
{
|
||||
var = find_function (name);
|
||||
|
||||
if (var)
|
||||
{
|
||||
if (readonly_p (var) && (flags_off & att_readonly))
|
||||
{
|
||||
builtin_error (_("%s: readonly function"), name);
|
||||
any_failed++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
|
||||
/* declare -[Ff] name [name...] */
|
||||
if (flags_on == att_function && flags_off == 0)
|
||||
{
|
||||
#if defined (DEBUGGER)
|
||||
if (nodefs && debugging_mode)
|
||||
{
|
||||
shell_fn = find_function_def (var->name);
|
||||
if (shell_fn)
|
||||
printf ("%s %d %s\n", var->name, shell_fn->line, shell_fn->source_file);
|
||||
else
|
||||
printf ("%s\n", var->name);
|
||||
}
|
||||
else
|
||||
#endif /* DEBUGGER */
|
||||
{
|
||||
t = nodefs ? var->name
|
||||
: named_function_string (name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL);
|
||||
printf ("%s\n", t);
|
||||
any_failed = sh_chkwrite (any_failed);
|
||||
}
|
||||
}
|
||||
else /* declare -[fF] -[rx] name [name...] */
|
||||
{
|
||||
VSETATTR (var, flags_on);
|
||||
VUNSETATTR (var, flags_off);
|
||||
}
|
||||
}
|
||||
else
|
||||
any_failed++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
}
|
||||
else /* declare -[aAirx] name [name...] */
|
||||
{
|
||||
/* Non-null if we just created or fetched a local variable. */
|
||||
/* Here's what ksh93 seems to do. If we are modifying an existing
|
||||
nameref variable, we don't follow the nameref chain past the last
|
||||
nameref, and we set the nameref variable's value so future
|
||||
references to that variable will return the value of the variable
|
||||
we're assigning right now. */
|
||||
if (var == 0 && (flags_on & att_nameref))
|
||||
{
|
||||
/* See if we are trying to modify an existing nameref variable */
|
||||
var = mkglobal ? find_global_variable_last_nameref (name) : find_variable_last_nameref (name);
|
||||
if (var && nameref_p (var) == 0)
|
||||
var = 0;
|
||||
}
|
||||
/* However, if we're turning off the nameref attribute on an existing
|
||||
nameref variable, we first follow the nameref chain to the end,
|
||||
modify the value of the variable this nameref variable references,
|
||||
*CHANGING ITS VALUE AS A SIDE EFFECT* then turn off the nameref
|
||||
flag *LEAVING THE NAMEREF VARIABLE'S VALUE UNCHANGED* */
|
||||
else if (var == 0 && (flags_off & att_nameref))
|
||||
{
|
||||
/* See if we are trying to modify an existing nameref variable */
|
||||
refvar = mkglobal ? find_global_variable_last_nameref (name) : find_variable_last_nameref (name);
|
||||
if (refvar && nameref_p (refvar) == 0)
|
||||
refvar = 0;
|
||||
if (refvar)
|
||||
var = mkglobal ? find_global_variable (nameref_cell (refvar)) : find_variable (nameref_cell (refvar));
|
||||
}
|
||||
|
||||
if (var == 0)
|
||||
var = mkglobal ? find_global_variable (name) : find_variable (name);
|
||||
|
||||
if (var == 0)
|
||||
{
|
||||
#if defined (ARRAY_VARS)
|
||||
if (flags_on & att_assoc)
|
||||
{
|
||||
var = make_new_assoc_variable (name);
|
||||
if (offset == 0)
|
||||
VSETATTR (var, att_invisible);
|
||||
}
|
||||
else if ((flags_on & att_array) || making_array_special)
|
||||
{
|
||||
var = make_new_array_variable (name);
|
||||
if (offset == 0)
|
||||
VSETATTR (var, att_invisible);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
if (offset)
|
||||
var = mkglobal ? bind_global_variable (name, "", 0) : bind_variable (name, "", 0);
|
||||
else
|
||||
{
|
||||
var = mkglobal ? bind_global_variable (name, (char *)NULL, 0) : bind_variable (name, (char *)NULL, 0);
|
||||
VSETATTR (var, att_invisible);
|
||||
}
|
||||
}
|
||||
/* Can't take an existing array variable and make it a nameref */
|
||||
else if ((array_p (var) || assoc_p (var)) && (flags_on & att_nameref))
|
||||
{
|
||||
builtin_error (_("%s: reference variable cannot be an array"), name);
|
||||
assign_error++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
|
||||
/* Cannot use declare +r to turn off readonly attribute. */
|
||||
if (readonly_p (var) && (flags_off & att_readonly))
|
||||
{
|
||||
sh_readonly (name);
|
||||
any_failed++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
|
||||
/* Cannot use declare to assign value to readonly or noassign
|
||||
variable. */
|
||||
if ((readonly_p (var) || noassign_p (var)) && offset)
|
||||
{
|
||||
if (readonly_p (var))
|
||||
sh_readonly (name);
|
||||
assign_error++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
if ((making_array_special || (flags_on & (att_array|att_assoc)) || array_p (var) || assoc_p (var)) && offset)
|
||||
{
|
||||
int vlen;
|
||||
vlen = STRLEN (value);
|
||||
|
||||
if (value[0] == '(' && value[vlen-1] == ')')
|
||||
compound_array_assign = 1;
|
||||
else
|
||||
simple_array_assign = 1;
|
||||
}
|
||||
|
||||
/* Cannot use declare +a name or declare +A name to remove an
|
||||
array variable. */
|
||||
if (((flags_off & att_array) && array_p (var)) || ((flags_off & att_assoc) && assoc_p (var)))
|
||||
{
|
||||
builtin_error (_("%s: cannot destroy array variables in this way"), name);
|
||||
any_failed++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
|
||||
if ((flags_on & att_array) && assoc_p (var))
|
||||
{
|
||||
builtin_error (_("%s: cannot convert associative to indexed array"), name);
|
||||
any_failed++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
if ((flags_on & att_assoc) && array_p (var))
|
||||
{
|
||||
builtin_error (_("%s: cannot convert indexed to associative array"), name);
|
||||
any_failed++;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
|
||||
/* declare -A name[[n]] makes name an associative array variable. */
|
||||
if (flags_on & att_assoc)
|
||||
{
|
||||
if (assoc_p (var) == 0)
|
||||
var = convert_var_to_assoc (var);
|
||||
}
|
||||
/* declare -a name[[n]] or declare name[n] makes name an indexed
|
||||
array variable. */
|
||||
else if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0 && assoc_p (var) == 0)
|
||||
var = convert_var_to_array (var);
|
||||
#endif /* ARRAY_VARS */
|
||||
|
||||
/* XXX - we note that we are turning on nameref attribute and defer
|
||||
setting it until the assignment has been made so we don't do an
|
||||
inadvertent nameref lookup. Might have to do the same thing for
|
||||
flags_off&att_nameref. */
|
||||
/* XXX - ksh93 makes it an error to set a readonly nameref variable
|
||||
using a single typeset command. */
|
||||
onref = (flags_on & att_nameref);
|
||||
flags_on &= ~att_nameref;
|
||||
#if defined (ARRAY_VARS)
|
||||
if (array_p (var) || assoc_p (var)
|
||||
|| (offset && compound_array_assign)
|
||||
|| simple_array_assign)
|
||||
onref = 0; /* array variables may not be namerefs */
|
||||
#endif
|
||||
|
||||
/* ksh93 seems to do this */
|
||||
offref = (flags_off & att_nameref);
|
||||
flags_off &= ~att_nameref;
|
||||
|
||||
VSETATTR (var, flags_on);
|
||||
VUNSETATTR (var, flags_off);
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
if (offset && compound_array_assign)
|
||||
assign_array_var_from_string (var, value, aflags);
|
||||
else if (simple_array_assign && subscript_start)
|
||||
{
|
||||
/* declare [-aA] name[N]=value */
|
||||
*subscript_start = '['; /* ] */
|
||||
var = assign_array_element (name, value, 0); /* XXX - not aflags */
|
||||
*subscript_start = '\0';
|
||||
if (var == 0) /* some kind of assignment error */
|
||||
{
|
||||
assign_error++;
|
||||
flags_on |= onref;
|
||||
flags_off |= offref;
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
}
|
||||
else if (simple_array_assign)
|
||||
{
|
||||
/* let bind_{array,assoc}_variable take care of this. */
|
||||
if (assoc_p (var))
|
||||
bind_assoc_variable (var, name, savestring ("0"), value, aflags);
|
||||
else
|
||||
bind_array_variable (name, 0, value, aflags);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
/* bind_variable_value duplicates the essential internals of
|
||||
bind_variable() */
|
||||
if (offset)
|
||||
bind_variable_value (var, value, aflags);
|
||||
|
||||
/* If we found this variable in the temporary environment, as with
|
||||
`var=value declare -x var', make sure it is treated identically
|
||||
to `var=value export var'. Do the same for `declare -r' and
|
||||
`readonly'. Preserve the attributes, except for att_tempvar. */
|
||||
/* XXX -- should this create a variable in the global scope, or
|
||||
modify the local variable flags? ksh93 has it modify the
|
||||
global scope.
|
||||
Need to handle case like in set_var_attribute where a temporary
|
||||
variable is in the same table as the function local vars. */
|
||||
if ((flags_on & (att_exported|att_readonly)) && tempvar_p (var))
|
||||
{
|
||||
SHELL_VAR *tv;
|
||||
char *tvalue;
|
||||
|
||||
tv = find_tempenv_variable (var->name);
|
||||
if (tv)
|
||||
{
|
||||
tvalue = var_isset (var) ? savestring (value_cell (var)) : savestring ("");
|
||||
tv = bind_variable (var->name, tvalue, 0);
|
||||
tv->attributes |= var->attributes & ~att_tempvar;
|
||||
if (tv->context > 0)
|
||||
VSETATTR (tv, att_propagate);
|
||||
free (tvalue);
|
||||
}
|
||||
VSETATTR (var, att_propagate);
|
||||
}
|
||||
}
|
||||
|
||||
/* Turn on nameref attribute we deferred above. */
|
||||
/* XXX - should we turn on the noassign attribute for consistency with
|
||||
ksh93 when we turn on the nameref attribute? */
|
||||
VSETATTR (var, onref);
|
||||
flags_on |= onref;
|
||||
VUNSETATTR (var, offref);
|
||||
flags_off |= offref;
|
||||
/* Yuck. ksh93 compatibility */
|
||||
if (refvar)
|
||||
VUNSETATTR (refvar, flags_off);
|
||||
|
||||
stupidly_hack_special_variables (name);
|
||||
|
||||
NEXT_VARIABLE ();
|
||||
}
|
||||
|
||||
return (assign_error ? EX_BADASSIGN
|
||||
: ((any_failed == 0) ? EXECUTION_SUCCESS
|
||||
: EXECUTION_FAILURE));
|
||||
}
|
||||
@@ -675,6 +675,9 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
|
||||
|
||||
run_pending_traps ();
|
||||
|
||||
/* Posix 2013 2.9.3.1: "the exit status of an asynchronous list
|
||||
shall be zero." */
|
||||
last_command_exit_value = 0;
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
+5413
File diff suppressed because it is too large
Load Diff
@@ -283,7 +283,9 @@ get_funky_string (char **dest, const char **src, bool equals_end, size_t *output
|
||||
|
||||
default:
|
||||
/* should we ? */
|
||||
abort ();
|
||||
/* abort (); no, we should not */
|
||||
state = ST_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -387,7 +389,16 @@ void _rl_parse_colors()
|
||||
}
|
||||
}
|
||||
if (state == -1)
|
||||
_rl_errmsg ("LS_COLORS: unrecognized prefix: %s", label);
|
||||
{
|
||||
_rl_errmsg ("LS_COLORS: unrecognized prefix: %s", label);
|
||||
/* recover from an unrecognized prefix */
|
||||
while (p && *p && *p != ':')
|
||||
p++;
|
||||
if (p && *p == ':')
|
||||
state = 1;
|
||||
else if (p && *p == 0)
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -400,6 +411,9 @@ void _rl_parse_colors()
|
||||
}
|
||||
else
|
||||
state = -1;
|
||||
/* XXX - recover here as with an unrecognized prefix? */
|
||||
if (state == -1 && ext->ext.string)
|
||||
_rl_errmsg ("LS_COLORS: syntax error: %s", ext->ext.string);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -417,6 +431,8 @@ void _rl_parse_colors()
|
||||
e = e->next;
|
||||
free (e2);
|
||||
}
|
||||
_rl_color_ext_list = NULL;
|
||||
_rl_colored_stats = 0; /* can't have colored stats without colors */
|
||||
}
|
||||
#else /* !COLOR_SUPPORT */
|
||||
;
|
||||
|
||||
+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
|
||||
|
||||
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
BUILD_DIR=/usr/local/build/chet/bash/bash-current
|
||||
THIS_SH=$BUILD_DIR/bash
|
||||
PATH=$PATH:$BUILD_DIR
|
||||
|
||||
export THIS_SH PATH
|
||||
|
||||
rm -f /tmp/xx
|
||||
|
||||
/bin/sh "$@"
|
||||
@@ -116,3 +116,4 @@ the -- 1
|
||||
./nameref6.sub: line 40: 2: invalid variable name for name reference
|
||||
./nameref6.sub: line 41: 2: invalid variable name for name reference
|
||||
2 -- 0
|
||||
bar
|
||||
|
||||
@@ -114,3 +114,4 @@ ${THIS_SH} ./nameref3.sub
|
||||
${THIS_SH} ./nameref4.sub
|
||||
${THIS_SH} ./nameref5.sub
|
||||
${THIS_SH} ./nameref6.sub
|
||||
${THIS_SH} ./nameref7.sub
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fn ()
|
||||
{
|
||||
declare -n var=foo; var=bar
|
||||
}
|
||||
|
||||
unset foo
|
||||
fn
|
||||
echo ${foo:-unset}
|
||||
+11
-2
@@ -2196,7 +2196,7 @@ make_local_variable (name)
|
||||
old_var = find_variable (name);
|
||||
if (old_var && local_p (old_var) && old_var->context == variable_context)
|
||||
{
|
||||
VUNSETATTR (old_var, att_invisible);
|
||||
VUNSETATTR (old_var, att_invisible); /* XXX */
|
||||
return (old_var);
|
||||
}
|
||||
|
||||
@@ -2277,6 +2277,8 @@ make_local_variable (name)
|
||||
if (ifsname (name))
|
||||
setifs (new_var);
|
||||
|
||||
if (was_tmpvar == 0)
|
||||
VSETATTR (new_var, att_invisible); /* XXX */
|
||||
return (new_var);
|
||||
}
|
||||
|
||||
@@ -2650,7 +2652,14 @@ bind_variable (name, value, flags)
|
||||
{
|
||||
nv = find_variable_last_nameref_context (v, vc, &nvc);
|
||||
if (nv && nameref_p (nv))
|
||||
return (bind_variable_internal (nameref_cell (nv), value, nvc->table, 0, flags));
|
||||
{
|
||||
/* If this nameref variable doesn't have a value yet,
|
||||
set the value. Otherwise, assign using the value as
|
||||
normal. */
|
||||
if (nameref_cell (nv) == 0)
|
||||
return (bind_variable_internal (nv->name, value, nvc->table, 0, flags));
|
||||
return (bind_variable_internal (nameref_cell (nv), value, nvc->table, 0, flags));
|
||||
}
|
||||
else
|
||||
v = nv;
|
||||
}
|
||||
|
||||
+5294
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user