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:
Chet Ramey
2024-03-25 10:32:07 -04:00
parent b1e7f68032
commit 8af5a8e0ca
6 changed files with 101 additions and 32 deletions
+30 -3
View File
@@ -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
View File
@@ -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;
+14 -3
View File
@@ -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);
+29 -20
View File
@@ -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)
{
+9
View File
@@ -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
+11
View File
@@ -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