autoconf-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: proposed gnulib-related additions to Autoconf


From: Ralf Wildenhues
Subject: Re: proposed gnulib-related additions to Autoconf
Date: Mon, 3 Apr 2006 18:49:44 +0200
User-agent: Mutt/1.5.11

Hi Paul,

I'm afraid there are still issues with the concept of these macros,
I believe.  I'd appreciate if you could enlighten me here, I may be
missing some things.

* Paul Eggert wrote on Fri, Mar 31, 2006 at 09:51:45PM CEST:
>
*snip*

> @@ -1670,3 +1634,132 @@ AC_DEFUN([AC_C_TYPEOF],
>      fi
>    fi
>  ])
> +
> +
> +# _AC_C_TYPE_BITS_INTEGER(TYPE, SIGNBITS, BITS-SHELLVAR,
> +#                      [INCLUDES = DEFAULT-INCLUDES])
> +# ------------------------------------------------------
> +# Compute the number of bits in the integer type TYPE.
> +# SIGNBITS should be 1 for a signed, type, 0 for unsigned.
> +# The shell variable BITS-SHELLVAR should already be initialized
> +# to a lower bound on the number of bits; store the
> +# result back into BITS-SHELLVAR.
> +# The type is either built in, or is defined in INCLUDES.
> +AC_DEFUN([_AC_C_TYPE_BITS_INTEGER],
> +[
> +  # Double the number of bits until this fails.
> +  while :; do
> +    $3[]1=`expr $$3 '*' 2`
> +    ac_max="((((($1) 1 << ($$3 - 1 - $2)) - 1) << 1) + 1)"
> +    ac_max1="((((($1) 1 << ($$3[]1 - 1 - $2)) - 1) << 1) + 1)"
> +    AC_COMPILE_IFELSE(
> +      [AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT([$4])],
> +      [$ac_max < $ac_max1 && ($1) $ac_max1 == $ac_max1])],

Strictly speaking, for signed types this invokes undefined behavior, if
we shifted too far in `$ac_max1', so we can't be certain that the
outcome of this test will be good to use.  We rely on the fact that in
practice, this isn't a problem, right?

Compared to your previous version, you fixed the possible undefined
behavior here for an unsigned TYPE.  (Before, $at_1 could still be
signed, e.g., when TYPE was `short'.)

> +      [],
> +      [break])
> +    $3=$$3[]1
> +  done
> +
> +  # Add 1 to the number of bits until this fails.
> +  while :; do
> +    $3[]1=`expr $$3 + 1`
> +    ac_max="((((($1) 1 << ($$3 - 1 - $2)) - 1) << 1) + 1)"
> +    ac_max1="((((($1) 1 << ($$3[]1 - 1 - $2)) - 1) << 1) + 1)"
> +    AC_COMPILE_IFELSE(
> +      [AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT([$4])],
> +      [$ac_max < $ac_max1 && ($1) $ac_max1 == $ac_max1])],
> +      [],
> +      [break])
> +    $3=$$3[]1
> +  done
> +])# _AC_C_TYPE_BITS_INTEGER
> +
> +# AC_C_TYPE_RANGE_INTEGER(TYPE, [MIN-VARIABLE], MAX-VARIABLE,
> +#                      [INCLUDES = DEFAULT-INCLUDES])
> +# -----------------------------------------------------------
> +# Compute the bounds of the integer TYPE and define MIN-VARIABLE and
> +# MAX-VARIABLE to those bounds.  The bounds are expressions that are
> +# suitable for use in the preprocessor.  If MIN-VARIABLE is absent, do
> +# not define it.  If either variable is already defined by INCLUDES, do
> +# not define it.  If TYPE does not work, do not define either variable.
> +# Works OK if cross compiling.
> +AC_DEFUN([AC_C_TYPE_RANGE_INTEGER],
> +[
> +  AC_CACHE_CHECK([for $3], [ac_cv_value_$3],
> +    [ac_cv_value_$3=no
> +     ac_signbits=
> +     AC_COMPILE_IFELSE(
> +       [AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT([$4])], [($1) -1 < 
> 0])],
> +       [ac_signbits=1; ac_suffix=; ac_unsigned=],
> +       [AC_COMPILE_IFELSE(
> +       [AC_LANG_BOOL_COMPILE_TRY(
> +          [AC_INCLUDES_DEFAULT([$4])], [0 < ($1) -1])],
> +       [ac_signbits=0; ac_suffix=U; ac_unsigned=unsigned])])
> +     if test -n "$ac_signbits"; then
> +       AC_COMPILE_IFELSE(
> +      [AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT([$4])], [$3 == $3])],
> +      [ac_cv_value_$3=yes],
> +      [ac_1=1 ac_bits=8
> +       for ac_type in \
> +           "$ac_unsigned int" \
> +           "$ac_unsigned long int" \
> +           "$ac_unsigned long long int"; do
> +         AC_COMPILE_IFELSE(
> +           [AC_LANG_PROGRAM(
> +              [$4
> +               extern $ac_type ac_$3;
> +               extern $1 ac_$3;],
> +              [return !ac_$3;])],
> +           [ac_1=1$ac_suffix
> +            case $ac_type in #(
> +            *'long long'*) ac_1=${ac_1}LL ac_bits=64;; #(
> +            *long*) ac_1=${ac_1}L ac_bits=32;; #(
> +            *) ac_bits=16;;
> +            esac
> +            break])
> +       done
> +
> +       _AC_C_TYPE_BITS_INTEGER([$1], [$ac_signbits], [ac_bits], [$4])
> +       ac_shift=`expr $ac_bits - 1 - $ac_signbits`
> +       ac_cv_value_$3="(((($ac_1 << $ac_shift) - 1) << 1) + 1)"])

