Here's a full patch including two small manpage tweaks.

It contains the three hunks that fix FreeBSD's regress tests from my
previous mail:

* initialize begin, ender, step, reps (from attila)
* set steps to -1 if ender < begin (adapted from FreeBSD)
* properly skip "%%" in the format string (from OpenBSD r1.8, pjanzen)

In addition, get rid of the nasty mask loop and just compute whatever we
need to compute in the most sensible order. This simplifies the code
quite a bit and is inspired by dsl@NetBSD's r1.21. Note that the output
loop only depends on reps, begin and step, so we never need to compute
ender and we only need to compute something else if ender was specified.

We now only produce infinite output if it was explicitly requested by
setting reps or steps to zero on the command line.

Also note that if randomized output is requested, there's never the need
to compute anything, so just skip that piece of code in that case.

I will import a tweaked and expanded version of the regress tests when
the tree is fully unlocked.

Index: jot.1
===================================================================
RCS file: /var/cvs/src/usr.bin/jot/jot.1,v
retrieving revision 1.21
diff -u -p -r1.21 jot.1
--- jot.1       17 Jul 2016 04:15:25 -0000      1.21
+++ jot.1       27 Jul 2016 19:27:38 -0000
@@ -104,11 +104,10 @@ in which case the data is inserted rathe
 The last four arguments indicate, respectively,
 the maximum number of data, the lower bound, the upper bound,
 and the step size.
-While at least one of them must appear,
-any of the other three may be omitted, and
+Any of these may be omitted, and
 will be considered as such if given as
 .Ql - .
-Any three of these arguments determines the fourth.
+Any three of these arguments determine the fourth.
 If four are specified and the given and computed values of
 .Ar reps
 conflict, the lower value is used.
Index: jot.c
===================================================================
RCS file: /var/cvs/src/usr.bin/jot/jot.c,v
retrieving revision 1.28
diff -u -p -r1.28 jot.c
--- jot.c       17 Jul 2016 04:04:46 -0000      1.28
+++ jot.c       28 Jul 2016 11:26:16 -0000
@@ -52,12 +52,17 @@
 #define        ENDER_DEF       100
 #define        STEP_DEF        1
 
+#define        STEP    1
+#define        ENDER   2
+#define        BEGIN   4
+#define        REPS    8
+
 #define        is_default(s)   (strcmp((s), "-") == 0)
 
-static double  begin;
-static double  ender;
-static double  s;
-static long    reps;
+static double  begin = BEGIN_DEF;
+static double  ender = ENDER_DEF;
+static double  step = STEP_DEF;
+static long    reps = REPS_DEF;
 static bool    randomize;
 static bool    infinity;
 static bool    boring;
