Re: determine base type of a typedef

2020-10-23 Thread Nick Bowler
On 2020-10-23, Nick Bowler  wrote:
> On 23/10/2020, Paul Eggert  wrote:
>> On 10/22/20 6:09 PM, Russell Shaw wrote:
>>> else if(sizeof(time_t) == sizeof(long int)) {
>>
>> This is not the right kind of test. You want to test whether time_t and
>> int
>> are
>> the same types, not whether they're the same size. To do that, you should
>> use
>> code like this:
>>
>> extern time_t foo;
>> extern long int foo;
>>
>> Of course this means you'll need to compile N programs rather than
>> one, but that's life in the big Autoconf city.
>
> To improve configure performance when N is more than one or two,
> you can use C11 _Generic and AC_COMPUTE_INT to pretty easily and
> quickly determine which type (out of a finite list of candidates)
> time_t or any other type is compatible with.
>
> But you'd need a fallback (probably by compiling one program
> like the one shown abovce for each type) to handle the case
> where _Generic is not supported by the implementation.
>
> Example (totally untested):
>
>   AC_COMPUTE_INT([timetype],
> [_Generic((time_t)0, long long: 3, default: 0)
>   + _Generic((time_t)0, long: 2, default: 0)
>   + _Generic((time_t)0, int: 1, default: 0)],

On review, it is obvious this list of types could be more succinctly
written with a single _Generic as they are all for sure different:

  _Generic((time_t)0, long long: 3, long: 2, int: 1, default: 0)

But care must be taken if any of the generic cases are themselves
typedefs, (for example, if we wanted to determine whether POSIX
ssize_t is compatible with a list of types that includes ptrdiff_t),
as it is an error to include compatible types among the list of
cases:

  /* error if ptrdiff_t happens to be compatible with long long */
  _Generic((ssize_t)0, long long: 2, ptrdiff_t: 1, default: 0)

Nesting avoids this problem better than adding as I did originally:

  _Generic((ssize_t)0, long long: 2, default:
_Generic((ssize_t)0, ptrdiff_t: 1, default: 0))

as only one "branch" can be matched.

> [#include ],
> [... slow fallback computation goes here])
>
>   AS_CASE([$timetype],
> [3], [... action when time_t is compatible with long long],
> [2], [... action when time_t is compatible with long],
> [1], [... action when time_t is compatible with int],
> [... action when time_t's compatibility is undetermined])

Cheers,
  Nick



Re: determine base type of a typedef

2020-10-23 Thread Nick Bowler
On 23/10/2020, Paul Eggert  wrote:
> On 10/22/20 6:09 PM, Russell Shaw wrote:
>> else if(sizeof(time_t) == sizeof(long int)) {
>
> This is not the right kind of test. You want to test whether time_t and int
> are
> the same types, not whether they're the same size. To do that, you should
> use
> code like this:
>
> extern time_t foo;
> extern long int foo;
>
> Of course this means you'll need to compile N programs rather than
> one, but that's life in the big Autoconf city.

To improve configure performance when N is more than one or two,
you can use C11 _Generic and AC_COMPUTE_INT to pretty easily and
quickly determine which type (out of a finite list of candidates)
time_t or any other type is compatible with.

But you'd need a fallback (probably by compiling one program
like the one shown abovce for each type) to handle the case
where _Generic is not supported by the implementation.

Example (totally untested):

  AC_COMPUTE_INT([timetype],
[_Generic((time_t)0, long long: 3, default: 0)
  + _Generic((time_t)0, long: 2, default: 0)
  + _Generic((time_t)0, int: 1, default: 0)],
[#include ],
[... slow fallback computation goes here])

  AS_CASE([$timetype],
[3], [... action when time_t is compatible with long long],
[2], [... action when time_t is compatible with long],
[1], [... action when time_t is compatible with int],
[... action when time_t's compatibility is undetermined])

Cheers,
  Nick



Re: determine base type of a typedef

2020-10-23 Thread Paul Eggert

On 10/22/20 6:09 PM, Russell Shaw wrote:
else if(sizeof(time_t) == sizeof(long int)) { 


This is not the right kind of test. You want to test whether time_t and int are 
the same types, not whether they're the same size. To do that, you should use 
code like this:


extern time_t foo;
extern long int foo;

Of course this means you'll need to compile N programs rather than one, but 
that's life in the big Autoconf city.




Re: determine base type of a typedef

2020-10-23 Thread Anatoli
Yeah, though the idea is not to silence the compiler, but to find a solution to 
the problem and make the compiler happy.

On 23/10/20 06:19, Peter Johansson wrote:
> 
> On 23/10/20 6:39 pm, Russell Shaw wrote:
>> If the compiler complains, then maybe you could capture that complaint 
>> output.
>>
>> Bit of a messy test.
> 
> When trying to detect compiler warnings, I've found AC_LANG_WERROR useful
> 
> https://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/autoconf.html#Generic-Compiler-Characteristics
> 
> Peter
> 
> 



Re: determine base type of a typedef

2020-10-23 Thread Peter Johansson



On 23/10/20 6:39 pm, Russell Shaw wrote:
If the compiler complains, then maybe you could capture that complaint 
output.


Bit of a messy test.


When trying to detect compiler warnings, I've found AC_LANG_WERROR useful

https://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/autoconf.html#Generic-Compiler-Characteristics

Peter




Re: determine base type of a typedef

2020-10-23 Thread Anatoli
> Is it not possible to always use "%lld" and always convert the
> arguments to (long long int)?

This is what I'm doing right now. GCC on Linux doesn't generate any
warnings in any case, though I'm not sure this is a clean way of doing
things, taking into account Clang on other archs and platforms. I'm
investigating it right now. That's why the initial question.

With respect to converting the arguments to (long long int), if I
understand you correctly, you suggest to cast the values? This is not
the desired way of solving this type of things.

I'll quote Ellie Timoney here:

>From a maintenance point of view, casting usually means "there's
something tricky going on here; treat carefully". If we start littering
every formatted string with casts, it becomes impossible to tell which
ones are actually something tricky, and which ones are just annoying
platform workarounds. The right place for platform workarounds is
configure.ac


On 23/10/20 04:00, Vivien Kraus wrote:
> Hello Anatoli,
> 
> Le jeudi 22 octobre 2020 à 19:23 -0300, Anatoli a écrit :
>> #if (AC_TYPE(time_t) == "long long int")
>> #define TIME_T_FMT "%lld"
>> #elif (AC_TYPE(time_t) == "long int")
>> #define TIME_T_FMT "%ld"
>> #else
>> #error dont know what to use for TIME_T_FMT
>> #endif
> 
> Is it not possible to always use "%lld" and always convert the
> arguments to (long long int)?
> 
> Best regards,
> 
> divoplade
> 
> 



Re: determine base type of a typedef

2020-10-23 Thread Russell Shaw

On 23/10/20 6:06 pm, Russell Shaw wrote:

On 23/10/20 5:54 pm, Anatoli wrote:

Russell,

Thanks for your suggestion. The problem is, as I mentioned in the initial
post, on amd64 sizeof(time_t) is always 8 bytes, as well as long and long
long, so sizeof(time_t) == sizeof(long int) == sizeof(long long int).

I've actually tried the following directly in configure.ac (for this test
it's not needed to run a custom code):

#if (SIZEOF_TIME_T == SIZEOF_LONG_LONG_INT) #define TIME_T_FMT "%lld" #elif
(SIZEOF_TIME_T == SIZEOF_LONG) #define TIME_T_FMT "%ld" #else #error dont
know what to use for TIME_T_FMT #endif

But both checks are true so it makes no sense.

I need something that would not depend on the size of the type. Not sure it's
even possible.

I might be missing something simple because i got up too early.

If a platform has time_t the same size as a long and long long, does it matter 
whether the printf uses "%ld" or "%lld" ?


[For GNU C this is "the same" as both are of 8 bytes, but clang generates a 
warning like: "warning: format specifies type 'long' but the argument has type 
'time_t' (aka 'long long')".]


I see that is the actual problem.

If the compiler complains, then maybe you could capture that complaint output.

Bit of a messy test.



Re: determine base type of a typedef

2020-10-23 Thread Russell Shaw

On 23/10/20 6:06 pm, Russell Shaw wrote:

On 23/10/20 5:54 pm, Anatoli wrote:

Russell,

Thanks for your suggestion. The problem is, as I mentioned in the initial
post, on amd64 sizeof(time_t) is always 8 bytes, as well as long and long
long, so sizeof(time_t) == sizeof(long int) == sizeof(long long int).

I've actually tried the following directly in configure.ac (for this test
it's not needed to run a custom code):

#if (SIZEOF_TIME_T == SIZEOF_LONG_LONG_INT) #define TIME_T_FMT "%lld" #elif
(SIZEOF_TIME_T == SIZEOF_LONG) #define TIME_T_FMT "%ld" #else #error dont
know what to use for TIME_T_FMT #endif

But both checks are true so it makes no sense.

I need something that would not depend on the size of the type. Not sure it's
even possible.

I might be missing something simple because i got up too early.

If a platform has time_t the same size as a long and long long, does it matter 
whether the printf uses "%ld" or "%lld" ?


[For GNU C this is "the same" as both are of 8 bytes, but clang generates a 
warning like: "warning: format specifies type 'long' but the argument has type 
'time_t' (aka 'long long')".]


I see that is the actual problem.



Re: determine base type of a typedef

2020-10-23 Thread Anatoli
Russell,

> If a platform has time_t the same size as a long and long long, does
> it matter whether the printf uses "%ld" or "%lld" ?

>From my first mail:

> For GNU C this is "the same" as both are of 8 bytes, but clang
> generates a warning like: "warning: format specifies type 'long' but
> the argument has type 'time_t' (aka 'long long')".

Clang warns that it's not OK, though I'm not sure why exactly.


On 23/10/20 04:06, Russell Shaw wrote:
> On 23/10/20 5:54 pm, Anatoli wrote:
>> Russell,
>>
>> Thanks for your suggestion. The problem is, as I mentioned in the initial
>> post, on amd64 sizeof(time_t) is always 8 bytes, as well as long and long
>> long, so sizeof(time_t) == sizeof(long int) == sizeof(long long int).
>>
>> I've actually tried the following directly in configure.ac (for this test
>> it's not needed to run a custom code):
>>
>> #if (SIZEOF_TIME_T == SIZEOF_LONG_LONG_INT) #define TIME_T_FMT "%lld" #elif
>> (SIZEOF_TIME_T == SIZEOF_LONG) #define TIME_T_FMT "%ld" #else #error dont
>> know what to use for TIME_T_FMT #endif
>>
>> But both checks are true so it makes no sense.
>>
>> I need something that would not depend on the size of the type. Not sure it's
>> even possible.
> I might be missing something simple because i got up too early.
> 
> If a platform has time_t the same size as a long and long long, does it 
> matter whether the printf uses "%ld" or "%lld" ?
> 



Re: determine base type of a typedef

2020-10-23 Thread Russell Shaw

On 23/10/20 5:54 pm, Anatoli wrote:

Russell,

Thanks for your suggestion. The problem is, as I mentioned in the initial
post, on amd64 sizeof(time_t) is always 8 bytes, as well as long and long
long, so sizeof(time_t) == sizeof(long int) == sizeof(long long int).

I've actually tried the following directly in configure.ac (for this test
it's not needed to run a custom code):

#if (SIZEOF_TIME_T == SIZEOF_LONG_LONG_INT) #define TIME_T_FMT "%lld" #elif
(SIZEOF_TIME_T == SIZEOF_LONG) #define TIME_T_FMT "%ld" #else #error dont
know what to use for TIME_T_FMT #endif

But both checks are true so it makes no sense.

I need something that would not depend on the size of the type. Not sure it's
even possible.

I might be missing something simple because i got up too early.

If a platform has time_t the same size as a long and long long, does it matter 
whether the printf uses "%ld" or "%lld" ?




Re: determine base type of a typedef

2020-10-23 Thread Vivien Kraus
Hello Anatoli,

Le jeudi 22 octobre 2020 à 19:23 -0300, Anatoli a écrit :
> #if (AC_TYPE(time_t) == "long long int")
> #define TIME_T_FMT "%lld"
> #elif (AC_TYPE(time_t) == "long int")
> #define TIME_T_FMT "%ld"
> #else
> #error dont know what to use for TIME_T_FMT
> #endif

Is it not possible to always use "%lld" and always convert the
arguments to (long long int)?

Best regards,

divoplade




Re: determine base type of a typedef

2020-10-23 Thread Anatoli
Russell,

Thanks for your suggestion. The problem is, as I mentioned in the initial post, 
on amd64 sizeof(time_t) is always 8 bytes, as well as long and long long, so 
sizeof(time_t) == sizeof(long int) == sizeof(long long int).

I've actually tried the following directly in configure.ac (for this test it's 
not needed to run a custom code):

#if (SIZEOF_TIME_T == SIZEOF_LONG_LONG_INT)
#define TIME_T_FMT "%lld"
#elif (SIZEOF_TIME_T == SIZEOF_LONG)
#define TIME_T_FMT "%ld"
#else
#error dont know what to use for TIME_T_FMT
#endif

But both checks are true so it makes no sense.

I need something that would not depend on the size of the type. Not sure it's 
even possible.

Thanks anyway.

Regards,
Anatoli


On 22/10/20 22:09, Russell Shaw wrote:
> 
> On 23/10/20 9:23 am, Anatoli wrote:
>> Hi All,
>>
>> Is there a way to determine with autoconf what's the base type of a typedef?
>>
>> I'm trying to accomplish the following:
>>
>> There are standard types time_t, off_t, size_t and similar that are defined
>> differently on different platforms/OS.
>>
>> For example, time_t is defined as "long int" on Linux amd64, but as "long
>> long int" on OpenBSD amd64. So when printing a time_t var with printf & co,
>> on Linux it's OK to use "%ld" format specifier, but on OpenBSD it should be
>> "%lld".
> You could use an AC_COMPILE thing to run a small bit of C that does something 
> like:
> 
> int
> test(int argc, char **argv)
> {
>     time_t t = -1;
> 
>     if(t < 0) {
> if(sizeof(time_t) == sizeof(int)) {
>     printf("d");
> }
> else if(sizeof(time_t) == sizeof(long int)) {
>     printf("ld");
> }
> else if(sizeof(time_t) == sizeof(long long int)) {
>     printf("lld");
> }
> else {
>     printf("error");
> }
>     }
>     else {
> if(sizeof(time_t) == sizeof(int)) {
>     printf("u");
> }
> else if(sizeof(time_t) == sizeof(long int)) {
>     printf("lu");
> }
> else if(sizeof(time_t) == sizeof(long long int)) {
>     printf("llu");
> }
> else {
>     printf("error");
> }
>     }
> 
>     return 0;
> }
>