mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-28 07:59:50 +02:00
first set of changes to eliminate array subscript double expansion in math contexts
This commit is contained in:
@@ -10151,3 +10151,60 @@ builtins/read.def
|
||||
builtins/mapfile.def
|
||||
- mapfile: call zsyncfd before calling the callback. Suggested by
|
||||
Koichi Murase <myoga.murase@gmail.com>; we'll see how it goes
|
||||
|
||||
5/5
|
||||
---
|
||||
subst.h
|
||||
- expand_subscript_string: extern declaration
|
||||
|
||||
{arrayfunc,subst}.c
|
||||
- expand_subscript_string: replace expand_assignment_string_to_string
|
||||
with calls to this when expanding array subscripts
|
||||
|
||||
subst.c
|
||||
- cond_expand_word: call expand_word_internal with Q_ARITH if `special'
|
||||
says we should quote for an arithmetic expression context
|
||||
- expand_word_internal: call expand_array_subscript when we see `[' in
|
||||
arithmetic or array subscript contexts, make conditional on the
|
||||
compatibility level later
|
||||
- expand_word_internal: make sure W_ARRAYREF makes it through this
|
||||
function and into the returned word
|
||||
|
||||
5/6
|
||||
---
|
||||
|
||||
arrayfunc.c
|
||||
- array_expand_index: call evalexp with a flag of 0 since we call
|
||||
expand_arith_string with Q_ARITH and we want evalexp to remove
|
||||
the quotes
|
||||
|
||||
execute_cmd.c
|
||||
- eval_arith_for_expr,execute_arith_command: now that Q_ARITH has an
|
||||
effect on array subscripts (it quotes the special expansion
|
||||
characters), call evalexp with 0 as the flags arg so quote removal
|
||||
is performed on this quoted argument. Make this conditional on the
|
||||
shell compatibility level later
|
||||
- execute_cond_command: make sure to expand the argument to -v by
|
||||
calling cond_expand_node with Q_ARITH, and correspondingly turn off
|
||||
assoc_expand_once when calling unary_test with that argument, since
|
||||
we want it to be expanded again to remove the quotes
|
||||
- execute_cond_command: expand the arguments to the arithmetic operators
|
||||
with Q_ARITH and pass TEST_ARITHEXP to binary_test to ensure that
|
||||
it lets evalexp expand the arguments to remove the quoting
|
||||
|
||||
test.c
|
||||
- arithcomp: if TEST_ARITHEXP is in FLAGS, call evalexp with a flag
|
||||
if 0 to force evalexp to expand the arguments to remove the quoting
|
||||
|
||||
subst.c
|
||||
- param_expand: since we call expand_arith_string with Q_ARITH, we need
|
||||
to call evalexp with 0 instead of EXP_EXPANDED for $((...)) expansion
|
||||
- expand_word_internal: if we recursively call expand_word_internal to
|
||||
expand the contents of a double-quoted string, make sure we pass
|
||||
through Q_ARITH if it appears in QUOTED
|
||||
- verify_substring_values: call expand_arith_string with Q_ARITH and
|
||||
correspondingly call evalexp with 0 instead of EXP_EXPANDED
|
||||
|
||||
execute_cmd.c
|
||||
- execute_cond_node: if -v is the operator, and the operand is a valid
|
||||
array reference, pass TEST_ARRAYEXP flag to unary_test
|
||||
|
||||
@@ -948,6 +948,7 @@ tests/assoc9.sub f
|
||||
tests/assoc10.sub f
|
||||
tests/assoc11.sub f
|
||||
tests/assoc12.sub f
|
||||
tests/assoc13.sub f
|
||||
tests/attr.tests f
|
||||
tests/attr.right f
|
||||
tests/attr1.sub f
|
||||
@@ -1307,6 +1308,11 @@ tests/quote1.sub f
|
||||
tests/quote2.sub f
|
||||
tests/quote3.sub f
|
||||
tests/quote4.sub f
|
||||
tests/quotearray.right f
|
||||
tests/quotearray.tests f
|
||||
tests/quotearray1.sub f
|
||||
tests/quotearray2.sub f
|
||||
tests/quotearray3.sub f
|
||||
tests/read.tests f
|
||||
tests/read.right f
|
||||
tests/read1.sub f
|
||||
@@ -1316,6 +1322,7 @@ tests/read4.sub f
|
||||
tests/read5.sub f
|
||||
tests/read6.sub f
|
||||
tests/read7.sub f
|
||||
tests/read8.sub f
|
||||
tests/redir.tests f
|
||||
tests/redir.right f
|
||||
tests/redir1.sub f
|
||||
@@ -1408,6 +1415,7 @@ tests/run-precedence f
|
||||
tests/run-printf f
|
||||
tests/run-procsub f
|
||||
tests/run-quote f
|
||||
tests/run-quotearray f
|
||||
tests/run-read f
|
||||
tests/run-redir f
|
||||
tests/run-rhs-exp f
|
||||
|
||||
+17
-12
@@ -374,7 +374,7 @@ assign_array_element_internal (entry, name, vname, sub, sublen, value, flags)
|
||||
{
|
||||
sub[sublen-1] = '\0';
|
||||
if ((flags & ASS_NOEXPAND) == 0)
|
||||
akey = expand_assignment_string_to_string (sub, 0); /* [ */
|
||||
akey = expand_subscript_string (sub, 0); /* [ */
|
||||
else
|
||||
akey = savestring (sub);
|
||||
sub[sublen-1] = ']';
|
||||
@@ -579,7 +579,7 @@ assign_assoc_from_kvlist (var, nlist, h, flags)
|
||||
if (list->next)
|
||||
list = list->next;
|
||||
|
||||
akey = expand_assignment_string_to_string (k, 0);
|
||||
akey = expand_subscript_string (k, 0);
|
||||
if (akey == 0 || *akey == 0)
|
||||
{
|
||||
err_badarraysub (k);
|
||||
@@ -587,7 +587,7 @@ assign_assoc_from_kvlist (var, nlist, h, flags)
|
||||
continue;
|
||||
}
|
||||
|
||||
aval = expand_assignment_string_to_string (v, 0);
|
||||
aval = expand_subscript_string (v, 0);
|
||||
if (aval == 0)
|
||||
{
|
||||
aval = (char *)xmalloc (1);
|
||||
@@ -614,7 +614,7 @@ expand_and_quote_kvpair_word (w)
|
||||
{
|
||||
char *t, *r;
|
||||
|
||||
t = w ? expand_assignment_string_to_string (w, 0) : 0;
|
||||
t = w ? expand_subscript_string (w, 0) : 0;
|
||||
r = sh_single_quote (t ? t : "");
|
||||
free (t);
|
||||
return r;
|
||||
@@ -740,7 +740,7 @@ assign_compound_array_list (var, nlist, flags)
|
||||
{
|
||||
/* This is not performed above, see expand_compound_array_assignment */
|
||||
w[len] = '\0'; /*[*/
|
||||
akey = expand_assignment_string_to_string (w+1, 0);
|
||||
akey = expand_subscript_string (w+1, 0);
|
||||
w[len] = ']';
|
||||
/* And we need to expand the value also, see below */
|
||||
if (akey == 0 || *akey == 0)
|
||||
@@ -776,7 +776,7 @@ assign_compound_array_list (var, nlist, flags)
|
||||
/* See above; we need to expand the value here */
|
||||
if (assoc_p (var))
|
||||
{
|
||||
val = expand_assignment_string_to_string (val, 0);
|
||||
val = expand_subscript_string (val, 0);
|
||||
if (val == 0)
|
||||
{
|
||||
val = (char *)xmalloc (1);
|
||||
@@ -938,7 +938,7 @@ expand_and_quote_assoc_word (w, type)
|
||||
return (sh_single_quote (w));
|
||||
|
||||
w[ind] = '\0';
|
||||
t = expand_assignment_string_to_string (w+1, 0);
|
||||
t = expand_subscript_string (w+1, 0);
|
||||
w[ind] = RBRACK;
|
||||
key = sh_single_quote (t ? t : "");
|
||||
free (t);
|
||||
@@ -954,7 +954,7 @@ expand_and_quote_assoc_word (w, type)
|
||||
nword[i++] = w[ind++];
|
||||
nword[i++] = w[ind++];
|
||||
|
||||
t = expand_assignment_string_to_string (w+ind, 0);
|
||||
t = expand_subscript_string (w+ind, 0);
|
||||
value = sh_single_quote (t ? t : "");
|
||||
free (t);
|
||||
nword = xrealloc (nword, wlen + 5 + STRLEN (value));
|
||||
@@ -1070,7 +1070,7 @@ unbind_array_element (var, sub, flags)
|
||||
|
||||
if (assoc_p (var))
|
||||
{
|
||||
akey = (flags & VA_NOEXPAND) ? sub : expand_assignment_string_to_string (sub, 0);
|
||||
akey = (flags & VA_NOEXPAND) ? sub : expand_subscript_string (sub, 0);
|
||||
if (akey == 0 || *akey == 0)
|
||||
{
|
||||
builtin_error ("[%s]: %s", sub, _(bash_badsub_errmsg));
|
||||
@@ -1218,7 +1218,7 @@ array_expand_index (var, s, len, flags)
|
||||
int flags;
|
||||
{
|
||||
char *exp, *t, *savecmd;
|
||||
int expok;
|
||||
int expok, eflag;
|
||||
arrayind_t val;
|
||||
|
||||
exp = (char *)xmalloc (len);
|
||||
@@ -1234,7 +1234,12 @@ array_expand_index (var, s, len, flags)
|
||||
#endif
|
||||
savecmd = this_command_name;
|
||||
this_command_name = (char *)NULL;
|
||||
val = evalexp (t, EXP_EXPANDED, &expok); /* XXX - was 0 but we expanded exp already */
|
||||
#if 0 /* TAG:bash-5.2 */
|
||||
eflag = (shell_compatibility_level > 51) ? 0 : EXP_EXPANDED;
|
||||
#else
|
||||
eflag = 0;
|
||||
#endif
|
||||
val = evalexp (t, eflag, &expok); /* XXX - was 0 but we expanded exp already */
|
||||
this_command_name = savecmd;
|
||||
if (t != exp)
|
||||
free (t);
|
||||
@@ -1435,7 +1440,7 @@ array_value_internal (s, quoted, flags, rtype, indp)
|
||||
{
|
||||
t[len - 1] = '\0';
|
||||
if ((flags & AV_NOEXPAND) == 0)
|
||||
akey = expand_assignment_string_to_string (t, 0); /* [ */
|
||||
akey = expand_subscript_string (t, 0); /* [ */
|
||||
else
|
||||
akey = savestring (t);
|
||||
t[len - 1] = ']';
|
||||
|
||||
+6
-4
@@ -5,12 +5,12 @@
|
||||
.\" Case Western Reserve University
|
||||
.\" chet.ramey@case.edu
|
||||
.\"
|
||||
.\" Last Change: Wed Apr 28 14:35:46 EDT 2021
|
||||
.\" Last Change: Wed May 5 16:28:46 EDT 2021
|
||||
.\"
|
||||
.\" bash_builtins, strip all but Built-Ins section
|
||||
.if \n(zZ=1 .ig zZ
|
||||
.if \n(zY=1 .ig zY
|
||||
.TH BASH 1 "2021 April 28" "GNU Bash 5.1"
|
||||
.TH BASH 1 "2021 May 5" "GNU Bash 5.1"
|
||||
.\"
|
||||
.\" There's some problem with having a `@'
|
||||
.\" in a tagged paragraph with the BSD man macros.
|
||||
@@ -700,8 +700,10 @@ below under
|
||||
.SM
|
||||
.BR "ARITHMETIC EVALUATION" .
|
||||
If the value of the expression is non-zero, the return status is 0;
|
||||
otherwise the return status is 1. This is exactly equivalent to
|
||||
\fBlet "\fIexpression\fP"\fR.
|
||||
otherwise the return status is 1.
|
||||
The \fIexpression\fP is expanded as if it were within double quotes,
|
||||
but double quote characters in \fIexpression\fP are not special and
|
||||
are removed.
|
||||
.TP
|
||||
\fB[[\fP \fIexpression\fP \fB]]\fP
|
||||
Return a status of 0 or 1 depending on the evaluation of
|
||||
|
||||
+5
-6
@@ -1126,13 +1126,12 @@ done
|
||||
|
||||
The arithmetic @var{expression} is evaluated according to the rules
|
||||
described below (@pxref{Shell Arithmetic}).
|
||||
The @var{expression} is expanded as if it were within double quotes,
|
||||
but double quote characters in @var{expression} are not special and
|
||||
are removed.
|
||||
If the value of the expression is non-zero, the return status is 0;
|
||||
otherwise the return status is 1. This is exactly equivalent to
|
||||
@example
|
||||
let "@var{expression}"
|
||||
@end example
|
||||
@noindent
|
||||
@xref{Bash Builtins}, for a full description of the @code{let} builtin.
|
||||
otherwise the return status is 1.
|
||||
|
||||
|
||||
@item [[@dots{}]]
|
||||
@rwindex [[
|
||||
|
||||
+3
-3
@@ -2,10 +2,10 @@
|
||||
Copyright (C) 1988-2021 Free Software Foundation, Inc.
|
||||
@end ignore
|
||||
|
||||
@set LASTCHANGE Wed Mar 31 11:53:05 EDT 2021
|
||||
@set LASTCHANGE Wed May 5 16:29:06 EDT 2021
|
||||
|
||||
@set EDITION 5.1
|
||||
@set VERSION 5.1
|
||||
|
||||
@set UPDATED 31 March 2021
|
||||
@set UPDATED-MONTH March 2021
|
||||
@set UPDATED 5 May 2021
|
||||
@set UPDATED-MONTH May 2021
|
||||
|
||||
+54
-17
@@ -3010,7 +3010,7 @@ eval_arith_for_expr (l, okp)
|
||||
{
|
||||
WORD_LIST *new;
|
||||
intmax_t expresult;
|
||||
int r;
|
||||
int r, eflag;
|
||||
char *expr, *temp;
|
||||
|
||||
expr = l->next ? string_list (l) : l->word->word;
|
||||
@@ -3037,9 +3037,15 @@ eval_arith_for_expr (l, okp)
|
||||
r = run_debug_trap ();
|
||||
/* In debugging mode, if the DEBUG trap returns a non-zero status, we
|
||||
skip the command. */
|
||||
#if 0 /* TAG:bash-5.2 */
|
||||
eflag = (shell_compatibility_level > 51) ? 0 : EXP_EXPANDED;
|
||||
#else
|
||||
eflag = 0;
|
||||
#endif
|
||||
|
||||
#if defined (DEBUGGER)
|
||||
if (debugging_mode == 0 || r == EXECUTION_SUCCESS)
|
||||
expresult = evalexp (new->word->word, EXP_EXPANDED, okp);
|
||||
expresult = evalexp (new->word->word, eflag, okp);
|
||||
else
|
||||
{
|
||||
expresult = 0;
|
||||
@@ -3047,7 +3053,7 @@ eval_arith_for_expr (l, okp)
|
||||
*okp = 1;
|
||||
}
|
||||
#else
|
||||
expresult = evalexp (new->word->word, EXP_EXPANDED, okp);
|
||||
expresult = evalexp (new->word->word, eflag, okp);
|
||||
#endif
|
||||
dispose_words (new);
|
||||
}
|
||||
@@ -3744,7 +3750,7 @@ static int
|
||||
execute_arith_command (arith_command)
|
||||
ARITH_COM *arith_command;
|
||||
{
|
||||
int expok, save_line_number, retval;
|
||||
int expok, save_line_number, retval, eflag;
|
||||
intmax_t expresult;
|
||||
WORD_LIST *new;
|
||||
char *exp, *t;
|
||||
@@ -3805,7 +3811,12 @@ execute_arith_command (arith_command)
|
||||
|
||||
if (exp)
|
||||
{
|
||||
expresult = evalexp (exp, EXP_EXPANDED, &expok);
|
||||
#if 0 /* TAG:bash-5.2 */
|
||||
eflag = (shell_compatibility_level > 51) ? 0 : EXP_EXPANDED;
|
||||
#else
|
||||
eflag = 0;
|
||||
#endif
|
||||
expresult = evalexp (exp, eflag, &expok);
|
||||
line_number = save_line_number;
|
||||
free (exp);
|
||||
}
|
||||
@@ -3831,8 +3842,8 @@ static int
|
||||
execute_cond_node (cond)
|
||||
COND_COM *cond;
|
||||
{
|
||||
int result, invert, patmatch, rmatch, mflags, ignore;
|
||||
char *arg1, *arg2;
|
||||
int result, invert, patmatch, rmatch, arith, mode, mflags, ignore;
|
||||
char *arg1, *arg2, *op;
|
||||
#if 0
|
||||
char *t1, *t2;
|
||||
#endif
|
||||
@@ -3863,41 +3874,67 @@ execute_cond_node (cond)
|
||||
}
|
||||
else if (cond->type == COND_UNARY)
|
||||
{
|
||||
int oa, varop, varflag;
|
||||
|
||||
if (ignore)
|
||||
comsub_ignore_return++;
|
||||
arg1 = cond_expand_word (cond->left->op, 0);
|
||||
varop = STREQ (cond->op->word, "-v");
|
||||
#if defined (ARRAY_VARS)
|
||||
varflag = (varop && valid_array_reference (cond->left->op->word, VA_NOEXPAND)) ? TEST_ARRAYEXP : 0;
|
||||
#else
|
||||
varflag = 0;
|
||||
#endif
|
||||
arg1 = cond_expand_word (cond->left->op, varop ? 3 : 0);
|
||||
if (ignore)
|
||||
comsub_ignore_return--;
|
||||
if (arg1 == 0)
|
||||
arg1 = nullstr;
|
||||
if (echo_command_at_execute)
|
||||
xtrace_print_cond_term (cond->type, invert, cond->op, arg1, (char *)NULL);
|
||||
result = unary_test (cond->op->word, arg1) ? EXECUTION_SUCCESS : EXECUTION_FAILURE;
|
||||
/* TAG:bash-5.2 fix up later with set_expand_once() */
|
||||
oa = assoc_expand_once;
|
||||
#if 0
|
||||
if (varop && shell_compatibility_level > 51)
|
||||
#else
|
||||
if (varop)
|
||||
#endif
|
||||
assoc_expand_once = 0;
|
||||
result = unary_test (cond->op->word, arg1, varflag) ? EXECUTION_SUCCESS : EXECUTION_FAILURE;
|
||||
assoc_expand_once = oa;
|
||||
if (arg1 != nullstr)
|
||||
free (arg1);
|
||||
}
|
||||
else if (cond->type == COND_BINARY)
|
||||
{
|
||||
rmatch = 0;
|
||||
patmatch = (((cond->op->word[1] == '=') && (cond->op->word[2] == '\0') &&
|
||||
(cond->op->word[0] == '!' || cond->op->word[0] == '=')) ||
|
||||
(cond->op->word[0] == '=' && cond->op->word[1] == '\0'));
|
||||
op = cond->op->word;
|
||||
mode = 0;
|
||||
patmatch = (((op[1] == '=') && (op[2] == '\0') &&
|
||||
(op[0] == '!' || op[0] == '=')) ||
|
||||
(op[0] == '=' && op[1] == '\0'));
|
||||
#if defined (COND_REGEXP)
|
||||
rmatch = (cond->op->word[0] == '=' && cond->op->word[1] == '~' &&
|
||||
cond->op->word[2] == '\0');
|
||||
rmatch = (op[0] == '=' && op[1] == '~' && op[2] == '\0');
|
||||
#endif
|
||||
arith = STREQ (op, "-eq") || STREQ (op, "-ne") || STREQ (op, "-lt") ||
|
||||
STREQ (op, "-le") || STREQ (op, "-gt") || STREQ (op, "-ge");
|
||||
|
||||
if (arith)
|
||||
mode = 3;
|
||||
else if (rmatch && shell_compatibility_level > 31)
|
||||
mode = 2;
|
||||
else if (patmatch)
|
||||
mode = 1;
|
||||
|
||||
if (ignore)
|
||||
comsub_ignore_return++;
|
||||
arg1 = cond_expand_word (cond->left->op, 0);
|
||||
arg1 = cond_expand_word (cond->left->op, arith ? mode : 0);
|
||||
if (ignore)
|
||||
comsub_ignore_return--;
|
||||
if (arg1 == 0)
|
||||
arg1 = nullstr;
|
||||
if (ignore)
|
||||
comsub_ignore_return++;
|
||||
arg2 = cond_expand_word (cond->right->op,
|
||||
(rmatch && shell_compatibility_level > 31) ? 2 : (patmatch ? 1 : 0));
|
||||
arg2 = cond_expand_word (cond->right->op, mode);
|
||||
if (ignore)
|
||||
comsub_ignore_return--;
|
||||
if (arg2 == 0)
|
||||
|
||||
@@ -59,6 +59,8 @@ zread (fd, buf, len)
|
||||
ssize_t r;
|
||||
|
||||
check_signals (); /* check for signals before a blocking read */
|
||||
/* should generalize into a mechanism where different parts of the shell can
|
||||
`register' timeouts and have them checked here. */
|
||||
while (((r = read_builtin_timeout (fd)) < 0 || (r = read (fd, buf, len)) < 0) &&
|
||||
errno == EINTR)
|
||||
{
|
||||
|
||||
@@ -3594,7 +3594,7 @@ expand_arith_string (string, quoted)
|
||||
if (EXP_CHAR (string[i]))
|
||||
break;
|
||||
else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"')
|
||||
saw_quote = 1;
|
||||
saw_quote = string[i];
|
||||
ADVANCE_CHAR (string, slen, i);
|
||||
}
|
||||
|
||||
@@ -3684,7 +3684,8 @@ cond_expand_word (w, special)
|
||||
|
||||
expand_no_split_dollar_star = 1;
|
||||
w->flags |= W_NOSPLIT2;
|
||||
l = call_expand_word_internal (w, 0, 0, (int *)0, (int *)0);
|
||||
qflags = (special == 3) ? Q_ARITH : 0;
|
||||
l = call_expand_word_internal (w, qflags, 0, (int *)0, (int *)0);
|
||||
expand_no_split_dollar_star = 0;
|
||||
if (l)
|
||||
{
|
||||
@@ -6714,7 +6715,7 @@ array_length_reference (s)
|
||||
if (assoc_p (var))
|
||||
{
|
||||
t[len - 1] = '\0';
|
||||
akey = expand_assignment_string_to_string (t, 0); /* [ */
|
||||
akey = expand_subscript_string (t, 0); /* [ */
|
||||
t[len - 1] = RBRACK;
|
||||
if (akey == 0 || *akey == 0)
|
||||
{
|
||||
@@ -7526,7 +7527,7 @@ verify_substring_values (v, value, substr, vtype, e1p, e2p)
|
||||
{
|
||||
char *t, *temp1, *temp2;
|
||||
arrayind_t len;
|
||||
int expok;
|
||||
int expok, eflag;
|
||||
#if defined (ARRAY_VARS)
|
||||
ARRAY *a;
|
||||
HASH_TABLE *h;
|
||||
@@ -7539,12 +7540,14 @@ verify_substring_values (v, value, substr, vtype, e1p, e2p)
|
||||
else
|
||||
t = (char *)0;
|
||||
|
||||
temp1 = expand_arith_string (substr, Q_DOUBLE_QUOTES); /* Q_ARITH? */
|
||||
#if 1 /* TAG: bash-5.2 */
|
||||
*e1p = evalexp (temp1, EXP_EXPANDED, &expok);
|
||||
temp1 = expand_arith_string (substr, Q_DOUBLE_QUOTES|Q_ARITH);
|
||||
#if 0 /* TAG: bash-5.2 */
|
||||
eflag = (shell_compatibility_level > 51) ? 0 : EXP_EXPANDED;
|
||||
#else
|
||||
*e1p = evalexp (temp1, 0, &expok); /* XXX - EXP_EXPANDED? */
|
||||
eflag = 0;
|
||||
#endif
|
||||
|
||||
*e1p = evalexp (temp1, eflag, &expok);
|
||||
free (temp1);
|
||||
if (expok == 0)
|
||||
return (0);
|
||||
@@ -7599,14 +7602,10 @@ verify_substring_values (v, value, substr, vtype, e1p, e2p)
|
||||
{
|
||||
t++;
|
||||
temp2 = savestring (t);
|
||||
temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES); /* Q_ARITH? */
|
||||
temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES|Q_ARITH);
|
||||
free (temp2);
|
||||
t[-1] = ':';
|
||||
#if 1 /* TAG: bash-5.2 */
|
||||
*e2p = evalexp (temp1, EXP_EXPANDED, &expok);
|
||||
#else
|
||||
*e2p = evalexp (temp1, 0, &expok); /* XXX - EXP_EXPANDED? */
|
||||
#endif
|
||||
*e2p = evalexp (temp1, eflag, &expok);
|
||||
free (temp1);
|
||||
if (expok == 0)
|
||||
return (0);
|
||||
@@ -9574,7 +9573,7 @@ param_expand (string, sindex, quoted, expanded_something,
|
||||
int *quoted_dollar_at_p, *had_quoted_null_p, pflags;
|
||||
{
|
||||
char *temp, *temp1, uerror[3], *savecmd;
|
||||
int zindex, t_index, expok;
|
||||
int zindex, t_index, expok, eflag;
|
||||
unsigned char c;
|
||||
intmax_t number;
|
||||
SHELL_VAR *var;
|
||||
@@ -9952,7 +9951,12 @@ arithsub:
|
||||
/* No error messages. */
|
||||
savecmd = this_command_name;
|
||||
this_command_name = (char *)NULL;
|
||||
number = evalexp (temp1, EXP_EXPANDED, &expok);
|
||||
#if 0 /* TAG: bash-5.2 */
|
||||
eflag = (shell_compatibility_level > 51) ? 0 : EXP_EXPANDED;
|
||||
#else
|
||||
eflag = 0;
|
||||
#endif
|
||||
number = evalexp (temp1, eflag, &expok);
|
||||
this_command_name = savecmd;
|
||||
free (temp);
|
||||
free (temp1);
|
||||
@@ -10435,6 +10439,26 @@ add_string:
|
||||
}
|
||||
#endif /* PROCESS_SUBSTITUTION */
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
case '[': /*]*/
|
||||
#if 0 /* TAG:bash-5.2 */
|
||||
if (((quoted & Q_ARITH) == 0 && (word->flags & W_ARRAYREF) == 0) || (shell_compatibility_level <= 51))
|
||||
#else
|
||||
if (((quoted & Q_ARITH) == 0 && (word->flags & W_ARRAYREF) == 0))
|
||||
#endif
|
||||
{
|
||||
if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
|
||||
goto add_ifs_character;
|
||||
else
|
||||
goto add_character;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp = expand_array_subscript (string, &sindex, quoted, word->flags);
|
||||
goto add_string;
|
||||
}
|
||||
#endif
|
||||
|
||||
case '=':
|
||||
/* Posix.2 section 3.6.1 says that tildes following `=' in words
|
||||
which are not assignment statements are not expanded. If the
|
||||
@@ -10708,6 +10732,7 @@ add_twochars:
|
||||
break;
|
||||
|
||||
case '"':
|
||||
/* XXX - revisit this */
|
||||
if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) && ((quoted & Q_ARITH) == 0))
|
||||
goto add_character;
|
||||
|
||||
@@ -10741,7 +10766,8 @@ add_twochars:
|
||||
|
||||
temp_has_dollar_at = 0; /* does this quoted (sub)string include $@? */
|
||||
/* Need to get W_HASQUOTEDNULL flag through this function. */
|
||||
list = expand_word_internal (tword, Q_DOUBLE_QUOTES, 0, &temp_has_dollar_at, (int *)NULL);
|
||||
/* XXX - preserve Q_ARITH here? */
|
||||
list = expand_word_internal (tword, Q_DOUBLE_QUOTES|(quoted&Q_ARITH), 0, &temp_has_dollar_at, (int *)NULL);
|
||||
has_dollar_at += temp_has_dollar_at;
|
||||
|
||||
if (list == &expand_word_error || list == &expand_word_fatal)
|
||||
@@ -11074,6 +11100,8 @@ finished_with_string:
|
||||
tword->flags |= W_NOGLOB; /* XXX */
|
||||
if (word->flags & W_NOBRACE)
|
||||
tword->flags |= W_NOBRACE; /* XXX */
|
||||
if (word->flags & W_ARRAYREF)
|
||||
tword->flags |= W_ARRAYREF;
|
||||
if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
|
||||
tword->flags |= W_QUOTED;
|
||||
list = make_word_list (tword, (WORD_LIST *)NULL);
|
||||
@@ -11182,6 +11210,8 @@ set_word_flags:
|
||||
tword->flags |= W_NOGLOB;
|
||||
if (word->flags & W_NOBRACE)
|
||||
tword->flags |= W_NOBRACE;
|
||||
if (word->flags & W_ARRAYREF)
|
||||
tword->flags |= W_ARRAYREF;
|
||||
list = make_word_list (tword, (WORD_LIST *)NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,6 +184,7 @@ extern WORD_LIST *expand_string PARAMS((char *, int));
|
||||
extern char *expand_string_to_string PARAMS((char *, int));
|
||||
extern char *expand_string_unsplit_to_string PARAMS((char *, int));
|
||||
extern char *expand_assignment_string_to_string PARAMS((char *, int));
|
||||
extern char *expand_subscript_string PARAMS((char *, int));
|
||||
|
||||
/* Expand an arithmetic expression string */
|
||||
extern char *expand_arith_string PARAMS((char *, int));
|
||||
|
||||
@@ -339,12 +339,19 @@ arithcomp (s, t, op, flags)
|
||||
intmax_t l, r;
|
||||
int expok;
|
||||
|
||||
if (flags & TEST_ARITHEXP)
|
||||
if (flags & TEST_ARITHEXP) /* conditional command */
|
||||
{
|
||||
l = evalexp (s, EXP_EXPANDED, &expok);
|
||||
int eflag;
|
||||
|
||||
#if 0 /* TAG:bash-5.2 */
|
||||
eflag = (shell_compatibility_level > 51) ? 0 : EXP_EXPANDED;
|
||||
#else
|
||||
eflag = 0;
|
||||
#endif
|
||||
l = evalexp (s, eflag, &expok);
|
||||
if (expok == 0)
|
||||
return (FALSE); /* should probably longjmp here */
|
||||
r = evalexp (t, EXP_EXPANDED, &expok);
|
||||
r = evalexp (t, eflag, &expok);
|
||||
if (expok == 0)
|
||||
return (FALSE); /* ditto */
|
||||
}
|
||||
@@ -492,13 +499,13 @@ unary_operator ()
|
||||
if (legal_number (argv[pos], &r))
|
||||
{
|
||||
advance (0);
|
||||
return (unary_test (op, argv[pos - 1]));
|
||||
return (unary_test (op, argv[pos - 1], 0));
|
||||
}
|
||||
else
|
||||
return (FALSE);
|
||||
}
|
||||
else
|
||||
return (unary_test (op, "1"));
|
||||
return (unary_test (op, "1", 0));
|
||||
}
|
||||
|
||||
/* All of the unary operators take an argument, so we first call
|
||||
@@ -506,12 +513,13 @@ unary_operator ()
|
||||
argument, and then advances pos right past it. This means that
|
||||
pos - 1 is the location of the argument. */
|
||||
unary_advance ();
|
||||
return (unary_test (op, argv[pos - 1]));
|
||||
return (unary_test (op, argv[pos - 1], 0));
|
||||
}
|
||||
|
||||
int
|
||||
unary_test (op, arg)
|
||||
unary_test (op, arg, flags)
|
||||
char *op, *arg;
|
||||
int flags;
|
||||
{
|
||||
intmax_t r;
|
||||
struct stat stat_buf;
|
||||
@@ -630,6 +638,8 @@ unary_test (op, arg)
|
||||
int rtype, ret, flags;
|
||||
|
||||
/* Let's assume that this has already been expanded once. */
|
||||
/* XXX - TAG:bash-5.2 fix with corresponding fix to execute_cmd.c:
|
||||
execute_cond_node() that passes TEST_ARRAYEXP in FLAGS */
|
||||
flags = assoc_expand_once ? AV_NOEXPAND : 0;
|
||||
t = array_value (arg, 0, flags, &rtype, (arrayind_t *)0);
|
||||
ret = t ? TRUE : FALSE;
|
||||
|
||||
@@ -27,11 +27,12 @@
|
||||
#define TEST_PATMATCH 0x01
|
||||
#define TEST_ARITHEXP 0x02
|
||||
#define TEST_LOCALE 0x04
|
||||
#define TEST_ARRAYEXP 0x08 /* array subscript expansion */
|
||||
|
||||
extern int test_unop PARAMS((char *));
|
||||
extern int test_binop PARAMS((char *));
|
||||
|
||||
extern int unary_test PARAMS((char *, char *));
|
||||
extern int unary_test PARAMS((char *, char *, int));
|
||||
extern int binary_test PARAMS((char *, char *, char *, int));
|
||||
|
||||
extern int test_command PARAMS((int, char **));
|
||||
|
||||
+7
-10
@@ -520,13 +520,11 @@ argv[1] = <y>
|
||||
<X> <X> <X> <X>
|
||||
./array23.sub: line 22: $( echo >&2 foo ) : syntax error: operand expected (error token is "$( echo >&2 foo ) ")
|
||||
./array23.sub: line 23: $( echo >&2 foo ) : syntax error: operand expected (error token is "$( echo >&2 foo ) ")
|
||||
foo
|
||||
0
|
||||
foo
|
||||
foo
|
||||
foo
|
||||
6
|
||||
./array23.sub: line 34: $( echo >&2 foo ): syntax error: operand expected (error token is "$( echo >&2 foo )")
|
||||
./array23.sub: line 24: $( echo >&2 foo ) : syntax error: operand expected (error token is "$( echo >&2 foo ) ")
|
||||
./array23.sub: line 26: $( echo >&2 foo ) : syntax error: operand expected (error token is "$( echo >&2 foo ) ")
|
||||
./array23.sub: line 30: $( echo >&2 foo ): syntax error: operand expected (error token is "$( echo >&2 foo )")
|
||||
./array23.sub: line 33: $( echo >&2 foo ): syntax error: operand expected (error token is "$( echo >&2 foo )")
|
||||
./array23.sub: line 34: $index: syntax error: operand expected (error token is "$index")
|
||||
./array23.sub: line 35: $( echo >&2 foo ): syntax error: operand expected (error token is "$( echo >&2 foo )")
|
||||
0
|
||||
0
|
||||
@@ -743,10 +741,9 @@ argv[1] = <b>
|
||||
argv[2] = <a>
|
||||
argv[1] = <b+a>
|
||||
7
|
||||
./array27.sub: line 24: a[]]=7 : syntax error: invalid arithmetic operator (error token is "]=7 ")
|
||||
7
|
||||
declare -A A=([$'\t']="2" [" "]="2" )
|
||||
./array27.sub: line 36: ((: A[]]=2 : syntax error: invalid arithmetic operator (error token is "]=2 ")
|
||||
declare -A A=([$'\t']="2" ["*"]="2" [" "]="2" ["@"]="2" )
|
||||
declare -A A=([$'\t']="2" ["*"]="2" [" "]="2" ["]"]="2" ["@"]="2" )
|
||||
declare -A A=([$'\t']="2" ["*"]="2" [" "]="2" ["]"]="2" ["@"]="2" )
|
||||
./array27.sub: line 52: A[]]: bad array subscript
|
||||
declare -A A=([$'\t']="X" ["*"]="X" [" "]="X" ["@"]="X" )
|
||||
|
||||
@@ -283,3 +283,12 @@ declare -A v3=(["1 2"]="3 4 5" ["\$xtra"]="xtra" )
|
||||
declare -A v1=(["20 40 80"]="new xtra" ["1 2"]="3 4 5" )
|
||||
declare -A v2=(["20 40 80"]="new xtra" ["1 2"]="3 4 5" )
|
||||
declare -A v3=(["1 2"]="3 4 5" ["\$xtra"]="new xtra" )
|
||||
declare -A assoc=(["*"]="star" ["!"]="bang" ["@"]="at" )
|
||||
at
|
||||
star
|
||||
declare -A a=(["@"]="at" )
|
||||
./assoc13.sub: line 22: ia[@]: bad array subscript
|
||||
declare -a ia
|
||||
declare -A a=(["@"]="at2" )
|
||||
declare -A a=(["@"]=" string" )
|
||||
declare -A a=(["*"]="star2" ["@"]="at" )
|
||||
|
||||
@@ -247,3 +247,6 @@ ${THIS_SH} ./assoc11.sub
|
||||
|
||||
# more kvpair associative array assignment tests
|
||||
${THIS_SH} ./assoc12.sub
|
||||
|
||||
# assignment to @ and *
|
||||
${THIS_SH} ./assoc13.sub
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
# assignment to @ and *
|
||||
|
||||
declare -A assoc
|
||||
key=@
|
||||
key2=*
|
||||
|
||||
assoc[$key]=at
|
||||
assoc[$key2]=star
|
||||
assoc[!]=bang
|
||||
declare -p assoc
|
||||
|
||||
echo ${assoc[$key]}
|
||||
echo ${assoc[$key2]}
|
||||
unset assoc
|
||||
|
||||
declare -A a
|
||||
|
||||
a[@]=at
|
||||
declare -p a
|
||||
|
||||
declare -a ia
|
||||
ia[@]=garbage
|
||||
|
||||
declare -p ia
|
||||
|
||||
declare a[@]=at2
|
||||
declare -p a
|
||||
|
||||
unset a ia
|
||||
|
||||
declare -A a
|
||||
printf -v a[@] "%10s" string
|
||||
|
||||
declare -p a
|
||||
unset a
|
||||
|
||||
declare -A a
|
||||
declare a[$key2]=star
|
||||
declare a[@]=at
|
||||
declare a[*]=star2
|
||||
|
||||
declare -p a
|
||||
unset a
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
declare -A assoc=(["x],b[\$(echo uname >&2)"]="1" )
|
||||
declare -A assoc=(["\$key"]="1" ["x],b[\$(echo uname >&2)"]="1" )
|
||||
declare -A assoc=(["\$key"]="1" ["x],b[\$(echo uname >&2)"]="2" )
|
||||
./quotearray.tests: line 31: ((: 'assoc[x\],b\[\$(echo uname >&2)]++' : syntax error: operand expected (error token is "'assoc[x\],b\[\$(echo uname >&2)]++' ")
|
||||
declare -A assoc=(["\$key"]="1" ["x],b[\$(echo uname >&2)"]="2" )
|
||||
./quotearray.tests: line 34: ((: 'assoc[x\],b\[\$(echo uname >&2)]'++ : syntax error: operand expected (error token is "'assoc[x\],b\[\$(echo uname >&2)]'++ ")
|
||||
declare -A assoc=(["\$key"]="1" ["x],b[\$(echo uname >&2)"]="2" )
|
||||
declare -A assoc=(["\$key"]="1" ["x],b[\$(echo uname >&2)"]="3" )
|
||||
4
|
||||
klmnopqrst
|
||||
klmnopqrst
|
||||
klmno
|
||||
klmnopqrst
|
||||
declare -A A=(["\$(echo %)"]="5" [%]="10" ["]"]="10" )
|
||||
declare -A A=(["~"]="42" )
|
||||
42
|
||||
declare -A A=(["~"]="43" )
|
||||
42
|
||||
declare -A A=(["~"]="43" ["~0"]="43" )
|
||||
12
|
||||
declare -a a=([0]="12" [1]="42")
|
||||
2
|
||||
2
|
||||
declare -Ai assoc=(["']"]="2" ["\$var"]="1" )
|
||||
105
|
||||
declare -A assoc=(["\` echo >&2 foo\`"]="42" ["\$( echo >&2 bar)"]="63" )
|
||||
./quotearray.tests: line 139: x],b[$(echo uname >&2): syntax error: invalid arithmetic operator (error token is "],b[$(echo uname >&2)")
|
||||
./quotearray.tests: line 143: x],b[$(echo uname >&2): syntax error: invalid arithmetic operator (error token is "],b[$(echo uname >&2)")
|
||||
1
|
||||
./quotearray.tests: line 146: x],b[$(echo uname >&2): syntax error: invalid arithmetic operator (error token is "],b[$(echo uname >&2)")
|
||||
1
|
||||
./quotearray.tests: line 149: x],b[$(echo uname >&2): syntax error: invalid arithmetic operator (error token is "],b[$(echo uname >&2)")
|
||||
1
|
||||
./quotearray.tests: line 152: x],b[$(echo uname >&2): syntax error: invalid arithmetic operator (error token is "],b[$(echo uname >&2)")
|
||||
1
|
||||
declare -A assoc
|
||||
0
|
||||
0
|
||||
1
|
||||
0
|
||||
0
|
||||
0
|
||||
declare -A assoc=(["\` echo >&2 foo\`"]="128" [0]="0" ["]"]="12" ["x],b[\$(echo uname >&2)"]="42" ["~"]="42" ["\$( echo 2>& date)"]="foo" )
|
||||
foo
|
||||
0
|
||||
0
|
||||
./quotearray1.sub: line 67: 0\],b\[1: syntax error: invalid arithmetic operator (error token is "\],b\[1")
|
||||
declare -a array
|
||||
0
|
||||
0
|
||||
0
|
||||
0
|
||||
1
|
||||
1
|
||||
declare -A aa=(["\$( echo 2>& date)"]="foo" )
|
||||
foo
|
||||
0
|
||||
1
|
||||
declare -A a=([1]="1" [0]="0" [" "]="11" )
|
||||
7
|
||||
7
|
||||
declare -A A=([$'\t']="2" [" "]="2" )
|
||||
declare -A A=([$'\t']="2" ["*"]="2" [" "]="2" ["]"]="2" ["@"]="2" )
|
||||
./quotearray2.sub: line 54: read: `A[]]': not a valid identifier
|
||||
declare -A A=([$'\t']="X" ["*"]="X" [" "]="X" ["@"]="X" )
|
||||
./quotearray2.sub: line 62: printf: `A[]]': not a valid identifier
|
||||
declare -A A=([$'\t']="X" ["*"]="X" [" "]="X" ["@"]="X" )
|
||||
./quotearray2.sub: line 70: declare: `A[]]=X': not a valid identifier
|
||||
declare -A A=(["*"]="X" ["@"]="X" )
|
||||
./quotearray2.sub: line 78: declare: `A[]]=X': not a valid identifier
|
||||
declare -A A=(["*"]="X" ["@"]="X" )
|
||||
./quotearray2.sub: line 89: let: assoc[x],b[$(echo: bad array subscript (error token is "b[$(echo")
|
||||
declare -A assoc
|
||||
declare -A assoc=(["\$var"]="value" )
|
||||
declare -A assoc=(["\$var"]="value" )
|
||||
declare -A assoc=(["\$var"]="value" )
|
||||
declare -A assoc=()
|
||||
declare -A a=()
|
||||
declare -A a=(["\$(echo foo)"]="1" )
|
||||
declare -A a=()
|
||||
declare -A a=(["\$(echo foo)"]="1" )
|
||||
./quotearray3.sub: line 66: typeset: assoc: not found
|
||||
1
|
||||
./quotearray3.sub: line 71: \@: syntax error: operand expected (error token is "\@")
|
||||
1
|
||||
@@ -0,0 +1,157 @@
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
# a set of tests for associative arrays in arithmetic contexts
|
||||
|
||||
declare -A assoc
|
||||
key='x],b[$(echo uname >&2)'
|
||||
|
||||
(( assoc[$key]++ ))
|
||||
declare -p assoc
|
||||
|
||||
(( assoc['$key']++ ))
|
||||
declare -p assoc
|
||||
|
||||
(( assoc["$key"]++ ))
|
||||
declare -p assoc
|
||||
|
||||
declare -A assoc
|
||||
|
||||
(( 'assoc[$key]++' ))
|
||||
declare -p assoc
|
||||
|
||||
(( 'assoc[$key]'++ ))
|
||||
declare -p assoc
|
||||
|
||||
(( "assoc[$key]++" ))
|
||||
declare -p assoc
|
||||
|
||||
unset assoc
|
||||
|
||||
typeset -A a
|
||||
b="80's"
|
||||
|
||||
((++a[$b]))
|
||||
|
||||
((++a["$b"]))
|
||||
[[ $((++a[$b])) ]]
|
||||
[[ $((++a["$b"])) ]]
|
||||
|
||||
echo ${a[$b]}
|
||||
unset a
|
||||
|
||||
declare -A A
|
||||
|
||||
string=abcdefghijklmnopqrstuvwxyz
|
||||
|
||||
echo ${string:10:10}
|
||||
k1='%'
|
||||
k2='$(echo %)'
|
||||
|
||||
A[%]=10
|
||||
A[']']=10
|
||||
A[$k2]=5
|
||||
|
||||
k3=']'
|
||||
|
||||
echo ${string:A[%]:A[$k1]}
|
||||
echo ${string:A[%]:A[$k2]}
|
||||
echo ${string:A[%]:A[$k3]}
|
||||
|
||||
declare -p A
|
||||
|
||||
unset A string key
|
||||
|
||||
key='~'
|
||||
|
||||
declare -A A
|
||||
A[$key]=42
|
||||
|
||||
declare -p A
|
||||
|
||||
echo $(( A[$key]++ ))
|
||||
declare -p A
|
||||
|
||||
key='~0'
|
||||
A[$key]=42
|
||||
echo $(( A[$key]++ ))
|
||||
declare -p A
|
||||
|
||||
declare -a a
|
||||
key='~-2'
|
||||
a[0]=12
|
||||
a[$key]=42
|
||||
echo $(( a[7<(4+2)] ))
|
||||
|
||||
declare -p a
|
||||
|
||||
unset A a key
|
||||
|
||||
declare -A A
|
||||
declare -a a
|
||||
|
||||
sString="devel packager's guide"
|
||||
i=2
|
||||
|
||||
A["$sString"]=$i
|
||||
a[$i]=$sString
|
||||
|
||||
echo "${A[${a[i]}]}"
|
||||
echo ${A["${a[i]}"]}
|
||||
|
||||
unset A a
|
||||
|
||||
#LANG=C
|
||||
unset var assoc
|
||||
var=\'\]
|
||||
declare -Ai assoc
|
||||
assoc[$var]=1
|
||||
assoc[$var]+=1
|
||||
((assoc['$var']++))
|
||||
typeset -p assoc
|
||||
|
||||
unset assoc
|
||||
|
||||
declare -A assoc
|
||||
key1='` echo >&2 foo`'
|
||||
key2='$( echo >&2 bar)'
|
||||
|
||||
assoc[$key1]=42
|
||||
assoc[$key2]=63
|
||||
|
||||
echo $(( assoc[$key1] + assoc[$key2] ))
|
||||
declare -p assoc
|
||||
unset assoc
|
||||
|
||||
declare -a a
|
||||
key='x],b[$(echo uname >&2)'
|
||||
a[$key]=42
|
||||
|
||||
expr='a[$key]'
|
||||
|
||||
(( $expr ))
|
||||
echo $?
|
||||
|
||||
echo $(( $expr ))
|
||||
echo $?
|
||||
|
||||
echo $(( expr ))
|
||||
echo $?
|
||||
|
||||
(( expr ))
|
||||
echo $?
|
||||
|
||||
${THIS_SH} ./quotearray1.sub
|
||||
${THIS_SH} ./quotearray2.sub
|
||||
${THIS_SH} ./quotearray3.sub
|
||||
@@ -0,0 +1,105 @@
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
# arithmetic operators for conditional commands and arithmetic commands
|
||||
|
||||
declare -A assoc
|
||||
declare -a index
|
||||
|
||||
key='x],b[$(echo uname >&2)'
|
||||
key1=']'
|
||||
key2='` echo >&2 foo`'
|
||||
key3='~'
|
||||
key4='7<(4+2)'
|
||||
key5='$( echo 2>& date)'
|
||||
|
||||
[[ -n assoc[$key] ]]
|
||||
declare -p assoc
|
||||
|
||||
assoc[$key]=42
|
||||
assoc[$key1]=12
|
||||
assoc[$key2]=128
|
||||
assoc[$key3]=42
|
||||
assoc[0]=0
|
||||
|
||||
[[ assoc[$key] -eq assoc[$key] ]]
|
||||
echo $?
|
||||
|
||||
[[ assoc[$key] -gt assoc[$key1] ]]
|
||||
echo $?
|
||||
|
||||
[[ assoc[$key2] -lt assoc[$key] ]]
|
||||
echo $?
|
||||
|
||||
[[ assoc[$key] -eq assoc[$key3] ]]
|
||||
echo $?
|
||||
|
||||
[[ index[7<(4+2)] -le assoc[0] ]]
|
||||
echo $?
|
||||
[[ index[$key4] -le assoc[0] ]]
|
||||
echo $?
|
||||
|
||||
assoc[$key5]=foo
|
||||
declare -p assoc
|
||||
|
||||
echo "${assoc[$key5]}"
|
||||
|
||||
[[ -v assoc[$key5] ]]
|
||||
echo $?
|
||||
[[ -v assoc[$key] ]]
|
||||
echo $?
|
||||
|
||||
unset assoc
|
||||
|
||||
declare -a array
|
||||
index='0],b[1';
|
||||
((array[$index]++))
|
||||
|
||||
declare -p array
|
||||
|
||||
unset array
|
||||
|
||||
declare -A assoc
|
||||
|
||||
assoc[$key]=42
|
||||
assoc[$key4]=42
|
||||
|
||||
[[ -v assoc[$key] ]]
|
||||
echo $?
|
||||
[[ -v assoc["$key"] ]]
|
||||
echo $?
|
||||
|
||||
[[ -v assoc[$key4] ]]
|
||||
echo $?
|
||||
[[ -v assoc["$key4"] ]]
|
||||
echo $?
|
||||
|
||||
[[ -v assoc['$key'] ]]
|
||||
echo $?
|
||||
[[ -v assoc['$key4'] ]]
|
||||
echo $?
|
||||
|
||||
declare -A aa
|
||||
aa[$key5]=foo
|
||||
|
||||
declare -p aa
|
||||
echo "${aa[$key5]}"
|
||||
|
||||
[[ -v aa[$key5] ]]
|
||||
echo $?
|
||||
|
||||
[[ -v aa[$key] ]]
|
||||
echo $?
|
||||
|
||||
unset aa key
|
||||
@@ -0,0 +1,92 @@
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
# assoc_expand_once for builtins
|
||||
|
||||
typeset -A a
|
||||
a[0]=0 a[1]=1
|
||||
|
||||
let "a[\" \"]=11" ; typeset -p a ; a[0]=0
|
||||
|
||||
unset a
|
||||
|
||||
# tests for `problem' keys when using associative arrays and assoc_expand_once
|
||||
# deal with problems for now; this is a placeholder for if and when I fix them
|
||||
|
||||
typeset -A a
|
||||
|
||||
k='['
|
||||
echo $(( a[$k]=7 ))
|
||||
|
||||
k=']'
|
||||
echo $(( a[$k]=7 ))
|
||||
|
||||
unset a
|
||||
|
||||
declare -A A
|
||||
|
||||
for k in $'\t' ' '; do
|
||||
(( A[$k]=2 ))
|
||||
done
|
||||
declare -p A
|
||||
|
||||
for k in ']' '*' '@'; do
|
||||
(( A[$k]=2 ))
|
||||
done
|
||||
|
||||
declare -p A
|
||||
|
||||
unset A
|
||||
declare -A A
|
||||
|
||||
for k in $'\t' ' ' ']' '*' '@'; do
|
||||
read "A[$k]" <<< X
|
||||
done
|
||||
declare -p A
|
||||
|
||||
unset A
|
||||
declare -A A
|
||||
|
||||
for k in $'\t' ' ' ']' '*' '@'; do
|
||||
printf -v "A[$k]" "%s" X
|
||||
done
|
||||
declare -p A
|
||||
|
||||
unset A
|
||||
declare -A A
|
||||
|
||||
for k in ']' '*' '@'; do
|
||||
declare A[$k]=X
|
||||
done
|
||||
declare -p A
|
||||
|
||||
unset A
|
||||
declare -A A
|
||||
|
||||
for k in ']' '*' '@'; do
|
||||
declare "A[$k]=X"
|
||||
done
|
||||
declare -p A
|
||||
|
||||
unset A
|
||||
|
||||
# this isn't right yet, but changes will show up here
|
||||
shopt -s assoc_expand_once
|
||||
declare -A assoc
|
||||
key='x],b[$(echo uname >&2)'
|
||||
|
||||
let assoc[$key]++
|
||||
declare -p assoc
|
||||
|
||||
unset assoc
|
||||
@@ -0,0 +1,74 @@
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
# assoc_expand_once and unset builtin, which is treated specially
|
||||
|
||||
declare -A assoc
|
||||
|
||||
var=x123
|
||||
assoc['$var']=value
|
||||
declare -p assoc
|
||||
|
||||
shopt -u assoc_expand_once
|
||||
unset "assoc[$var]"
|
||||
declare -p assoc
|
||||
|
||||
unset 'assoc[$var]'
|
||||
declare -p assoc
|
||||
|
||||
assoc['$var']=value
|
||||
shopt -s assoc_expand_once
|
||||
unset 'assoc[$var]'
|
||||
declare -p assoc
|
||||
|
||||
unset assoc
|
||||
|
||||
declare -A a
|
||||
a['$(echo foo)']=1
|
||||
|
||||
unset 'a[$(echo foo)]'
|
||||
declare -p a
|
||||
|
||||
key='$(echo foo)'
|
||||
a[$key]=1
|
||||
|
||||
unset 'a[$key]'
|
||||
declare -p a
|
||||
|
||||
a[$key]=1
|
||||
unset "a[$key]"
|
||||
declare -p a
|
||||
|
||||
a[$key]=1
|
||||
unset a[$key]
|
||||
declare -p a
|
||||
|
||||
unset a
|
||||
|
||||
typeset -A assoc
|
||||
key=@
|
||||
|
||||
assoc[@]=at
|
||||
assoc[!]=bang
|
||||
|
||||
unset -v assoc[$key]
|
||||
typeset -p assoc
|
||||
|
||||
test -v assoc[$key]
|
||||
echo $?
|
||||
|
||||
[[ -v assoc[$key] ]]
|
||||
echo $?
|
||||
|
||||
unset assoc
|
||||
@@ -0,0 +1,2 @@
|
||||
${THIS_SH} ./quotearray.tests >${BASH_TSTOUT} 2>&1
|
||||
diff ${BASH_TSTOUT} quotearray.right && rm -f ${BASH_TSTOUT}
|
||||
Reference in New Issue
Block a user