summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>2003-07-26 12:22:42 +0000
committerJim Meyering <jim@meyering.net>2003-07-26 12:22:42 +0000
commit9fed987cf27c75e141a9fe3dac1ca4923ea48b6d (patch)
tree90d7fd543c5184ba4b8123b8606d551e7a051093
parent8f808b6208355800946b369a6c2f7f974737ad80 (diff)
downloadcoreutils-9fed987cf27c75e141a9fe3dac1ca4923ea48b6d.tar.xz
Include exitfail.h.
(TEST_FAILURE): New constant, used for exit status if 'test' fails. (test-syntax_error): Use it. (binary_operator): Now takes bool arg specifying whether left operand is -l ARG, so that caller determines this rather than us. All uses changed. (term): Use posixtest to evaluate parenthesized subexpressions. (unary_operator, one_argument): Remove support for -t without operand. (one_argument): Take argument from argv[pos]. (one_argument, two_arguments, three_arguments): Advance pos. All callers changed. (three_arguments): Look for binary ops before "!". Then look for parenthesized one_argument expressions, instead of trusting expr () to do the right thing. (posixtest): Now takes number of args. All callers changed. Treat "( A B )" like "A B". (main): Set exit_failure to TEST_FAILURE. Don't depend on POSIXLY_CORRECT, as we now conform to POSIX by default. (main) [!LBRACKET]: Do not recognize "--help" or "--verbose" unless.
-rw-r--r--src/test.c163
1 files changed, 83 insertions, 80 deletions
diff --git a/src/test.c b/src/test.c
index 95cff6ebf..fa00a396b 100644
--- a/src/test.c
+++ b/src/test.c
@@ -27,17 +27,22 @@
#include <stdio.h>
#include <sys/types.h>
-/* The official name of this program (e.g., no `g' prefix). */
-#define PROGRAM_NAME "test"
-
#define TEST_STANDALONE 1
#ifndef LBRACKET
# define LBRACKET 0
#endif
+/* The official name of this program (e.g., no `g' prefix). */
+#if LBRACKET
+# define PROGRAM_NAME "["
+#else
+# define PROGRAM_NAME "test"
+#endif
+
#include "system.h"
#include "error.h"
+#include "exitfail.h"
#include "euidaccess.h"
#ifndef _POSIX_VERSION
@@ -63,9 +68,6 @@ extern uid_t geteuid ();
# define F_OK 0
#endif /* R_OK */
-/* This name is used solely when printing --version information. */
-#define PROGRAM_NAME "test"
-
/* The following few defines control the truth and false output of each stage.
TRUE and FALSE are what we use to compute the final output value.
SHELL_BOOLEAN is the form which returns truth or falseness in shell terms.
@@ -79,6 +81,9 @@ extern uid_t geteuid ();
#define TRUTH_OR(a, b) ((a) | (b))
#define TRUTH_AND(a, b) ((a) & (b))
+/* Exit status for syntax errors, etc. */
+enum { TEST_FAILURE = 2 };
+
#if defined (TEST_STANDALONE)
# define test_exit(val) exit (val)
#else
@@ -94,10 +99,10 @@ static char **argv; /* The argument list. */
static int test_unop (char const *s);
static int binop (char *s);
static int unary_operator (void);
-static int binary_operator (void);
+static int binary_operator (bool);
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);
@@ -114,7 +119,7 @@ test_syntax_error (char const *format, char const *arg)
fprintf (stderr, "%s: ", argv[0]);
fprintf (stderr, format, arg);
fflush (stderr);
- test_exit (SHELL_BOOLEAN (FALSE));
+ test_exit (TEST_FAILURE);
}
#if HAVE_SETREUID && HAVE_SETREGID
@@ -318,8 +323,20 @@ term (void)
/* A paren-bracketed argument. */
if (argv[pos][0] == '(' && argv[pos][1] == '\0')
{
+ int nargs;
+
advance (1);
- value = expr ();
+
+ for (nargs = 1;
+ pos + nargs < argc && ! STREQ (argv[pos + nargs], ")");
+ nargs++)
+ if (nargs == 4)
+ {
+ nargs = argc - pos;
+ break;
+ }
+
+ value = posixtest (nargs);
if (argv[pos] == 0)
test_syntax_error (_("')' expected\n"), NULL);
else
@@ -330,9 +347,10 @@ term (void)
}
/* are there enough arguments left that this could be dyadic? */
- if (((pos + 3 <= argc) && binop (argv[pos + 1])) ||
- ((pos + 4 <= argc && STREQ (argv[pos], "-l") && binop (argv[pos + 2]))))
- value = binary_operator ();
+ if (pos + 4 <= argc && STREQ (argv[pos], "-l") && binop (argv[pos + 2]))
+ value = binary_operator (true);
+ else if (pos + 3 <= argc && binop (argv[pos + 1]))
+ value = binary_operator (false);
/* Might be a switch type argument */
else if (argv[pos][0] == '-' && argv[pos][1] && argv[pos][2] == '\0')
@@ -352,31 +370,18 @@ term (void)
}
static int
-binary_operator (void)
+binary_operator (bool l_is_l)
{
register int op;
struct stat stat_buf, stat_spare;
intmax_t l, r;
int value;
- /* Are the left and right integer expressions of the form '-l string'? */
- int l_is_l, r_is_l;
-
- if (strcmp (argv[pos], "-l") == 0)
- {
- l_is_l = 1;
- op = pos + 2;
-
- /* Make sure that OP is still a valid binary operator. */
- if ((op >= argc - 1) || (binop (argv[op]) == 0))
- test_syntax_error (_("%s: binary operator expected\n"), argv[op]);
+ /* Is the right integer expression of the form '-l string'? */
+ int r_is_l;
- advance (0);
- }
- else
- {
- l_is_l = 0;
- op = pos + 1;
- }
+ if (l_is_l)
+ advance (0);
+ op = pos + 1;
if ((op < argc - 2) && (strcmp (argv[op + 1], "-l") == 0))
{
@@ -758,17 +763,9 @@ unary_operator (void)
case 't': /* File (fd) is a terminal? */
{
intmax_t fd;
- advance (0);
- if (pos < argc)
- {
- if (!isint (argv[pos], &fd))
- integer_expected_error (_("after -t"));
- advance (0);
- }
- else
- {
- fd = 1;
- }
+ unary_advance ();
+ if (!isint (argv[pos - 1], &fd))
+ integer_expected_error (_("after -t"));
return (TRUE == (fd == (int) fd && isatty (fd)));
}
@@ -866,12 +863,9 @@ test_unop (char const *op)
}
static int
-one_argument (const char *s)
+one_argument (void)
{
- if (! getenv ("POSIXLY_CORRECT") && STREQ (s, "-t"))
- return (TRUE == (isatty (1)));
-
- return strlen (s) != 0;
+ return argv[pos++][0] != '\0';
}
static int
@@ -880,7 +874,10 @@ two_arguments (void)
int value;
if (STREQ (argv[pos], "!"))
- value = ! one_argument (argv[pos+1]);
+ {
+ advance (0);
+ value = ! one_argument ();
+ }
else if (argv[pos][0] == '-'
&& argv[pos][1] != '\0'
&& argv[pos][2] == '\0')
@@ -900,18 +897,20 @@ three_arguments (void)
{
int value;
- if (STREQ (argv[pos], "!"))
+ if (binop (argv[pos + 1]))
+ value = binary_operator (false);
+ else if (STREQ (argv[pos], "!"))
{
advance (1);
value = !two_arguments ();
}
- else if (binop (argv[pos+1]))
+ else if (STREQ (argv[pos], "(") && STREQ (argv[pos + 2], ")"))
{
- value = binary_operator ();
- pos = argc;
+ advance (0);
+ value = one_argument ();
+ advance (0);
}
- else if ((STREQ (argv[pos+1], "-a")) || (STREQ (argv[pos+1], "-o")) ||
- (argv[pos][0] == '('))
+ else if (STREQ (argv[pos + 1], "-a") || STREQ (argv[pos + 1], "-o"))
value = expr ();
else
test_syntax_error (_("%s: binary operator expected\n"), argv[pos+1]);
@@ -920,25 +919,18 @@ 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_argument (argv[1]);
- pos = argc;
+ value = one_argument ();
break;
case 2:
value = two_arguments ();
- pos = argc;
break;
case 3:
@@ -952,9 +944,18 @@ posixtest (void)
value = !three_arguments ();
break;
}
+ if (STREQ (argv[pos], "(") && STREQ (argv[pos + 3], ")"))
+ {
+ advance (0);
+ value = two_arguments ();
+ advance (0);
+ break;
+ }
/* FALLTHROUGH */
case 5:
default:
+ if (nargs <= 0)
+ abort ();
value = expr ();
}
@@ -972,13 +973,10 @@ usage (int status)
program_name);
else
{
- printf (_("\
-Usage: %s EXPRESSION\n\
- or: [ EXPRESSION ]\n\
- or: %s OPTION\n\
-"),
- program_name, program_name);
fputs (_("\
+Usage: test EXPRESSION\n\
+ or: [ EXPRESSION ]\n\
+ or: [ OPTION\n\
Exit with the status determined by EXPRESSION.\n\
\n\
"), stdout);
@@ -1087,22 +1085,27 @@ main (int margc, char **margv)
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
+ exit_failure = TEST_FAILURE;
atexit (close_stdout);
#endif /* TEST_STANDALONE */
- /* Recognize --help or --version unless POSIXLY_CORRECT is set. */
- if (! getenv ("POSIXLY_CORRECT"))
- parse_long_options (margc, margv, PROGRAM_NAME, GNU_PACKAGE, VERSION,
- AUTHORS, usage);
-
argv = margv;
if (LBRACKET)
{
- --margc;
+ /* Recognize --help or --version, but only when invoked in the
+ "[" form, and when the last argument is not "]". POSIX
+ allows "[ --help" and "[ --version" to have the usual GNU
+ behavior, but it requires "test --help" and "test --version"
+ to exit silently with status 1. */
+ if (margc < 2 || strcmp (margv[margc - 1], "]") != 0)
+ {
+ parse_long_options (margc, margv, PROGRAM_NAME, GNU_PACKAGE, VERSION,
+ AUTHORS, usage);
+ test_syntax_error (_("missing `]'\n"), NULL);
+ }
- if (margc < 1 || strcmp (margv[margc], "]") != 0)
- test_syntax_error (_("missing `]'\n"), NULL);
+ --margc;
}
argc = margc;
@@ -1111,7 +1114,7 @@ main (int margc, char **margv)
if (pos >= argc)
test_exit (SHELL_BOOLEAN (FALSE));
- value = posixtest ();
+ value = posixtest (argc - 1);
if (pos != argc)
test_syntax_error (_("too many arguments\n"), NULL);