summaryrefslogtreecommitdiff
path: root/src/test.c
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2005-05-27 20:36:58 +0000
committerPaul Eggert <eggert@cs.ucla.edu>2005-05-27 20:36:58 +0000
commita2b86be29574145e2f26770bc495893c27ec6016 (patch)
tree1c8d0ed402c67baecb42f2b961810865f0c69d79 /src/test.c
parent58aa95b54b7cf8b4aaa8264d8d8235b86b992457 (diff)
downloadcoreutils-a2b86be29574145e2f26770bc495893c27ec6016.tar.xz
Include inttostr.h, strnumcmp.h.
(whitespace, digit, digit_value, integer_expected_error): Remove. (is_int): Remove; replaced by... (find_int): New function. (binary_operator): Don't let integers overflow in comparisons; return the correct answer instead. Simplify the code. (unary_operator): Convert the integer ourself, since find_int no longer does so.
Diffstat (limited to 'src/test.c')
-rw-r--r--src/test.c260
1 files changed, 55 insertions, 205 deletions
diff --git a/src/test.c b/src/test.c
index ede47d48b..e6806bf15 100644
--- a/src/test.c
+++ b/src/test.c
@@ -43,14 +43,13 @@
#include "system.h"
#include "error.h"
#include "euidaccess.h"
+#include "inttostr.h"
#include "quote.h"
+#include "strnumcmp.h"
#ifndef _POSIX_VERSION
# include <sys/param.h>
#endif /* _POSIX_VERSION */
-#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
-#define digit(c) ((c) >= '0' && (c) <= '9')
-#define digit_value(c) ((c) - '0')
char *program_name;
@@ -131,81 +130,40 @@ beyond (void)
test_syntax_error (_("missing argument after %s"), quote (argv[argc - 1]));
}
-/* Syntax error for when an integer argument was expected, but
- something else was found. */
-static void
-integer_expected_error (char const *pch)
+/* If the characters pointed to by STRING constitute a valid number,
+ return a pointer to the start of the number, skipping any blanks or
+ leading '+'. Otherwise, report an error and exit. */
+static char const *
+find_int (char const *string)
{
- test_syntax_error (_("%s: integer expression expected\n"), pch);
-}
-
-/* Return true if the characters pointed to by STRING constitute a
- valid number. Stuff the converted number into RESULT if RESULT is
- not null. */
-static bool
-is_int (char const *string, intmax_t *result)
-{
- int sign;
- intmax_t value;
- char const *orig_string;
-
- sign = 1;
- value = 0;
-
- if (result)
- *result = 0;
+ char const *p;
+ char const *number_start;
- /* Skip leading whitespace characters. */
- while (whitespace (*string))
- string++;
+ for (p = string; ISBLANK (to_uchar (*p)); p++)
+ continue;
- if (!*string)
- return false;
-
- /* Save a pointer to the start, for diagnostics. */
- orig_string = string;
-
- /* We allow leading `-' or `+'. */
- if (*string == '-' || *string == '+')
+ if (*p == '+')
{
- if (!digit (string[1]))
- return false;
-
- if (*string == '-')
- sign = -1;
-
- string++;
+ p++;
+ number_start = p;
}
-
- while (digit (*string))
+ else
{
- if (result)
- {
- intmax_t new_v = 10 * value + sign * (*string - '0');
- if (0 < sign
- ? (INTMAX_MAX / 10 < value || new_v < 0)
- : (value < INTMAX_MIN / 10 || 0 < new_v))
- test_syntax_error ((0 < sign
- ? _("integer is too large: %s\n")
- : _("integer is too small: %s\n")),
- orig_string);
- value = new_v;
- }
- string++;
+ number_start = p;
+ p += (*p == '-');
}
- /* Skip trailing whitespace, if any. */
- while (whitespace (*string))
- string++;
-
- /* Error if not at end of string. */
- if (*string)
- return false;
-
- if (result)
- *result = value;
+ if (ISDIGIT (*p++))
+ {
+ while (ISDIGIT (*p))
+ p++;
+ while (ISBLANK (to_uchar (*p)))
+ p++;
+ if (!*p)
+ return number_start;
+ }
- return true;
+ test_syntax_error (_("invalid integer %s\n"), quote (string));
}
/* Find the modification time of FILE, and stuff it into *AGE.
@@ -317,7 +275,6 @@ binary_operator (bool l_is_l)
{
int op;
struct stat stat_buf, stat_spare;
- intmax_t l, r;
/* Is the right integer expression of the form '-l string'? */
bool r_is_l;
@@ -336,100 +293,33 @@ binary_operator (bool l_is_l)
if (argv[op][0] == '-')
{
/* check for eq, nt, and stuff */
+ if ((((argv[op][1] == 'l' || argv[op][1] == 'g')
+ && (argv[op][2] == 'e' || argv[op][2] == 't'))
+ || (argv[op][1] == 'e' && argv[op][2] == 'q')
+ || (argv[op][1] == 'n' && argv[op][2] == 'e'))
+ && !argv[op][3])
+ {
+ char lbuf[INT_BUFSIZE_BOUND (uintmax_t)];
+ char rbuf[INT_BUFSIZE_BOUND (uintmax_t)];
+ char const *l = (l_is_l
+ ? umaxtostr (strlen (argv[op - 1]), lbuf)
+ : find_int (argv[op - 1]));
+ char const *r = (r_is_l
+ ? umaxtostr (strlen (argv[op + 2]), rbuf)
+ : find_int (argv[op + 1]));
+ int cmp = strintcmp (l, r);
+ bool xe_operator = (argv[op][2] == 'e');
+ pos += 3;
+ return (argv[op][1] == 'l' ? cmp < xe_operator
+ : argv[op][1] == 'g' ? cmp > - xe_operator
+ : (cmp != 0) == xe_operator);
+ }
+
switch (argv[op][1])
{
default:
break;
- case 'l':
- if (argv[op][2] == 't' && !argv[op][3])
- {
- /* lt */
- if (l_is_l)
- l = strlen (argv[op - 1]);
- else
- {
- if (!is_int (argv[op - 1], &l))
- integer_expected_error (_("before -lt"));
- }
-
- if (r_is_l)
- r = strlen (argv[op + 2]);
- else
- {
- if (!is_int (argv[op + 1], &r))
- integer_expected_error (_("after -lt"));
- }
- pos += 3;
- return l < r;
- }
-
- if (argv[op][2] == 'e' && !argv[op][3])
- {
- /* le */
- if (l_is_l)
- l = strlen (argv[op - 1]);
- else
- {
- if (!is_int (argv[op - 1], &l))
- integer_expected_error (_("before -le"));
- }
- if (r_is_l)
- r = strlen (argv[op + 2]);
- else
- {
- if (!is_int (argv[op + 1], &r))
- integer_expected_error (_("after -le"));
- }
- pos += 3;
- return l <= r;
- }
- break;
-
- case 'g':
- if (argv[op][2] == 't' && !argv[op][3])
- {
- /* gt integer greater than */
- if (l_is_l)
- l = strlen (argv[op - 1]);
- else
- {
- if (!is_int (argv[op - 1], &l))
- integer_expected_error (_("before -gt"));
- }
- if (r_is_l)
- r = strlen (argv[op + 2]);
- else
- {
- if (!is_int (argv[op + 1], &r))
- integer_expected_error (_("after -gt"));
- }
- pos += 3;
- return l > r;
- }
-
- if (argv[op][2] == 'e' && !argv[op][3])
- {
- /* ge - integer greater than or equal to */
- if (l_is_l)
- l = strlen (argv[op - 1]);
- else
- {
- if (!is_int (argv[op - 1], &l))
- integer_expected_error (_("before -ge"));
- }
- if (r_is_l)
- r = strlen (argv[op + 2]);
- else
- {
- if (!is_int (argv[op + 1], &r))
- integer_expected_error (_("after -ge"));
- }
- pos += 3;
- return l >= r;
- }
- break;
-
case 'n':
if (argv[op][2] == 't' && !argv[op][3])
{
@@ -444,51 +334,9 @@ binary_operator (bool l_is_l)
re = age_of (argv[op + 1], &rt);
return le > re || (le && lt > rt);
}
-
- if (argv[op][2] == 'e' && !argv[op][3])
- {
- /* ne - integer not equal */
- if (l_is_l)
- l = strlen (argv[op - 1]);
- else
- {
- if (!is_int (argv[op - 1], &l))
- integer_expected_error (_("before -ne"));
- }
- if (r_is_l)
- r = strlen (argv[op + 2]);
- else
- {
- if (!is_int (argv[op + 1], &r))
- integer_expected_error (_("after -ne"));
- }
- pos += 3;
- return l != r;
- }
break;
case 'e':
- if (argv[op][2] == 'q' && !argv[op][3])
- {
- /* eq - integer equal */
- if (l_is_l)
- l = strlen (argv[op - 1]);
- else
- {
- if (!is_int (argv[op - 1], &l))
- integer_expected_error (_("before -eq"));
- }
- if (r_is_l)
- r = strlen (argv[op + 2]);
- else
- {
- if (!is_int (argv[op + 1], &r))
- integer_expected_error (_("after -eq"));
- }
- pos += 3;
- return l == r;
- }
-
if (argv[op][2] == 'f' && !argv[op][3])
{
/* ef - hard link? */
@@ -645,11 +493,13 @@ unary_operator (void)
case 't': /* File (fd) is a terminal? */
{
- intmax_t fd;
+ long int fd;
+ char const *arg;
unary_advance ();
- if (!is_int (argv[pos - 1], &fd))
- integer_expected_error (_("after -t"));
- return INT_MIN <= fd && fd <= INT_MAX && isatty (fd);
+ arg = find_int (argv[pos - 1]);
+ errno = 0;
+ fd = strtol (arg, NULL, 10);
+ return (errno != ERANGE && 0 <= fd && fd <= INT_MAX && isatty (fd));
}
case 'n': /* True if arg has some length. */