mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-07-03 18:30:49 +02:00
more changes to handle @ and * as associative array keys
This commit is contained in:
@@ -10247,3 +10247,68 @@ builtins/shopt.def
|
||||
|
||||
builtins/common.h
|
||||
- expand_once_flag: extern declaration
|
||||
|
||||
5/10
|
||||
----
|
||||
doc/{bash.1,bashref.texi}
|
||||
- note that case patterns undergo quote removal. Reported by
|
||||
AlvinSeville7cf <alvinseville7cf@gmail.com>
|
||||
|
||||
5/11
|
||||
----
|
||||
|
||||
builtins/bashgetopt.c
|
||||
- list_optflags: flags associated with the word corresponding to
|
||||
list_optarg, assuming list_optarg is a separate argument
|
||||
|
||||
builtins/bashgetopt.h
|
||||
- list_optflags: extern declaration
|
||||
|
||||
builtins/set.def
|
||||
- unset_builtin: set VFLAGS each time through the loop, since we take
|
||||
whether or not the word has W_ARRAYREF set into account
|
||||
- unset_builtin: don't pass VA_ALLOWALL to unbind_array_element for
|
||||
now
|
||||
|
||||
test.c
|
||||
- unary_test: in the -v case, use assoc_expand_once in the first call
|
||||
to valid_array_reference ()
|
||||
|
||||
builtins/printf.def
|
||||
- printf_builtin: only set VA_ONEWORD if the option argument to -v has
|
||||
W_ARRAYREF set (look at list_optflags)
|
||||
|
||||
5/12
|
||||
----
|
||||
|
||||
subst.c
|
||||
- expand_array_subscript: don't quote @ or * in the expanded subscript
|
||||
at all, even when they are the only character in the subscript. See
|
||||
how this works out -- it might uncover places where we need to allow
|
||||
`*' and `@' as subscripts where they are not allowed now
|
||||
|
||||
expr.c
|
||||
- expr_bind_variable: pass ASS_ALLOWALLSUB to bind_int_variable so we
|
||||
can allow (( A[@]=value )) when A is an existing associative array
|
||||
|
||||
arrayfunc.h
|
||||
- AV_ATSTARKEYS: new flag value, means to accept a[@] and a[*] but
|
||||
treat them as keys/expressions and not special values
|
||||
|
||||
arrayfunc.c
|
||||
- array_value_internal: check AV_ATSTARKEYS and don't treat them as
|
||||
ALL_ELEMENT_SUB values; they fall through to use as keys/indices
|
||||
|
||||
test.c
|
||||
- unary_test: if -v is passed an array reference, add AV_ATSTARKEYS to
|
||||
the flags passed to array_value so we treat @ and * as keys for an
|
||||
existing associative array
|
||||
|
||||
5/13
|
||||
----
|
||||
|
||||
subst.c
|
||||
- expand_cond_word: if SPECIAL == 3 (arithmetic expression), dequote the
|
||||
resulting WORD_LIST * as if special == 0, because we don't want to
|
||||
quote the list for pattern matching. Report from
|
||||
Adjudicator Darren <adjudicatordarren@protonmail.com>
|
||||
|
||||
@@ -1313,6 +1313,7 @@ tests/quotearray.tests f
|
||||
tests/quotearray1.sub f
|
||||
tests/quotearray2.sub f
|
||||
tests/quotearray3.sub f
|
||||
tests/quotearray4.sub f
|
||||
tests/read.tests f
|
||||
tests/read.right f
|
||||
tests/read1.sub f
|
||||
|
||||
+5
-2
@@ -1370,7 +1370,7 @@ array_value_internal (s, quoted, flags, rtype, indp)
|
||||
int quoted, flags, *rtype;
|
||||
arrayind_t *indp;
|
||||
{
|
||||
int len;
|
||||
int len, isassoc;
|
||||
arrayind_t ind;
|
||||
char *akey;
|
||||
char *retval, *t, *temp;
|
||||
@@ -1389,9 +1389,12 @@ array_value_internal (s, quoted, flags, rtype, indp)
|
||||
if (len == 0)
|
||||
return ((char *)NULL); /* error message already printed */
|
||||
|
||||
isassoc = var && assoc_p (var);
|
||||
/* [ */
|
||||
akey = 0;
|
||||
if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
|
||||
/* Backwards compatibility: we only change the behavior of A[@] and A[*]
|
||||
for associative arrays, and the caller has to request it. */
|
||||
if ((isassoc == 0 || (flags & AV_ATSTARKEYS) == 0) && ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
|
||||
{
|
||||
if (rtype)
|
||||
*rtype = (t[0] == '*') ? 1 : 2;
|
||||
|
||||
+7
-1
@@ -33,12 +33,14 @@ extern int assoc_expand_once;
|
||||
extern int array_expand_once;
|
||||
|
||||
/* Flags for array_value_internal and callers array_value/get_array_value */
|
||||
#define AV_ALLOWALL 0x001
|
||||
#define AV_ALLOWALL 0x001 /* treat a[@] like $@ and a[*] like $* */
|
||||
#define AV_QUOTED 0x002
|
||||
#define AV_USEIND 0x004
|
||||
#define AV_USEVAL 0x008 /* XXX - should move this */
|
||||
#define AV_ASSIGNRHS 0x010 /* no splitting, special case ${a[@]} */
|
||||
#define AV_NOEXPAND 0x020 /* don't run assoc subscripts through word expansion */
|
||||
#define AV_ONEWORD 0x040 /* not used yet */
|
||||
#define AV_ATSTARKEYS 0x080 /* accept a[@] and a[*] but use them as keys, not special values */
|
||||
|
||||
/* Flags for valid_array_reference. Value 1 is reserved for skipsubscript().
|
||||
Also used by unbind_array_element, which is currently the only function
|
||||
@@ -94,7 +96,11 @@ extern SHELL_VAR *array_variable_part PARAMS((const char *, int, char **, int *)
|
||||
#define AV_ALLOWALL 0
|
||||
#define AV_QUOTED 0
|
||||
#define AV_USEIND 0
|
||||
#define AV_USEVAL 0
|
||||
#define AV_ASSIGNRHS 0
|
||||
#define AV_NOEXPAND 0
|
||||
#define AV_ONEWORD 0
|
||||
#define AV_ATSTARKEYS 0
|
||||
|
||||
#define VA_NOEXPAND 0
|
||||
#define VA_ONEWORD 0
|
||||
|
||||
+14
-1
@@ -39,6 +39,7 @@
|
||||
static int sp;
|
||||
|
||||
char *list_optarg;
|
||||
int list_optflags;
|
||||
int list_optopt;
|
||||
int list_opttype;
|
||||
|
||||
@@ -62,6 +63,7 @@ char *opts;
|
||||
|
||||
if (list == 0) {
|
||||
list_optarg = (char *)NULL;
|
||||
list_optflags = 0;
|
||||
loptend = (WORD_LIST *)NULL; /* No non-option arguments */
|
||||
return -1;
|
||||
}
|
||||
@@ -102,6 +104,7 @@ char *opts;
|
||||
sp = 1;
|
||||
}
|
||||
list_optarg = NULL;
|
||||
list_optflags = 0;
|
||||
if (lcurrent)
|
||||
loptend = lcurrent->next;
|
||||
return('?');
|
||||
@@ -113,6 +116,7 @@ char *opts;
|
||||
/* We allow -l2 as equivalent to -l 2 */
|
||||
if (lcurrent->word->word[sp+1]) {
|
||||
list_optarg = lcurrent->word->word + sp + 1;
|
||||
list_optflags = 0;
|
||||
lcurrent = lcurrent->next;
|
||||
/* If the specifier is `;', don't set optarg if the next
|
||||
argument looks like another option. */
|
||||
@@ -123,15 +127,18 @@ char *opts;
|
||||
#endif
|
||||
lcurrent = lcurrent->next;
|
||||
list_optarg = lcurrent->word->word;
|
||||
list_optflags = lcurrent->word->flags;
|
||||
lcurrent = lcurrent->next;
|
||||
} else if (*cp == ';') {
|
||||
list_optarg = (char *)NULL;
|
||||
list_optflags = 0;
|
||||
lcurrent = lcurrent->next;
|
||||
} else { /* lcurrent->next == NULL */
|
||||
errstr[1] = c;
|
||||
sh_needarg (errstr);
|
||||
sp = 1;
|
||||
list_optarg = (char *)NULL;
|
||||
list_optflags = 0;
|
||||
return('?');
|
||||
}
|
||||
sp = 1;
|
||||
@@ -140,19 +147,24 @@ char *opts;
|
||||
if (lcurrent->word->word[sp+1]) {
|
||||
if (DIGIT(lcurrent->word->word[sp+1])) {
|
||||
list_optarg = lcurrent->word->word + sp + 1;
|
||||
list_optflags = 0;
|
||||
lcurrent = lcurrent->next;
|
||||
} else
|
||||
} else {
|
||||
list_optarg = (char *)NULL;
|
||||
list_optflags = 0;
|
||||
}
|
||||
} else {
|
||||
if (lcurrent->next && legal_number(lcurrent->next->word->word, (intmax_t *)0)) {
|
||||
lcurrent = lcurrent->next;
|
||||
list_optarg = lcurrent->word->word;
|
||||
list_optflags = lcurrent->word->flags;
|
||||
lcurrent = lcurrent->next;
|
||||
} else {
|
||||
errstr[1] = c;
|
||||
sh_neednumarg (errstr);
|
||||
sp = 1;
|
||||
list_optarg = (char *)NULL;
|
||||
list_optflags = 0;
|
||||
return ('?');
|
||||
}
|
||||
}
|
||||
@@ -164,6 +176,7 @@ char *opts;
|
||||
lcurrent = lcurrent->next;
|
||||
}
|
||||
list_optarg = (char *)NULL;
|
||||
list_optflags = 0;
|
||||
}
|
||||
|
||||
return(c);
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#define GETOPT_HELP -99
|
||||
|
||||
extern char *list_optarg;
|
||||
extern int list_optflags;
|
||||
|
||||
extern int list_optopt;
|
||||
extern int list_opttype;
|
||||
|
||||
@@ -980,6 +980,11 @@ builtin_bind_variable (name, value, flags)
|
||||
SHELL_VAR *v;
|
||||
|
||||
#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. */
|
||||
if (valid_array_reference (name, assoc_expand_once ? (VA_NOEXPAND|VA_ONEWORD) : 0) == 0)
|
||||
v = bind_variable (name, value, flags);
|
||||
else
|
||||
|
||||
+7
-4
@@ -1,7 +1,7 @@
|
||||
This file is printf.def, from which is created printf.c.
|
||||
It implements the builtin "printf" in Bash.
|
||||
|
||||
Copyright (C) 1997-2020 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997-2021 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -267,11 +267,14 @@ printf_builtin (list)
|
||||
case 'v':
|
||||
vname = list_optarg;
|
||||
#if defined (ARRAY_VARS)
|
||||
arrayflags = assoc_expand_once ? (VA_NOEXPAND|VA_ONEWORD) : 0;
|
||||
if (legal_identifier (vname) || valid_array_reference (vname, arrayflags))
|
||||
arrayflags = assoc_expand_once ? VA_NOEXPAND : 0;
|
||||
if (assoc_expand_once && (list_optflags & W_ARRAYREF))
|
||||
arrayflags |= VA_ONEWORD; /* XXX - VA_NOEXPAND? */
|
||||
retval = legal_identifier (vname) || valid_array_reference (vname, arrayflags);
|
||||
#else
|
||||
if (legal_identifier (vname))
|
||||
retval = legal_identifier (vname);
|
||||
#endif
|
||||
if (retval)
|
||||
{
|
||||
vflag = 1;
|
||||
if (vbsize == 0)
|
||||
|
||||
+14
-9
@@ -835,7 +835,7 @@ unset_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int unset_function, unset_variable, unset_array, opt, nameref, any_failed;
|
||||
int global_unset_func, global_unset_var, vflags, valid_id;
|
||||
int global_unset_func, global_unset_var, vflags, base_vflags, valid_id;
|
||||
char *name, *tname;
|
||||
|
||||
unset_function = unset_variable = unset_array = nameref = any_failed = 0;
|
||||
@@ -872,9 +872,7 @@ unset_builtin (list)
|
||||
else if (unset_function && nameref)
|
||||
nameref = 0;
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
vflags = assoc_expand_once ? (VA_NOEXPAND|VA_ONEWORD) : 0;
|
||||
#endif
|
||||
base_vflags = assoc_expand_once ? VA_NOEXPAND : 0;
|
||||
|
||||
while (list)
|
||||
{
|
||||
@@ -889,6 +887,16 @@ unset_builtin (list)
|
||||
unset_function = global_unset_func;
|
||||
unset_variable = global_unset_var;
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
vflags = base_vflags;
|
||||
/* Don't require assoc_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. */
|
||||
if (list->word->flags & W_ARRAYREF)
|
||||
vflags |= VA_ONEWORD|VA_NOEXPAND;
|
||||
#endif
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
unset_array = 0;
|
||||
/* XXX valid array reference second arg was 0 */
|
||||
@@ -959,15 +967,12 @@ unset_builtin (list)
|
||||
#if defined (ARRAY_VARS)
|
||||
if (var && unset_array)
|
||||
{
|
||||
int tvflags;
|
||||
|
||||
tvflags = vflags;
|
||||
#if 0 /* TAG:bash-5.2 */
|
||||
if (shell_compatibility_level <= 51)
|
||||
tvflags |= VA_ALLOWALL;
|
||||
vflags |= VA_ALLOWALL;
|
||||
#endif
|
||||
/* Let unbind_array_element decide what to do with non-array vars */
|
||||
tem = unbind_array_element (var, t, tvflags); /* XXX new third arg */
|
||||
tem = unbind_array_element (var, t, vflags); /* XXX new third arg */
|
||||
if (tem == -2 && array_p (var) == 0 && assoc_p (var) == 0)
|
||||
{
|
||||
builtin_error (_("%s: not an array variable"), var->name);
|
||||
|
||||
+3
-3
@@ -5,12 +5,12 @@
|
||||
.\" Case Western Reserve University
|
||||
.\" chet.ramey@case.edu
|
||||
.\"
|
||||
.\" Last Change: Wed May 5 16:28:46 EDT 2021
|
||||
.\" Last Change: Mon May 10 10:12:31 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 May 5" "GNU Bash 5.1"
|
||||
.TH BASH 1 "2021 May 10" "GNU Bash 5.1"
|
||||
.\"
|
||||
.\" There's some problem with having a `@'
|
||||
.\" in a tagged paragraph with the BSD man macros.
|
||||
@@ -894,7 +894,7 @@ expansion, parameter and variable expansion, arithmetic expansion,
|
||||
command substitution, process substitution and quote removal.
|
||||
Each \fIpattern\fP examined is expanded using tilde
|
||||
expansion, parameter and variable expansion, arithmetic expansion,
|
||||
command substitution, and process substitution.
|
||||
command substitution, process substitution, and quote removal.
|
||||
If the
|
||||
.B nocasematch
|
||||
shell option is enabled, the match is performed without regard to the case
|
||||
|
||||
+4
-3
@@ -1039,9 +1039,10 @@ Each clause must be terminated with @samp{;;}, @samp{;&}, or @samp{;;&}.
|
||||
The @var{word} undergoes tilde expansion, parameter expansion, command
|
||||
substitution, arithmetic expansion, and quote removal
|
||||
(@pxref{Shell Parameter Expansion})
|
||||
before matching is
|
||||
attempted. Each @var{pattern} undergoes tilde expansion, parameter
|
||||
expansion, command substitution, and arithmetic expansion.
|
||||
before matching is attempted.
|
||||
Each @var{pattern} undergoes tilde expansion, parameter expansion,
|
||||
command substitution, arithmetic expansion, process substitution, and
|
||||
quote removal.
|
||||
|
||||
There may be an arbitrary number of @code{case} clauses, each terminated
|
||||
by a @samp{;;}, @samp{;&}, or @samp{;;&}.
|
||||
|
||||
+2
-2
@@ -2,10 +2,10 @@
|
||||
Copyright (C) 1988-2021 Free Software Foundation, Inc.
|
||||
@end ignore
|
||||
|
||||
@set LASTCHANGE Wed May 5 16:29:06 EDT 2021
|
||||
@set LASTCHANGE Mon May 10 10:12:46 EDT 2021
|
||||
|
||||
@set EDITION 5.1
|
||||
@set VERSION 5.1
|
||||
|
||||
@set UPDATED 5 May 2021
|
||||
@set UPDATED 10 May 2021
|
||||
@set UPDATED-MONTH May 2021
|
||||
|
||||
@@ -54,6 +54,7 @@ char *fn;
|
||||
write(2, "\n", 1);
|
||||
return 1;
|
||||
}
|
||||
QUIT;
|
||||
w = write(1, buf, n);
|
||||
if (w != n) {
|
||||
e = errno;
|
||||
@@ -63,6 +64,7 @@ char *fn;
|
||||
write(2, "\n", 1);
|
||||
return 1;
|
||||
}
|
||||
QUIT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -79,6 +81,7 @@ char **argv;
|
||||
return (fcopy(0, "standard input"));
|
||||
|
||||
for (i = r = 1; i < argc; i++) {
|
||||
QUIT;
|
||||
if (argv[i][0] == '-' && argv[i][1] == '\0')
|
||||
fd = 0;
|
||||
else {
|
||||
@@ -97,6 +100,7 @@ char **argv;
|
||||
if (fd != 0)
|
||||
close(fd);
|
||||
}
|
||||
QUIT;
|
||||
return (r);
|
||||
}
|
||||
|
||||
@@ -108,6 +112,7 @@ WORD_LIST *list;
|
||||
int c, r;
|
||||
|
||||
v = make_builtin_argv(list, &c);
|
||||
QUIT;
|
||||
r = cat_main(c, v);
|
||||
free(v);
|
||||
|
||||
|
||||
@@ -415,10 +415,14 @@ cutfile (v, list, ops)
|
||||
#endif
|
||||
|
||||
while ((n = zgetline (fd, &line, &llen, '\n', unbuffered_read)) != -1)
|
||||
{
|
||||
QUIT;
|
||||
cutline (v, line, ops); /* can modify line */
|
||||
}
|
||||
if (fd > 0)
|
||||
close (fd);
|
||||
|
||||
QUIT;
|
||||
if (l)
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
@@ -79,11 +79,13 @@ file_head (fp, cnt)
|
||||
{
|
||||
while ((ch = getc (fp)) != EOF)
|
||||
{
|
||||
QUIT;
|
||||
if (putchar (ch) == EOF)
|
||||
{
|
||||
builtin_error ("write error: %s", strerror (errno));
|
||||
return EXECUTION_FAILURE;
|
||||
}
|
||||
QUIT;
|
||||
if (ch == '\n')
|
||||
break;
|
||||
}
|
||||
@@ -141,6 +143,7 @@ head_builtin (list)
|
||||
printf ("%s==> %s <==\n", opt ? "" : "\n", l->word->word);
|
||||
opt = 0;
|
||||
}
|
||||
QUIT;
|
||||
rval = file_head (fp, nline);
|
||||
fclose (fp);
|
||||
}
|
||||
|
||||
@@ -59,7 +59,8 @@ _remove_directory(const char *dirname)
|
||||
char *fname;
|
||||
int fnsize;
|
||||
#endif
|
||||
|
||||
|
||||
QUIT;
|
||||
if (*dp->d_name == '.' && (dp->d_name[1] == 0 || (dp->d_name[1] == '.' && dp->d_name[2] == 0)))
|
||||
continue;
|
||||
|
||||
@@ -76,6 +77,7 @@ _remove_directory(const char *dirname)
|
||||
#ifndef __GNUC__
|
||||
free (fname);
|
||||
#endif
|
||||
QUIT;
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
@@ -98,6 +100,7 @@ rm_file(const char *fname)
|
||||
if (unlink (fname) == 0)
|
||||
return 0;
|
||||
|
||||
QUIT;
|
||||
/* If FNAME is a directory glibc returns EISDIR but correct POSIX value
|
||||
would be EPERM. If we get that error and FNAME is a directory and -r
|
||||
was supplied, recursively remove the directory and its contents */
|
||||
@@ -155,6 +158,7 @@ rm_builtin (list)
|
||||
|
||||
for (l = list; l; l = l->next)
|
||||
{
|
||||
QUIT;
|
||||
if (rm_file(l->word->word) && force == 0)
|
||||
rval = EXECUTION_FAILURE;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/* See Makefile for compilation details. */
|
||||
|
||||
/*
|
||||
Copyright (C) 1999-2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 1999-2021 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash.
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
@@ -121,6 +121,7 @@ tee_builtin (list)
|
||||
fl = fl->next;
|
||||
fl->next = (FLIST *)NULL;
|
||||
}
|
||||
QUIT;
|
||||
}
|
||||
|
||||
while ((nr = read(0, buf, TEE_BUFSIZE)) > 0)
|
||||
@@ -137,6 +138,7 @@ tee_builtin (list)
|
||||
break;
|
||||
}
|
||||
bp += nw;
|
||||
QUIT;
|
||||
}
|
||||
while (n -= nw);
|
||||
}
|
||||
@@ -156,7 +158,8 @@ tee_builtin (list)
|
||||
tee_flist = tee_flist->next;
|
||||
free (fl);
|
||||
}
|
||||
|
||||
|
||||
QUIT;
|
||||
return (rval);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/* See Makefile for compilation details. */
|
||||
|
||||
/*
|
||||
Copyright (C) 1999-2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 1999-2021 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash.
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
@@ -55,6 +55,7 @@ tty_builtin (list)
|
||||
list = loptend;
|
||||
|
||||
t = ttyname (0);
|
||||
QUIT;
|
||||
if (sflag == 0)
|
||||
puts (t ? t : "not a tty");
|
||||
return (t ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
|
||||
|
||||
@@ -330,6 +330,7 @@ expr_bind_variable (lhs, rhs)
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
aflags = (assoc_expand_once && already_expanded) ? ASS_NOEXPAND : 0;
|
||||
aflags |= ASS_ALLOWALLSUB; /* allow assoc[@]=value */
|
||||
#else
|
||||
aflags = 0;
|
||||
#endif
|
||||
|
||||
Binary file not shown.
+6
-11
@@ -5,13 +5,13 @@
|
||||
# Zi-You Dai <ioppooster@gmail.com>, 2008.
|
||||
# Mingye Wang (Arthur2e5) <arthur200126@hotmail.com>, 2015.
|
||||
# Wei-Lun Chao <bluebat@member.fsf.org>, 2015.
|
||||
# Yi-Jyun Pan <pan93412@gmail.com>, 2018, 2019, 2020.
|
||||
# Yi-Jyun Pan <pan93412@gmail.com>, 2018, 2019, 2020, 2021.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: bash 5.1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-11-28 12:51-0500\n"
|
||||
"PO-Revision-Date: 2020-12-08 06:39+0800\n"
|
||||
"PO-Revision-Date: 2021-05-09 20:48+0800\n"
|
||||
"Last-Translator: Yi-Jyun Pan <pan93412@gmail.com>\n"
|
||||
"Language-Team: Chinese (traditional) <zh-l10n@lists.linux.org.tw>\n"
|
||||
"Language: zh_TW\n"
|
||||
@@ -20,7 +20,7 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Bugs: Report translation errors to the Language-Team address.\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Poedit 2.4.2\n"
|
||||
"X-Generator: Poedit 2.4.3\n"
|
||||
|
||||
#: arrayfunc.c:66
|
||||
msgid "bad array subscript"
|
||||
@@ -144,7 +144,6 @@ msgid "only meaningful in a `for', `while', or `until' loop"
|
||||
msgstr "僅在「for」,「while」, 或者「until」迴圈中有意義"
|
||||
|
||||
#: builtins/caller.def:136
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Returns the context of the current subroutine call.\n"
|
||||
" \n"
|
||||
@@ -158,15 +157,11 @@ msgstr ""
|
||||
"回傳目前子呼叫的語境。\n"
|
||||
" \n"
|
||||
" 不帶有 EXPR 時,回傳「$line $filename」。帶有 EXPR 時,回傳\n"
|
||||
" 「$line $subroutine $filename」;這個額外的資訊可以被用於提供\n"
|
||||
" 堆疊追蹤。\n"
|
||||
" 「$line $subroutine $filename」;提供堆疊追蹤時可以用到這個\n"
|
||||
" 延伸資訊。\n"
|
||||
" \n"
|
||||
" EXPR 的值顯示了到目前呼叫框格需要回去多少個呼叫框格;頂部框格\n"
|
||||
" 是第 0 框格。\n"
|
||||
" \n"
|
||||
" 結束狀態:\n"
|
||||
" 除非 shell 不在執行一個 shell 函數或者 EXPR 無效,否則回傳結\n"
|
||||
" 果為 0。"
|
||||
" 是第 0 框格。"
|
||||
|
||||
#: builtins/cd.def:327
|
||||
msgid "HOME not set"
|
||||
|
||||
@@ -3696,6 +3696,13 @@ cond_expand_word (w, special)
|
||||
dequote_list (l);
|
||||
r = string_list (l);
|
||||
}
|
||||
else if (special == 3) /* arithmetic expression, Q_ARITH */
|
||||
{
|
||||
if (l->word)
|
||||
word_list_remove_quoted_nulls (l); /* for now */
|
||||
dequote_list (l);
|
||||
r = string_list (l);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Need to figure out whether or not we should call dequote_escapes
|
||||
@@ -10192,6 +10199,7 @@ expand_array_subscript (string, sindex, quoted, flags)
|
||||
abstab[LBRACK] = abstab[RBRACK] = 1;
|
||||
abstab['$'] = abstab['`'] = abstab['~'] = 1;
|
||||
abstab['\\'] = abstab['\''] = 1;
|
||||
/* We don't quote `@' or `*' in the subscript at all. */
|
||||
}
|
||||
|
||||
/* string[si] == LBRACK */
|
||||
@@ -10215,11 +10223,6 @@ itrace("expand_array_subscript: bad subscript string: `%s'", string+si);
|
||||
exp = substring (string, si+1, ni);
|
||||
t = expand_subscript_string (exp, quoted & ~(Q_ARITH|Q_DOUBLE_QUOTES));
|
||||
free (exp);
|
||||
/* Only quote `@' and `*' if they are the only character in the subscript */
|
||||
if (ALL_ELEMENT_SUB (t[0]) && t[1] == '\0')
|
||||
abstab['*'] = abstab['@'] = 1;
|
||||
else
|
||||
abstab['*'] = abstab['@'] = 0;
|
||||
exp = sh_backslash_quote (t, abstab, 0);
|
||||
free (t);
|
||||
|
||||
|
||||
@@ -632,16 +632,22 @@ unary_test (op, arg, flags)
|
||||
|
||||
case 'v':
|
||||
#if defined (ARRAY_VARS)
|
||||
if (valid_array_reference (arg, 0))
|
||||
if (valid_array_reference (arg, assoc_expand_once ? VA_NOEXPAND : 0))
|
||||
{
|
||||
char *t;
|
||||
int rtype, ret, flags;
|
||||
int rtype, ret, aflags;
|
||||
|
||||
/* 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);
|
||||
|
||||
aflags = assoc_expand_once ? AV_NOEXPAND : 0;
|
||||
#if 0
|
||||
/* TAG:bash-5.2 */
|
||||
if (shell_compatibility_level > 51)
|
||||
#endif
|
||||
aflags |= AV_ATSTARKEYS;
|
||||
t = array_value (arg, 0, aflags, &rtype, (arrayind_t *)0);
|
||||
ret = t ? TRUE : FALSE;
|
||||
if (rtype > 0) /* subscript is * or @ */
|
||||
free (t);
|
||||
|
||||
+1
-1
@@ -747,7 +747,7 @@ 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" )
|
||||
./array27.sub: line 60: A[]]: bad array subscript
|
||||
./array27.sub: line 60: printf: `A[]]': not a valid identifier
|
||||
declare -A A=([$'\t']="X" ["*"]="X" [" "]="X" ["@"]="X" )
|
||||
./array27.sub: line 68: declare: `A[]]=X': not a valid identifier
|
||||
declare -A A=(["*"]="X" ["@"]="X" )
|
||||
|
||||
+1
-5
@@ -199,11 +199,7 @@ declare -A hash=([key]="value1 value2" )
|
||||
declare -A b=([")"]="" ["\""]="" ["]"]="" ["\\"]="" ["\`"]="" )
|
||||
declare -A b=(["]"]="" ["\`"]="" )
|
||||
declare -A dict=(["'"]="3" ["\""]="1" ["\\"]="4" ["\`"]="2" )
|
||||
./assoc9.sub: line 36: unset: `dict[']': not a valid identifier
|
||||
./assoc9.sub: line 36: unset: `dict["]': not a valid identifier
|
||||
./assoc9.sub: line 36: unset: `dict[\]': not a valid identifier
|
||||
./assoc9.sub: line 36: unset: `dict[`]': not a valid identifier
|
||||
declare -A dict=(["'"]="3" ["\""]="1" ["\\"]="4" ["\`"]="2" )
|
||||
declare -A dict=()
|
||||
declare -A dict=(["'"]="3" ["\""]="1" ["\\"]="4" ["\`"]="2" )
|
||||
declare -A dict=()
|
||||
4
|
||||
|
||||
@@ -179,10 +179,16 @@ unset2
|
||||
1
|
||||
1
|
||||
1
|
||||
0
|
||||
0
|
||||
assoc A unset
|
||||
array a
|
||||
assoc A
|
||||
array a
|
||||
assoc B unset
|
||||
array b unset
|
||||
assoc B unset
|
||||
array b unset
|
||||
scalar 1
|
||||
scalar 2
|
||||
scalar 3 unset
|
||||
|
||||
+10
-1
@@ -36,15 +36,25 @@ echo ${#a[@]}
|
||||
typeset -A B
|
||||
typeset -a b
|
||||
|
||||
echo ${#B[@]}
|
||||
echo ${#b[@]}
|
||||
|
||||
scalar1=foo
|
||||
scalar2=
|
||||
|
||||
# this now checks for A[@] treating @ as a valid key - post-bash-5.1
|
||||
if [ -v A[@] ]; then echo assoc A; else echo assoc A unset; fi
|
||||
if [ -v a[@] ]; then echo array a; else echo array a unset; fi
|
||||
|
||||
if [ ${#A[@]} -gt 0 ]; then echo assoc A; else echo assoc A unset; fi
|
||||
if [ ${#a[@]} -gt 0 ]; then echo array a; else echo array a unset; fi
|
||||
|
||||
if [ -v B[@] ]; then echo assoc B; else echo assoc B unset; fi
|
||||
if [ -v b[@] ]; then echo array b; else echo array b unset; fi
|
||||
|
||||
if [ ${#B[@]} -gt 0 ]; then echo assoc B; else echo assoc B unset; fi
|
||||
if [ ${#b[@]} -gt 0 ]; then echo array b; else echo array b unset; fi
|
||||
|
||||
if [ -v scalar1[@] ]; then echo scalar 1; else echo scalar 1 unset; fi
|
||||
if [ -v scalar2[@] ]; then echo scalar 2; else echo scalar 2 unset; fi
|
||||
if [ -v scalar3[@] ]; then echo scalar 3; else echo scalar 3 unset; fi
|
||||
@@ -71,4 +81,3 @@ echo scalar: ${#scalar3}
|
||||
echo scalar: ${#scalar3[@]}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ returns: 0
|
||||
returns: 1
|
||||
returns: 0
|
||||
returns: 0
|
||||
returns: 0
|
||||
returns: 0
|
||||
returns: 1
|
||||
returns: 0
|
||||
returns: 0
|
||||
|
||||
@@ -122,6 +122,13 @@ A=7
|
||||
[[ $IVAR -eq A ]]
|
||||
echo returns: $?
|
||||
|
||||
[[ "$IVAR" -eq "7" ]]
|
||||
echo returns: $?
|
||||
|
||||
A=7
|
||||
[[ "$IVAR" -eq "A" ]]
|
||||
echo returns: $?
|
||||
|
||||
unset IVAR A
|
||||
|
||||
# more pattern matching tests
|
||||
|
||||
+38
-1
@@ -44,7 +44,7 @@ declare -A assoc=(["\` echo >&2 foo\`"]="128" [0]="0" ["]"]="12" ["x],b[\$(echo
|
||||
foo
|
||||
0
|
||||
0
|
||||
./quotearray1.sub: line 67: 0\],b\[1: syntax error: invalid arithmetic operator (error token is "\],b\[1")
|
||||
./quotearray1.sub: line 68: 0\],b\[1: syntax error: invalid arithmetic operator (error token is "\],b\[1")
|
||||
declare -a array
|
||||
0
|
||||
0
|
||||
@@ -56,6 +56,9 @@ declare -A aa=(["\$( echo 2>& date)"]="foo" )
|
||||
foo
|
||||
0
|
||||
1
|
||||
1
|
||||
./quotearray1.sub: line 111: test: aa[$(echo: binary operator expected
|
||||
2
|
||||
declare -A a=([1]="1" [0]="0" [" "]="11" )
|
||||
7
|
||||
7
|
||||
@@ -71,6 +74,8 @@ declare -A A=(["*"]="X" ["@"]="X" )
|
||||
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=(["\$(echo foo)"]="1" )
|
||||
0
|
||||
declare -A assoc=(["\$var"]="value" )
|
||||
declare -A assoc=(["\$var"]="value" )
|
||||
declare -A assoc=(["\$var"]="value" )
|
||||
@@ -80,5 +85,37 @@ declare -A a=(["\$(echo foo)"]="1" )
|
||||
declare -A a=()
|
||||
declare -A a=(["\$(echo foo)"]="1" )
|
||||
declare -A assoc=(["!"]="bang" )
|
||||
1
|
||||
1
|
||||
declare -A assoc=(["!"]="bang" ["@"]="at" )
|
||||
declare -A assoc=(["!"]="bang" )
|
||||
declare -a array=([0]="1" [1]="2" [2]="3")
|
||||
./quotearray3.sub: line 93: declare: array: not found
|
||||
./quotearray3.sub: line 97: declare: array: not found
|
||||
declare -A assoc=(["*"]="star" ["!"]="bang" ["@"]="at" )
|
||||
declare -A assoc=(["*"]="star" ["!"]="bang" )
|
||||
declare -A assoc=(["!"]="bang" )
|
||||
./quotearray4.sub: line 41: declare: assoc: not found
|
||||
declare -A assoc=(["*"]="star" ["!"]="bang" ["@"]="at" )
|
||||
declare -A assoc=(["*"]="star" ["!"]="bang" )
|
||||
declare -A assoc=(["!"]="bang" )
|
||||
declare -A assoc=(["*"]="star" ["!"]="bang" )
|
||||
declare -A assoc=(["!"]="bang" )
|
||||
star bang at
|
||||
star bang at
|
||||
0
|
||||
0
|
||||
0
|
||||
1
|
||||
1
|
||||
declare -A assoc=(["*"]="star" ["!"]="bang" ["@"]=" key" )
|
||||
===
|
||||
1
|
||||
1
|
||||
declare -a array=([0]="1" [1]="2" [2]="3")
|
||||
1 2 3
|
||||
1 2 3
|
||||
0
|
||||
0
|
||||
./quotearray4.sub: line 115: array[@]: bad array subscript
|
||||
declare -a array=([0]="1" [1]="2" [2]="3")
|
||||
|
||||
@@ -155,3 +155,6 @@ echo $?
|
||||
${THIS_SH} ./quotearray1.sub
|
||||
${THIS_SH} ./quotearray2.sub
|
||||
${THIS_SH} ./quotearray3.sub
|
||||
|
||||
# behavior of builtins with array subscripts @ and *
|
||||
${THIS_SH} ./quotearray4.sub
|
||||
|
||||
@@ -23,6 +23,7 @@ key2='` echo >&2 foo`'
|
||||
key3='~'
|
||||
key4='7<(4+2)'
|
||||
key5='$( echo 2>& date)'
|
||||
key6='$(echo foo)'
|
||||
|
||||
[[ -n assoc[$key] ]]
|
||||
declare -p assoc
|
||||
@@ -102,4 +103,12 @@ echo $?
|
||||
[[ -v aa[$key] ]]
|
||||
echo $?
|
||||
|
||||
aa[$key6]=42
|
||||
# this still performs expansion
|
||||
test -v aa["$key6"]
|
||||
echo $?
|
||||
# should be an error
|
||||
test -v aa[$key6]
|
||||
echo $?
|
||||
|
||||
unset aa key
|
||||
|
||||
@@ -90,3 +90,14 @@ let assoc[$key]++
|
||||
declare -p assoc
|
||||
|
||||
unset assoc
|
||||
|
||||
typeset -A assoc
|
||||
at=@
|
||||
|
||||
key='$(echo foo)'
|
||||
|
||||
assoc[$key]=1
|
||||
declare -p assoc
|
||||
|
||||
shopt -s assoc_expand_once
|
||||
test -v assoc["$key"] ; echo $?
|
||||
|
||||
+23
-2
@@ -66,11 +66,32 @@ assoc[!]=bang
|
||||
unset -v assoc[$key]
|
||||
typeset -p assoc
|
||||
|
||||
# this doesn't work yet
|
||||
# this should check for assoc[@] and return 1
|
||||
test -v assoc[$key]
|
||||
echo $?
|
||||
|
||||
# this should too
|
||||
[[ -v assoc[$key] ]]
|
||||
echo $?
|
||||
|
||||
unset assoc
|
||||
unset assoc array
|
||||
|
||||
declare -A assoc
|
||||
declare -a array
|
||||
|
||||
assoc=([@]=at [!]=bang)
|
||||
declare -p assoc
|
||||
|
||||
unset assoc[@]
|
||||
declare -p assoc
|
||||
|
||||
array=(1 2 3)
|
||||
declare -p array
|
||||
|
||||
# right now, this still unsets the entire array
|
||||
unset array[@]
|
||||
declare -p array
|
||||
|
||||
BASH_COMPAT=51
|
||||
unset array[@]
|
||||
declare -p array
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
# tests for builtins handling associative array keys `*' and `@', with some
|
||||
# indexed array tests as well (backwards compatible)
|
||||
|
||||
# derived from test cases posted to bug-bash by myoga.murase@gmail.com
|
||||
|
||||
declare -A assoc
|
||||
declare -a array
|
||||
|
||||
assoc[@]=at
|
||||
assoc[*]=star
|
||||
assoc[!]=bang
|
||||
|
||||
key=@
|
||||
|
||||
iref='array[@]'
|
||||
aref='assoc[@]'
|
||||
|
||||
declare -p assoc
|
||||
|
||||
unset assoc[@]
|
||||
declare -p assoc
|
||||
|
||||
unset assoc[*]
|
||||
declare -p assoc
|
||||
|
||||
unset assoc
|
||||
declare -p assoc
|
||||
|
||||
declare -A assoc
|
||||
assoc[@]=at
|
||||
assoc[*]=star
|
||||
assoc[!]=bang
|
||||
|
||||
declare -p assoc
|
||||
|
||||
unset assoc["$key"]
|
||||
declare -p assoc
|
||||
|
||||
unset assoc["*"]
|
||||
declare -p assoc
|
||||
|
||||
assoc[@]=at assoc[*]=star
|
||||
|
||||
unset assoc['@']
|
||||
declare -p assoc
|
||||
|
||||
unset assoc['*']
|
||||
|
||||
declare -p assoc
|
||||
|
||||
assoc[@]=at assoc[*]=star
|
||||
echo ${!aref}
|
||||
|
||||
declare -n nref=$aref
|
||||
echo ${nref}
|
||||
unset -n nref
|
||||
|
||||
# for associative arrays, test -v treats @ and * as keys
|
||||
|
||||
test -v 'assoc[@]'
|
||||
echo $?
|
||||
test -v assoc[$key]
|
||||
echo $?
|
||||
[[ -v assoc[$key] ]]
|
||||
echo $?
|
||||
|
||||
unset -v 'assoc[@]'
|
||||
|
||||
test -v 'assoc[@]'
|
||||
echo $?
|
||||
[[ -v assoc[@] ]]
|
||||
echo $?
|
||||
|
||||
assoc[@]=at
|
||||
|
||||
printf -v assoc[@] "%10s" key
|
||||
declare -p assoc
|
||||
|
||||
echo ===
|
||||
array=()
|
||||
test -v array[@]
|
||||
echo $?
|
||||
[[ -v array[@] ]]
|
||||
echo $?
|
||||
|
||||
array=(1 2 3)
|
||||
declare -p array
|
||||
|
||||
echo ${!iref}
|
||||
declare -n nref=$iref
|
||||
|
||||
echo $nref
|
||||
unset -n nref
|
||||
|
||||
# but for indexed arrays, test -v treats @ and * as standing for the entire array
|
||||
test -v 'array[@]'
|
||||
echo $?
|
||||
[[ -v array[@] ]]
|
||||
echo $?
|
||||
|
||||
printf -v array[@] "%-10s" key
|
||||
declare -p array
|
||||
Reference in New Issue
Block a user