summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggert <eggert@CS.UCLA.EDU>2008-10-26 00:45:18 -0700
committerJim Meyering <meyering@redhat.com>2008-10-26 09:51:33 +0100
commit2bf151cd937dd44f00bc7249d5d8d95e9a34f207 (patch)
treeac51409f8525344548b2b3bbae71856bf8b9722b
parent153477479abd5b4dfda5feb109e3ebf28a578bad (diff)
downloadcoreutils-2bf151cd937dd44f00bc7249d5d8d95e9a34f207.tar.xz
seq: improve quality of format-checking code
* 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.
-rw-r--r--src/seq.c71
-rwxr-xr-xtests/misc/seq10
2 files changed, 25 insertions, 56 deletions
diff --git a/src/seq.c b/src/seq.c
index 3ae158b08..5f9da963b 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 227132208..7f808cf6c 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