Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F148035910
D40802.1785178771.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D40802.1785178771.diff
View Options
diff --git a/usr.bin/seq/seq.1 b/usr.bin/seq/seq.1
--- a/usr.bin/seq/seq.1
+++ b/usr.bin/seq/seq.1
@@ -97,7 +97,10 @@
defined in
.St -ansiC .
The default is
-.Cm %g .
+.Cm %g ,
+unless all numbers are integers representable losslessly as floating
+point (with mantissa bits), in which case the default is
+.Cm %.0f .
.It Fl s Ar string , Fl -separator Ar string
Use
.Ar string
diff --git a/usr.bin/seq/seq.c b/usr.bin/seq/seq.c
--- a/usr.bin/seq/seq.c
+++ b/usr.bin/seq/seq.c
@@ -38,6 +38,7 @@
#include <errno.h>
#include <getopt.h>
#include <math.h>
+#include <float.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
@@ -51,11 +52,16 @@
#define ISSIGN(c) ((int)(c) == '-' || (int)(c) == '+')
#define ISEXP(c) ((int)(c) == 'e' || (int)(c) == 'E')
#define ISODIGIT(c) ((int)(c) >= '0' && (int)(c) <= '7')
+#define VALID_INT(v) (floor(v) == (v) && fabs(v) <= abs_int_max)
/* Globals */
static const char *decimal_point = "."; /* default */
static char default_format[] = { "%g" }; /* default */
+static char integer_format[] = { "%.0f" }; /* for integer printing */
+
+/* largest representable integer in a double */
+static const double abs_int_max = (double)(1ULL << DBL_MANT_DIG);
static const struct option long_opts[] =
{
@@ -74,7 +80,7 @@
static int numeric(const char *);
static int valid_format(const char *);
-static char *generate_format(double, double, double, int, char);
+static char *generate_format(double, double, double, int, char, int *);
static char *unescape(char *);
/*
@@ -90,7 +96,7 @@
struct lconv *locale;
char pad, *fmt, *cur_print, *last_print, *prev_print;
double first, last, incr, prev, cur, step;
- int c, errflg, equalize;
+ int c, errflg, equalize, may_trunc = 1;
pad = ZERO;
fmt = NULL;
@@ -180,7 +186,7 @@
* newline if none found at the end of the format string.
*/
} else
- fmt = generate_format(first, incr, last, equalize, pad);
+ fmt = generate_format(first, incr, last, equalize, pad, &may_trunc);
for (step = 1, cur = first; incr > 0 ? cur <= last : cur >= last;
cur = first + incr * step++) {
@@ -189,6 +195,13 @@
prev = cur;
}
+ /*
+ * If we guarantee no truncation (which happens when only integers are
+ * used), skip the code below in order to avoid extra allocations.
+ */
+ if (!may_trunc)
+ goto do_term;
+
/*
* Did we miss the last value of the range in the loop above?
*
@@ -212,6 +225,7 @@
free(last_print);
free(prev_print);
+do_term:
if (term != NULL)
fputs(term, stdout);
@@ -459,14 +473,13 @@
* when "%g" prints as "%e" (this way no width adjustments are made)
*/
static char *
-generate_format(double first, double incr, double last, int equalize, char pad)
+generate_format(double first, double incr, double last, int equalize, char pad, int *may_trunc)
{
static char buf[256];
char cc = '\0';
int precision, width1, width2, places;
-
- if (equalize == 0)
- return (default_format);
+ int do_ints = 0;
+ char *def_fmt;
/* figure out "last" value printed */
if (first > last)
@@ -474,12 +487,22 @@
else
last = first + incr * floor((last - first) / incr);
- sprintf(buf, "%g", incr);
+ do_ints = VALID_INT(first) && VALID_INT(last) && VALID_INT(incr);
+ if (do_ints) {
+ *may_trunc = 0;
+ def_fmt = (integer_format);
+ } else
+ def_fmt = (default_format);
+
+ if (equalize == 0)
+ return def_fmt;
+
+ sprintf(buf, def_fmt, incr);
if (strchr(buf, 'e'))
cc = 'e';
precision = decimal_places(buf);
- width1 = sprintf(buf, "%g", first);
+ width1 = sprintf(buf, def_fmt, first);
if (strchr(buf, 'e'))
cc = 'e';
if ((places = decimal_places(buf)))
@@ -487,7 +510,7 @@
precision = MAX(places, precision);
- width2 = sprintf(buf, "%g", last);
+ width2 = sprintf(buf, def_fmt, last);
if (strchr(buf, 'e'))
cc = 'e';
if ((places = decimal_places(buf)))
@@ -497,6 +520,8 @@
sprintf(buf, "%%%c%d.%d%c", pad,
MAX(width1, width2) + (int) strlen(decimal_point) +
precision, precision, (cc) ? cc : 'f');
+ } else if (do_ints) {
+ sprintf(buf, "%%%c%d.0f", pad, MAX(width1, width2));
} else {
sprintf(buf, "%%%c%d%c", pad, MAX(width1, width2),
(cc) ? cc : 'g');
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Jul 27, 6:59 PM (3 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29280632
Default Alt Text
D40802.1785178771.diff (4 KB)
Attached To
Mode
D40802: seq(1): print integers up to 2^mantissa as integers
Attached
Detach File
Event Timeline
Log In to Comment