Hi Scott,

Scott Cheloha wrote on Sun, Jun 30, 2019 at 06:49:28AM -0500:

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

I like that.
It is easier to understand and survived my code review and testing.

> ok?

OK schwarze@
  Ingo


> 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