There's one issue here which I can't see how it works at the moment:

Let's assume short and int have identical layout and range (some
embedded system, or some Cray).  Then ac_1 should be `1U' because
unsigned short promotes to unsigned int.  But we compute `1' and
thus this value is wrong.  Am I missing anything here?

If not, I see two possibilities out here:

a) For unsigned types, always add `U'.  Then, the type of the
resulting expression in MAX-VARIABLE would in general not be the
default-promoted type of the largest value.  This would violate
the corresponding C99 rules for the limits.h/stdint.h types
(but not C89).  Would that be a big problem?

b) If we detect that neither of unsigned int, unsigned long, or unsigned
long long matches the unsigned type TYPE, we also have to compute the
number of value bits in `unsigned int'; if that equals the number of
value bits in TYPE, then we have to add `U'.

Is there maybe a better way?

> +     fi])
> +
> +  case $ac_cv_value_$3 in #(
> +  yes|no) ;; #(
> +  *)
> +    AC_DEFINE_UNQUOTED([$3], [$ac_cv_value_$3],
> +      [Define to the maximum value for the integer type `$1', if the
> +       usual headers do not define $3 and if `$1' is a valid type.]);;
> +  esac
> +
> +  m4_ifval([$2],
> +    [AC_CACHE_CHECK([for $2], [ac_cv_value_$2],
> +       [if test "$ac_cv_value_$3" = no; then
> +       ac_cv_value_$2=no
> +     else
> +       AC_COMPILE_IFELSE(
> +         [AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT([$4])],
> +            [$2 == $2])],
> +         [ac_cv_value_$2=yes],
> +         [ac_min='(- $3)'
> +          ac_min1='(-1 - $3)'
> +          AC_COMPILE_IFELSE(
> +            [AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT([$4])],
> +               [$ac_min1 < $ac_min && ($1) $ac_min1 == $ac_min1])],

For signed types, and for unsigned types where the default promotion
leads to a signed type (note even if above, change (a) was done,
because $3 may have been already defined, but $2 not), this may again
invoke undefined behavior.  I assume again that in practice "it works".

> +            [ac_min=$ac_min1],
> +            [AC_COMPILE_IFELSE(
> +               [AC_LANG_BOOL_COMPILE_TRY([AC_INCLUDES_DEFAULT([$4])],
> +                  [($1) -1 < 0])],
> +               [],
> +               [ac_min=0])])
> +          ac_cv_value_$2=$ac_min])
> +      fi])
> +
> +     case $ac_cv_value_$2 in #(
> +     yes|no) ;; #(
> +     *)
> +       AC_DEFINE_UNQUOTED([$2], [$ac_cv_value_$2],
> +      [Define to the minimum value for the integer type `$1', if the
> +       usual headers do not define $2 and if `$1' is a valid type.]);;
> +     esac])
> +])# AC_C_TYPE_RANGE_INTEGER

Cheers,
Ralf




reply via email to

[Prev in Thread] Current Thread [Next in Thread]