mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-07-02 09:50:50 +02:00
fixes to LINENO, read -n, command substitution and backslash-escaped newlines
This commit is contained in:
@@ -2662,3 +2662,78 @@ subst.c
|
||||
it's the value ultimately assigned to the variable after possible
|
||||
modification (e.g., arithmetic evaluation). Reported by
|
||||
oguzismailuysal@gmail.com after flawed fix applied 11/16
|
||||
|
||||
12/14
|
||||
-----
|
||||
arrayfunc.h
|
||||
- array_eltstate_t: an object that encapsulates an array element's
|
||||
state (type, index, key, value) whether it's an indexed or
|
||||
associative array
|
||||
|
||||
arrayfunc.c
|
||||
- {init,flush}_eltstate: new functions to initialize and flush any
|
||||
allocated memory from array_eltstate_t objects. No allocation/
|
||||
deallocation functions yet; the only use is with a static instance
|
||||
- assign_array_element_internal: take an array_eltstate_t * instead of
|
||||
a char ** as the final argument, so we can return keys/indices and
|
||||
values depending on the type of array; populates it with the
|
||||
appropriate values
|
||||
- assign_array_element: take array_eltstate_t * as final argument
|
||||
instead of a char **; pass it to assign_array_element_internal
|
||||
|
||||
{subst,variables}.c,builtins/{common.c,declare.def}
|
||||
- assign_array_element: change callers to modify final argument
|
||||
|
||||
12/15
|
||||
-----
|
||||
arrayfunc.c
|
||||
- array_value_internal: now takes an array_eltstate_t * as the final
|
||||
argument; there is no more `rtype' argument in favor of the
|
||||
`subtype' member; returns the appropriate values in its members
|
||||
- array_value: changed to pass array_eltstate_t to array_value_internal,
|
||||
saves and fetches its `ind' member into *indp; saves `subtype'
|
||||
member into *rtype
|
||||
- get_arrary_value: changed to take array_eltstate_t as third argument,
|
||||
passes it to array_value_internal
|
||||
|
||||
{redir,expr}.c
|
||||
- get_array_value: changed callers; initializing the array_eltstate_t
|
||||
argument as necessary
|
||||
|
||||
test.c
|
||||
- test_builtin: changed to use get_array_value, adding AV_ALLOWALL to
|
||||
the flags, since it didn't use any QUOTED argument. Pass
|
||||
array_eltstate_t * as final argument and get subtype from it (the
|
||||
only thing we're interested in, to deallocate memory)
|
||||
|
||||
12/16
|
||||
-----
|
||||
arrayfunc.c
|
||||
- array_value: now takes a final argument of array_eltstate_t *, which
|
||||
it passes to array_value_internal; no more rtype and indp args.
|
||||
Callers are responsible for marshalling values into estatep
|
||||
|
||||
arrayfunc.h
|
||||
- array_value: changed function signature
|
||||
|
||||
subst.c
|
||||
- get_var_and_type,parameter_brace_expand_word: changed calls to
|
||||
array_value to use array_eltstate_t argument and initialize it
|
||||
appropriately. Copy values back from it to the parameters we need
|
||||
to modify
|
||||
|
||||
variables.c
|
||||
- assign_lineno: call set_int_value to store the value, like with
|
||||
RANDOM and SECONDS (from 12/10)
|
||||
|
||||
12/17
|
||||
-----
|
||||
{eval,execute_cmd}.c
|
||||
- when bypassing a parsed command because read_but_dont_execute is
|
||||
set, don't modify last_command_exit_value. From a report by
|
||||
Robert Elz <kre@munnari.OZ.AU>
|
||||
|
||||
parse.y
|
||||
- parse_comsub: make sure the first call to shell_getc to check whether
|
||||
or not it's an arithmetic expansion skips a quoted newline. From a
|
||||
report by Robert Elz <kre@munnari.OZ.AU>
|
||||
|
||||
+109
-47
@@ -53,14 +53,14 @@ int assoc_expand_once = 0;
|
||||
int array_expand_once = 0;
|
||||
|
||||
static SHELL_VAR *bind_array_var_internal PARAMS((SHELL_VAR *, arrayind_t, char *, char *, int));
|
||||
static SHELL_VAR *assign_array_element_internal PARAMS((SHELL_VAR *, char *, char *, char *, int, char *, int, char **));
|
||||
static SHELL_VAR *assign_array_element_internal PARAMS((SHELL_VAR *, char *, char *, char *, int, char *, int, array_eltstate_t *));
|
||||
|
||||
static void assign_assoc_from_kvlist PARAMS((SHELL_VAR *, WORD_LIST *, HASH_TABLE *, int));
|
||||
|
||||
static char *quote_assign PARAMS((const char *));
|
||||
static void quote_array_assignment_chars PARAMS((WORD_LIST *));
|
||||
static char *quote_compound_array_word PARAMS((char *, int));
|
||||
static char *array_value_internal PARAMS((const char *, int, int, int *, arrayind_t *));
|
||||
static char *array_value_internal PARAMS((const char *, int, int, array_eltstate_t *));
|
||||
|
||||
/* Standard error message to use when encountering an invalid array subscript */
|
||||
const char * const bash_badsub_errmsg = N_("bad array subscript");
|
||||
@@ -318,14 +318,33 @@ bind_assoc_variable (entry, name, key, value, flags)
|
||||
return (bind_assoc_var_internal (entry, assoc_cell (entry), key, value, flags));
|
||||
}
|
||||
|
||||
inline void
|
||||
init_eltstate (array_eltstate_t *estatep)
|
||||
{
|
||||
if (estatep)
|
||||
{
|
||||
estatep->type = ARRAY_INVALID;
|
||||
estatep->subtype = 0;
|
||||
estatep->key = estatep->value = 0;
|
||||
estatep->ind = INTMAX_MIN;
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
flush_eltstate (array_eltstate_t *estatep)
|
||||
{
|
||||
if (estatep)
|
||||
FREE (estatep->key);
|
||||
}
|
||||
|
||||
/* Parse NAME, a lhs of an assignment statement of the form v[s], and
|
||||
assign VALUE to that array element by calling bind_array_variable().
|
||||
Flags are ASS_ assignment flags */
|
||||
SHELL_VAR *
|
||||
assign_array_element (name, value, flags, nvalp)
|
||||
assign_array_element (name, value, flags, estatep)
|
||||
char *name, *value;
|
||||
int flags;
|
||||
char **nvalp;
|
||||
array_eltstate_t *estatep;
|
||||
{
|
||||
char *sub, *vname;
|
||||
int sublen, isassoc;
|
||||
@@ -353,14 +372,14 @@ assign_array_element (name, value, flags, nvalp)
|
||||
return ((SHELL_VAR *)NULL);
|
||||
}
|
||||
|
||||
entry = assign_array_element_internal (entry, name, vname, sub, sublen, value, flags, nvalp);
|
||||
entry = assign_array_element_internal (entry, name, vname, sub, sublen, value, flags, estatep);
|
||||
|
||||
free (vname);
|
||||
return entry;
|
||||
}
|
||||
|
||||
static SHELL_VAR *
|
||||
assign_array_element_internal (entry, name, vname, sub, sublen, value, flags, nvalp)
|
||||
assign_array_element_internal (entry, name, vname, sub, sublen, value, flags, estatep)
|
||||
SHELL_VAR *entry;
|
||||
char *name; /* only used for error messages */
|
||||
char *vname;
|
||||
@@ -368,12 +387,14 @@ assign_array_element_internal (entry, name, vname, sub, sublen, value, flags, nv
|
||||
int sublen;
|
||||
char *value;
|
||||
int flags;
|
||||
char **nvalp;
|
||||
array_eltstate_t *estatep;
|
||||
{
|
||||
char *akey;
|
||||
char *akey, *nkey;
|
||||
arrayind_t ind;
|
||||
char *newval;
|
||||
|
||||
/* rely on the caller to initialize estatep */
|
||||
|
||||
if (entry && assoc_p (entry))
|
||||
{
|
||||
sub[sublen-1] = '\0';
|
||||
@@ -388,8 +409,15 @@ assign_array_element_internal (entry, name, vname, sub, sublen, value, flags, nv
|
||||
FREE (akey);
|
||||
return ((SHELL_VAR *)NULL);
|
||||
}
|
||||
if (estatep)
|
||||
nkey = savestring (akey); /* assoc_insert/assoc_replace frees akey */
|
||||
entry = bind_assoc_variable (entry, vname, akey, value, flags);
|
||||
newval = entry ? assoc_reference (assoc_cell (entry), akey) : 0;
|
||||
if (estatep)
|
||||
{
|
||||
estatep->type = ARRAY_ASSOC;
|
||||
estatep->key = nkey;
|
||||
estatep->value = entry ? assoc_reference (assoc_cell (entry), nkey) : 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -403,14 +431,14 @@ assign_array_element_internal (entry, name, vname, sub, sublen, value, flags, nv
|
||||
return ((SHELL_VAR *)NULL);
|
||||
}
|
||||
entry = bind_array_variable (vname, ind, value, flags);
|
||||
newval = entry ? array_reference (array_cell (entry), ind) : 0;
|
||||
if (estatep)
|
||||
{
|
||||
estatep->type = ARRAY_INDEXED;
|
||||
estatep->ind = ind;
|
||||
estatep->value = entry ? array_reference (array_cell (entry), ind) : 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the caller asks, return the (possibly modified) final value assigned.
|
||||
This saves subseqent lookups. */
|
||||
if (nvalp)
|
||||
*nvalp = newval;
|
||||
|
||||
return (entry);
|
||||
}
|
||||
|
||||
@@ -1419,12 +1447,12 @@ array_variable_part (s, flags, subp, lenp)
|
||||
is non-null it gets 1 if the array reference is name[*], 2 if the
|
||||
reference is name[@], and 0 otherwise. */
|
||||
static char *
|
||||
array_value_internal (s, quoted, flags, rtype, indp)
|
||||
array_value_internal (s, quoted, flags, estatep)
|
||||
const char *s;
|
||||
int quoted, flags, *rtype;
|
||||
arrayind_t *indp;
|
||||
int quoted, flags;
|
||||
array_eltstate_t *estatep;
|
||||
{
|
||||
int len, isassoc;
|
||||
int len, isassoc, subtype;
|
||||
arrayind_t ind;
|
||||
char *akey;
|
||||
char *retval, *t, *temp;
|
||||
@@ -1446,38 +1474,50 @@ array_value_internal (s, quoted, flags, rtype, indp)
|
||||
isassoc = var && assoc_p (var);
|
||||
/* [ */
|
||||
akey = 0;
|
||||
subtype = 0;
|
||||
if (estatep)
|
||||
estatep->value = (char *)NULL;
|
||||
|
||||
/* Backwards compatibility: we only change the behavior of A[@] and A[*]
|
||||
for associative arrays, and the caller has to request it. */
|
||||
if ((isassoc == 0 || (flags & AV_ATSTARKEYS) == 0) && ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
|
||||
{
|
||||
if (rtype)
|
||||
*rtype = (t[0] == '*') ? 1 : 2;
|
||||
if (estatep)
|
||||
estatep->subtype = (t[0] == '*') ? 1 : 2;
|
||||
if ((flags & AV_ALLOWALL) == 0)
|
||||
{
|
||||
err_badarraysub (s);
|
||||
return ((char *)NULL);
|
||||
}
|
||||
else if (var == 0 || value_cell (var) == 0) /* XXX - check for invisible_p(var) ? */
|
||||
else if (var == 0 || value_cell (var) == 0)
|
||||
return ((char *)NULL);
|
||||
else if (invisible_p (var))
|
||||
return ((char *)NULL);
|
||||
else if (array_p (var) == 0 && assoc_p (var) == 0)
|
||||
l = add_string_to_list (value_cell (var), (WORD_LIST *)NULL);
|
||||
{
|
||||
if (estatep)
|
||||
estatep->type = ARRAY_SCALAR;
|
||||
l = add_string_to_list (value_cell (var), (WORD_LIST *)NULL);
|
||||
}
|
||||
else if (assoc_p (var))
|
||||
{
|
||||
if (estatep)
|
||||
estatep->type = ARRAY_ASSOC;
|
||||
l = assoc_to_word_list (assoc_cell (var));
|
||||
if (l == (WORD_LIST *)NULL)
|
||||
return ((char *)NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (estatep)
|
||||
estatep->type = ARRAY_ASSOC;
|
||||
l = array_to_word_list (array_cell (var));
|
||||
if (l == (WORD_LIST *)NULL)
|
||||
return ((char *) NULL);
|
||||
}
|
||||
|
||||
/* Caller of array_value takes care of inspecting rtype and duplicating
|
||||
retval if rtype == 0, so this is not a memory leak */
|
||||
/* Caller of array_value takes care of inspecting estatep->subtype and
|
||||
duplicating retval if subtype == 0, so this is not a memory leak */
|
||||
if (t[0] == '*' && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
|
||||
{
|
||||
temp = string_list_dollar_star (l, quoted, (flags & AV_ASSIGNRHS) ? PF_ASSIGNRHS : 0);
|
||||
@@ -1491,11 +1531,11 @@ array_value_internal (s, quoted, flags, rtype, indp)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rtype)
|
||||
*rtype = 0;
|
||||
if (estatep)
|
||||
estatep->subtype = 0;
|
||||
if (var == 0 || array_p (var) || assoc_p (var) == 0)
|
||||
{
|
||||
if ((flags & AV_USEIND) == 0 || indp == 0)
|
||||
if ((flags & AV_USEIND) == 0 || estatep == 0)
|
||||
{
|
||||
ind = array_expand_index (var, t, len, flags);
|
||||
if (ind < 0)
|
||||
@@ -1506,16 +1546,24 @@ array_value_internal (s, quoted, flags, rtype, indp)
|
||||
if (ind < 0)
|
||||
INDEX_ERROR();
|
||||
}
|
||||
if (indp)
|
||||
*indp = ind;
|
||||
if (estatep)
|
||||
estatep->ind = ind;
|
||||
}
|
||||
else if (indp)
|
||||
ind = *indp;
|
||||
else if (estatep && (flags & AV_USEIND))
|
||||
ind = estatep->ind;
|
||||
if (estatep && var)
|
||||
estatep->type = array_p (var) ? ARRAY_INDEXED : ARRAY_SCALAR;
|
||||
}
|
||||
else if (assoc_p (var))
|
||||
{
|
||||
if (flags & AV_USEIND)
|
||||
itrace("array_value_internal: %s: assoc var with AV_USEIND: %s", dollar_vars[0], s);
|
||||
t[len - 1] = '\0';
|
||||
if ((flags & AV_NOEXPAND) == 0)
|
||||
if (estatep)
|
||||
estatep->type = ARRAY_ASSOC;
|
||||
if ((flags & AV_USEIND) && estatep && estatep->key)
|
||||
akey = savestring (estatep->key);
|
||||
else if ((flags & AV_NOEXPAND) == 0)
|
||||
akey = expand_subscript_string (t, 0); /* [ */
|
||||
else
|
||||
akey = savestring (t);
|
||||
@@ -1526,26 +1574,34 @@ array_value_internal (s, quoted, flags, rtype, indp)
|
||||
INDEX_ERROR();
|
||||
}
|
||||
}
|
||||
|
||||
if (var == 0 || value_cell (var) == 0) /* XXX - check invisible_p(var) ? */
|
||||
|
||||
if (var == 0 || value_cell (var) == 0)
|
||||
{
|
||||
FREE (akey);
|
||||
FREE (akey);
|
||||
return ((char *)NULL);
|
||||
}
|
||||
else if (invisible_p (var))
|
||||
{
|
||||
FREE (akey);
|
||||
FREE (akey);
|
||||
return ((char *)NULL);
|
||||
}
|
||||
if (array_p (var) == 0 && assoc_p (var) == 0)
|
||||
return (ind == 0 ? value_cell (var) : (char *)NULL);
|
||||
retval = (ind == 0) ? value_cell (var) : (char *)NULL;
|
||||
else if (assoc_p (var))
|
||||
{
|
||||
retval = assoc_reference (assoc_cell (var), akey);
|
||||
free (akey);
|
||||
if (estatep && estatep->key && (flags & AV_USEIND))
|
||||
free (akey); /* duplicated estatep->key */
|
||||
else if (estatep)
|
||||
estatep->key = akey; /* XXX - caller must manage */
|
||||
else /* not saving it anywhere */
|
||||
free (akey);
|
||||
}
|
||||
else
|
||||
retval = array_reference (array_cell (var), ind);
|
||||
|
||||
if (estatep)
|
||||
estatep->value = retval;
|
||||
}
|
||||
|
||||
return retval;
|
||||
@@ -1554,12 +1610,15 @@ array_value_internal (s, quoted, flags, rtype, indp)
|
||||
/* Return a string containing the elements described by the array and
|
||||
subscript contained in S, obeying quoting for subscripts * and @. */
|
||||
char *
|
||||
array_value (s, quoted, flags, rtype, indp)
|
||||
array_value (s, quoted, flags, estatep)
|
||||
const char *s;
|
||||
int quoted, flags, *rtype;
|
||||
arrayind_t *indp;
|
||||
int quoted, flags;
|
||||
array_eltstate_t *estatep;
|
||||
{
|
||||
return (array_value_internal (s, quoted, flags|AV_ALLOWALL, rtype, indp));
|
||||
char *retval;
|
||||
|
||||
retval = array_value_internal (s, quoted, flags|AV_ALLOWALL, estatep);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Return the value of the array indexing expression S as a single string.
|
||||
@@ -1567,12 +1626,15 @@ array_value (s, quoted, flags, rtype, indp)
|
||||
is used by other parts of the shell such as the arithmetic expression
|
||||
evaluator in expr.c. */
|
||||
char *
|
||||
get_array_value (s, flags, rtype, indp)
|
||||
get_array_value (s, flags, estatep)
|
||||
const char *s;
|
||||
int flags, *rtype;
|
||||
arrayind_t *indp;
|
||||
int flags;
|
||||
array_eltstate_t *estatep;
|
||||
{
|
||||
return (array_value_internal (s, 0, flags, rtype, indp));
|
||||
char *retval;
|
||||
|
||||
retval = array_value_internal (s, 0, flags, estatep);
|
||||
return retval;
|
||||
}
|
||||
|
||||
char *
|
||||
|
||||
+29
-3
@@ -23,6 +23,29 @@
|
||||
|
||||
/* Must include variables.h before including this file. */
|
||||
|
||||
/* An object to encapsulate the state of an array element. It can describe
|
||||
an array assignment A[KEY]=VALUE or a[IND]=VALUE depending on TYPE, or
|
||||
for passing array subscript references around, where VALUE would be
|
||||
${a[IND]} or ${A[KEY]}. This is not dependent on ARRAY_VARS so we can
|
||||
use it in function parameters. */
|
||||
|
||||
/* values for `type' field */
|
||||
#define ARRAY_INVALID -1
|
||||
#define ARRAY_SCALAR 0
|
||||
#define ARRAY_INDEXED 1
|
||||
#define ARRAY_ASSOC 2
|
||||
|
||||
/* KEY will contain allocated memory if called through the assign_array_element
|
||||
code path because of how assoc_insert works. */
|
||||
typedef struct element_state
|
||||
{
|
||||
short type; /* assoc or indexed, says which fields are valid */
|
||||
short subtype; /* `*', `@', or something else */
|
||||
arrayind_t ind;
|
||||
char *key; /* can be allocated memory */
|
||||
char *value;
|
||||
} array_eltstate_t;
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
|
||||
/* This variable means to not expand associative array subscripts more than
|
||||
@@ -56,7 +79,7 @@ extern char *make_array_variable_value PARAMS((SHELL_VAR *, arrayind_t, char *,
|
||||
|
||||
extern SHELL_VAR *bind_array_variable PARAMS((char *, arrayind_t, char *, int));
|
||||
extern SHELL_VAR *bind_array_element PARAMS((SHELL_VAR *, arrayind_t, char *, int));
|
||||
extern SHELL_VAR *assign_array_element PARAMS((char *, char *, int, char **));
|
||||
extern SHELL_VAR *assign_array_element PARAMS((char *, char *, int, array_eltstate_t *));
|
||||
|
||||
extern SHELL_VAR *bind_assoc_variable PARAMS((SHELL_VAR *, char *, char *, char *, int));
|
||||
|
||||
@@ -85,14 +108,17 @@ extern arrayind_t array_expand_index PARAMS((SHELL_VAR *, char *, int, int));
|
||||
extern int valid_array_reference PARAMS((const char *, int));
|
||||
extern int tokenize_array_reference PARAMS((char *, int, char **));
|
||||
|
||||
extern char *array_value PARAMS((const char *, int, int, int *, arrayind_t *));
|
||||
extern char *get_array_value PARAMS((const char *, int, int *, arrayind_t *));
|
||||
extern char *array_value PARAMS((const char *, int, int, array_eltstate_t *));
|
||||
extern char *get_array_value PARAMS((const char *, int, array_eltstate_t *));
|
||||
|
||||
extern char *array_keys PARAMS((char *, int, int));
|
||||
|
||||
extern char *array_variable_name PARAMS((const char *, int, char **, int *));
|
||||
extern SHELL_VAR *array_variable_part PARAMS((const char *, int, char **, int *));
|
||||
|
||||
extern void init_eltstate (array_eltstate_t *);
|
||||
extern void flush_eltstate (array_eltstate_t *);
|
||||
|
||||
#else
|
||||
|
||||
#define AV_ALLOWALL 0
|
||||
|
||||
+1
-1
@@ -1004,7 +1004,7 @@ builtin_bind_variable (name, value, flags)
|
||||
if (valid_array_reference (name, vflags) == 0)
|
||||
v = bind_variable (name, value, flags);
|
||||
else
|
||||
v = assign_array_element (name, value, bindflags, (char **)0);
|
||||
v = assign_array_element (name, value, bindflags, (array_eltstate_t *)0);
|
||||
#else /* !ARRAY_VARS */
|
||||
v = bind_variable (name, value, flags);
|
||||
#endif /* !ARRAY_VARS */
|
||||
|
||||
@@ -949,7 +949,7 @@ restart_new_var_name:
|
||||
local_aflags = aflags&ASS_APPEND;
|
||||
local_aflags |= assoc_noexpand ? ASS_NOEXPAND : 0;
|
||||
local_aflags |= ASS_ALLOWALLSUB; /* allow declare a[@]=at */
|
||||
var = assign_array_element (name, value, local_aflags, (char **)0); /* XXX - not aflags */
|
||||
var = assign_array_element (name, value, local_aflags, (array_eltstate_t *)0); /* XXX - not aflags */
|
||||
*subscript_start = '\0';
|
||||
if (var == 0) /* some kind of assignment error */
|
||||
{
|
||||
|
||||
@@ -114,22 +114,22 @@ Returns the status of the last command executed.
|
||||
$END
|
||||
|
||||
$BUILTIN while
|
||||
$SHORT_DOC while COMMANDS; do COMMANDS; done
|
||||
$SHORT_DOC while COMMANDS; do COMMANDS-2; done
|
||||
Execute commands as long as a test succeeds.
|
||||
|
||||
Expand and execute COMMANDS as long as the final command in the
|
||||
`while' COMMANDS has an exit status of zero.
|
||||
Expand and execute COMMANDS-2 as long as the final command in COMMANDS has
|
||||
an exit status of zero.
|
||||
|
||||
Exit Status:
|
||||
Returns the status of the last command executed.
|
||||
$END
|
||||
|
||||
$BUILTIN until
|
||||
$SHORT_DOC until COMMANDS; do COMMANDS; done
|
||||
$SHORT_DOC until COMMANDS; do COMMANDS-2; done
|
||||
Execute commands as long as a test does not succeed.
|
||||
|
||||
Expand and execute COMMANDS as long as the final command in the
|
||||
`until' COMMANDS has an exit status which is not zero.
|
||||
Expand and execute COMMANDS-2 as long as the final command in COMMANDS has
|
||||
an exit status which is not zero.
|
||||
|
||||
Exit Status:
|
||||
Returns the status of the last command executed.
|
||||
|
||||
@@ -140,7 +140,7 @@ reader_loop ()
|
||||
{
|
||||
if (interactive_shell == 0 && read_but_dont_execute)
|
||||
{
|
||||
set_exit_status (EXECUTION_SUCCESS);
|
||||
set_exit_status (last_command_exit_value);
|
||||
dispose_command (global_command);
|
||||
global_command = (COMMAND *)NULL;
|
||||
}
|
||||
|
||||
+3
-1
@@ -588,7 +588,9 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
|
||||
|
||||
if (breaking || continuing)
|
||||
return (last_command_exit_value);
|
||||
if (command == 0 || read_but_dont_execute)
|
||||
if (read_but_dont_execute)
|
||||
return (last_command_exit_value);
|
||||
if (command == 0)
|
||||
return (EXECUTION_SUCCESS);
|
||||
|
||||
QUIT;
|
||||
|
||||
@@ -1149,6 +1149,7 @@ expr_streval (tok, e, lvalue)
|
||||
#if defined (ARRAY_VARS)
|
||||
arrayind_t ind;
|
||||
int tflag, aflag;
|
||||
array_eltstate_t es;
|
||||
#endif
|
||||
|
||||
/*itrace("expr_streval: %s: noeval = %d expanded=%d", tok, noeval, already_expanded);*/
|
||||
@@ -1203,13 +1204,16 @@ expr_streval (tok, e, lvalue)
|
||||
}
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
ind = -1;
|
||||
init_eltstate (&es);
|
||||
es.ind = -1;
|
||||
/* If the second argument to get_array_value doesn't include AV_ALLOWALL,
|
||||
we don't allow references like array[@]. In this case, get_array_value
|
||||
is just like get_variable_value in that it does not return newly-allocated
|
||||
memory or quote the results. AFLAG is set above and is either AV_NOEXPAND
|
||||
or 0. */
|
||||
value = (e == ']') ? get_array_value (tok, aflag, (int *)NULL, &ind) : get_variable_value (v);
|
||||
value = (e == ']') ? get_array_value (tok, aflag, &es) : get_variable_value (v);
|
||||
ind = es.ind;
|
||||
flush_eltstate (&es);
|
||||
#else
|
||||
value = get_variable_value (v);
|
||||
#endif
|
||||
|
||||
@@ -4066,7 +4066,7 @@ parse_comsub (qc, open, close, lenp, flags)
|
||||
assume $(( introduces arithmetic expansion and parse accordingly. */
|
||||
if (open == '(') /*)*/
|
||||
{
|
||||
peekc = shell_getc (0);
|
||||
peekc = shell_getc (1);
|
||||
shell_ungetc (peekc);
|
||||
if (peekc == '(') /*)*/
|
||||
return (parse_matched_pair (qc, open, close, lenp, 0));
|
||||
|
||||
@@ -1509,7 +1509,7 @@ redir_varvalue (redir)
|
||||
/* get_variable_value handles references to array variables without
|
||||
subscripts */
|
||||
if (vr && (array_p (v) || assoc_p (v)))
|
||||
val = get_array_value (w, 0, (int *)NULL, (arrayind_t *)0);
|
||||
val = get_array_value (w, 0, (array_eltstate_t *)NULL);
|
||||
else
|
||||
#endif
|
||||
val = get_variable_value (v);
|
||||
|
||||
@@ -3308,7 +3308,7 @@ do_assignment_internal (word, expand)
|
||||
ASSIGN_RETURN (0);
|
||||
}
|
||||
aflags |= ASS_ALLOWALLSUB; /* allow a[@]=value for existing associative arrays */
|
||||
entry = assign_array_element (name, value, aflags, (char **)0);
|
||||
entry = assign_array_element (name, value, aflags, (array_eltstate_t *)0);
|
||||
if (entry == 0)
|
||||
ASSIGN_RETURN (0);
|
||||
}
|
||||
@@ -6935,8 +6935,8 @@ parameter_brace_expand_word (name, var_is_special, quoted, pflags, indp)
|
||||
char *temp, *tt;
|
||||
intmax_t arg_index;
|
||||
SHELL_VAR *var;
|
||||
int atype, rflags;
|
||||
arrayind_t ind;
|
||||
int rflags;
|
||||
array_eltstate_t es;
|
||||
|
||||
ret = 0;
|
||||
temp = 0;
|
||||
@@ -6972,6 +6972,10 @@ parameter_brace_expand_word (name, var_is_special, quoted, pflags, indp)
|
||||
else if (valid_array_reference (name, 0))
|
||||
{
|
||||
expand_arrayref:
|
||||
init_eltstate (&es);
|
||||
if (indp)
|
||||
es.ind = *indp;
|
||||
|
||||
var = array_variable_part (name, 0, &tt, (int *)0);
|
||||
/* These are the cases where word splitting will not be performed */
|
||||
if (pflags & PF_ASSIGNRHS)
|
||||
@@ -6980,12 +6984,12 @@ expand_arrayref:
|
||||
{
|
||||
/* Only treat as double quoted if array variable */
|
||||
if (var && (array_p (var) || assoc_p (var)))
|
||||
temp = array_value (name, quoted|Q_DOUBLE_QUOTES, AV_ASSIGNRHS, &atype, &ind);
|
||||
temp = array_value (name, quoted|Q_DOUBLE_QUOTES, AV_ASSIGNRHS, &es);
|
||||
else
|
||||
temp = array_value (name, quoted, 0, &atype, &ind);
|
||||
temp = array_value (name, quoted, 0, &es);
|
||||
}
|
||||
else
|
||||
temp = array_value (name, quoted, 0, &atype, &ind);
|
||||
temp = array_value (name, quoted, 0, &es);
|
||||
}
|
||||
/* Posix interp 888 */
|
||||
else if (pflags & PF_NOSPLIT2)
|
||||
@@ -6996,30 +7000,30 @@ expand_arrayref:
|
||||
#else
|
||||
if (tt[0] == '@' && tt[1] == RBRACK && var && quoted == 0 && ifs_is_set && ifs_is_null == 0 && ifs_firstc != ' ')
|
||||
#endif
|
||||
temp = array_value (name, Q_DOUBLE_QUOTES, AV_ASSIGNRHS, &atype, &ind);
|
||||
temp = array_value (name, Q_DOUBLE_QUOTES, AV_ASSIGNRHS, &es);
|
||||
else if (tt[0] == '@' && tt[1] == RBRACK)
|
||||
temp = array_value (name, quoted, 0, &atype, &ind);
|
||||
temp = array_value (name, quoted, 0, &es);
|
||||
else if (tt[0] == '*' && tt[1] == RBRACK && expand_no_split_dollar_star && ifs_is_null)
|
||||
temp = array_value (name, Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT, 0, &atype, &ind);
|
||||
temp = array_value (name, Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT, 0, &es);
|
||||
else if (tt[0] == '*' && tt[1] == RBRACK)
|
||||
temp = array_value (name, quoted, 0, &atype, &ind);
|
||||
temp = array_value (name, quoted, 0, &es);
|
||||
else
|
||||
temp = array_value (name, quoted, 0, &atype, &ind);
|
||||
temp = array_value (name, quoted, 0, &es);
|
||||
}
|
||||
else if (tt[0] == '*' && tt[1] == RBRACK && expand_no_split_dollar_star && ifs_is_null)
|
||||
temp = array_value (name, Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT, 0, &atype, &ind);
|
||||
temp = array_value (name, Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT, 0, &es);
|
||||
else
|
||||
temp = array_value (name, quoted, 0, &atype, &ind);
|
||||
if (atype == 0 && temp)
|
||||
temp = array_value (name, quoted, 0, &es);
|
||||
if (es.subtype == 0 && temp)
|
||||
{
|
||||
temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
|
||||
? quote_string (temp)
|
||||
: quote_escapes (temp);
|
||||
rflags |= W_ARRAYIND;
|
||||
if (indp)
|
||||
*indp = ind;
|
||||
}
|
||||
else if (atype == 1 && temp && QUOTED_NULL (temp) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
|
||||
*indp = es.ind;
|
||||
}
|
||||
else if (es.subtype == 1 && temp && QUOTED_NULL (temp) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
|
||||
rflags |= W_HASQUOTEDNULL;
|
||||
}
|
||||
#endif
|
||||
@@ -7230,6 +7234,7 @@ parameter_brace_expand_rhs (name, value, op, quoted, pflags, qdollaratp, hasdoll
|
||||
char *t, *t1, *temp, *vname, *newval;
|
||||
int l_hasdollat, sindex, arrayref;
|
||||
SHELL_VAR *v;
|
||||
array_eltstate_t es;
|
||||
|
||||
/*itrace("parameter_brace_expand_rhs: %s:%s pflags = %d", name, value, pflags);*/
|
||||
/* If the entire expression is between double quotes, we want to treat
|
||||
@@ -7378,8 +7383,10 @@ parameter_brace_expand_rhs (name, value, op, quoted, pflags, qdollaratp, hasdoll
|
||||
#if defined (ARRAY_VARS)
|
||||
if (valid_array_reference (vname, 0))
|
||||
{
|
||||
v = assign_array_element (vname, t1, ASS_ALLOWALLSUB, &newval);
|
||||
init_eltstate (&es);
|
||||
v = assign_array_element (vname, t1, ASS_ALLOWALLSUB, &es);
|
||||
arrayref = 1;
|
||||
newval = es.value;
|
||||
}
|
||||
else
|
||||
#endif /* ARRAY_VARS */
|
||||
@@ -7408,7 +7415,13 @@ parameter_brace_expand_rhs (name, value, op, quoted, pflags, qdollaratp, hasdoll
|
||||
{
|
||||
FREE (t1);
|
||||
#if defined (ARRAY_VARS)
|
||||
t1 = arrayref ? newval : get_variable_value (v);
|
||||
if (arrayref)
|
||||
{
|
||||
t1 = newval;
|
||||
flush_eltstate (&es);
|
||||
}
|
||||
else
|
||||
t1 = get_variable_value (v);
|
||||
#else
|
||||
t1 = value_cell (v);
|
||||
#endif
|
||||
@@ -7744,7 +7757,7 @@ verify_substring_values (v, value, substr, vtype, e1p, e2p)
|
||||
by VARNAME (value of a variable or a reference to an array element).
|
||||
QUOTED is the standard description of quoting state, using Q_* defines.
|
||||
FLAGS is currently a set of flags to pass to array_value. If IND is
|
||||
non-null and not INTMAX_MIN, and FLAGS includes AV_USEIND, IND is
|
||||
not INTMAX_MIN, and FLAGS includes AV_USEIND, IND is
|
||||
passed to array_value so the array index is not computed again.
|
||||
If this returns VT_VARIABLE, the caller assumes that CTLESC and CTLNUL
|
||||
characters in the value are quoted with CTLESC and takes appropriate
|
||||
@@ -7761,6 +7774,7 @@ get_var_and_type (varname, value, ind, quoted, flags, varp, valp)
|
||||
char *temp, *vname;
|
||||
SHELL_VAR *v;
|
||||
arrayind_t lind;
|
||||
array_eltstate_t es;
|
||||
|
||||
want_indir = *varname == '!' &&
|
||||
(legal_variable_starter ((unsigned char)varname[1]) || DIGIT (varname[1])
|
||||
@@ -7792,6 +7806,9 @@ get_var_and_type (varname, value, ind, quoted, flags, varp, valp)
|
||||
/* If we want to signal array_value to use an already-computed index,
|
||||
set LIND to that index */
|
||||
lind = (ind != INTMAX_MIN && (flags & AV_USEIND)) ? ind : 0;
|
||||
init_eltstate (&es);
|
||||
es.ind = lind;
|
||||
|
||||
if (v && invisible_p (v))
|
||||
{
|
||||
vtype = VT_ARRAYMEMBER;
|
||||
@@ -7811,7 +7828,7 @@ get_var_and_type (varname, value, ind, quoted, flags, varp, valp)
|
||||
else
|
||||
{
|
||||
vtype = VT_ARRAYMEMBER;
|
||||
*valp = array_value (vname, Q_DOUBLE_QUOTES, flags, (int *)NULL, &lind);
|
||||
*valp = array_value (vname, Q_DOUBLE_QUOTES, flags, &es);
|
||||
}
|
||||
*varp = v;
|
||||
}
|
||||
@@ -7828,8 +7845,9 @@ get_var_and_type (varname, value, ind, quoted, flags, varp, valp)
|
||||
{
|
||||
vtype = VT_ARRAYMEMBER;
|
||||
*varp = v;
|
||||
*valp = array_value (vname, Q_DOUBLE_QUOTES, flags, (int *)NULL, &lind);
|
||||
*valp = array_value (vname, Q_DOUBLE_QUOTES, flags, &es);
|
||||
}
|
||||
flush_eltstate (&es);
|
||||
}
|
||||
else if ((v = find_variable (vname)) && (invisible_p (v) == 0) && (assoc_p (v) || array_p (v)))
|
||||
{
|
||||
|
||||
@@ -633,7 +633,8 @@ unary_test (op, arg, flags)
|
||||
if (valid_array_reference (arg, aflags))
|
||||
{
|
||||
char *t;
|
||||
int rtype, ret;
|
||||
int ret;
|
||||
array_eltstate_t es;
|
||||
|
||||
/* Let's assume that this has already been expanded once. */
|
||||
/* XXX - TAG:bash-5.2 fix with corresponding fix to execute_cmd.c:
|
||||
@@ -642,11 +643,13 @@ unary_test (op, arg, flags)
|
||||
if (shell_compatibility_level > 51)
|
||||
/* Allow associative arrays to use `test -v array[@]' to look for
|
||||
a key named `@'. */
|
||||
aflags |= AV_ATSTARKEYS;
|
||||
t = array_value (arg, 0, aflags, &rtype, (arrayind_t *)0);
|
||||
aflags |= AV_ATSTARKEYS; /* XXX */
|
||||
init_eltstate (&es);
|
||||
t = get_array_value (arg, aflags|AV_ALLOWALL, &es);
|
||||
ret = t ? TRUE : FALSE;
|
||||
if (rtype > 0) /* subscript is * or @ */
|
||||
if (es.subtype > 0) /* subscript is * or @ */
|
||||
free (t);
|
||||
flush_eltstate (&es);
|
||||
return ret;
|
||||
}
|
||||
else if (legal_number (arg, &r)) /* -v n == is $n set? */
|
||||
|
||||
+5
-5
@@ -1442,7 +1442,7 @@ assign_lineno (var, value, unused, key)
|
||||
if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0)
|
||||
new_value = 0;
|
||||
line_number = line_number_base = new_value;
|
||||
return var;
|
||||
return (set_int_value (var, line_number, integer_p (var) != 0));
|
||||
}
|
||||
|
||||
/* Function which returns the current line number. */
|
||||
@@ -3110,8 +3110,8 @@ bind_variable_internal (name, value, table, hflags, aflags)
|
||||
We don't need to call make_variable_value here, since
|
||||
assign_array_element will eventually do it itself based on
|
||||
newval and aflags. */
|
||||
|
||||
entry = assign_array_element (newval, value, aflags|ASS_NAMEREF, (char **)0);
|
||||
|
||||
entry = assign_array_element (newval, value, aflags|ASS_NAMEREF, (array_eltstate_t *)0);
|
||||
if (entry == 0)
|
||||
return entry;
|
||||
}
|
||||
@@ -3268,7 +3268,7 @@ bind_variable (name, value, flags)
|
||||
return (bind_variable_internal (nv->name, value, nvc->table, 0, flags));
|
||||
#if defined (ARRAY_VARS)
|
||||
else if (valid_array_reference (nameref_cell (nv), 0))
|
||||
return (assign_array_element (nameref_cell (nv), value, flags, (char **)0));
|
||||
return (assign_array_element (nameref_cell (nv), value, flags, (array_eltstate_t *)0));
|
||||
else
|
||||
#endif
|
||||
return (bind_variable_internal (nameref_cell (nv), value, nvc->table, 0, flags));
|
||||
@@ -3433,7 +3433,7 @@ bind_int_variable (lhs, rhs, flags)
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
if (isarr)
|
||||
v = assign_array_element (lhs, rhs, flags, (char **)0);
|
||||
v = assign_array_element (lhs, rhs, flags, (array_eltstate_t *)0);
|
||||
else if (implicitarray)
|
||||
v = bind_array_variable (lhs, 0, rhs, 0); /* XXX - check on flags */
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user