This is cleaner, shorter.

 - Remove the intermediate variables and just build the timespec
   directly.

 - Use for-loops to consolidate initialization/incrementation of cp
   into one spot in each loop.

 - Use one loop to parse fractions of a second: less duplicate code
   keeps the fraction path shorter.  Expand the comment to detail why
   this is fine.  We then explain the magic multiplier at the point
   of use instead of making you read the next loop to find out what
   happened in the prior loop.

ok?

Index: sleep.c
===================================================================
RCS file: /cvs/src/bin/sleep/sleep.c,v
retrieving revision 1.27
diff -u -p -r1.27 sleep.c
--- sleep.c     10 Jan 2019 16:41:10 -0000      1.27
+++ sleep.c     30 Jun 2019 11:22:58 -0000
@@ -49,9 +49,8 @@ int
 main(int argc, char *argv[])
 {
        int ch;
-       time_t secs = 0, t;
+       time_t t;
        char *cp;
-       long nsecs = 0;
        struct timespec rqtp;
        int i;
 
@@ -71,40 +70,32 @@ main(int argc, char *argv[])
        if (argc != 1)
                usage();
 
-       cp = *argv;
-       while ((*cp != '\0') && (*cp != '.')) {
+       timespecclear(&rqtp);
+
+       /* Handle whole seconds. */
+       for (cp = *argv; *cp != '\0' && *cp != '.'; cp++) {
                if (!isdigit((unsigned char)*cp))
                        errx(1, "seconds is invalid: %s", *argv);
-               t = (secs * 10) + (*cp++ - '0');
-               if (t / 10 != secs)     /* oflow */
+               t = (rqtp.tv_sec * 10) + (*cp - '0');
+               if (t / 10 != rqtp.tv_sec)      /* overflow */
                        errx(1, "seconds is too large: %s", *argv);
-               secs = t;
+               rqtp.tv_sec = t;
        }
 
-       /* Handle fractions of a second */
+       /*
+        * Handle fractions of a second.  The multiplier divides to zero
+        * after nine digits so anything more precise than a nanosecond is
+        * validated but not used.
+        */
        if (*cp == '.') {
-               cp++;
-               for (i = 100000000; i > 0; i /= 10) {
-                       if (*cp == '\0')
-                               break;
+               i = 100000000;
+               for (cp++; *cp != '\0'; cp++) {
                        if (!isdigit((unsigned char)*cp))
                                errx(1, "seconds is invalid: %s", *argv);
-                       nsecs += (*cp++ - '0') * i;
-               }
-
-               /*
-                * We parse all the way down to nanoseconds
-                * in the above for loop. Be pedantic about
-                * checking the rest of the argument.
-                */
-               while (*cp != '\0') {
-                       if (!isdigit((unsigned char)*cp++))
-                               errx(1, "seconds is invalid: %s", *argv);
+                       rqtp.tv_nsec += (*cp - '0') * i;
+                       i /= 10;
                }
        }
-
-       rqtp.tv_sec = secs;
-       rqtp.tv_nsec = nsecs;
 
        if (timespecisset(&rqtp)) {
                if (nanosleep(&rqtp, NULL) == -1)

Reply via email to