changes to make builtins that perform assignments work better with arbitrary associative array keys

This commit is contained in:
Chet Ramey
2022-01-04 10:54:28 -05:00
parent 186129835e
commit 1d17c604fc
12 changed files with 649 additions and 480 deletions
+4 -6
View File
@@ -990,10 +990,7 @@ builtin_bind_variable (name, value, flags)
#if defined (ARRAY_VARS)
/* Callers are responsible for calling this with array references that have
already undergone valid_array_reference checks.
Affected builtins: read, printf
To make this *really* work, needs additional downstream support, starting
with assign_array_element and array_variable_name. */
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)
@@ -1016,13 +1013,14 @@ builtin_bind_variable (name, value, flags)
}
SHELL_VAR *
builtin_bind_var_to_int (name, val)
builtin_bind_var_to_int (name, val, flags)
char *name;
intmax_t val;
int flags;
{
SHELL_VAR *v;
v = bind_var_to_int (name, val, ASS_ALLOWALLSUB);
v = bind_var_to_int (name, val, flags|ASS_ALLOWALLSUB);
return v;
}
+16 -1
View File
@@ -232,7 +232,7 @@ extern sh_builtin_func_t *this_shell_builtin;
extern sh_builtin_func_t *last_shell_builtin;
extern SHELL_VAR *builtin_bind_variable PARAMS((char *, char *, int));
extern SHELL_VAR *builtin_bind_var_to_int PARAMS((char *, intmax_t));
extern SHELL_VAR *builtin_bind_var_to_int PARAMS((char *, intmax_t, int));
extern int builtin_unbind_variable PARAMS((const char *));
extern int builtin_arrayref_flags PARAMS((WORD_DESC *, int));
@@ -263,4 +263,19 @@ extern int source_uses_path;
/* variables from wait.def */
extern int wait_intr_flag;
/* common code to set flags for valid_array_reference and builtin_bind_variable */
#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 |= VA_ONEWORD|VA_NOEXPAND; \
if (vflags & VA_NOEXPAND) \
bindflags |= ASS_NOEXPAND; \
if (vflags & VA_ONEWORD) \
bindflags |= ASS_ONEWORD; \
} while (0)
#endif
#endif /* !__COMMON_H */
+4 -4
View File
@@ -151,7 +151,7 @@ extern int errno;
if (vflag) \
{ \
SHELL_VAR *v; \
v = builtin_bind_variable (vname, vbuf, 0); \
v = builtin_bind_variable (vname, vbuf, bindflags); \
stupidly_hack_special_variables (vname); \
if (v == 0 || readonly_p (v) || noassign_p (v)) \
return (EXECUTION_FAILURE); \
@@ -232,6 +232,7 @@ static int conversion_error;
/* printf -v var support */
static int vflag = 0;
static int bindflags = 0;
static char *vbuf, *vname;
static size_t vbsize;
static int vblen;
@@ -266,10 +267,9 @@ printf_builtin (list)
{
case 'v':
vname = list_optarg;
bindflags = 0;
#if defined (ARRAY_VARS)
arrayflags = assoc_expand_once ? VA_NOEXPAND : 0;
if (assoc_expand_once && (list_optflags & W_ARRAYREF))
arrayflags |= VA_ONEWORD|VA_NOEXPAND;
SET_VFLAGS (list_optflags, arrayflags, bindflags);
retval = legal_identifier (vname) || valid_array_reference (vname, arrayflags);
#else
retval = legal_identifier (vname);
+3 -17
View File
@@ -190,20 +190,6 @@ read_builtin_timeout (fd)
: shtimer_select (read_timeout));
}
#if defined (ARRAY_VARS)
#define SET_VFLAGS(wordflags) \
do { \
vflags = assoc_expand_once ? VA_NOEXPAND : 0; \
bindflags = assoc_expand_once ? ASS_NOEXPAND : 0; \
if (assoc_expand_once && (wordflags & W_ARRAYREF)) \
vflags |= VA_ONEWORD|VA_NOEXPAND; \
if (vflags & VA_NOEXPAND) \
bindflags |= ASS_NOEXPAND; \
if (vflags & VA_ONEWORD) \
bindflags |= ASS_ONEWORD; \
} while (0)
#endif
/* Read the value of the shell variables whose names follow.
The reading is done from the current input stream, whatever
that may be. Successive words of the input line are assigned
@@ -378,7 +364,7 @@ read_builtin (list)
variable names is a valid identifier, and bail early if so. */
#if defined (ARRAY_VARS)
if (list)
SET_VFLAGS (list->word->flags);
SET_VFLAGS (list->word->flags, vflags, bindflags);
if (list && legal_identifier (list->word->word) == 0 && valid_array_reference (list->word->word, vflags) == 0)
#else
bindflags = 0;
@@ -969,7 +955,7 @@ assign_vars:
{
varname = list->word->word;
#if defined (ARRAY_VARS)
SET_VFLAGS (list->word->flags);
SET_VFLAGS (list->word->flags, vflags, bindflags);
if (legal_identifier (varname) == 0 && valid_array_reference (varname, vflags) == 0)
#else
if (legal_identifier (varname) == 0)
@@ -1018,7 +1004,7 @@ assign_vars:
/* Now assign the rest of the line to the last variable argument. */
#if defined (ARRAY_VARS)
SET_VFLAGS (list->word->flags);
SET_VFLAGS (list->word->flags, vflags, bindflags);
if (legal_identifier (list->word->word) == 0 && valid_array_reference (list->word->word, vflags) == 0)
#else
if (legal_identifier (list->word->word) == 0)
+7 -11
View File
@@ -111,7 +111,7 @@ int
wait_builtin (list)
WORD_LIST *list;
{
int status, code, opt, nflag;
int status, code, opt, nflag, vflags, bindflags;
volatile int wflags;
char *vname;
SHELL_VAR *pidvar;
@@ -119,7 +119,7 @@ wait_builtin (list)
USE_VAR(list);
nflag = wflags = 0;
nflag = wflags = vflags = 0;
vname = NULL;
pidvar = (SHELL_VAR *)NULL;
reset_internal_getopt ();
@@ -136,6 +136,7 @@ wait_builtin (list)
break;
case 'p':
vname = list_optarg;
vflags = list_optflags;
break;
#endif
CASE_HELPOPT;
@@ -152,15 +153,10 @@ wait_builtin (list)
#if defined (ARRAY_VARS)
int arrayflags;
#if 0
arrayflags = assoc_expand_once ? VA_NOEXPAND : 0;
if (assoc_expand_once && (list_optflags & W_ARRAYREF))
arrayflags |= VA_ONEWORD|VA_NOEXPAND;
#else
arrayflags = 0; /* not yet without builtin_bind_var_to_int support */
#endif
SET_VFLAGS (vflags, arrayflags, bindflags);
if (legal_identifier (vname) == 0 && valid_array_reference (vname, arrayflags) == 0)
#else
bindflags = 0;
if (legal_identifier (vname) == 0)
#endif
{
@@ -225,7 +221,7 @@ wait_builtin (list)
status = wait_for_any_job (wflags, &pstat);
if (vname && status >= 0)
builtin_bind_var_to_int (vname, pstat.pid);
builtin_bind_var_to_int (vname, pstat.pid, bindflags);
if (status < 0)
status = 127;
@@ -241,7 +237,7 @@ wait_builtin (list)
{
wait_for_background_pids (&pstat);
if (vname)
builtin_bind_var_to_int (vname, pstat.pid);
builtin_bind_var_to_int (vname, pstat.pid, bindflags);
WAIT_RETURN (EXECUTION_SUCCESS);
}