diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog
index a667dbe9..f822f4f8 100644
--- a/CWRU/CWRU.chlog
+++ b/CWRU/CWRU.chlog
@@ -6569,3 +6569,48 @@ shell.c
the shell decides it's being run by ssh and runs bashrc (only if
SSH_SOURCE_BASHRC is defined). Non-zero while the startup files
are being run. Not used by any other part of the shell yet.
+
+ 6/12
+ ----
+arrayfunc.h
+ - new inline functions to convert between assignment flags (ASS_*),
+ array value flags (AV_*), and valid array flags (VA_*)
+
+shell.h
+ - include arrayfunc.h after subst.h and variables.h so all the values
+ for the new inline functions are available
+
+variables.c
+ - bind_int_variable: use convert_assign_flags_to_validarray_flags and
+ convert_assign_flags_to_arrayval flags instead of inline assignments
+
+builtins/common.c
+ - builtin_bind_variable: use convert_assign_flags_to_validarray_flags
+ instead of inline assignments
+
+arrayfunc.c
+ - assign_array_element: use convert_assign_flags_to_arrayval_flags
+ instead of inline code
+ - assign_array_element_internal: use convert_assign_flags_to_arrayval_flags
+ to pass the right values to array_expand_index
+ - assign_array_var_from_string: since expand_compound_array_assignment
+ performs one round of expansion on the subscripts, make sure to add
+ ASS_NOEXPAND (if assoc_expand_once is set) and ASS_ALLOWALLSUB to the
+ flags we pass to assign_compound_array_list
+ - unbind_array_index: use convert_validarray_flags_to_array_value_flags
+ to pass the right values to array_expand_index
+ - array_expand_index: uncomment code tagged for bash-5.3 that checks
+ AV_NOEXPAND and suppresses call to expand_arith_string if it's set.
+ This set of changes extends assoc_expand_once to indexed arrays
+
+arrayfunc.[ch],execute_cmd.c,expr.c,test.c,builtins/common.c,builtins/mkbuiltins.c
+builtins/declare.def,builtins/set.def,builtins/shopt.def
+ - array_expand_once: new name for internal assoc_expand_once variable
+
+ 6/13
+ ----
+builtins/shopt.def
+ - array_expand_once: new option, replaces assoc_expand_once
+
+doc/bash.1,doc/bashref.texi
+ - array_expand_once: document new shopt option
diff --git a/MANIFEST b/MANIFEST
index 7d7d313d..d1a937cd 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -948,6 +948,7 @@ tests/array28.sub f
tests/array29.sub f
tests/array30.sub f
tests/array31.sub f
+tests/array32.sub f
tests/array-at-star f
tests/array2.right f
tests/assoc.tests f
diff --git a/arrayfunc.c b/arrayfunc.c
index b85a7cf9..28aee54b 100644
--- a/arrayfunc.c
+++ b/arrayfunc.c
@@ -45,11 +45,8 @@
# 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 (SHELL_VAR *, arrayind_t, char *, const char *, int);
@@ -317,11 +314,7 @@ assign_array_element (const char *name, const char *value, int flags, array_elts
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)
@@ -358,6 +351,10 @@ assign_array_element (const char *name, const char *value, int flags, array_elts
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 (SHELL_VAR *entry, const char *name, char *vname,
char *sub, int sublen, const char *value,
@@ -395,7 +392,11 @@ assign_array_element_internal (SHELL_VAR *entry, const char *name, char *vname,
}
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;
@@ -745,7 +746,11 @@ assign_compound_array_list (SHELL_VAR *var, WORD_LIST *nlist, int flags)
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;
@@ -829,17 +834,23 @@ assign_compound_array_list (SHELL_VAR *var, WORD_LIST *nlist, int flags)
}
/* 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 (SHELL_VAR *var, char *value, int flags)
{
WORD_LIST *nlist;
+ int aflags;
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;
+ assign_compound_array_list (var, nlist, aflags);
if (nlist)
dispose_words (nlist);
@@ -1062,6 +1073,7 @@ 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
@@ -1118,7 +1130,9 @@ unbind_array_element (SHELL_VAR *var, char *sub, int 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;
@@ -1134,7 +1148,8 @@ unbind_array_element (SHELL_VAR *var, char *sub, int 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)
{
@@ -1265,7 +1280,8 @@ valid_array_reference (const char *name, int flags)
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 (SHELL_VAR *var, const char *s, int len, int flags)
{
@@ -1276,8 +1292,12 @@ array_expand_index (SHELL_VAR *var, const char *s, int len, int 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;
diff --git a/arrayfunc.h b/arrayfunc.h
index 8fcec160..aa111013 100644
--- a/arrayfunc.h
+++ b/arrayfunc.h
@@ -48,11 +48,8 @@ typedef struct element_state
#if defined (ARRAY_VARS)
-/* This variable means to not expand associative array subscripts more than
- once, when performing variable expansion. */
-extern int assoc_expand_once;
-
-/* The analog for indexed array subscripts */
+/* This variable means to not expand associative or indexed array subscripts
+ more than once, when performing variable expansion. */
extern int array_expand_once;
/* Flags for array_value_internal and callers array_value/get_array_value; also
@@ -137,4 +134,58 @@ extern void flush_eltstate (array_eltstate_t *);
#endif
+/* Functions to convert from other flag values to AV_ array variable flags */
+
+#if defined (ASS_NOEXPAND)
+static inline int
+convert_assign_flags_to_arrayval_flags (int aflags)
+{
+ int avflags;
+
+ avflags = 0;
+ if (aflags & ASS_NOEXPAND)
+ avflags |= AV_NOEXPAND;
+ if (aflags & ASS_ONEWORD)
+ avflags |= AV_ONEWORD;
+ if (aflags & ASS_NOEVAL)
+ avflags |= AV_NOEXPAND;
+ if (aflags & ASS_ALLOWALLSUB)
+ avflags |= AV_ATSTARKEYS;
+ return avflags;
+}
+#endif
+
+#if defined (VA_NOEXPAND)
+static inline int
+convert_validarray_flags_to_arrayval_flags (int vflags)
+{
+ int avflags;
+
+ if (vflags & VA_NOEXPAND)
+ avflags |= AV_NOEXPAND;
+ if (vflags & VA_ONEWORD)
+ avflags |= AV_ONEWORD;
+ if (vflags & VA_ALLOWALL)
+ avflags |= AV_ATSTARKEYS;
+ return avflags;
+}
+#endif
+
+#if defined (ASS_NOEXPAND)
+static inline int
+convert_assign_flags_to_validarray_flags (int flags)
+{
+ int vflags;
+
+ vflags = 0;
+ if (flags & ASS_NOEXPAND)
+ vflags |= VA_NOEXPAND;
+ if (flags & ASS_ONEWORD)
+ vflags |= VA_ONEWORD;
+ if (flags & ASS_ALLOWALLSUB)
+ vflags |= VA_ALLOWALL;
+ return vflags;
+}
+#endif
+
#endif /* !_ARRAYFUNC_H_ */
diff --git a/builtins/common.c b/builtins/common.c
index e5402961..35fd710a 100644
--- a/builtins/common.c
+++ b/builtins/common.c
@@ -932,12 +932,11 @@ builtin_bind_variable (char *name, char *value, int flags)
#if defined (ARRAY_VARS)
/* Callers are responsible for calling this with array references that have
already undergone valid_array_reference checks (read, printf). */
- vflags = assoc_expand_once ? (VA_NOEXPAND|VA_ONEWORD) : 0;
- bindflags = flags | (assoc_expand_once ? ASS_NOEXPAND : 0) | ASS_ALLOWALLSUB;
- if (flags & ASS_NOEXPAND)
- vflags |= VA_NOEXPAND;
- if (flags & ASS_ONEWORD)
- vflags |= VA_ONEWORD;
+ /* XXX - should we unconditionally set ASS_NOEXPAND if the shell
+ compatibility level is > 52? */
+ bindflags = flags | (array_expand_once ? ASS_NOEXPAND : 0) | ASS_ALLOWALLSUB;
+ vflags = convert_assign_flags_to_validarray_flags (flags);
+ vflags |= array_expand_once ? (VA_NOEXPAND|VA_ONEWORD) : 0;
if (valid_array_reference (name, vflags) == 0)
v = bind_variable (name, value, flags);
@@ -1022,7 +1021,7 @@ builtin_arrayref_flags (WORD_DESC *w, int baseflags)
vflags = baseflags;
- /* Don't require assoc_expand_once if we have an argument that's already
+ /* Don't require array_expand_once if we have an argument that's already
passed through valid_array_reference and been expanded once. That
doesn't protect it from normal expansions like word splitting, so
proper quoting is still required. */
@@ -1031,7 +1030,7 @@ builtin_arrayref_flags (WORD_DESC *w, int baseflags)
# if 0
/* This is a little sketchier but handles quoted arguments. */
- if (assoc_expand_once && (t = strchr (w->word, '[')) && t[strlen(t) - 1] == ']')
+ if (array_expand_once && (t = strchr (w->word, '[')) && t[strlen(t) - 1] == ']')
vflags |= VA_ONEWORD|VA_NOEXPAND;
# endif
@@ -1050,12 +1049,12 @@ set_expand_once (int nval, int uwp)
{
int oa;
- oa = assoc_expand_once;
+ oa = array_expand_once;
if (shell_compatibility_level > 51) /* XXX - internal */
{
if (uwp)
- unwind_protect_int (assoc_expand_once);
- assoc_expand_once = nval;
+ unwind_protect_int (array_expand_once);
+ array_expand_once = nval;
}
return oa;
}
diff --git a/builtins/common.h b/builtins/common.h
index 630ebd44..aced205f 100644
--- a/builtins/common.h
+++ b/builtins/common.h
@@ -275,9 +275,9 @@ extern int wait_intr_flag;
#if defined (ARRAY_VARS)
#define SET_VFLAGS(wordflags, vflags, bindflags) \
do { \
- vflags = assoc_expand_once ? VA_NOEXPAND : 0; \
- bindflags = assoc_expand_once ? ASS_NOEXPAND : 0; \
- if (assoc_expand_once && (wordflags & W_ARRAYREF)) \
+ vflags = array_expand_once ? VA_NOEXPAND : 0; \
+ bindflags = array_expand_once ? ASS_NOEXPAND : 0; \
+ if (array_expand_once && (wordflags & W_ARRAYREF)) \
vflags |= VA_ONEWORD|VA_NOEXPAND; \
if (vflags & VA_NOEXPAND) \
bindflags |= ASS_NOEXPAND; \
diff --git a/builtins/declare.def b/builtins/declare.def
index 41c11e1f..e652f639 100644
--- a/builtins/declare.def
+++ b/builtins/declare.def
@@ -393,7 +393,7 @@ declare_internal (WORD_LIST *list, int local_var)
name = savestring (list->word->word);
wflags = list->word->flags;
#if defined (ARRAY_VARS)
- assoc_noexpand = assoc_expand_once && (wflags & W_ASSIGNMENT);
+ assoc_noexpand = array_expand_once && (wflags & W_ASSIGNMENT);
#else
assoc_noexpand = 0;
#endif
diff --git a/builtins/mkbuiltins.c b/builtins/mkbuiltins.c
index d0d5559f..658db057 100644
--- a/builtins/mkbuiltins.c
+++ b/builtins/mkbuiltins.c
@@ -178,7 +178,7 @@ char *posix_builtins[] =
};
/* The builtin commands that can take array references as arguments and pay
- attention to `assoc_expand_once'. These are the ones that don't assign
+ attention to `array_expand_once'. These are the ones that don't assign
values, but need to avoid double expansions. */
char *arrayvar_builtins[] =
{
diff --git a/builtins/set.def b/builtins/set.def
index a6f5c253..138899ab 100644
--- a/builtins/set.def
+++ b/builtins/set.def
@@ -866,7 +866,7 @@ unset_builtin (WORD_LIST *list)
nameref = 0;
#if defined (ARRAY_VARS)
- base_vflags = assoc_expand_once ? VA_NOEXPAND : 0;
+ base_vflags = array_expand_once ? VA_NOEXPAND : 0;
#endif
while (list)
diff --git a/builtins/shopt.def b/builtins/shopt.def
index f94116ea..f621ec6b 100644
--- a/builtins/shopt.def
+++ b/builtins/shopt.def
@@ -122,7 +122,6 @@ extern int debugging_mode;
#endif
#if defined (ARRAY_VARS)
-extern int assoc_expand_once;
extern int array_expand_once;
int expand_once_flag;
#endif
@@ -146,7 +145,7 @@ static int shopt_set_complete_direxpand (char *, int);
#endif
#if defined (ARRAY_VARS)
-static int set_assoc_expand (char *, int);
+static int set_array_expand (char *, int);
#endif
#if defined (EXTENDED_GLOB)
@@ -180,7 +179,8 @@ static struct {
} shopt_vars[] = {
{ "autocd", &autocd, (shopt_set_func_t *)NULL },
#if defined (ARRAY_VARS)
- { "assoc_expand_once", &expand_once_flag, set_assoc_expand },
+ { "array_expand_once", &expand_once_flag, set_array_expand },
+ { "assoc_expand_once", &expand_once_flag, set_array_expand },
#endif
{ "cdable_vars", &cdable_vars, (shopt_set_func_t *)NULL },
{ "cdspell", &cdspelling, (shopt_set_func_t *)NULL },
@@ -386,7 +386,7 @@ reset_shopt_options (void)
glob_always_skip_dot_and_dotdot = 1; /* new default as of bash-5.2 */
#if defined (ARRAY_VARS)
- expand_once_flag = assoc_expand_once = 0;
+ expand_once_flag = array_expand_once = 0;
#endif
#if defined (HISTORY)
@@ -914,12 +914,12 @@ initialize_bashopts (int no_bashopts)
#if defined (ARRAY_VARS)
static int
-set_assoc_expand (char *option_name, int mode)
+set_array_expand (char *option_name, int mode)
{
#if 0 /* leave this disabled */
if (shell_compatibility_level <= 51)
#endif
- assoc_expand_once = expand_once_flag;
+ array_expand_once = expand_once_flag;
return 0;
}
#endif
diff --git a/doc/bash.0 b/doc/bash.0
index 1ae611e1..48f78a48 100644
--- a/doc/bash.0
+++ b/doc/bash.0
@@ -5901,12 +5901,14 @@ SSHHEELLLL BBUUIILLTTIINN CCOOMMMMAANNDDSS
The list of sshhoopptt options is:
- aassssoocc__eexxppaanndd__oonnccee
+ aarrrraayy__eexxppaanndd__oonnccee
If set, the shell suppresses multiple evaluation of as-
- sociative array subscripts during arithmetic expression
- evaluation, while executing builtins that can perform
- variable assignments, and while executing builtins that
- perform array dereferencing.
+ sociative and indexed array subscripts during arithmetic
+ expression evaluation, while executing builtins that can
+ perform variable assignments, and while executing
+ builtins that perform array dereferencing.
+ aassssoocc__eexxppaanndd__oonnccee
+ Deprecated; a synonym for aarrrraayy__eexxppaanndd__oonnccee.
aauuttooccdd If set, a command name that is the name of a directory
is executed as if it were the argument to the ccdd com-
mand. This option is only used by interactive shells.
@@ -6778,4 +6780,4 @@ BBUUGGSS
-GNU Bash 5.2 2023 May 23 BASH(1)
+GNU Bash 5.2 2023 June 13 BASH(1)
diff --git a/doc/bash.1 b/doc/bash.1
index ea23fc1e..98c8c048 100644
--- a/doc/bash.1
+++ b/doc/bash.1
@@ -5,12 +5,12 @@
.\" Case Western Reserve University
.\" chet.ramey@case.edu
.\"
-.\" Last Change: Tue May 23 11:29:30 EDT 2023
+.\" Last Change: Tue Jun 13 10:33:46 EDT 2023
.\"
.\" bash_builtins, strip all but Built-Ins section
.if \n(zZ=1 .ig zZ
.if \n(zY=1 .ig zY
-.TH BASH 1 "2023 May 23" "GNU Bash 5.2"
+.TH BASH 1 "2023 June 13" "GNU Bash 5.2"
.\"
.\" There's some problem with having a `@'
.\" in a tagged paragraph with the BSD man macros.
@@ -10385,12 +10385,16 @@ The list of \fBshopt\fP options is:
.if n .sp 1v
.PD 0
.TP 8
-.B assoc_expand_once
-If set, the shell suppresses multiple evaluation of associative array
-subscripts during arithmetic expression evaluation, while executing
+.B array_expand_once
+If set, the shell suppresses multiple evaluation of
+associative and indexed array subscripts
+during arithmetic expression evaluation, while executing
builtins that can perform variable assignments,
and while executing builtins that perform array dereferencing.
.TP 8
+.B assoc_expand_once
+Deprecated; a synonym for \fBarray_expand_once\fP.
+.TP 8
.B autocd
If set, a command name that is the name of a directory is executed as if
it were the argument to the \fBcd\fP command.
diff --git a/doc/bash.html b/doc/bash.html
index d2e5effb..261e6689 100644
--- a/doc/bash.html
+++ b/doc/bash.html
@@ -3,7 +3,7 @@
-| BASH(1) | 2023 May 23 | BASH(1)
+ | BASH(1) | 2023 June 13 | BASH(1)
|
Index
@@ -13061,13 +13061,18 @@ The list of shopt options is:
+- array_expand_once
+
+
-
+If set, the shell suppresses multiple evaluation of
+associative and indexed array subscripts
+during arithmetic expression evaluation, while executing
+builtins that can perform variable assignments,
+and while executing builtins that perform array dereferencing.
- assoc_expand_once
-
-If set, the shell suppresses multiple evaluation of associative array
-subscripts during arithmetic expression evaluation, while executing
-builtins that can perform variable assignments,
-and while executing builtins that perform array dereferencing.
+Deprecated; a synonym for array_expand_once.
- autocd
-
@@ -14999,7 +15004,7 @@ There may be only one active coprocess at a time.
-| GNU Bash 5.2 | 2023 May 23 | BASH(1)
+ | GNU Bash 5.2 | 2023 June 13 | BASH(1)
|
@@ -15105,7 +15110,7 @@ There may be only one active coprocess at a time.
- BUGS
-
-This document was created by man2html from /usr/local/src/bash/bash-20230522/doc/bash.1.
-Time: 23 May 2023 11:31:51 EDT
+This document was created by man2html from /usr/local/src/bash/bash-20230612/doc/bash.1.
+Time: 13 June 2023 10:42:12 EDT