mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-07-13 15:10:49 +02:00
commit bash-20180803 snapshot
This commit is contained in:
@@ -4109,3 +4109,47 @@ subst.c
|
||||
subst.c
|
||||
- get_var_and_type: if VALUE is NULL, check before calling dequote_string.
|
||||
Report and fix from Grisha Levit <grishalevit@gmail.com>
|
||||
|
||||
7/30
|
||||
----
|
||||
variables.c
|
||||
- make_local_{array,assoc}_variable: make sure we're not trying to
|
||||
inherit a value from an incompatible array type. Fixes issue raised
|
||||
by Grisha Levit <grishalevit@gmail.com>
|
||||
- nameref_transform_name: if we're trying to resolve a nameref that
|
||||
will be used to create a local variable, make sure the nameref is
|
||||
at the same variable scope. Report from Grisha Levit
|
||||
<grishalevit@gmail.com>
|
||||
|
||||
8/2
|
||||
---
|
||||
array.c
|
||||
- array_subrange: change to use string_list_pos_params after creating a
|
||||
WORD_LIST from the array slice, like assoc_subrange does
|
||||
|
||||
subst.c
|
||||
- parameter_brace_substring: since assoc_subrange and array_subrange
|
||||
both call string_list_pos_params now, treat the results the same as
|
||||
the VT_POSPARAMS case (pos_params also calls string_list_pos_params).
|
||||
Fixes behavior difference between ${a[@]:sub} and ${@:sub} reported
|
||||
by Ilkka Virta <itvirta@iki.fi>
|
||||
|
||||
8/3
|
||||
---
|
||||
array.c
|
||||
- array_patsub: rewrite to work in terms of a WORD_LIST * and call
|
||||
string_list_pos_params on the result to be consistent with the
|
||||
expansions of ${@/pat/rep} and ${*/pat/rep}
|
||||
|
||||
assoc.c
|
||||
- assoc_patsub: rewrite to work in terms of a WORD_LIST * and call
|
||||
string_list_pos_params on the result to be consistent with the
|
||||
expansions of ${@/pat/rep} and ${*/pat/rep}
|
||||
|
||||
subst.c
|
||||
- parameter_brace_patsub: change how return value of {array,assoc}_patsub
|
||||
is treated to make it identical to pos_params_pat_subst, since they
|
||||
all call string_list_pos_params now
|
||||
- expand_string_for_pat: make sure we preserve the value of
|
||||
expand_no_split_dollar_star instead of just unconditionally setting
|
||||
it back to 0 in case it was 1 before this function was called
|
||||
|
||||
@@ -1359,7 +1359,7 @@ tests/unicode1.sub f
|
||||
tests/unicode2.sub f
|
||||
tests/unicode3.sub f
|
||||
tests/varenv.right f
|
||||
tests/varenv.sh f
|
||||
tests/varenv.tests f
|
||||
tests/varenv1.sub f
|
||||
tests/varenv2.sub f
|
||||
tests/varenv3.sub f
|
||||
@@ -1373,6 +1373,7 @@ tests/varenv10.sub f
|
||||
tests/varenv11.sub f
|
||||
tests/varenv12.sub f
|
||||
tests/varenv13.sub f
|
||||
tests/varenv14.sub f
|
||||
tests/version f
|
||||
tests/version.mini f
|
||||
tests/vredir.tests f
|
||||
|
||||
@@ -406,8 +406,8 @@ int starsub, quoted;
|
||||
ARRAY *a2;
|
||||
ARRAY_ELEMENT *h, *p;
|
||||
arrayind_t i;
|
||||
char *ifs, *sifs, *t;
|
||||
int slen;
|
||||
char *t;
|
||||
WORD_LIST *wl;
|
||||
|
||||
p = a ? array_head (a) : 0;
|
||||
if (p == 0 || array_empty (a) || start > array_max_index(a))
|
||||
@@ -432,32 +432,12 @@ int starsub, quoted;
|
||||
|
||||
a2 = array_slice(a, h, p);
|
||||
|
||||
if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
|
||||
array_quote(a2);
|
||||
else
|
||||
array_quote_escapes(a2);
|
||||
|
||||
if (starsub && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))) {
|
||||
/* ${array[*]} */
|
||||
array_remove_quoted_nulls (a2);
|
||||
sifs = ifs_firstchar ((int *)NULL);
|
||||
t = array_to_string (a2, sifs, 0);
|
||||
free (sifs);
|
||||
} else if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) {
|
||||
/* ${array[@]} */
|
||||
sifs = ifs_firstchar (&slen);
|
||||
ifs = getifs ();
|
||||
if (ifs == 0 || *ifs == 0) {
|
||||
if (slen < 2)
|
||||
sifs = xrealloc(sifs, 2);
|
||||
sifs[0] = ' ';
|
||||
sifs[1] = '\0';
|
||||
}
|
||||
t = array_to_string (a2, sifs, 0);
|
||||
free (sifs);
|
||||
} else
|
||||
t = array_to_string (a2, " ", 0);
|
||||
wl = array_to_word_list(a2);
|
||||
array_dispose(a2);
|
||||
if (wl == 0)
|
||||
return (char *)NULL;
|
||||
t = string_list_pos_params(starsub ? '*' : '@', wl, quoted);
|
||||
dispose_words(wl);
|
||||
|
||||
return t;
|
||||
}
|
||||
@@ -468,50 +448,28 @@ ARRAY *a;
|
||||
char *pat, *rep;
|
||||
int mflags;
|
||||
{
|
||||
ARRAY *a2;
|
||||
ARRAY_ELEMENT *e;
|
||||
char *t, *sifs, *ifs;
|
||||
int slen;
|
||||
char *t;
|
||||
int pchar, qflags;
|
||||
WORD_LIST *wl, *save;
|
||||
|
||||
if (a == 0 || array_head(a) == 0 || array_empty(a))
|
||||
return ((char *)NULL);
|
||||
|
||||
a2 = array_copy(a);
|
||||
for (e = element_forw(a2->head); e != a2->head; e = element_forw(e)) {
|
||||
t = pat_subst(element_value(e), pat, rep, mflags);
|
||||
FREE(element_value(e));
|
||||
e->value = t;
|
||||
wl = array_to_word_list(a);
|
||||
if (wl == 0)
|
||||
return (char *)NULL;
|
||||
|
||||
for (save = wl; wl; wl = wl->next) {
|
||||
t = pat_subst (wl->word->word, pat, rep, mflags);
|
||||
FREE (wl->word->word);
|
||||
wl->word->word = t;
|
||||
}
|
||||
|
||||
if (mflags & MATCH_QUOTED)
|
||||
array_quote(a2);
|
||||
else
|
||||
array_quote_escapes(a2);
|
||||
pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
|
||||
qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
|
||||
|
||||
if (mflags & MATCH_STARSUB) {
|
||||
array_remove_quoted_nulls (a2);
|
||||
if ((mflags & MATCH_QUOTED) == 0 && ifs_is_null)
|
||||
sifs = spacesep;
|
||||
else
|
||||
sifs = ifs_firstchar((int *)NULL);
|
||||
t = array_to_string (a2, sifs, 0);
|
||||
if (sifs != spacesep)
|
||||
free(sifs);
|
||||
} else if (mflags & MATCH_QUOTED) {
|
||||
/* ${array[@]} */
|
||||
sifs = ifs_firstchar (&slen);
|
||||
ifs = getifs ();
|
||||
if (ifs == 0 || *ifs == 0) {
|
||||
if (slen < 2)
|
||||
sifs = xrealloc (sifs, 2);
|
||||
sifs[0] = ' ';
|
||||
sifs[1] = '\0';
|
||||
}
|
||||
t = array_to_string (a2, sifs, 0);
|
||||
free(sifs);
|
||||
} else
|
||||
t = array_to_string (a2, " ", 0);
|
||||
array_dispose (a2);
|
||||
t = string_list_pos_params (pchar, save, qflags);
|
||||
dispose_words(save);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -305,54 +305,29 @@ assoc_patsub (h, pat, rep, mflags)
|
||||
char *pat, *rep;
|
||||
int mflags;
|
||||
{
|
||||
BUCKET_CONTENTS *tlist;
|
||||
int i, slen;
|
||||
HASH_TABLE *h2;
|
||||
char *t, *sifs, *ifs;
|
||||
char *t;
|
||||
int pchar, qflags;
|
||||
WORD_LIST *wl, *save;
|
||||
|
||||
if (h == 0 || assoc_empty (h))
|
||||
return ((char *)NULL);
|
||||
|
||||
h2 = assoc_copy (h);
|
||||
for (i = 0; i < h2->nbuckets; i++)
|
||||
for (tlist = hash_items (i, h2); tlist; tlist = tlist->next)
|
||||
{
|
||||
t = pat_subst ((char *)tlist->data, pat, rep, mflags);
|
||||
FREE (tlist->data);
|
||||
tlist->data = t;
|
||||
}
|
||||
wl = assoc_to_word_list (h);
|
||||
if (wl == 0)
|
||||
return (char *)NULL;
|
||||
|
||||
if (mflags & MATCH_QUOTED)
|
||||
assoc_quote (h2);
|
||||
else
|
||||
assoc_quote_escapes (h2);
|
||||
|
||||
if (mflags & MATCH_STARSUB)
|
||||
for (save = wl; wl; wl = wl->next)
|
||||
{
|
||||
assoc_remove_quoted_nulls (h2);
|
||||
sifs = ifs_firstchar ((int *)NULL);
|
||||
t = assoc_to_string (h2, sifs, 0);
|
||||
free (sifs);
|
||||
t = pat_subst (wl->word->word, pat, rep, mflags);
|
||||
FREE (wl->word->word);
|
||||
wl->word->word = t;
|
||||
}
|
||||
else if (mflags & MATCH_QUOTED)
|
||||
{
|
||||
/* ${array[@]} */
|
||||
sifs = ifs_firstchar (&slen);
|
||||
ifs = getifs ();
|
||||
if (ifs == 0 || *ifs == 0)
|
||||
{
|
||||
if (slen < 2)
|
||||
sifs = xrealloc (sifs, 2);
|
||||
sifs[0] = ' ';
|
||||
sifs[1] = '\0';
|
||||
}
|
||||
t = assoc_to_string (h2, sifs, 0);
|
||||
free(sifs);
|
||||
}
|
||||
else
|
||||
t = assoc_to_string (h2, " ", 0);
|
||||
|
||||
assoc_dispose (h2);
|
||||
pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
|
||||
qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
|
||||
|
||||
t = string_list_pos_params (pchar, save, qflags);
|
||||
dispose_words (save);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -3903,15 +3903,17 @@ expand_string_for_pat (string, quoted, dollar_at_p, expanded_p)
|
||||
{
|
||||
WORD_DESC td;
|
||||
WORD_LIST *tresult;
|
||||
int oexp;
|
||||
|
||||
if (string == 0 || *string == '\0')
|
||||
return (WORD_LIST *)NULL;
|
||||
|
||||
oexp = expand_no_split_dollar_star;
|
||||
expand_no_split_dollar_star = 1;
|
||||
td.flags = W_NOSPLIT2; /* no splitting, remove "" and '' */
|
||||
td.word = string;
|
||||
tresult = call_expand_word_internal (&td, quoted, 1, dollar_at_p, expanded_p);
|
||||
expand_no_split_dollar_star = 0;
|
||||
expand_no_split_dollar_star = oexp;
|
||||
|
||||
return (tresult);
|
||||
}
|
||||
@@ -7706,7 +7708,7 @@ parameter_brace_substring (varname, value, ind, substr, quoted, pflags, flags)
|
||||
int quoted, pflags, flags;
|
||||
{
|
||||
intmax_t e1, e2;
|
||||
int vtype, r, starsub, qflags;
|
||||
int vtype, r, starsub;
|
||||
char *temp, *val, *tt, *oname;
|
||||
SHELL_VAR *v;
|
||||
|
||||
@@ -7755,9 +7757,23 @@ parameter_brace_substring (varname, value, ind, substr, quoted, pflags, flags)
|
||||
FREE (tt);
|
||||
break;
|
||||
case VT_POSPARMS:
|
||||
qflags = quoted;
|
||||
tt = pos_params (varname, e1, e2, qflags);
|
||||
/* string_list_dollar_at will quote the list if ifs_is_null != 0 */
|
||||
case VT_ARRAYVAR:
|
||||
if (vtype == VT_POSPARMS)
|
||||
tt = pos_params (varname, e1, e2, quoted);
|
||||
#if defined (ARRAY_VARS)
|
||||
/* assoc_subrange and array_subrange both call string_list_pos_params,
|
||||
so we can treat this case just like VT_POSPARAMS. */
|
||||
else if (assoc_p (v))
|
||||
/* we convert to list and take first e2 elements starting at e1th
|
||||
element -- officially undefined for now */
|
||||
tt = assoc_subrange (assoc_cell (v), e1, e2, starsub, quoted);
|
||||
else
|
||||
/* We want E2 to be the number of elements desired (arrays can be
|
||||
sparse, so verify_substring_values just returns the numbers
|
||||
specified and we rely on array_subrange to understand how to
|
||||
deal with them). */
|
||||
tt = array_subrange (array_cell (v), e1, e2, starsub, quoted);
|
||||
#endif
|
||||
/* We want to leave this alone in every case where pos_params/
|
||||
string_list_pos_params quotes the list members */
|
||||
if (tt && quoted == 0 && ifs_is_null)
|
||||
@@ -7772,21 +7788,7 @@ parameter_brace_substring (varname, value, ind, substr, quoted, pflags, flags)
|
||||
else
|
||||
temp = tt;
|
||||
break;
|
||||
#if defined (ARRAY_VARS)
|
||||
case VT_ARRAYVAR:
|
||||
if (assoc_p (v))
|
||||
/* we convert to list and take first e2 elements starting at e1th
|
||||
element -- officially undefined for now */
|
||||
temp = assoc_subrange (assoc_cell (v), e1, e2, starsub, quoted);
|
||||
else
|
||||
/* We want E2 to be the number of elements desired (arrays can be sparse,
|
||||
so verify_substring_values just returns the numbers specified and we
|
||||
rely on array_subrange to understand how to deal with them). */
|
||||
temp = array_subrange (array_cell (v), e1, e2, starsub, quoted);
|
||||
/* array_subrange now calls array_quote_escapes as appropriate, so the
|
||||
caller no longer needs to. */
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
temp = (char *)NULL;
|
||||
}
|
||||
@@ -7978,7 +7980,7 @@ pos_params_pat_subst (string, pat, rep, mflags)
|
||||
qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
|
||||
|
||||
/* If we are expanding in a context where word splitting will not be
|
||||
performed, treat as quoted. This changes how $* will be expanded. */
|
||||
performed, treat as quoted. This changes how $* will be expanded. */
|
||||
if (pchar == '*' && (mflags & MATCH_ASSIGNRHS) && expand_no_split_dollar_star && ifs_is_null)
|
||||
qflags |= Q_DOUBLE_QUOTES; /* Posix interp 888 */
|
||||
|
||||
@@ -8145,11 +8147,22 @@ parameter_brace_patsub (varname, value, ind, patsub, quoted, pflags, flags)
|
||||
if ((mflags & MATCH_STARSUB) && (mflags & MATCH_ASSIGNRHS) && ifs_is_null)
|
||||
mflags |= MATCH_QUOTED; /* Posix interp 888 */
|
||||
|
||||
temp = assoc_p (v) ? assoc_patsub (assoc_cell (v), p, rep, mflags)
|
||||
: array_patsub (array_cell (v), p, rep, mflags);
|
||||
/* Don't call quote_escapes anymore; array_patsub calls
|
||||
array_quote_escapes as appropriate before adding the
|
||||
space separators; ditto for assoc_patsub. */
|
||||
/* these eventually call string_list_pos_params */
|
||||
if (assoc_p (v))
|
||||
temp = assoc_patsub (assoc_cell (v), p, rep, mflags);
|
||||
else
|
||||
temp = array_patsub (array_cell (v), p, rep, mflags);
|
||||
|
||||
if (temp && quoted == 0 && ifs_is_null)
|
||||
{
|
||||
/* Posix interp 888 */
|
||||
}
|
||||
else if (temp && (mflags & MATCH_QUOTED) == 0)
|
||||
{
|
||||
tt = quote_escapes (temp);
|
||||
free (temp);
|
||||
temp = tt;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -270,6 +270,74 @@ argv[1] = <element1 with spaces>
|
||||
argv[2] = <element2 with spaces>
|
||||
argv[1] = <element1 with spaces>
|
||||
argv[2] = <element2 with spaces>
|
||||
argv[1] = <aa>
|
||||
argv[2] = <bb>
|
||||
argv[1] = <aa>
|
||||
argv[2] = <bb>
|
||||
argv[1] = <aa>
|
||||
argv[2] = <bb>
|
||||
argv[1] = <aa>
|
||||
argv[2] = <bb>
|
||||
argv[1] = <aa>
|
||||
argv[2] = <bb>
|
||||
argv[3] = <aa>
|
||||
argv[4] = <bb>
|
||||
argv[1] = <aa>
|
||||
argv[2] = <bb>
|
||||
argv[3] = <aa>
|
||||
argv[4] = <bb>
|
||||
argv[1] = <aa+bb>
|
||||
argv[2] = <aa+bb>
|
||||
argv[1] = <aa>
|
||||
argv[2] = <bb>
|
||||
argv[3] = <aa>
|
||||
argv[4] = <bb>
|
||||
argv[1] = <xa>
|
||||
argv[2] = <bb>
|
||||
argv[1] = <xa>
|
||||
argv[2] = <bb>
|
||||
argv[1] = <xa>
|
||||
argv[2] = <bb>
|
||||
argv[1] = <xa>
|
||||
argv[2] = <bb>
|
||||
argv[1] = <xa>
|
||||
argv[2] = <bb>
|
||||
argv[1] = <xa>
|
||||
argv[2] = <bb>
|
||||
argv[1] = <xa+bb>
|
||||
argv[1] = <xa+bb>
|
||||
argv[1] = <xa+bb>
|
||||
argv[2] = <xa+bb>
|
||||
argv[1] = <xa>
|
||||
argv[2] = <bb>
|
||||
argv[1] = <xa>
|
||||
argv[2] = <bb>
|
||||
argv[1] = <xa>
|
||||
argv[2] = <bb>
|
||||
argv[1] = <xa+bb>
|
||||
argv[1] = <xa>
|
||||
argv[2] = <bb>
|
||||
argv[1] = <xa>
|
||||
argv[2] = <bb>
|
||||
argv[1] = <xa>
|
||||
argv[2] = <bb>
|
||||
argv[1] = <xa>
|
||||
argv[2] = <bb>
|
||||
argv[1] = <xa>
|
||||
argv[2] = <bb>
|
||||
argv[1] = <xa>
|
||||
argv[2] = <bb>
|
||||
argv[1] = <xabb>
|
||||
argv[1] = <xabb>
|
||||
argv[1] = <xabb>
|
||||
argv[2] = <xabb>
|
||||
argv[1] = <xa>
|
||||
argv[2] = <bb>
|
||||
argv[1] = <xa>
|
||||
argv[2] = <bb>
|
||||
argv[1] = <xa>
|
||||
argv[2] = <bb>
|
||||
argv[1] = <xabb>
|
||||
nord!olz
|
||||
|
||||
rdholz
|
||||
|
||||
@@ -113,3 +113,76 @@ recho $@
|
||||
|
||||
IFS="$oIFS"
|
||||
unset a a2 array foo
|
||||
|
||||
# these should produce the same results
|
||||
a=(aa bb)
|
||||
set -- aa bb
|
||||
|
||||
IFS=+
|
||||
|
||||
recho ${a[@]}
|
||||
recho ${a[@]:0}
|
||||
|
||||
recho $@
|
||||
recho ${@:1}
|
||||
|
||||
A=${a[*]} B=${a[*]:0}
|
||||
recho $* ${*:1}
|
||||
recho ${a[*]} ${a[*]:0}
|
||||
recho "$A" "$B"
|
||||
recho $A $B
|
||||
|
||||
unset A B
|
||||
|
||||
recho ${@/a/x}
|
||||
recho ${a[@]/a/x}
|
||||
recho "${@/a/x}"
|
||||
recho "${a[@]/a/x}"
|
||||
|
||||
recho ${*/a/x}
|
||||
recho ${a[*]/a/x}
|
||||
recho "${*/a/x}"
|
||||
recho "${a[*]/a/x}"
|
||||
|
||||
A=${*/a/x}
|
||||
B=${a[*]/a/x}
|
||||
|
||||
recho "$A" "$B"
|
||||
|
||||
unset A B
|
||||
declare -A A
|
||||
A[0]=aa
|
||||
A[1]=bb
|
||||
|
||||
recho ${A[@]/a/x}
|
||||
recho "${A[@]/a/x}"
|
||||
recho ${A[*]/a/x}
|
||||
recho "${A[*]/a/x}"
|
||||
|
||||
unset A
|
||||
IFS=
|
||||
|
||||
recho ${@/a/x}
|
||||
recho ${a[@]/a/x}
|
||||
recho "${@/a/x}"
|
||||
recho "${a[@]/a/x}"
|
||||
|
||||
recho ${*/a/x}
|
||||
recho ${a[*]/a/x}
|
||||
recho "${*/a/x}"
|
||||
recho "${a[*]/a/x}"
|
||||
|
||||
A=${*/a/x}
|
||||
B=${a[*]/a/x}
|
||||
|
||||
recho "$A" "$B"
|
||||
|
||||
unset A B
|
||||
declare -A A
|
||||
A[0]=aa
|
||||
A[1]=bb
|
||||
|
||||
recho ${A[@]/a/x}
|
||||
recho "${A[@]/a/x}"
|
||||
recho ${A[*]/a/x}
|
||||
recho "${A[*]/a/x}"
|
||||
|
||||
@@ -463,3 +463,9 @@ outside:
|
||||
./nameref20.sub: line 45: declare: var: not found
|
||||
declare -n ref="var"
|
||||
declare -a var=([0]="Y")
|
||||
declare -- ref="Y"
|
||||
declare -- var="X"
|
||||
ref=Y
|
||||
declare -- ref="Y"
|
||||
./nameref20.sub: line 61: declare: var: not found
|
||||
ref=Y
|
||||
|
||||
@@ -54,3 +54,16 @@ f()
|
||||
declare -p ref var
|
||||
}
|
||||
f
|
||||
|
||||
unset -f f
|
||||
|
||||
declare -n ref=var
|
||||
f() { local ref=Y; declare -p ref var; local; }
|
||||
|
||||
var=X
|
||||
f
|
||||
|
||||
unset -v var
|
||||
f
|
||||
|
||||
unset -n ref
|
||||
|
||||
@@ -119,3 +119,13 @@ argv[3] = <uv^Aw^Axy>
|
||||
argv[1] = <@2>
|
||||
argv[2] = <uv^Aw^Axy>
|
||||
argv[3] = <uv^Aw^Axy>
|
||||
argv[1] = <aa1>
|
||||
argv[2] = <uv^A^A>
|
||||
argv[1] = <aa2>
|
||||
argv[2] = <uv^A^A>
|
||||
argv[1] = <aa3>
|
||||
argv[2] = <uv^A^Awx>
|
||||
argv[3] = <uv^A^Awx>
|
||||
argv[1] = <aa4>
|
||||
argv[2] = <uv^A^Awx>
|
||||
argv[3] = <uv^A^Awx>
|
||||
|
||||
@@ -95,3 +95,12 @@ recho d2 "${1:2:2}"
|
||||
|
||||
recho @1 ${@:1:2}
|
||||
recho @2 "${@:1:2}"
|
||||
|
||||
declare -A assoc
|
||||
assoc=( [0]=$e [1]=$e )
|
||||
|
||||
recho aa1 ${assoc:0:4}
|
||||
recho aa2 "${assoc:0:4}"
|
||||
|
||||
recho aa3 ${assoc[@]:0:2}
|
||||
recho aa4 "${assoc[@]:0:2}"
|
||||
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
${THIS_SH} ./varenv.sh 2>&1 | grep -v '^expect' > ${BASH_TSTOUT}
|
||||
${THIS_SH} ./varenv.tests 2>&1 | grep -v '^expect' > ${BASH_TSTOUT}
|
||||
diff ${BASH_TSTOUT} varenv.right && rm -f ${BASH_TSTOUT}
|
||||
|
||||
@@ -160,6 +160,23 @@ declare -A var=([0]="X" )
|
||||
help
|
||||
./varenv13.sub: line 21: `var[0]': not a valid identifier
|
||||
1
|
||||
./varenv14.sub: line 6: warning: var: cannot inherit value from incompatible type
|
||||
declare -a var=([0]="X")
|
||||
./varenv14.sub: line 9: warning: var: cannot inherit value from incompatible type
|
||||
declare -a var=([0]="Y")
|
||||
./varenv14.sub: line 10: warning: var: cannot inherit value from incompatible type
|
||||
declare -a var=([0]="Y")
|
||||
./varenv14.sub: line 11: warning: var: cannot inherit value from incompatible type
|
||||
declare -a var=()
|
||||
./varenv14.sub: line 12: warning: var: cannot inherit value from incompatible type
|
||||
declare -a var=()
|
||||
./varenv14.sub: line 18: f: var: cannot convert indexed to associative array
|
||||
declare -a a=([0]="X")
|
||||
declare -a s=([0]="X")
|
||||
declare -a a=([0]="X" [1]="Y")
|
||||
declare -a s=([0]="X" [1]="Y")
|
||||
declare -a a=([0]="XY")
|
||||
declare -a s=([0]="XY")
|
||||
a=z
|
||||
a=b
|
||||
a=z
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
#
|
||||
# varenv.sh
|
||||
#
|
||||
# Test the behavior of the shell with respect to variable and environment
|
||||
# assignments
|
||||
#
|
||||
expect()
|
||||
{
|
||||
echo expect "$@"
|
||||
}
|
||||
|
||||
a=1
|
||||
b=2
|
||||
c=3
|
||||
d=4
|
||||
e=5
|
||||
f=6 g=7 h=8
|
||||
|
||||
a=3 b=4 $CHMOD $MODE $FN
|
||||
|
||||
# This should echo "3 4" according to Posix.2
|
||||
expect "3 4"
|
||||
echo $a $b
|
||||
|
||||
set -k
|
||||
|
||||
# Assignment statements made when no words are left affect the shell's
|
||||
# environment
|
||||
a=5 b=6 $CHMOD c=7 $MODE d=8 $FN e=9
|
||||
|
||||
expect "5 6 7 8 9"
|
||||
echo $a $b $c $d $e
|
||||
|
||||
$CHMOD f=7 $MODE g=8 $FN h=9
|
||||
expect "7 8 9"
|
||||
echo $f $g $h
|
||||
|
||||
set +k
|
||||
|
||||
# The temporary environment does not affect variable expansion, only the
|
||||
# environment given to the command
|
||||
|
||||
export HOME=/usr/chet
|
||||
expect $HOME
|
||||
echo $HOME
|
||||
|
||||
expect $HOME
|
||||
HOME=/a/b/c /bin/echo $HOME
|
||||
|
||||
expect $HOME
|
||||
echo $HOME
|
||||
|
||||
# This should echo /a/b/c
|
||||
expect /a/b/c
|
||||
HOME=/a/b/c printenv HOME
|
||||
|
||||
set -k
|
||||
|
||||
# This should echo $HOME 9, NOT /a/b/c 9
|
||||
|
||||
expect "$HOME"
|
||||
HOME=/a/b/c /bin/echo $HOME c=9
|
||||
expect "$HOME 7"
|
||||
echo $HOME $c
|
||||
|
||||
# I claim the next two echo calls should give identical output.
|
||||
# ksh agrees, the System V.3 sh does not
|
||||
|
||||
expect "/a/b/c 9 /a/b/c"
|
||||
HOME=/a/b/c $ECHO a=$HOME c=9
|
||||
echo $HOME $c $a
|
||||
|
||||
expect "/a/b/c 9 /a/b/c"
|
||||
HOME=/a/b/c a=$HOME c=9
|
||||
echo $HOME $c $a
|
||||
set +k
|
||||
|
||||
# How do assignment statements affect subsequent assignments on the same
|
||||
# line?
|
||||
expect "/a/b/c /a/b/c"
|
||||
HOME=/a/b/c a=$HOME
|
||||
echo $HOME $a
|
||||
|
||||
# The system V.3 sh does this wrong; the last echo should output "1 1",
|
||||
# but the system V.3 sh has it output "2 2". Posix.2 says the assignment
|
||||
# statements are processed left-to-right. bash and ksh output the right
|
||||
# thing
|
||||
c=1
|
||||
d=2
|
||||
expect "1 2"
|
||||
echo $c $d
|
||||
d=$c c=$d
|
||||
expect "1 1"
|
||||
echo $c $d
|
||||
|
||||
# just for completeness
|
||||
unset d c
|
||||
expect unset
|
||||
echo ${d-unset}
|
||||
|
||||
# no output
|
||||
export a
|
||||
a=bcde
|
||||
export a
|
||||
/bin/true 2>/dev/null
|
||||
|
||||
func()
|
||||
{
|
||||
local YYZ
|
||||
|
||||
YYZ="song by rush"
|
||||
echo $YYZ
|
||||
echo $A
|
||||
}
|
||||
|
||||
YYZ="toronto airport"
|
||||
A="AVAR"
|
||||
echo $YYZ
|
||||
echo $A
|
||||
A=BVAR func
|
||||
echo $YYZ
|
||||
echo $A
|
||||
|
||||
export A
|
||||
# Make sure expansion doesn't use assignment statements preceding a builtin
|
||||
A=ZVAR echo $A
|
||||
|
||||
XPATH=/bin:/usr/bin:/usr/local/bin:.
|
||||
func2()
|
||||
{
|
||||
local z=yy
|
||||
local -a avar=( ${XPATH//: } )
|
||||
echo ${avar[@]}
|
||||
local
|
||||
}
|
||||
|
||||
avar=42
|
||||
echo $avar
|
||||
func2
|
||||
echo $avar
|
||||
|
||||
# try to set an attribute for an unset variable; make sure it persists
|
||||
# when the variable is assigned a value
|
||||
declare -i ivar
|
||||
|
||||
ivar=10
|
||||
|
||||
declare -p ivar
|
||||
unset ivar
|
||||
|
||||
# export an unset variable, make sure it is not suddenly set, but make
|
||||
# sure the export attribute persists when the variable is assigned a
|
||||
# value
|
||||
export ivar
|
||||
echo ${ivar-unset}
|
||||
|
||||
ivar=42
|
||||
declare -p ivar
|
||||
|
||||
# make sure set [-+]o ignoreeof and $IGNOREEOF are reflected
|
||||
unset IGNOREEOF
|
||||
set +o ignoreeof
|
||||
set -o ignoreeof
|
||||
if [ "$IGNOREEOF" -ne 10 ]; then
|
||||
echo "./varenv.sh: set -o ignoreeof is not reflected in IGNOREEOF" >&2
|
||||
fi
|
||||
unset IGNOREEOF
|
||||
set +o ignoreeof
|
||||
|
||||
# older versions of bash used to not reset RANDOM in subshells correctly
|
||||
[[ $RANDOM -eq $(echo $RANDOM) ]] && echo "RANDOM: problem with subshells"
|
||||
|
||||
# make sure that shopt -o is reflected in $SHELLOPTS
|
||||
# first, get rid of things that might be set automatically via shell
|
||||
# variables
|
||||
set +o posix
|
||||
set +o ignoreeof
|
||||
set +o monitor
|
||||
echo $-
|
||||
echo ${SHELLOPTS}
|
||||
shopt -so physical
|
||||
echo $-
|
||||
echo ${SHELLOPTS}
|
||||
|
||||
# and make sure it is readonly
|
||||
readonly -p | grep SHELLOPTS
|
||||
|
||||
# This was an error in bash versions prior to bash-2.04. The `set -a'
|
||||
# should cause the assignment statement that's an argument to typeset
|
||||
# to create an exported variable
|
||||
unset FOOFOO
|
||||
FOOFOO=bar
|
||||
set -a
|
||||
typeset FOOFOO=abcde
|
||||
|
||||
printenv FOOFOO
|
||||
|
||||
# test out export behavior of variable assignments preceding builtins and
|
||||
# functions
|
||||
$THIS_SH ./varenv1.sub
|
||||
|
||||
# more tests; bugs in bash up to version 2.05a
|
||||
$THIS_SH ./varenv2.sub
|
||||
|
||||
# more tests; bugs in bash IFS scoping up through version 4.2
|
||||
$THIS_SH ./varenv3.sub
|
||||
|
||||
# scoping problems with declare -g through bash-4.2
|
||||
${THIS_SH} ./varenv4.sub
|
||||
|
||||
# more scoping and declaration problems with -g and arrays through bash-4.2
|
||||
${THIS_SH} ./varenv5.sub
|
||||
|
||||
# variable scoping in the presence of nameref
|
||||
${THIS_SH} ./varenv6.sub
|
||||
|
||||
# variable declaration problems with arrays and readonly local variables
|
||||
${THIS_SH} ./varenv7.sub
|
||||
|
||||
# variable visibility problems with process substitution subshells in
|
||||
# redirections
|
||||
${THIS_SH} ./varenv8.sub
|
||||
|
||||
# make sure that builtins like readonly and export modify local array variables
|
||||
# if executed in shell functions, like they modify local scalar variables
|
||||
${THIS_SH} ./varenv9.sub
|
||||
|
||||
# more tests of unset and local variables with dynamic scoping
|
||||
${THIS_SH} ./varenv10.sub
|
||||
|
||||
# tests of compound assignments in function scope
|
||||
${THIS_SH} ./varenv11.sub
|
||||
|
||||
# temporary environment variable propagation and scoping in posix mode
|
||||
${THIS_SH} ./varenv12.sub
|
||||
|
||||
# temporary environment and invalid shell indentifier names
|
||||
${THIS_SH} ./varenv13.sub
|
||||
|
||||
# localvar_inherit
|
||||
${THIS_SH} ./varenv14.sub
|
||||
|
||||
# make sure variable scoping is done right
|
||||
tt() { typeset a=b;echo a=$a; };a=z;echo a=$a;tt;echo a=$a
|
||||
@@ -0,0 +1,33 @@
|
||||
# testing framework for local variable inheritence
|
||||
|
||||
shopt -s localvar_inherit
|
||||
declare -A var
|
||||
|
||||
f() { declare var+=([0]=X); declare -p var; }
|
||||
f
|
||||
|
||||
f() { declare var=([Y]=Y); declare -p var; }; f
|
||||
f() { declare var+=([Y]=Y); declare -p var; }; f
|
||||
f() { declare var+=(); declare -p var; }; f
|
||||
f() { declare var=(); declare -p var; }; f
|
||||
|
||||
unset -f f
|
||||
unset -v var
|
||||
|
||||
declare -a var=( [0]=12 )
|
||||
f() { declare -A var+=([0]=X); declare -p var; }
|
||||
f
|
||||
|
||||
unset -f f
|
||||
unset a s
|
||||
|
||||
a=(X) s=X
|
||||
|
||||
f() { local -a a s; declare -p a s; }
|
||||
f
|
||||
|
||||
f() { local a+=(Y) s+=(Y); declare -p a s; }
|
||||
f
|
||||
|
||||
f() { local -a a+=Y s+=Y; declare -p a s; }
|
||||
f
|
||||
+39
-9
@@ -2282,7 +2282,13 @@ nameref_transform_name (name, flags)
|
||||
|
||||
v = 0;
|
||||
if (flags & ASS_MKLOCAL)
|
||||
v = find_variable_last_nameref (name, 1);
|
||||
{
|
||||
v = find_variable_last_nameref (name, 1);
|
||||
/* If we're making local variables, only follow namerefs that point to
|
||||
non-existant variables at the same variable context. */
|
||||
if (v && v->context != variable_context)
|
||||
v = 0;
|
||||
}
|
||||
else if (flags & ASS_MKGLOBAL)
|
||||
v = (flags & ASS_CHKLOCAL) ? find_variable_last_nameref (name, 1)
|
||||
: find_global_variable_last_nameref (name, 1);
|
||||
@@ -2781,11 +2787,23 @@ make_local_array_variable (name, assoc_ok)
|
||||
|
||||
/* Validate any value we inherited from a variable instance at a previous
|
||||
scope and disard anything that's invalid. */
|
||||
if (localvar_inherit && assoc_p (var))
|
||||
{
|
||||
internal_warning ("%s: cannot inherit value from incompatible type", name);
|
||||
VUNSETATTR (var, att_assoc);
|
||||
dispose_variable_value (var);
|
||||
array = array_create ();
|
||||
var_setarray (var, array);
|
||||
}
|
||||
else if (localvar_inherit)
|
||||
var = convert_var_to_array (var); /* XXX */
|
||||
else
|
||||
{
|
||||
dispose_variable_value (var);
|
||||
array = array_create ();
|
||||
var_setarray (var, array);
|
||||
}
|
||||
|
||||
array = array_create ();
|
||||
|
||||
dispose_variable_value (var);
|
||||
var_setarray (var, array);
|
||||
VSETATTR (var, att_array);
|
||||
return var;
|
||||
}
|
||||
@@ -2822,11 +2840,23 @@ make_local_assoc_variable (name, array_ok)
|
||||
|
||||
/* Validate any value we inherited from a variable instance at a previous
|
||||
scope and disard anything that's invalid. */
|
||||
if (localvar_inherit && array_p (var))
|
||||
{
|
||||
internal_warning ("%s: cannot inherit value from incompatible type", name);
|
||||
VUNSETATTR (var, att_array);
|
||||
dispose_variable_value (var);
|
||||
hash = assoc_create (0);
|
||||
var_setassoc (var, hash);
|
||||
}
|
||||
else if (localvar_inherit)
|
||||
var = convert_var_to_assoc (var); /* XXX */
|
||||
else
|
||||
{
|
||||
dispose_variable_value (var);
|
||||
hash = assoc_create (0);
|
||||
var_setassoc (var, hash);
|
||||
}
|
||||
|
||||
dispose_variable_value (var);
|
||||
hash = assoc_create (0);
|
||||
|
||||
var_setassoc (var, hash);
|
||||
VSETATTR (var, att_assoc);
|
||||
return var;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user