@@ -131,9 +136,9 @@ main(int argc, char *argv[])
        switch (argc) { /* examine args right to left, falling thru cases */
        case 4:
                if (!is_default(argv[3])) {
-                       if (!sscanf(argv[3], "%lf", &s))
+                       if (!sscanf(argv[3], "%lf", &step))
                                errx(1, "Bad s value:  %s", argv[3]);
-                       mask |= 01;
+                       mask |= STEP;
                        if (randomize)
                                warnx("random seeding not supported");
                }
@@ -141,7 +146,7 @@ main(int argc, char *argv[])
                if (!is_default(argv[2])) {
                        if (!sscanf(argv[2], "%lf", &ender))
                                ender = argv[2][strlen(argv[2])-1];
-                       mask |= 02;
+                       mask |= ENDER;
                        if (prec == -1)
                                n = getprec(argv[2]);
                }
@@ -149,7 +154,7 @@ main(int argc, char *argv[])
                if (!is_default(argv[1])) {
                        if (!sscanf(argv[1], "%lf", &begin))
                                begin = argv[1][strlen(argv[1])-1];
-                       mask |= 04;
+                       mask |= BEGIN;
                        if (prec == -1)
                                prec = getprec(argv[1]);
                        if (n > prec)           /* maximum precision */
@@ -159,114 +164,65 @@ main(int argc, char *argv[])
                if (!is_default(argv[0])) {
                        if (!sscanf(argv[0], "%ld", &reps))
                                errx(1, "Bad reps value:  %s", argv[0]);
-                       mask |= 010;
+                       mask |= REPS;
                        if (prec == -1)
                                prec = 0;
                }
                break;
        case 0:
-               usage();
+               /* Use defaults. */
                break;
        default:
                errx(1, "Too many arguments.  What do you mean by %s?",
                    argv[4]);
        }
        getformat();
-       while (mask)    /* 4 bit mask has 1's where last 4 args were given */
-               switch (mask) { /* fill in the 0's by default or computation */
-               case 001:
-                       reps = REPS_DEF;
-                       mask = 011;
-                       break;
-               case 002:
-                       reps = REPS_DEF;
-                       mask = 012;
-                       break;
-               case 003:
-                       reps = REPS_DEF;
-                       mask = 013;
-                       break;
-               case 004:
-                       reps = REPS_DEF;
-                       mask = 014;
-                       break;
-               case 005:
-                       reps = REPS_DEF;
-                       mask = 015;
-                       break;
-               case 006:
-                       reps = REPS_DEF;
-                       mask = 016;
-                       break;
-               case 007:
-                       if (randomize) {
-                               reps = REPS_DEF;
-                               mask = 0;
-                               break;
-                       }
-                       if (s == 0.0) {
+       if (!randomize) {
+               switch (mask) {
+               case BEGIN | ENDER:
+                       step = ender < begin ? -1 : 1;
+                       /* FALLTHROUGH */
+               case BEGIN | ENDER | STEP:
+                       if (step == 0.0)
                                reps = 0;
-                               mask = 0;
-                               break;
+                       else {
+                               reps = (ender - begin + step) / step;
+                               if (reps <= 0)
+                                       errx(1, "Impossible stepsize");
                        }
-                       reps = (ender - begin + s) / s;
-                       if (reps <= 0)
-                               errx(1, "Impossible stepsize");
-                       mask = 0;
-                       break;
-               case 010:
-                       begin = BEGIN_DEF;
-                       mask = 014;
-                       break;
-               case 011:
-                       begin = BEGIN_DEF;
-                       mask = 015;
-                       break;
-               case 012:
-                       s = STEP_DEF;
-                       mask = 013;
                        break;
-               case 013:
-                       if (randomize)
-                               begin = BEGIN_DEF;
-                       else if (reps == 0)
+               case ENDER:
+               case ENDER | STEP:
+               case REPS | ENDER:
+               case REPS | ENDER | STEP:
+                       if (reps == 0)
                                errx(1, "Must specify begin if reps == 0");
-                       begin = ender - reps * s + s;
-                       mask = 0;
-                       break;
-               case 014:
-                       s = STEP_DEF;
-                       mask = 015;
-                       break;
-               case 015:
-                       if (randomize)
-                               ender = ENDER_DEF;
-                       else
-                               ender = begin + reps * s - s;
-                       mask = 0;
+                       begin = ender - reps * step + step;
                        break;
-               case 016:
+               case REPS | BEGIN | ENDER:
                        if (reps == 0)
-                               errx(1, "Infinite sequences cannot be bounded");
+                               errx(1, "Cannot specify end if reps == 0");
                        else if (reps == 1)
-                               s = 0.0;
+                               step = 0.0;
                        else
-                               s = (ender - begin) / (reps - 1);
-                       mask = 0;
+                               step = (ender - begin) / (reps - 1);
                        break;
-               case 017:               /* if reps given and implied, */
-                       if (!randomize && s != 0.0) {
-                               long t = (ender - begin + s) / s;
+               case REPS | BEGIN | ENDER | STEP:
+                       if (reps == 0)
+                               errx(1, "Cannot specify end if reps == 0");
+                       if (step != 0.0) {
+                               long t = (ender - begin + step) / step;
                                if (t <= 0)
                                        errx(1, "Impossible stepsize");
                                if (t < reps)           /* take lesser */
                                        reps = t;
                        }
-                       mask = 0;
                        break;
                default:
-                       errx(1, "bad mask");
+                       /* Use defaults. */
+                       break;
                }
+       }
        if (reps == 0)
                infinity = true;
        if (randomize) {
@@ -315,14 +271,13 @@ main(int argc, char *argv[])
                        if (putdata(v, reps == i && !infinity))
                                errx(1, "range error in conversion: %f", v);
                }
-       }
-       else
-               for (i = 1, x = begin; i <= reps || infinity; i++, x += s)
+       } else
+               for (i = 1, x = begin; i <= reps || infinity; i++, x += step)
                        if (putdata(x, reps == i && !infinity))
                                errx(1, "range error in conversion: %f", x);
        if (finalnl)
                putchar('\n');
-       exit(0);
+       return (0);
 }
 
 static int
@@ -394,8 +349,11 @@ getformat(void)
        if (boring)                             /* no need to bother */
                return;
        for (p = format; *p != '\0'; p++)       /* look for '%' */
-               if (*p == '%' && *(p+1) != '%') /* leave %% alone */
-                       break;
+               if (*p == '%') {
+                      if (*(p + 1) != '%')
+                              break;
+                      p++;                     /* leave %% alone */
+               }
        sz = sizeof(format) - strlen(format) - 1;
        if (*p == '\0' && !chardata) {
                int n;

Reply via email to