mirror of
https://git.savannah.gnu.org/git/coreutils.git
synced 2025-09-10 07:59:52 +02:00
printf,seq,sleep,tail,timeout: accept current-locale floats
These commands now accept floating-point numbers in the current locale, as well as in the C locale. Compatibility problem reported by Robert Elz. * NEWS: Document this. * bootstrap.conf (gnulib_modules): Add cl-strtod, cl-strtold. Remove c-strtold. * doc/coreutils.texi (Floating point, tail invocation) (printf invocation, timeout invocation, sleep invocation) (seq invocation): Document this. * gl/lib/cl-strtod.c, gl/lib/cl-strtod.h, gl/lib/cl-strtold.c: * gl/modules/cl-strtod, gl/modules/cl-strtold: New files. * src/printf.c, src/seq.c, src/sleep.c, src/tail.c, src/timeout.c: Include cl-strtod.h instead of c-strtod. * src/printf.c (vstrtold): * src/seq.c (scan_arg, print_numbers): * src/sleep.c (main): * src/tail.c (parse_options): * src/timeout.c (parse_duration): Use cl_strtold instead of c_strtold.
This commit is contained in:
7
NEWS
7
NEWS
@@ -53,6 +53,13 @@ GNU coreutils NEWS -*- outline -*-
|
||||
|
||||
id now supports specifying multiple users.
|
||||
|
||||
printf, seq, sleep, tail, and timeout now accept floating point
|
||||
numbers in either the current or the C locale. For example, if the
|
||||
current locale's decimal point is ',', 'sleep 0,1' and 'sleep 0.1'
|
||||
now mean the same thing. Previously, these commands accepted only
|
||||
C-locale syntax with '.' as the decimal point. The new behavior is
|
||||
more compatible with other implementations in non-C locales.
|
||||
|
||||
test now supports the '-N FILE' unary operator (like e.g. bash) to check
|
||||
whether FILE exists and has been modified since it was last read.
|
||||
|
||||
|
||||
@@ -41,7 +41,8 @@ gnulib_modules="
|
||||
buffer-lcm
|
||||
c-strcase
|
||||
c-strtod
|
||||
c-strtold
|
||||
cl-strtod
|
||||
cl-strtold
|
||||
calloc-gnu
|
||||
canon-host
|
||||
canonicalize
|
||||
|
||||
@@ -1088,7 +1088,6 @@ information, please see David Goldberg's paper
|
||||
@uref{https://@/docs.oracle.com/@/cd/@/E19957-01/@/806-3568/@/ncg_goldberg.html,
|
||||
What Every Computer Scientist Should Know About Floating-Point Arithmetic}.
|
||||
|
||||
@vindex LC_NUMERIC
|
||||
Commands that accept floating point numbers as options, operands or
|
||||
input use the standard C functions @code{strtod} and @code{strtold} to
|
||||
convert from text to floating point numbers. These floating point
|
||||
@@ -1098,10 +1097,16 @@ case-insensitive @code{inf}, @code{infinity}, and @code{NaN}, although
|
||||
whether such values are useful depends on the command in question.
|
||||
Modern C implementations also accept hexadecimal floating point
|
||||
numbers such as @code{-0x.ep-3}, which stands for @minus{}14/16 times
|
||||
@math{2^-3}, which equals @minus{}0.109375. The @env{LC_NUMERIC}
|
||||
locale determines the decimal-point character. @xref{Parsing of
|
||||
@math{2^-3}, which equals @minus{}0.109375. @xref{Parsing of
|
||||
Floats,,, libc, The GNU C Library Reference Manual}.
|
||||
|
||||
@vindex LC_NUMERIC
|
||||
Normally the @env{LC_NUMERIC} locale determines the decimal-point
|
||||
character. However, some commands' descriptions specify that they
|
||||
accept numbers in either the current or the C locale; for example,
|
||||
they treat @samp{3.14} like @samp{3,14} if the current locale uses
|
||||
comma as a decimal point.
|
||||
|
||||
@node Signal specifications
|
||||
@section Signal specifications
|
||||
@cindex signals, specifying
|
||||
@@ -3187,13 +3192,12 @@ never checks it again.
|
||||
Change the number of seconds to wait between iterations (the default is 1.0).
|
||||
During one iteration, every specified file is checked to see if it has
|
||||
changed size.
|
||||
Historical implementations of @command{tail} have required that
|
||||
@var{number} be an integer. However, GNU @command{tail} accepts
|
||||
an arbitrary floating point number. @xref{Floating point}.
|
||||
When @command{tail} uses inotify, this polling-related option
|
||||
is usually ignored. However, if you also specify @option{--pid=@var{p}},
|
||||
@command{tail} checks whether process @var{p} is alive at least
|
||||
every @var{number} seconds.
|
||||
The @var{number} must be non-negative and can be a floating-point number
|
||||
in either the current or the C locale. @xref{Floating point}.
|
||||
|
||||
@item -v
|
||||
@itemx --verbose
|
||||
@@ -12829,11 +12833,11 @@ warning is printed. For example, @samp{printf "%d" "'a"} outputs
|
||||
@end itemize
|
||||
|
||||
@vindex LC_NUMERIC
|
||||
A floating-point argument must use a period before any fractional
|
||||
digits, but is printed according to the @env{LC_NUMERIC} category of the
|
||||
current locale. For example, in a locale whose radix character is a
|
||||
comma, the command @samp{printf %g 3.14} outputs @samp{3,14} whereas
|
||||
the command @samp{printf %g 3,14} is an error.
|
||||
A floating point argument is interpreted according to
|
||||
the @env{LC_NUMERIC} category of either the current or the C locale,
|
||||
and is printed according to the current locale.
|
||||
For example, in a locale whose decimal point character is a comma,
|
||||
the command @samp{printf '%g %g' 2,5 2.5} outputs @samp{2,5 2,5}.
|
||||
@xref{Floating point}.
|
||||
|
||||
@kindex \@var{ooo}
|
||||
@@ -17985,7 +17989,8 @@ Diagnose to stderr, any signal sent upon timeout.
|
||||
@end table
|
||||
|
||||
@cindex time units
|
||||
@var{duration} is a floating point number followed by an optional unit:
|
||||
@var{duration} is a floating point number in either the current or the
|
||||
C locale (@pxref{Floating point}) followed by an optional unit:
|
||||
@display
|
||||
@samp{s} for seconds (the default)
|
||||
@samp{m} for minutes
|
||||
@@ -18138,7 +18143,7 @@ days
|
||||
Although portable POSIX scripts must give @command{sleep} a single
|
||||
non-negative integer argument without a suffix, GNU @command{sleep}
|
||||
also accepts two or more arguments, unit suffixes, and floating-point
|
||||
numbers. @xref{Floating point}.
|
||||
numbers in either the current or the C locale. @xref{Floating point}.
|
||||
|
||||
The only options are @option{--help} and @option{--version}. @xref{Common
|
||||
options}.
|
||||
@@ -18587,7 +18592,8 @@ so @code{seq 1 10 10} only produces @samp{1}.
|
||||
@var{increment} must not be @samp{0}; use @command{yes} to get
|
||||
repeated output of a constant number.
|
||||
@var{first}, @var{increment} and @var{last} must not be @code{NaN}.
|
||||
Floating-point numbers may be specified. @xref{Floating point}.
|
||||
Floating-point numbers may be specified in either the current or
|
||||
the C locale. @xref{Floating point}.
|
||||
|
||||
The program accepts the following options. Also see @ref{Common options}.
|
||||
Options must precede operands.
|
||||
|
||||
74
gl/lib/cl-strtod.c
Normal file
74
gl/lib/cl-strtod.c
Normal file
@@ -0,0 +1,74 @@
|
||||
/* Convert string to double in the current locale, falling back on the C locale.
|
||||
|
||||
Copyright 2019 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Written by Paul Eggert. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "cl-strtod.h"
|
||||
|
||||
#include <c-strtod.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if LONG
|
||||
# define CL_STRTOD cl_strtold
|
||||
# define DOUBLE long double
|
||||
# define C_STRTOD c_strtold
|
||||
#else
|
||||
# define CL_STRTOD cl_strtod
|
||||
# define DOUBLE double
|
||||
# define C_STRTOD c_strtod
|
||||
#endif
|
||||
|
||||
/* This function acts like strtod or strtold, except that it falls
|
||||
back on the C locale if the initial prefix is not parsable in
|
||||
the current locale. If the prefix is parsable in both locales,
|
||||
it uses the longer parse, breaking ties in favor of the current locale.
|
||||
|
||||
Parse the initial prefix of NPTR as a floating-point number in the
|
||||
current locale or in the C locale (preferring the locale that
|
||||
yields the longer parse, or the current locale if there is a tie).
|
||||
If ENDPTR is not NULL, set *ENDPTR to the first unused byte, or to
|
||||
NPTR if the prefix cannot be parsed.
|
||||
|
||||
If successful, return a number without changing errno.
|
||||
If the prefix cannot be parsed, return 0 and possibly set errno to EINVAL.
|
||||
If the number overflows, return an extreme value and set errno to ERANGE.
|
||||
If the number underflows, return a value close to 0 and set errno to ERANGE.
|
||||
If there is some other error, return 0 and set errno. */
|
||||
|
||||
DOUBLE
|
||||
CL_STRTOD (char const *nptr, char **restrict endptr)
|
||||
{
|
||||
char *end;
|
||||
DOUBLE d = strtod (nptr, &end);
|
||||
if (*end)
|
||||
{
|
||||
int strtod_errno = errno;
|
||||
char *c_end;
|
||||
DOUBLE c = C_STRTOD (nptr, &c_end);
|
||||
if (end < c_end)
|
||||
d = c, end = c_end;
|
||||
else
|
||||
errno = strtod_errno;
|
||||
}
|
||||
if (endptr)
|
||||
*endptr = end;
|
||||
return d;
|
||||
}
|
||||
2
gl/lib/cl-strtod.h
Normal file
2
gl/lib/cl-strtod.h
Normal file
@@ -0,0 +1,2 @@
|
||||
double cl_strtod (char const *, char **restrict);
|
||||
long double cl_strtold (char const *, char **restrict);
|
||||
2
gl/lib/cl-strtold.c
Normal file
2
gl/lib/cl-strtold.c
Normal file
@@ -0,0 +1,2 @@
|
||||
#define LONG 1
|
||||
#include "cl-strtod.c"
|
||||
24
gl/modules/cl-strtod
Normal file
24
gl/modules/cl-strtod
Normal file
@@ -0,0 +1,24 @@
|
||||
Description:
|
||||
Convert string to double in current or C locale.
|
||||
|
||||
Files:
|
||||
lib/cl-strtod.c
|
||||
lib/cl-strtod.h
|
||||
|
||||
Depends-on:
|
||||
c-strtod
|
||||
|
||||
configure.ac:
|
||||
AC_REQUIRE([AC_C_RESTRICT])
|
||||
|
||||
Makefile.am:
|
||||
lib_SOURCES += cl-strtod.c
|
||||
|
||||
Include:
|
||||
"cl-strtod.h"
|
||||
|
||||
License:
|
||||
GPL
|
||||
|
||||
Maintainer:
|
||||
all
|
||||
23
gl/modules/cl-strtold
Normal file
23
gl/modules/cl-strtold
Normal file
@@ -0,0 +1,23 @@
|
||||
Description:
|
||||
Convert string to long double in current or C locale.
|
||||
|
||||
Files:
|
||||
lib/cl-strtold.c
|
||||
|
||||
Depends-on:
|
||||
c-strtold
|
||||
cl-strtod
|
||||
|
||||
configure.ac:
|
||||
|
||||
Makefile.am:
|
||||
lib_SOURCES += cl-strtold.c
|
||||
|
||||
Include:
|
||||
"cl-strtod.h"
|
||||
|
||||
License:
|
||||
GPL
|
||||
|
||||
Maintainer:
|
||||
all
|
||||
@@ -55,7 +55,7 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "system.h"
|
||||
#include "c-strtod.h"
|
||||
#include "cl-strtod.h"
|
||||
#include "die.h"
|
||||
#include "error.h"
|
||||
#include "quote.h"
|
||||
@@ -188,7 +188,7 @@ FUNC_NAME (char const *s) \
|
||||
|
||||
STRTOX (intmax_t, vstrtoimax, strtoimax (s, &end, 0))
|
||||
STRTOX (uintmax_t, vstrtoumax, strtoumax (s, &end, 0))
|
||||
STRTOX (long double, vstrtold, c_strtold (s, &end))
|
||||
STRTOX (long double, vstrtold, cl_strtold (s, &end))
|
||||
|
||||
/* Output a single-character \ escape. */
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#include "system.h"
|
||||
#include "die.h"
|
||||
#include "c-strtod.h"
|
||||
#include "cl-strtod.h"
|
||||
#include "error.h"
|
||||
#include "quote.h"
|
||||
#include "xstrtod.h"
|
||||
@@ -142,7 +142,7 @@ scan_arg (const char *arg)
|
||||
{
|
||||
operand ret;
|
||||
|
||||
if (! xstrtold (arg, NULL, &ret.value, c_strtold))
|
||||
if (! xstrtold (arg, NULL, &ret.value, cl_strtold))
|
||||
{
|
||||
error (0, 0, _("invalid floating point argument: %s"), quote (arg));
|
||||
usage (EXIT_FAILURE);
|
||||
@@ -331,7 +331,7 @@ print_numbers (char const *fmt, struct layout layout,
|
||||
xalloc_die ();
|
||||
x_str[x_strlen - layout.suffix_len] = '\0';
|
||||
|
||||
if (xstrtold (x_str + layout.prefix_len, NULL, &x_val, c_strtold)
|
||||
if (xstrtold (x_str + layout.prefix_len, NULL, &x_val, cl_strtold)
|
||||
&& x_val == last)
|
||||
{
|
||||
char *x0_str = NULL;
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <getopt.h>
|
||||
|
||||
#include "system.h"
|
||||
#include "c-strtod.h"
|
||||
#include "cl-strtod.h"
|
||||
#include "die.h"
|
||||
#include "error.h"
|
||||
#include "long-options.h"
|
||||
@@ -128,7 +128,7 @@ main (int argc, char **argv)
|
||||
{
|
||||
double s;
|
||||
const char *p;
|
||||
if (! (xstrtod (argv[i], &p, &s, c_strtod) || errno == ERANGE)
|
||||
if (! (xstrtod (argv[i], &p, &s, cl_strtod) || errno == ERANGE)
|
||||
/* Nonnegative interval. */
|
||||
|| ! (0 <= s)
|
||||
/* No extra chars after the number and an optional s,m,h,d char. */
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
#include "system.h"
|
||||
#include "argmatch.h"
|
||||
#include "c-strtod.h"
|
||||
#include "cl-strtod.h"
|
||||
#include "die.h"
|
||||
#include "error.h"
|
||||
#include "fcntl--.h"
|
||||
@@ -2244,7 +2244,7 @@ parse_options (int argc, char **argv,
|
||||
case 's':
|
||||
{
|
||||
double s;
|
||||
if (! (xstrtod (optarg, NULL, &s, c_strtod) && 0 <= s))
|
||||
if (! (xstrtod (optarg, NULL, &s, cl_strtod) && 0 <= s))
|
||||
die (EXIT_FAILURE, 0,
|
||||
_("invalid number of seconds: %s"), quote (optarg));
|
||||
*sleep_interval = s;
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "system.h"
|
||||
#include "c-strtod.h"
|
||||
#include "cl-strtod.h"
|
||||
#include "xstrtod.h"
|
||||
#include "sig2str.h"
|
||||
#include "operand2sig.h"
|
||||
@@ -316,12 +316,12 @@ apply_time_suffix (double *x, char suffix_char)
|
||||
}
|
||||
|
||||
static double
|
||||
parse_duration (const char* str)
|
||||
parse_duration (const char *str)
|
||||
{
|
||||
double duration;
|
||||
const char *ep;
|
||||
|
||||
if (! (xstrtod (str, &ep, &duration, c_strtod) || errno == ERANGE)
|
||||
if (! (xstrtod (str, &ep, &duration, cl_strtod) || errno == ERANGE)
|
||||
/* Nonnegative interval. */
|
||||
|| ! (0 <= duration)
|
||||
/* No extra chars after the number and an optional s,m,h,d char. */
|
||||
|
||||
Reference in New Issue
Block a user