1
0
mirror of git://git.sv.gnu.org/coreutils.git synced 2026-04-11 14:44:18 +02:00

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.
This commit is contained in:
Paul Eggert
2008-10-26 00:45:18 -07:00
committed by Jim Meyering
parent 153477479a
commit 2bf151cd93
2 changed files with 24 additions and 55 deletions

View File

@@ -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;
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++; ! (fmt[i] == '%' && fmt[i + 1] != '%'); i += (fmt[i] == '%') + 1)
if (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++]);

View File

@@ -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