fixes to LINENO, read -n, command substitution and backslash-escaped newlines

This commit is contained in:
Chet Ramey
2021-12-20 20:03:26 -05:00
parent 5f2dd5ff95
commit b2b78a6348
16 changed files with 895 additions and 1185 deletions
+75
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 */
+1 -1
View File
@@ -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 */
{
+6 -6
View File
@@ -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.
+1 -1
View File
@@ -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
View File
@@ -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;
+6 -2
View File
@@ -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
+1 -1
View File
@@ -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));
BIN
View File
Binary file not shown.
+610 -1090
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -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);
+40 -22
View File
@@ -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)))
{
+7 -4
View File
@@ -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
View File
@@ -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