Bash-5.3-alpha release

This commit is contained in:
Chet Ramey
2024-04-22 10:33:38 -04:00
parent f3b6bd1945
commit 622d318652
700 changed files with 136534 additions and 96420 deletions
+197 -196
View File
@@ -1,6 +1,6 @@
/* arrayfunc.c -- High-level array functions used by other parts of the shell. */
/* Copyright (C) 2001-2021 Free Software Foundation, Inc.
/* Copyright (C) 2001-2024 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -45,22 +45,19 @@
# define RBRACK ']'
#endif
/* This variable means to not expand associative array subscripts more than
once, when performing variable expansion. */
int assoc_expand_once = 0;
/* Ditto for indexed array subscripts -- currently unused */
/* This variable means to not expand associative or indexed array subscripts
more than once, when performing variable expansion. */
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, array_eltstate_t *));
static SHELL_VAR *bind_array_var_internal (SHELL_VAR *, arrayind_t, char *, const char *, int);
static SHELL_VAR *assign_array_element_internal (SHELL_VAR *, const char *, char *, char *, int, const char *, int, array_eltstate_t *);
static void assign_assoc_from_kvlist PARAMS((SHELL_VAR *, WORD_LIST *, HASH_TABLE *, int));
static void assign_assoc_from_kvlist (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, array_eltstate_t *));
static char *quote_assign (const char *);
static void quote_array_assignment_chars (WORD_LIST *);
static char *quote_compound_array_word (char *, int);
static char *array_value_internal (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");
@@ -74,8 +71,7 @@ const char * const bash_badsub_errmsg = N_("bad array subscript");
/* Convert a shell variable to an array variable. The original value is
saved as array[0]. */
SHELL_VAR *
convert_var_to_array (var)
SHELL_VAR *var;
convert_var_to_array (SHELL_VAR *var)
{
char *oldval;
ARRAY *array;
@@ -112,8 +108,7 @@ convert_var_to_array (var)
/* Convert a shell variable to an array variable. The original value is
saved as array[0]. */
SHELL_VAR *
convert_var_to_assoc (var)
SHELL_VAR *var;
convert_var_to_assoc (SHELL_VAR *var)
{
char *oldval;
HASH_TABLE *hash;
@@ -147,13 +142,28 @@ convert_var_to_assoc (var)
return var;
}
/* Copy the array (ARRAY *) or assoc (HASH_TABLE *) from variable V1 to V2,
and return V2. */
SHELL_VAR *
arrayvar_copyval (SHELL_VAR *v1, SHELL_VAR *v2)
{
FREE (value_cell (v2));
VUNSETATTR (v2, (att_array | att_assoc));
if (array_p (v1))
{
var_setarray (v2, array_copy (array_cell (v1)));
VSETATTR (v2, att_array);
}
else if (assoc_p (v1))
{
var_setassoc (v2, assoc_copy (assoc_cell (v1)));
VSETATTR (v2, att_assoc);
}
return v2;
}
char *
make_array_variable_value (entry, ind, key, value, flags)
SHELL_VAR *entry;
arrayind_t ind;
char *key;
char *value;
int flags;
make_array_variable_value (SHELL_VAR *entry, arrayind_t ind, const char *key, const char *value, int flags)
{
SHELL_VAR *dentry;
char *newval;
@@ -195,12 +205,7 @@ make_array_variable_value (entry, ind, key, value, flags)
XXX - make sure that any dynamic associative array variables recreate the
hash table on each assignment. BASH_CMDS and BASH_ALIASES already do this */
static SHELL_VAR *
bind_assoc_var_internal (entry, hash, key, value, flags)
SHELL_VAR *entry;
HASH_TABLE *hash;
char *key;
char *value;
int flags;
bind_assoc_var_internal (SHELL_VAR *entry, HASH_TABLE *hash, char *key, const char *value, int flags)
{
char *newval;
@@ -208,7 +213,10 @@ bind_assoc_var_internal (entry, hash, key, value, flags)
newval = make_array_variable_value (entry, 0, key, value, flags);
if (entry->assign_func)
(*entry->assign_func) (entry, newval, 0, key);
{
(*entry->assign_func) (entry, newval, 0, key);
FREE (key);
}
else
assoc_insert (hash, key, newval);
@@ -223,12 +231,7 @@ bind_assoc_var_internal (entry, hash, key, value, flags)
/* Perform ENTRY[IND]=VALUE or ENTRY[KEY]=VALUE. This is not called for every
assignment to an associative array; see assign_compound_array_list below. */
static SHELL_VAR *
bind_array_var_internal (entry, ind, key, value, flags)
SHELL_VAR *entry;
arrayind_t ind;
char *key;
char *value;
int flags;
bind_array_var_internal (SHELL_VAR *entry, arrayind_t ind, char *key, const char *value, int flags)
{
char *newval;
@@ -256,11 +259,7 @@ bind_array_var_internal (entry, ind, key, value, flags)
If NAME does not exist, just create an array variable, no matter what
IND's value may be. */
SHELL_VAR *
bind_array_variable (name, ind, value, flags)
char *name;
arrayind_t ind;
char *value;
int flags;
bind_array_variable (const char *name, arrayind_t ind, const char *value, int flags)
{
SHELL_VAR *entry;
@@ -291,22 +290,13 @@ bind_array_variable (name, ind, value, flags)
}
SHELL_VAR *
bind_array_element (entry, ind, value, flags)
SHELL_VAR *entry;
arrayind_t ind;
char *value;
int flags;
bind_array_element (SHELL_VAR *entry, arrayind_t ind, char *value, int flags)
{
return (bind_array_var_internal (entry, ind, 0, value, flags));
}
SHELL_VAR *
bind_assoc_variable (entry, name, key, value, flags)
SHELL_VAR *entry;
char *name;
char *key;
char *value;
int flags;
bind_assoc_variable (SHELL_VAR *entry, const char *name, char *key, const char *value, int flags)
{
if ((readonly_p (entry) && (flags&ASS_FORCE) == 0) || noassign_p (entry))
{
@@ -341,20 +331,13 @@ flush_eltstate (array_eltstate_t *estatep)
assign VALUE to that array element by calling bind_array_variable().
Flags are ASS_ assignment flags */
SHELL_VAR *
assign_array_element (name, value, flags, estatep)
char *name, *value;
int flags;
array_eltstate_t *estatep;
assign_array_element (const char *name, const char *value, int flags, array_eltstate_t *estatep)
{
char *sub, *vname;
int sublen, isassoc, avflags;
SHELL_VAR *entry;
avflags = 0;
if (flags & ASS_NOEXPAND)
avflags |= AV_NOEXPAND;
if (flags & ASS_ONEWORD)
avflags |= AV_ONEWORD;
avflags = convert_assign_flags_to_arrayval_flags (flags);
vname = array_variable_name (name, avflags, &sub, &sublen);
if (vname == 0)
@@ -391,16 +374,14 @@ assign_array_element (name, value, flags, estatep)
return entry;
}
/* Assign VALUE to the index computed from SUB of length SUBLEN of array
VNAME. NAME is the complete variable reference. FLAGS are ASS_ assignment
flags. ENTRY is the SHELL_VAR corresponding to VNAME. The caller
initializes ESTATEP, and we set it to the values we compute. */
static SHELL_VAR *
assign_array_element_internal (entry, name, vname, sub, sublen, value, flags, estatep)
SHELL_VAR *entry;
char *name; /* only used for error messages */
char *vname;
char *sub;
int sublen;
char *value;
int flags;
array_eltstate_t *estatep;
assign_array_element_internal (SHELL_VAR *entry, const char *name, char *vname,
char *sub, int sublen, const char *value,
int flags, array_eltstate_t *estatep)
{
char *akey, *nkey;
arrayind_t ind;
@@ -434,7 +415,11 @@ assign_array_element_internal (entry, name, vname, sub, sublen, value, flags, es
}
else
{
ind = array_expand_index (entry, sub, sublen, 0);
/* convert ASS_ flags to AV_FLAGS here */
int avflags;
avflags = convert_assign_flags_to_arrayval_flags (flags);
ind = array_expand_index (entry, sub, sublen, avflags);
/* negative subscripts to indexed arrays count back from end */
if (entry && ind < 0)
ind = (array_p (entry) ? array_max_index (array_cell (entry)) : 0) + 1 + ind;
@@ -460,11 +445,10 @@ assign_array_element_internal (entry, name, vname, sub, sublen, value, flags, es
convert it to an indexed array. If FLAGS&1 is non-zero, an existing
variable is checked for the readonly or noassign attribute in preparation
for assignment (e.g., by the `read' builtin). If FLAGS&2 is non-zero, we
create an associative array. */
create an associative array. If FLAGS&4 is non-zero, we return noassign
variables instead of NULL because the caller wants to handle them. */
SHELL_VAR *
find_or_make_array_variable (name, flags)
char *name;
int flags;
find_or_make_array_variable (const char *name, int flags)
{
SHELL_VAR *var;
@@ -496,6 +480,8 @@ find_or_make_array_variable (name, flags)
{
if (readonly_p (var))
err_readonly (name);
if ((flags & 4) && noassign_p (var))
return (var);
return ((SHELL_VAR *)NULL);
}
else if ((flags & 2) && array_p (var))
@@ -515,9 +501,7 @@ find_or_make_array_variable (name, flags)
/* Perform a compound assignment statement for array NAME, where VALUE is
the text between the parens: NAME=( VALUE ) */
SHELL_VAR *
assign_array_from_string (name, value, flags)
char *name, *value;
int flags;
assign_array_from_string (const char *name, char *value, int flags)
{
SHELL_VAR *var;
int vflags;
@@ -525,10 +509,11 @@ assign_array_from_string (name, value, flags)
vflags = 1;
if (flags & ASS_MKASSOC)
vflags |= 2;
vflags |= 4; /* we want to handle noassign variables ourselves */
var = find_or_make_array_variable (name, vflags);
if (var == 0)
return ((SHELL_VAR *)NULL);
if (var == 0 || noassign_p (var))
return (var);
return (assign_array_var_from_string (var, value, flags));
}
@@ -536,10 +521,7 @@ assign_array_from_string (name, value, flags)
/* Sequentially assign the indices of indexed array variable VAR from the
words in LIST. */
SHELL_VAR *
assign_array_var_from_word_list (var, list, flags)
SHELL_VAR *var;
WORD_LIST *list;
int flags;
assign_array_var_from_word_list (SHELL_VAR *var, WORD_LIST *list, int flags)
{
register arrayind_t i;
register WORD_LIST *l;
@@ -549,7 +531,19 @@ assign_array_var_from_word_list (var, list, flags)
i = (flags & ASS_APPEND) ? array_max_index (a) + 1 : 0;
for (l = list; l; l = l->next, i++)
bind_array_var_internal (var, i, 0, l->word->word, flags & ~ASS_APPEND);
{
if (a && i < 0) /* overflow */
{
char *num;
num = itos (i);
report_error ("%s[%s]: %s", var->name, num, bash_badsub_errmsg);
free (num);
return (var); /* XXX */
}
bind_array_var_internal (var, i, 0, l->word->word, flags & ~ASS_APPEND);
}
VUNSETATTR (var, att_invisible); /* no longer invisible */
@@ -557,14 +551,11 @@ assign_array_var_from_word_list (var, list, flags)
}
WORD_LIST *
expand_compound_array_assignment (var, value, flags)
SHELL_VAR *var;
char *value;
int flags;
expand_compound_array_assignment (SHELL_VAR *var, char *value, int flags)
{
WORD_LIST *list, *nlist;
char *val;
int ni;
size_t ni;
/* This condition is true when invoked from the declare builtin with a
command like
@@ -624,17 +615,22 @@ expand_compound_array_assignment (var, value, flags)
}
#if ASSOC_KVPAIR_ASSIGNMENT
/* If non-zero, we split the words in kv-pair compound array assignments in
addition to performing the other expansions. */
int split_kvpair_assignments = 0;
/* We have a set of key-value pairs that should be expanded and split
(because they are not assignment statements). They are not expanded
and split in expand_compound_array_assignment because assoc_p (var)
is true. We defer the expansion until now. */
static void
assign_assoc_from_kvlist (var, nlist, h, flags)
SHELL_VAR *var;
WORD_LIST *nlist;
HASH_TABLE *h;
int flags;
assign_assoc_from_kvlist (SHELL_VAR *var, WORD_LIST *nlist, HASH_TABLE *h, int flags)
{
WORD_LIST *list;
WORD_LIST *list, *explist;
char *akey, *aval, *k, *v;
for (list = nlist; list; list = list->next)
explist = split_kvpair_assignments ? expand_words_no_vars (nlist) : nlist;
for (list = explist; list; list = list->next)
{
k = list->word->word;
v = list->next ? list->next->word->word : 0;
@@ -642,7 +638,7 @@ assign_assoc_from_kvlist (var, nlist, h, flags)
if (list->next)
list = list->next;
akey = expand_subscript_string (k, 0);
akey = split_kvpair_assignments ? savestring (k) : expand_subscript_string (k, 0);
if (akey == 0 || *akey == 0)
{
err_badarraysub (k);
@@ -650,7 +646,7 @@ assign_assoc_from_kvlist (var, nlist, h, flags)
continue;
}
aval = expand_assignment_string_to_string (v, 0);
aval = split_kvpair_assignments ? savestring (v) : expand_assignment_string_to_string (v, 0);
if (aval == 0)
{
aval = (char *)xmalloc (1);
@@ -658,22 +654,24 @@ assign_assoc_from_kvlist (var, nlist, h, flags)
}
bind_assoc_var_internal (var, h, akey, aval, flags);
free (aval);
}
if (explist != nlist)
dispose_words (explist);
}
/* Return non-zero if L appears to be a key-value pair associative array
compound assignment. */
int
kvpair_assignment_p (l)
WORD_LIST *l;
kvpair_assignment_p (WORD_LIST *l)
{
return (l && (l->word->flags & W_ASSIGNMENT) == 0 && l->word->word[0] != '['); /*]*/
}
char *
expand_and_quote_kvpair_word (w)
char *w;
expand_and_quote_kvpair_word (const char *w)
{
char *r, *s, *t;
@@ -695,17 +693,14 @@ expand_and_quote_kvpair_word (w)
If this is an associative array, we perform the assignments into NHASH and
set NHASH to be the value of VAR after processing the assignments in NLIST */
void
assign_compound_array_list (var, nlist, flags)
SHELL_VAR *var;
WORD_LIST *nlist;
int flags;
int
assign_compound_array_list (SHELL_VAR *var, WORD_LIST *nlist, int flags)
{
ARRAY *a;
HASH_TABLE *h, *nhash;
WORD_LIST *list;
char *w, *val, *nval, *savecmd;
int len, iflags, free_val;
int len, iflags, free_val, any_failed;
arrayind_t ind, last_ind;
char *akey;
@@ -715,6 +710,8 @@ assign_compound_array_list (var, nlist, flags)
akey = (char *)0;
ind = 0;
any_failed = 0;
/* Now that we are ready to assign values to the array, kill the existing
value. */
if ((flags & ASS_APPEND) == 0)
@@ -725,8 +722,6 @@ assign_compound_array_list (var, nlist, flags)
nhash = assoc_create (h->nbuckets);
}
last_ind = (a && (flags & ASS_APPEND)) ? array_max_index (a) + 1 : 0;
#if ASSOC_KVPAIR_ASSIGNMENT
if (assoc_p (var) && kvpair_assignment_p (nlist))
{
@@ -738,10 +733,12 @@ assign_compound_array_list (var, nlist, flags)
var_setassoc (var, nhash);
assoc_dispose (h);
}
return;
return 1; /* XXX - check return value */
}
#endif
last_ind = (a && (flags & ASS_APPEND)) ? array_max_index (a) + 1 : 0;
for (list = nlist; list; list = list->next)
{
/* Don't allow var+=(values) to make assignments in VALUES append to
@@ -760,10 +757,11 @@ assign_compound_array_list (var, nlist, flags)
/* XXX - changes for `+=' */
if (w[len] != ']' || (w[len+1] != '=' && (w[len+1] != '+' || w[len+2] != '=')))
{
if (assoc_p (var))
if (assoc_p (var) || last_ind < 0)
{
err_badarraysub (w);
continue;
any_failed++;
break;
}
nval = make_variable_value (var, w, flags);
if (var->assign_func)
@@ -778,26 +776,33 @@ assign_compound_array_list (var, nlist, flags)
if (len == 1)
{
err_badarraysub (w);
continue;
any_failed++;
break;
}
if (ALL_ELEMENT_SUB (w[1]) && len == 2 && array_p (var))
{
set_exit_status (EXECUTION_FAILURE);
report_error (_("%s: cannot assign to non-numeric index"), w);
continue;
any_failed++;
break;
}
if (array_p (var))
{
ind = array_expand_index (var, w + 1, len, 0);
int avflags;
/* convert ASS_ FLAGS to AV_ flags here */
avflags = convert_assign_flags_to_arrayval_flags (flags);
ind = array_expand_index (var, w + 1, len, avflags);
/* negative subscripts to indexed arrays count back from end */
if (ind < 0)
ind = array_max_index (array_cell (var)) + 1 + ind;
if (ind < 0)
{
err_badarraysub (w);
continue;
any_failed++;
break;
}
last_ind = ind;
@@ -813,7 +818,8 @@ assign_compound_array_list (var, nlist, flags)
{
err_badarraysub (w);
FREE (akey);
continue;
any_failed++;
break;
}
}
@@ -830,7 +836,8 @@ assign_compound_array_list (var, nlist, flags)
{
set_exit_status (EXECUTION_FAILURE);
report_error (_("%s: %s: must use subscript when assigning associative array"), var->name, w);
continue;
any_failed++;
break;
}
else /* No [ind]=value, just a stray `=' */
{
@@ -838,6 +845,16 @@ assign_compound_array_list (var, nlist, flags)
val = w;
}
if (array_p (var) && ind < 0) /* overflow */
{
char *num;
num = itos (ind);
report_error ("%s[%s]: %s", var->name, num, bash_badsub_errmsg);
free (num);
return 0;
}
free_val = 0;
/* See above; we need to expand the value here */
if (assoc_p (var))
@@ -853,7 +870,7 @@ assign_compound_array_list (var, nlist, flags)
savecmd = this_command_name;
if (integer_p (var))
this_command_name = (char *)NULL; /* no command name for errors */
this_command_name = 0; /* no command name for errors */
if (assoc_p (var))
bind_assoc_var_internal (var, nhash, akey, val, iflags);
else
@@ -871,23 +888,36 @@ assign_compound_array_list (var, nlist, flags)
var_setassoc (var, nhash);
assoc_dispose (h);
}
#if ARRAY_EXPORT
if (var && exported_p (var))
{
INVALIDATE_EXPORTSTR (var);
array_needs_making = 1;
}
#endif
return (any_failed ? 0 : 1);
}
/* Perform a compound array assignment: VAR->name=( VALUE ). The
VALUE has already had the parentheses stripped. */
VALUE has already had the parentheses stripped. FLAGS are ASS_
assignment flags. */
SHELL_VAR *
assign_array_var_from_string (var, value, flags)
SHELL_VAR *var;
char *value;
int flags;
assign_array_var_from_string (SHELL_VAR *var, char *value, int flags)
{
WORD_LIST *nlist;
int aflags, r;
if (value == 0)
return var;
nlist = expand_compound_array_assignment (var, value, flags);
assign_compound_array_list (var, nlist, flags);
/* This is were we set ASS_NOEXPAND and ASS_ONEWORD if we need to, since
expand_compound_array_assignment performs word expansions. Honors
array_expand_once; allows @ and * as associative array keys. */
aflags = flags | (array_expand_once ? ASS_NOEXPAND : 0) | ASS_ALLOWALLSUB;
r = assign_compound_array_list (var, nlist, aflags);
if (nlist)
dispose_words (nlist);
@@ -895,15 +925,14 @@ assign_array_var_from_string (var, value, flags)
if (var)
VUNSETATTR (var, att_invisible); /* no longer invisible */
return (var);
return (r == 0 ? (SHELL_VAR *)0 : var);
}
/* Quote globbing chars and characters in $IFS before the `=' in an assignment
statement (usually a compound array assignment) to protect them from
unwanted filename expansion or word splitting. */
static char *
quote_assign (string)
const char *string;
quote_assign (const char *string)
{
size_t slen;
int saw_eq;
@@ -949,9 +978,7 @@ quote_assign (string)
indexed arrays. W has already undergone word expansions. If W has no [IND]=,
just single-quote and return it. */
static char *
quote_compound_array_word (w, type)
char *w;
int type;
quote_compound_array_word (char *w, int type)
{
char *nword, *sub, *value, *t;
int ind, wlen, i;
@@ -985,6 +1012,7 @@ quote_compound_array_word (w, type)
if (t != w+ind)
free (t);
strcpy (nword + i, value);
free (value);
return nword;
}
@@ -997,9 +1025,7 @@ quote_compound_array_word (w, type)
Used for compound assignments to associative arrays that are arguments to
declaration builtins (declare -A a=( list )). */
char *
expand_and_quote_assoc_word (w, type)
char *w;
int type;
expand_and_quote_assoc_word (char *w, int type)
{
char *nword, *key, *value, *s, *t;
int ind, wlen, i;
@@ -1050,9 +1076,7 @@ expand_and_quote_assoc_word (w, type)
the = sign (and any `+') alone. If it's not an assignment, just single-
quote the word. This is used for indexed arrays. */
void
quote_compound_array_list (list, type)
WORD_LIST *list;
int type;
quote_compound_array_list (WORD_LIST *list, int type)
{
char *s, *t;
WORD_LIST *l;
@@ -1078,8 +1102,7 @@ quote_compound_array_list (list, type)
/* For each word in a compound array assignment, if the word looks like
[ind]=value, quote globbing chars and characters in $IFS before the `='. */
static void
quote_array_assignment_chars (list)
WORD_LIST *list;
quote_array_assignment_chars (WORD_LIST *list)
{
char *nword;
WORD_LIST *l;
@@ -1112,14 +1135,12 @@ quote_array_assignment_chars (list)
the subscript, we just assume the subscript ends with a close bracket,
if one is present, and use what's inside the brackets. */
int
unbind_array_element (var, sub, flags)
SHELL_VAR *var;
char *sub;
int flags;
unbind_array_element (SHELL_VAR *var, char *sub, int flags)
{
arrayind_t ind;
char *akey;
ARRAY_ELEMENT *ae;
int avflags;
/* Assume that the caller (unset_builtin) passes us a null-terminated SUB,
so we don't have to use VA_ONEWORD or parse the subscript again with
@@ -1176,7 +1197,9 @@ unbind_array_element (var, sub, flags)
}
/* Fall through for behavior 3 */
}
ind = array_expand_index (var, sub, strlen (sub) + 1, 0);
avflags = convert_validarray_flags_to_arrayval_flags (flags);
ind = array_expand_index (var, sub, strlen (sub) + 1, avflags);
/* negative subscripts to indexed arrays count back from end */
if (ind < 0)
ind = array_max_index (array_cell (var)) + 1 + ind;
@@ -1192,7 +1215,8 @@ unbind_array_element (var, sub, flags)
else /* array_p (var) == 0 && assoc_p (var) == 0 */
{
akey = this_command_name;
ind = array_expand_index (var, sub, strlen (sub) + 1, 0);
avflags = convert_validarray_flags_to_arrayval_flags (flags);
ind = array_expand_index (var, sub, strlen (sub) + 1, avflags);
this_command_name = akey;
if (ind == 0)
{
@@ -1209,9 +1233,7 @@ unbind_array_element (var, sub, flags)
/* Format and output an array assignment in compound form VAR=(VALUES),
suitable for re-use as input. */
void
print_array_assignment (var, quoted)
SHELL_VAR *var;
int quoted;
print_array_assignment (SHELL_VAR *var, int quoted)
{
char *vstr;
@@ -1229,9 +1251,7 @@ print_array_assignment (var, quoted)
/* Format and output an associative array assignment in compound form
VAR=(VALUES), suitable for re-use as input. */
void
print_assoc_assignment (var, quoted)
SHELL_VAR *var;
int quoted;
print_assoc_assignment (SHELL_VAR *var, int quoted)
{
char *vstr;
@@ -1254,8 +1274,6 @@ print_assoc_assignment (var, quoted)
/* Return 1 if NAME is a properly-formed array reference v[sub]. */
/* Return 1 if NAME is a properly-formed array reference v[sub]. */
/* When NAME is a properly-formed array reference and a non-null argument SUBP
is supplied, '[' and ']' that enclose the subscript are replaced by '\0',
and the pointer to the subscript in NAME is assigned to *SUBP, so that NAME
@@ -1264,10 +1282,7 @@ print_assoc_assignment (var, quoted)
not be modified. */
/* We need to reserve 1 for FLAGS, which we pass to skipsubscript. */
int
tokenize_array_reference (name, flags, subp)
char *name;
int flags;
char **subp;
tokenize_array_reference (const char *name, int flags, char **subp)
{
char *t;
int r, len, isassoc, ssflags;
@@ -1278,7 +1293,7 @@ tokenize_array_reference (name, flags, subp)
if (t)
{
*t = '\0';
r = legal_identifier (name);
r = valid_identifier (name);
if (flags & VA_NOEXPAND) /* Don't waste a lookup if we don't need one */
isassoc = (entry = find_variable (name)) && assoc_p (entry);
*t = '[';
@@ -1327,20 +1342,15 @@ tokenize_array_reference (name, flags, subp)
/* We need to reserve 1 for FLAGS, which we pass to skipsubscript. */
int
valid_array_reference (name, flags)
const char *name;
int flags;
valid_array_reference (const char *name, int flags)
{
return tokenize_array_reference ((char *)name, flags, (char **)NULL);
return tokenize_array_reference (name, flags, (char **)NULL);
}
/* Expand the array index beginning at S and extending LEN characters. */
/* Expand the array index beginning at S and extending LEN characters. FLAGS
are AV_ flags saying how to compute the array value. */
arrayind_t
array_expand_index (var, s, len, flags)
SHELL_VAR *var;
char *s;
int len;
int flags;
array_expand_index (SHELL_VAR *var, const char *s, int len, int flags)
{
char *exp, *t, *savecmd;
int expok, eflag;
@@ -1349,8 +1359,12 @@ array_expand_index (var, s, len, flags)
exp = (char *)xmalloc (len);
strncpy (exp, s, len - 1);
exp[len - 1] = '\0';
#if 0 /* TAG: maybe bash-5.2 */
#if 1 /* TAG: bash-5.3 */
#if 0
if (shell_compatibility_level <= 52 || (flags & AV_NOEXPAND) == 0)
#else
if ((flags & AV_NOEXPAND) == 0)
#endif
t = expand_arith_string (exp, Q_DOUBLE_QUOTES|Q_ARITH|Q_ARRAYSUB); /* XXX - Q_ARRAYSUB for future use */
else
t = exp;
@@ -1382,11 +1396,7 @@ array_expand_index (var, s, len, flags)
in *SUBP. If LENP is non-null, the length of the subscript is returned
in *LENP. This returns newly-allocated memory. */
char *
array_variable_name (s, flags, subp, lenp)
const char *s;
int flags;
char **subp;
int *lenp;
array_variable_name (const char *s, int flags, char **subp, int *lenp)
{
char *t, *ret;
int ind, ni, ssflags;
@@ -1436,11 +1446,7 @@ array_variable_name (s, flags, subp, lenp)
non-null, return a pointer to the start of the subscript in *SUBP.
If LENP is non-null, the length of the subscript is returned in *LENP. */
SHELL_VAR *
array_variable_part (s, flags, subp, lenp)
const char *s;
int flags;
char **subp;
int *lenp;
array_variable_part (const char *s, int flags, char **subp, int *lenp)
{
char *t;
SHELL_VAR *var;
@@ -1475,10 +1481,7 @@ 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, estatep)
const char *s;
int quoted, flags;
array_eltstate_t *estatep;
array_value_internal (const char *s, int quoted, int flags, array_eltstate_t *estatep)
{
int len, isassoc, subtype;
arrayind_t ind;
@@ -1552,6 +1555,12 @@ array_value_internal (s, quoted, flags, estatep)
retval = quote_string (temp);
free (temp);
}
else if (t[0] == '*' && quoted == 0 && (flags & AV_ASSIGNRHS))
{
temp = string_list_dollar_star (l, quoted, PF_ASSIGNRHS);
retval = quote_nosplit (temp);
free (temp);
}
else /* ${name[@]} or unquoted ${name[*]} */
retval = string_list_dollar_at (l, quoted, (flags & AV_ASSIGNRHS) ? PF_ASSIGNRHS : 0);
@@ -1636,10 +1645,7 @@ array_value_internal (s, quoted, flags, estatep)
/* 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, estatep)
const char *s;
int quoted, flags;
array_eltstate_t *estatep;
array_value (const char *s, int quoted, int flags, array_eltstate_t *estatep)
{
char *retval;
@@ -1652,10 +1658,7 @@ array_value (s, quoted, flags, estatep)
is used by other parts of the shell such as the arithmetic expression
evaluator in expr.c. */
char *
get_array_value (s, flags, estatep)
const char *s;
int flags;
array_eltstate_t *estatep;
get_array_value (const char *s, int flags, array_eltstate_t *estatep)
{
char *retval;
@@ -1664,9 +1667,7 @@ get_array_value (s, flags, estatep)
}
char *
array_keys (s, quoted, pflags)
char *s;
int quoted, pflags;
array_keys (const char *s, int quoted, int pflags)
{
int len;
char *retval, *t, *temp;