mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-29 00:19:51 +02:00
change to test builtin for parenthesized expressions when there are more than four arguments to test; tentative change to @A transformation to output declare commands for local variables
This commit is contained in:
+30
-3
@@ -8830,14 +8830,14 @@ builtins/printf.def
|
||||
overflow, since we don't call printf
|
||||
- printstr,printwidestr: set field width and precision on integer
|
||||
overflow the way we do in printf_builtin
|
||||
From a report by Paul Eggert <eggert@cs.ucla.edu>
|
||||
From a report and patch by Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
bashtypes.h
|
||||
- PRIdMAX: move redefinition here after including inttypes.h
|
||||
|
||||
builtins/printf.def,examples/loadables/seq.c,examples/loadables/getconf.h
|
||||
- remove PRIdMAX redefinitions, since it's now fixed in bashtypes.h
|
||||
From a report by Paul Eggert <eggert@cs.ucla.edu>
|
||||
From a report and patch by Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
3/15
|
||||
----
|
||||
@@ -8895,4 +8895,31 @@ braces.c
|
||||
sprintf family has trouble when width > INT_MAX
|
||||
- expand_seqterm: use size_t instead of int for length and width
|
||||
variables
|
||||
From a report by Paul Eggert <eggert@cs.ucla.edu>
|
||||
From a report and patch by Paul Eggert <eggert@cs.ucla.edu>
|
||||
|
||||
3/18
|
||||
----
|
||||
builtins/printf.def
|
||||
- printstr,bexpand: changed size/length arguments to be size_t; changed
|
||||
callers
|
||||
|
||||
subst.c
|
||||
- string_var_assignment: if the variable is a local variable at the
|
||||
current scope, output a declare command even if there are no
|
||||
attributes or value. Still tagged as tentative
|
||||
|
||||
3/23
|
||||
----
|
||||
test.c
|
||||
- posixtest: takes an argument, the number of test arguments to parse
|
||||
- two_arguments,three_arguments: use advance() instead of accessing
|
||||
and manipulating pos directly
|
||||
- posixtest,three_arguments,two_arguments: don't set pos = argc
|
||||
directly, rely on functions to advance pos appropriately
|
||||
Picked up from coreutils test
|
||||
- term: if we see a left paren, scan forward for a closing right paren
|
||||
and use posixtest() if there are 1-4 arguments between the parens to
|
||||
avoid ambiguous behavior for expressions like true -a \( ! -a \),
|
||||
which a user would expect to return false instead of an error
|
||||
message
|
||||
Picked up from coreutils test
|
||||
|
||||
+8
-6
@@ -193,9 +193,9 @@ extern int vsnprintf (char *, size_t, const char *, va_list) __attribute__((__fo
|
||||
|
||||
static inline void printf_erange (char *);
|
||||
static inline void report_erange (char *, char *);
|
||||
static int printstr (char *, char *, int, int, int);
|
||||
static int printstr (char *, char *, size_t, int, int);
|
||||
static int tescape (char *, char *, int *, int *);
|
||||
static char *bexpand (char *, int, int *, int *);
|
||||
static char *bexpand (char *, size_t, int *, size_t *);
|
||||
static char *vbadd (char *, int);
|
||||
static int vbprintf (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
|
||||
static char *mklong (char *, char *, size_t);
|
||||
@@ -552,10 +552,12 @@ printf_builtin (WORD_LIST *list)
|
||||
case 'b': /* expand escapes in argument */
|
||||
{
|
||||
char *p, *xp;
|
||||
int rlen, r;
|
||||
size_t rlen;
|
||||
int r;
|
||||
|
||||
p = getstr ();
|
||||
ch = rlen = r = 0;
|
||||
ch = r = 0;
|
||||
rlen = 0;
|
||||
xp = bexpand (p, strlen (p), &ch, &rlen);
|
||||
|
||||
if (xp)
|
||||
@@ -846,7 +848,7 @@ report_erange (char *s, char *e)
|
||||
Returns -1 on detectable write error, 0 otherwise. */
|
||||
|
||||
static int
|
||||
printstr (char *fmt, char *string, int len, int fieldwidth, int precision)
|
||||
printstr (char *fmt, char *string, size_t len, int fieldwidth, int precision)
|
||||
{
|
||||
#if 0
|
||||
char *s;
|
||||
@@ -1161,7 +1163,7 @@ tescape (char *estart, char *cp, int *lenp, int *sawc)
|
||||
}
|
||||
|
||||
static char *
|
||||
bexpand (char *string, int len, int *sawc, int *lenp)
|
||||
bexpand (char *string, size_t len, int *sawc, size_t *lenp)
|
||||
{
|
||||
int temp, c;
|
||||
char *ret, *r, *s, *send;
|
||||
|
||||
@@ -8639,15 +8639,26 @@ string_var_assignment (SHELL_VAR *v, char *s)
|
||||
|
||||
val = (v && (invisible_p (v) || var_isset (v) == 0)) ? (char *)NULL : sh_quote_reusable (s, 0);
|
||||
i = var_attribute_string (v, 0, flags);
|
||||
#if 0 /*TAG: notyet */
|
||||
if (v && local_p (v) == 0 && variable_context > 0)
|
||||
flags[i++] = 'g';
|
||||
#endif
|
||||
/* i = strlen (flags) */
|
||||
if (i == 0 && val == 0)
|
||||
if (i == 0 && val == 0 && (local_p (v) == 0 || v->context != variable_context))
|
||||
return (char *)NULL;
|
||||
|
||||
ret = (char *)xmalloc (i + STRLEN (val) + strlen (v->name) + 16 + MAX_ATTRIBUTES);
|
||||
|
||||
if (i > 0 && val == 0)
|
||||
sprintf (ret, "declare -%s %s", flags, v->name);
|
||||
sprintf (ret, "declare -%s %s", flags, v->name); /* just attributes, unset */
|
||||
else if (i > 0)
|
||||
sprintf (ret, "declare -%s %s=%s", flags, v->name, val);
|
||||
sprintf (ret, "declare -%s %s=%s", flags, v->name, val); /* attributes, set */
|
||||
#if 1 /*TAG: tentative */
|
||||
else if (i == 0 && val && local_p (v) && variable_context == v->context)
|
||||
sprintf (ret, "declare %s=%s", v->name, val); /* set local variable at current scope */
|
||||
else if (i == 0 && val == 0 && local_p (v) && variable_context == v->context)
|
||||
sprintf (ret, "declare %s", v->name); /* unset local variable at current scope, unset */
|
||||
#endif
|
||||
else
|
||||
sprintf (ret, "%s=%s", v->name, val);
|
||||
free (val);
|
||||
|
||||
@@ -74,6 +74,9 @@ extern int errno;
|
||||
#define ISPRIMARY(s, c) (s[0] == '-' && s[1] == c && s[2] == '\0')
|
||||
#define ANDOR(s) (s[0] == '-' && (s[1] == 'a' || s[1] == 'o') && s[2] == 0)
|
||||
|
||||
/* single-character tokens like `!', `(', and `)' */
|
||||
#define ISTOKEN(s, c) (s[0] == (c) && s[1] == '\0')
|
||||
|
||||
#if !defined (R_OK)
|
||||
#define R_OK 4
|
||||
#define W_OK 2
|
||||
@@ -125,7 +128,7 @@ static int unary_operator (void);
|
||||
static int binary_operator (void);
|
||||
static int two_arguments (void);
|
||||
static int three_arguments (void);
|
||||
static int posixtest (void);
|
||||
static int posixtest (int);
|
||||
|
||||
static int expr (void);
|
||||
static int term (void);
|
||||
@@ -264,8 +267,16 @@ term (void)
|
||||
/* A paren-bracketed argument. */
|
||||
if (argv[pos][0] == '(' && argv[pos][1] == '\0') /* ) */
|
||||
{
|
||||
int nargs;
|
||||
|
||||
advance (1);
|
||||
value = expr ();
|
||||
/* Steal an idea from coreutils and scan forward to check where the right
|
||||
paren appears to prevent some ambiguity. If we find a valid sub-
|
||||
expression that has 1-4 arguments, call posixtest on it ( */
|
||||
for (nargs = 1; pos + nargs < argc && ISTOKEN (argv[pos+nargs], ')') == 0; nargs++)
|
||||
;
|
||||
/* only do this if we have a valid parenthesized expression */
|
||||
value = (pos + nargs < argc && nargs <= 4) ? posixtest (nargs) : expr ();
|
||||
if (argv[pos] == 0) /* ( */
|
||||
test_syntax_error (_("`)' expected"), (char *)NULL);
|
||||
else if (argv[pos][0] != ')' || argv[pos][1]) /* ( */
|
||||
@@ -758,7 +769,10 @@ static int
|
||||
two_arguments (void)
|
||||
{
|
||||
if (argv[pos][0] == '!' && argv[pos][1] == '\0')
|
||||
return (argv[pos + 1][0] == '\0');
|
||||
{
|
||||
advance (0);
|
||||
return (argv[pos++][0] == '\0');
|
||||
}
|
||||
else if (argv[pos][0] == '-' && argv[pos][1] && argv[pos][2] == '\0')
|
||||
{
|
||||
if (test_unop (argv[pos]))
|
||||
@@ -782,28 +796,25 @@ three_arguments (void)
|
||||
int value;
|
||||
|
||||
if (test_binop (argv[pos+1]))
|
||||
{
|
||||
value = binary_operator ();
|
||||
pos = argc;
|
||||
}
|
||||
value = binary_operator ();
|
||||
else if (ANDOR (argv[pos+1]))
|
||||
{
|
||||
if (argv[pos+1][1] == 'a')
|
||||
value = ONE_ARG_TEST(argv[pos]) && ONE_ARG_TEST(argv[pos+2]);
|
||||
else
|
||||
value = ONE_ARG_TEST(argv[pos]) || ONE_ARG_TEST(argv[pos+2]);
|
||||
pos = argc;
|
||||
pos += 3;
|
||||
}
|
||||
else if (argv[pos][0] == '!' && argv[pos][1] == '\0')
|
||||
{
|
||||
advance (1);
|
||||
value = !two_arguments ();
|
||||
pos = argc;
|
||||
}
|
||||
else if (argv[pos][0] == '(' && argv[pos+2][0] == ')')
|
||||
else if (ISTOKEN (argv[pos], '(') && ISTOKEN (argv[pos+2], ')'))
|
||||
{
|
||||
value = ONE_ARG_TEST(argv[pos+1]);
|
||||
pos = argc;
|
||||
advance (0);
|
||||
value = ONE_ARG_TEST(argv[pos]);
|
||||
pos += 2;
|
||||
}
|
||||
else
|
||||
test_syntax_error (_("%s: binary operator expected"), argv[pos+1]);
|
||||
@@ -813,25 +824,23 @@ three_arguments (void)
|
||||
|
||||
/* This is an implementation of a Posix.2 proposal by David Korn. */
|
||||
static int
|
||||
posixtest (void)
|
||||
posixtest (int nargs)
|
||||
{
|
||||
int value;
|
||||
|
||||
switch (argc - 1) /* one extra passed in */
|
||||
switch (nargs)
|
||||
{
|
||||
case 0:
|
||||
value = FALSE;
|
||||
pos = argc;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
value = ONE_ARG_TEST(argv[1]);
|
||||
pos = argc;
|
||||
advance (0);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
value = two_arguments ();
|
||||
pos = argc;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
@@ -845,11 +854,11 @@ posixtest (void)
|
||||
value = !three_arguments ();
|
||||
break;
|
||||
}
|
||||
else if (argv[pos][0] == '(' && argv[pos][1] == '\0' && argv[argc-1][0] == ')' && argv[argc-1][1] == '\0')
|
||||
else if (ISTOKEN (argv[pos], '(') && ISTOKEN (argv[pos+3], ')'))
|
||||
{
|
||||
advance (1);
|
||||
value = two_arguments ();
|
||||
pos = argc;
|
||||
advance (0);
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
@@ -916,7 +925,7 @@ test_command (int margc, char **margv)
|
||||
test_exit (SHELL_BOOLEAN (FALSE));
|
||||
|
||||
noeval = 0;
|
||||
value = posixtest ();
|
||||
value = posixtest (argc - 1);
|
||||
|
||||
if (pos != argc)
|
||||
{
|
||||
|
||||
@@ -323,6 +323,15 @@ t -t /dev/tty4444444...
|
||||
2
|
||||
./test.tests: line 26: test: : integer expected
|
||||
2
|
||||
1
|
||||
0
|
||||
0
|
||||
./test.tests: line 26: test: `)' expected
|
||||
2
|
||||
./test.tests: line 26: test: (: unary operator expected
|
||||
2
|
||||
./test.tests: line 26: test: `)' expected
|
||||
2
|
||||
t -p /dev/fd/6
|
||||
1
|
||||
t -p /dev/fd/6
|
||||
|
||||
@@ -494,4 +494,15 @@ t -t /dev/tty4444444...
|
||||
# fixed in bash-4.0-beta
|
||||
t -t ' '
|
||||
|
||||
# ambiguous parenthesized test expressions with more than 4 arguments
|
||||
|
||||
t true -a \( ! -a \)
|
||||
t true -a \( -n foo \)
|
||||
t true -a \( foo \)
|
||||
|
||||
t 1 = 1 -a \( \)
|
||||
t \( \)
|
||||
|
||||
t 1 = 1 -a \( \) -a -n ""
|
||||
|
||||
${THIS_SH} ./test1.sub
|
||||
|
||||
Reference in New Issue
Block a user