Implicit assumptions (was: Re: Some fun with -O2)

Mark Millard marklmi at yahoo.com
Sat Jan 16 22:08:41 UTC 2021


On 2021-Jan-16, at 12:19, Walter von Entferndt <walter.von.entferndt at posteo.net> wrote:

> At Samstag, 16. Januar 2021, 11:23:03 CET, Mark Millard wrote:
>> This is the sort of thing where FreeBSD and Linux use a C subset
>> for the specific issue, as defined by POSIX.1-2017/"The Open Group
>> Base Specifications" Issue 7, 2018 edition/IEEE STd 1003-2017/... .
>> For example:
>> 
>> https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_types.h.html
>> 
>> reports (in its own terminology that may not be a full match to C's):
>> 
>> QUOTE
>> clock_t shall be an integer or real-floating type. time_t shall be an
>> integer type. END QUOTE
>> 
>> Limiting to such a time_t is easier to cover. [...]
>> Restricting time_t to integer types leaves a compatible context.
>> So: no "conflict" in that respect.
>> 
> My understanding is that check_mktime.c is a test program called by autoconf 
> or such, designed to run on various UNIX platforms?  I mean it does not only 
> need to run on BSD & Linux.

QUOTE ( from https://en.wikipedia.org/wiki/POSIX )
The Portable Operating System Interface (POSIX) is a family of standards specified by the IEEE Computer Society for maintaining compatibility between operating systems.[1] POSIX defines the application programming interface (API), along with command line shells and utility interfaces, for software compatibility with variants of Unix and other operating systems.
END QUOTE

The section "POSIX-oriented operating systems" lists many OSs
that are either certified, mostly-compliant, have means of
having a POSIX environment (includes Microsoft Windows, OS/2,
DOS), or have a (optional) POSIX compatibility layer. I'll
not make a full list here.

You can use that to help judge if only supporting time_t as an
integer type is worthwhile in your view.

> Maybe something like this will cover the most cases in practice:

There are more details here that I'd need to think about
that I've not dealt with yet.

> --- check_mktime.c.patch ---
> --- check_mktime.c.orig	2021-01-15 03:19:33.962253000 +0100
> +++ check_mktime.c	2021-01-16 21:00:36.160616000 +0100
> @@ -3,6 +3,13 @@
> # include <sys/time.h>
> # include <time.h>
> # include <unistd.h>
> +# include <stdlib.h>
> +#include <stdint.h>
> +# include <stdio.h>	/* printf() */
> +# include <limits.h>	/* CHAR_BIT */
> +#if 0
> +# include <inttypes.h>	/* format spec PRIX64: ll/l + X on 32/64-bit arch */
> +#endif
> 
> /* Work around redefinition to rpl_putenv by other config tests.  */
> #undef putenv
> @@ -16,6 +23,78 @@
> };
> #define N_STRINGS (sizeof (tz_strings) / sizeof (tz_strings[0]))
> 
> +/* Count the bits set in any unsigned integer type.
> + * Returns the precision (width - padding bits - sign bit) iff given
> + * the xxx_MAX value of any integer type, signed or unsigned.
> + * From SEI CERT C Coding Standard:
> + * Rules for Developing Safe, Reliable, and Secure Systems (2016)
> + */
> +size_t
> +popcount (num)
> +uintmax_t num;
> +{
> +  size_t cnt = 0;
> +    
> +  while (num != 0)
> +    {
> +      if (num % 2 == 1)
> +      cnt++;
> +      num >>= 1;
> +    }
> +  return cnt;
> +}
> +#define PRECISION(max_value) popcount(max_value)
> +
> +/* Guess the maximum value of a time_t from it's storage width.
> + * ASSERT time_t is not a floating point, or of any arcane width, or 
> unsigned.
> + * Only 4...8 byte width of a time_t are tested.
> + * On error: returns (time_t)(-1)
> + */
> +time_t
> +guess_time_t_max ()
> +{
> +  time_t t0, t1 = (time_t)(-1);
> +  size_t size, prec;
> +
> +  switch ((size = sizeof(time_t)))
> +    {
> +      case 4:
> +	prec = PRECISION((time_t) 0xFFFFFFFF);
> +	break;
> +      case 5:
> +	prec = PRECISION((time_t) 0xFFFFFFFFFF);
> +	break;
> +      case 6:
> +	prec = PRECISION((time_t) 0xFFFFFFFFFFFF);
> +	break;
> +      case 7:
> +	prec = PRECISION((time_t) 0xFFFFFFFFFFFFFF);
> +	break;
> +      case 8:
> +	prec = PRECISION((time_t) 0xFFFFFFFFFFFFFFFF);
> +	break;
> +      default:
> +	prec = 1;
> +	break;
> +    }
> +  prec--; /* assumption: time_t is signed */
> +  if (prec)
> +    {
> +      t0 = (time_t) 1 << (prec - 1);
> +      t1 = t0|(t0 - 1);
> +    }
> +
> +  /* FIXME not portable: time_t can be floating point type,
> +   * or another integer type other than long or long long.
> +   *
> +  fprintf (stderr, "time_t_max\t= 0x%"PRIX64"\n", t1);*/
> +  fprintf (stderr, "sizeof(time_t)\t= %2zd byte\n", size);
> +  fprintf (stderr, "precision\t= %2zd bit\n", prec);
> +  fprintf (stderr, "padding\t\t= %2zd bit\n", size*CHAR_BIT - prec - 1 /* 
> sign */);
> +
> +  return t1;
> +}
> +
> /* Fail if mktime fails to convert a date in the spring-forward gap.
>    Based on a problem report from Andreas Jaeger.  */
> static void
> @@ -106,9 +185,7 @@
>   time_t t, delta;
>   int i, j;
> 
> -  for (time_t_max = 1; 0 < time_t_max; time_t_max *= 2)
> -    continue;
> -  time_t_max--;
> +  time_t_max = guess_time_t_max ();
>   delta = time_t_max / 997; /* a suitable prime number */
>   for (i = 0; i < N_STRINGS; i++)
>     {
> @@ -128,3 +205,4 @@
>   spring_forward_gap ();
>   exit (0);
> }
> +/*! vi: set ai tabstop=8 shiftwidth=2: */
> 


===
Mark Millard
marklmi at yahoo.com
( dsl-only.net went
away in early 2018-Mar)



More information about the freebsd-hackers mailing list