mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-24 06:17:57 +02:00
changes to make builtins that perform assignments work better with arbitrary associative array keys
This commit is contained in:
@@ -2815,3 +2815,51 @@ subst.c
|
||||
unset A[$rkey]
|
||||
work because the unset builtin sees the W_ARRAYREF flag on its
|
||||
argument
|
||||
|
||||
12/29
|
||||
-----
|
||||
builtins/common.h
|
||||
- SET_VFLAGS: take a set of word flags, and set flags for use with
|
||||
valid_array_reference (vflags) and assign_array_element/bind_int_variable
|
||||
(bindflags) based on those flags and the setting of assoc_expand_once
|
||||
(moved from read.def and generalized)
|
||||
|
||||
arrayfunc.c
|
||||
- array_variable_name: now exclusively takes AV_xxx flags; understands
|
||||
how to translate AV_NOEXPAND to the right flag for skipsubscript;
|
||||
understands AV_ONEWORD and AV_NOEXPAND
|
||||
- array_variable_part: just passes the FLAGS arg to array_variable_name
|
||||
- assign_array_element: translates ASS_ flags to AV_ flags for
|
||||
array_variable_name
|
||||
- array_value_internal: now just passes flags straight through to
|
||||
array_variable_part (which sends them to array_variable_name)
|
||||
|
||||
builtins/common.[ch]
|
||||
- builtin_bind_var_to_int: now takes a new FLAGS third argument; passes
|
||||
it to bind_var_to_int
|
||||
|
||||
builtins/printf.def
|
||||
- printf_builtin: use SET_VFLAGS to set flags for builtin_bind_variable
|
||||
(bindflags); makes things like
|
||||
declare -A A; key=']' ; printf -v A[$key] "foo"
|
||||
work without a subscript error as long as assoc_expand_once is defined
|
||||
|
||||
builtins/read.def
|
||||
- read_builtin: use new common version of SET_VFLAGS instead of
|
||||
private version; changed to use new calling sequence; makes things like
|
||||
declare -A A; key=']' ; read A[$key] <<<"foo"
|
||||
work without a subscript error as long as assoc_expand_once is defined
|
||||
|
||||
builtins/wait.def
|
||||
- wait_builtin: use SET_VFLAGS for variable name with -p option
|
||||
- wait_builtin: call builtin_bind_var_to_int with new bindflags third
|
||||
argument
|
||||
|
||||
expr.c
|
||||
- expr_streval: just pass TFLAG (AV_xxx flags) straight through to
|
||||
array_variable_part
|
||||
|
||||
variables.c
|
||||
- bind_int_variable: translate the assignment flags (ASS_xxx) to
|
||||
VA_xxx flags for valid_array_reference calls (ASS_ONEWORD); translate
|
||||
assignment flags to AV_xxx flags for array_variable_part
|
||||
|
||||
+18
-5
@@ -347,10 +347,15 @@ assign_array_element (name, value, flags, estatep)
|
||||
array_eltstate_t *estatep;
|
||||
{
|
||||
char *sub, *vname;
|
||||
int sublen, isassoc;
|
||||
int sublen, isassoc, avflags;
|
||||
SHELL_VAR *entry;
|
||||
|
||||
vname = array_variable_name (name, (flags & ASS_NOEXPAND) != 0, &sub, &sublen);
|
||||
avflags = 0;
|
||||
if (flags & ASS_NOEXPAND)
|
||||
avflags |= AV_NOEXPAND;
|
||||
if (flags & ASS_ONEWORD)
|
||||
avflags |= AV_ONEWORD;
|
||||
vname = array_variable_name (name, avflags, &sub, &sublen);
|
||||
|
||||
if (vname == 0)
|
||||
return ((SHELL_VAR *)NULL);
|
||||
@@ -1374,7 +1379,7 @@ array_variable_name (s, flags, subp, lenp)
|
||||
int *lenp;
|
||||
{
|
||||
char *t, *ret;
|
||||
int ind, ni;
|
||||
int ind, ni, ssflags;
|
||||
|
||||
t = mbschr (s, '[');
|
||||
if (t == 0)
|
||||
@@ -1386,7 +1391,15 @@ array_variable_name (s, flags, subp, lenp)
|
||||
return ((char *)NULL);
|
||||
}
|
||||
ind = t - s;
|
||||
ni = skipsubscript (s, ind, flags&1); /* XXX - was 0 not flags */
|
||||
if ((flags & (AV_NOEXPAND|AV_ONEWORD)) == (AV_NOEXPAND|AV_ONEWORD))
|
||||
ni = strlen (s) - 1;
|
||||
else
|
||||
{
|
||||
ssflags = 0;
|
||||
if (flags & AV_NOEXPAND)
|
||||
ssflags |= 1;
|
||||
ni = skipsubscript (s, ind, ssflags);
|
||||
}
|
||||
if (ni <= ind + 1 || s[ni] != ']')
|
||||
{
|
||||
err_badarraysub (s);
|
||||
@@ -1464,7 +1477,7 @@ array_value_internal (s, quoted, flags, estatep)
|
||||
WORD_LIST *l;
|
||||
SHELL_VAR *var;
|
||||
|
||||
var = array_variable_part (s, (flags&AV_NOEXPAND) ? 1 : 0, &t, &len); /* XXX */
|
||||
var = array_variable_part (s, flags, &t, &len); /* XXX */
|
||||
|
||||
/* Expand the index, even if the variable doesn't exist, in case side
|
||||
effects are needed, like ${w[i++]} where w is unset. */
|
||||
|
||||
+2
-1
@@ -55,7 +55,8 @@ extern int assoc_expand_once;
|
||||
/* The analog for indexed array subscripts */
|
||||
extern int array_expand_once;
|
||||
|
||||
/* Flags for array_value_internal and callers array_value/get_array_value */
|
||||
/* Flags for array_value_internal and callers array_value/get_array_value; also
|
||||
used by array_variable_name and array_variable_part. */
|
||||
#define AV_ALLOWALL 0x001 /* treat a[@] like $@ and a[*] like $* */
|
||||
#define AV_QUOTED 0x002
|
||||
#define AV_USEIND 0x004
|
||||
|
||||
+4
-6
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -1161,12 +1161,12 @@ expr_streval (tok, e, lvalue)
|
||||
initial_depth = expr_depth;
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
tflag = assoc_expand_once && already_expanded; /* for a start */
|
||||
tflag = (assoc_expand_once && already_expanded) ? AV_NOEXPAND : 0; /* for a start */
|
||||
#endif
|
||||
|
||||
/* [[[[[ */
|
||||
#if defined (ARRAY_VARS)
|
||||
aflag = (tflag) ? AV_NOEXPAND : 0;
|
||||
aflag = tflag; /* use a different variable for now */
|
||||
v = (e == ']') ? array_variable_part (tok, tflag, (char **)0, (int *)0) : find_variable (tok);
|
||||
#else
|
||||
v = find_variable (tok);
|
||||
|
||||
+10
-2
@@ -3401,16 +3401,24 @@ bind_int_variable (lhs, rhs, flags)
|
||||
int flags;
|
||||
{
|
||||
register SHELL_VAR *v;
|
||||
int isint, isarr, implicitarray, vflags;
|
||||
int isint, isarr, implicitarray, vflags, avflags;
|
||||
|
||||
isint = isarr = implicitarray = 0;
|
||||
#if defined (ARRAY_VARS)
|
||||
/* Don't rely on VA_NOEXPAND being 1, set it explicitly */
|
||||
vflags = (flags & ASS_NOEXPAND) ? VA_NOEXPAND : 0;
|
||||
if (flags & ASS_ONEWORD)
|
||||
vflags |= VA_ONEWORD;
|
||||
if (valid_array_reference (lhs, vflags))
|
||||
{
|
||||
isarr = 1;
|
||||
v = array_variable_part (lhs, (flags & ASS_NOEXPAND) != 0, (char **)0, (int *)0);
|
||||
avflags = 0;
|
||||
/* Common code to translate between assignment and reference flags. */
|
||||
if (flags & ASS_NOEXPAND)
|
||||
avflags |= AV_NOEXPAND;
|
||||
if (flags & ASS_ONEWORD)
|
||||
avflags |= AV_ONEWORD;
|
||||
v = array_variable_part (lhs, avflags, (char **)0, (int *)0);
|
||||
}
|
||||
else if (legal_identifier (lhs) == 0)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user