bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Improve quality of format-checking code for seq.


From: Paul Eggert
Subject: [PATCH] Improve quality of format-checking code for seq.
Date: Sun, 26 Oct 2008 00:45:18 -0700
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/22.3 (gnu/linux)

* src/seq.c (validate_format): Remove. Migrate its checks into...
(long_double_format): Report an error and exit if an error is found,
instead of returning NULL.  All callers changed.
Use a more-consistent format for diagnostics.
* tests/misc/seq: Adjust to the more-consistent format for diagnostics.
---
 src/seq.c      |   71 +++++++++++++++----------------------------------------
 tests/misc/seq |   10 ++++----
 2 files changed, 25 insertions(+), 56 deletions(-)

diff --git a/src/seq.c b/src/seq.c
index 3ae158b..5f9da96 100644
--- a/src/seq.c
+++ b/src/seq.c
@@ -174,37 +174,10 @@ scan_arg (const char *arg)
   return ret;
 }
 
-/* Validate the format, FMT.  Print a diagnostic and exit
-   if there is not exactly one %-directive.  */
-
-static void
-validate_format (char const *fmt)
-{
-  unsigned int n_directives = 0;
-  char const *p;
-
-  for (p = fmt; *p; p++)
-    {
-      if (p[0] == '%' && p[1] != '%' && p[1] != '\0')
-       {
-         ++n_directives;
-         ++p;
-       }
-    }
-  if (n_directives == 0)
-    {
-      error (0, 0, _("no %% directive in format string %s"), quote (fmt));
-      usage (EXIT_FAILURE);
-    }
-  else if (1 < n_directives)
-    error (EXIT_FAILURE, 0, _("too many %% directives in format string %s"),
-          quote (fmt));
-}
-
 /* If FORMAT is a valid printf format for a double argument, return
-   its long double equivalent, possibly allocated from dynamic
-   storage, and store into *LAYOUT a description of the output layout;
-   otherwise, return NULL.  */
+   its long double equivalent, allocated from dynamic storage, and
+   store into *LAYOUT a description of the output layout; otherwise,
+   report an error and exit.  */
 
 static char const *
 long_double_format (char const *fmt, struct layout *layout)
@@ -216,10 +189,12 @@ long_double_format (char const *fmt, struct layout 
*layout)
   bool has_L;
 
   for (i = 0; ! (fmt[i] == '%' && fmt[i + 1] != '%'); i += (fmt[i] == '%') + 1)
-    if (fmt[i])
+    {
+      if (!fmt[i])
+       error (EXIT_FAILURE, 0,
+              _("format %s has no %% directive"), quote (fmt));
       prefix_len++;
-    else
-      return NULL;
+    }
 
   i++;
   i += strspn (fmt + i, "-+#0 '");
@@ -233,12 +208,17 @@ long_double_format (char const *fmt, struct layout 
*layout)
   length_modifier_offset = i;
   has_L = (fmt[i] == 'L');
   i += has_L;
-  /* In a valid format string, fmt[i] must be one of these specifiers.  */
-  if (fmt[i] == '\0' || ! strchr ("efgaEFGA", fmt[i]))
-    return NULL;
-
-  for (i++; ! (fmt[i] == '%' && fmt[i + 1] != '%'); i += (fmt[i] == '%') + 1)
-    if (fmt[i])
+  if (fmt[i] == '\0')
+    error (EXIT_FAILURE, 0, _("format %s ends in %%"), quote (fmt));
+  if (! strchr ("efgaEFGA", fmt[i]))
+    error (EXIT_FAILURE, 0,
+          _("format %s has unknown %%%c directive"), quote (fmt), fmt[i]);
+
+  for (i++; ; i += (fmt[i] == '%') + 1)
+    if (fmt[i] == '%' && fmt[i + 1] != '%')
+      error (EXIT_FAILURE, 0, _("format %s has too many %% directives"),
+            quote (fmt));
+    else if (fmt[i])
       suffix_len++;
     else
       {
@@ -252,8 +232,6 @@ long_double_format (char const *fmt, struct layout *layout)
        layout->suffix_len = suffix_len;
        return ldfmt;
       }
-
-  return NULL;
 }
 
 /* Actually print the sequence of numbers in the specified range, with the
@@ -432,16 +410,7 @@ main (int argc, char **argv)
     }
 
   if (format_str)
-    {
-      validate_format (format_str);
-      char const *f = long_double_format (format_str, &layout);
-      if (! f)
-       {
-         error (0, 0, _("invalid format string: %s"), quote (format_str));
-         usage (EXIT_FAILURE);
-       }
-      format_str = f;
-    }
+    format_str = long_double_format (format_str, &layout);
 
   last = scan_arg (argv[optind++]);
 
diff --git a/tests/misc/seq b/tests/misc/seq
index 2271322..7f808cf 100755
--- a/tests/misc/seq
+++ b/tests/misc/seq
@@ -81,20 +81,20 @@ my @Tests =
 
    # In coreutils-[6.0..6.9], this would mistakenly succeed and print "%Lg".
    ['fmt-c',   qw(-f %%g 1), {EXIT => 1},
-    {ERR => "seq: invalid format string: `%%g'\n" . $try_help }],
+    {ERR => "seq: format `%%g' has no % directive\n"}],
 
    # In coreutils-6.9..6.10, this would fail with an erroneous diagnostic:
    # "seq: memory exhausted".  In coreutils-6.0..6.8, it would mistakenly
    # succeed and print a blank line.
    ['fmt-eos1', qw(-f % 1), {EXIT => 1},
-    {ERR => "seq: no % directive in format string `%'\n" . $try_help }],
+    {ERR => "seq: format `%' ends in %\n"}],
    ['fmt-eos2', qw(-f %g% 1), {EXIT => 1},
-    {ERR => "seq: invalid format string: `%g%'\n" . $try_help }],
+    {ERR => "seq: format `%g%' has too many % directives\n"}],
 
    ['fmt-d',   qw(-f "" 1), {EXIT => 1},
-    {ERR => "seq: no % directive in format string `'\n" . $try_help }],
+    {ERR => "seq: format `' has no % directive\n"}],
    ['fmt-e',   qw(-f %g%g 1), {EXIT => 1},
-    {ERR => "seq: too many % directives in format string `%g%g'\n"}],
+    {ERR => "seq: format `%g%g' has too many % directives\n"}],
 
    # With coreutils-6.12 and earlier, with a UTF8 numeric locale that uses
    # something other than "." as the decimal point, this use of seq would
-- 
1.5.3.2





reply via email to

[Prev in Thread] Current Thread [Next in Thread]