Hi,

AC_CHECK_SIZEOF currently does not know how to determine the value when
crosscompiling. Here is a patch which enable this. It is based on the
fact that all C and C++ compilers reject declarations of arrays with
negative size.

What the patch does, essentially, is to compile

int _array_ [1 - 2 * !(expr)];

for various boolean expressions 'expr'. Each compilation success or
failure is 1 bit of informations. To determine the sizeof(foo) == 6,
the test will try the following expressions:

sizeof(foo) >= 0  -> true
sizeof(foo) <= 0  -> false
sizeof(foo) <= 1  -> false
sizeof(foo) <= 3  -> false
sizeof(foo) <= 7  -> true
sizeof(foo) <= 5  -> false
sizeof(foo) <= 6  -> true


The sample configure.in contains three macros that would be interesting
additions for autoconf.

-   AC_CHECK_EVAL_BOOL(INCLUDES, BOOLEAN-CONSTANT-EXPRESSION
                       [, ACTION-IF-TRUE [, ACTION-IF-FALSE]])

Evaluates a boolean constant expression.

-   AC_CHECK_EVAL_INT(INCLUDES, INT-CONSTANT-EXPRESSION, VARIABLE)

Evaluates an integer constant expression, and assigns the value (in decimal)
to the shell variable VARIABLE.

-   AC_CHECK_SIZEOF(TYPE)

Evaluates the sizof of a builtin type. (Sizeof of types defined in header
files can be dealt with using AC_CHECK_EVAL_INT.)

I apologize for the horrific use of 'patsubst'. It serves the purpose of
determining a reasonable cache variable for an arbitrary C expression.

The macros AC_CHECK_EVAL_BOOL_UNCACHED and AC_CHECK_EVAL_INT_UNCACHED are
auxiliary macros. Their existence permits to use the same technique with
different arguments or different AC_MSG_* messages.

Bruno


================================== sample configure.in ====================
AC_INIT(rebox-utf8.gif)
AC_CONFIG_HEADER(config.h)

AC_PROG_CC
AC_PROG_CPP

dnl AC_CHECK_EVAL_BOOL_UNCACHED(INCLUDES, BOOLEAN-CONSTANT-EXPRESSION)
define(AC_CHECK_EVAL_BOOL_UNCACHED,
[AC_TRY_COMPILE([$1
#define _expr_ $2
int _array_ [1 - 2 * !(_expr_)];
], , AC_CV_NAME=true, AC_CV_NAME=false)])

dnl AC_CHECK_EVAL_BOOL(INCLUDES, BOOLEAN-CONSTANT-EXPRESSION
dnl                    [, ACTION-IF-TRUE [, ACTION-IF-FALSE]])
AC_DEFUN(AC_CHECK_EVAL_BOOL,
[dnl All C/C++ compilers reject arrays with negative size.
changequote(<<, >>)dnl
dnl The cache variable name.
define(<<AC_CV_NAME>>,
<<ac_cv_eval_bool_>>dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
translit(<<$2>>,<<(),^ >>,<<{}`$>>),
 <<[!]>>,<<X21>>),
 <<["]>>,<<X22>>),
 <<[%]>>,<<X25>>),
 <<[&]>>,<<X26>>),
 <<[']>>,<<X27>>),
 <<[{]>>,<<X28>>),
 <<[}]>>,<<X29>>),
 <<[*]>>,<<X2A>>),
 <<[+]>>,<<X2B>>),
 <<[`]>>,<<X2C>>),
 <<[-]>>,<<X2D>>),
 <<[.]>>,<<X2E>>),
 <<[/]>>,<<X2F>>),
 <<[:]>>,<<X3A>>),
 <<[<]>>,<<X3C>>),
 <<[=]>>,<<X3D>>),
 <<[>]>>,<<X3E>>),
 <<[?]>>,<<X3F>>),
 <<[$]>>,<<X5E>>),
 <<[|]>>,<<X7C>>),
 <<[~]>>,<<X7E>>))dnl
changequote([, ])dnl
AC_MSG_CHECKING(value of $2)
AC_CACHE_VAL(AC_CV_NAME, [AC_CHECK_EVAL_BOOL_UNCACHED([$1],[$2])])dnl
AC_MSG_RESULT($AC_CV_NAME)
if test $AC_CV_NAME = true; then
  ifelse([$3], , :, [$3])
ifelse([$4], , , [else
  $4
])dnl
fi
undefine([AC_CV_NAME])dnl
])

dnl AC_CHECK_EVAL_INT_UNCACHED(INCLUDES, INT-CONSTANT-EXPRESSION)
define(AC_CHECK_EVAL_INT_UNCACHED,
[if test "$cross_compiling" = yes; then
  # First determine the sign, then a bound, then perform a binary search.
  AC_TRY_COMPILE([$1
#define _expr_ $2
int _array_ [1 - 2 * !((_expr_) >= 0)];
], , ac_result=true, ac_result=false)
  if test $ac_result = true; then
    ac_lo="0"
    ac_try="0"
    while true; do
      AC_TRY_COMPILE([$1
#define _expr_ $2
int _array_ [1 - 2 * !((_expr_) <= $ac_try)];
], , ac_result=true, ac_result=false)
      if test $ac_result = true; then
        ac_hi=$ac_try
        break
      else
        ac_lo=`expr $ac_try + 1`
        ac_try=`expr 2 '*' $ac_try + 1`
      fi
    done
  else
    ac_hi="-1"
    ac_try="-1"
    while true; do
      AC_TRY_COMPILE([$1
#define _expr_ $2
int _array_ [1 - 2 * !((_expr_) >= $ac_try)];
], , ac_result=true, ac_result=false)
      if test $ac_result = true; then
        ac_lo=$ac_try
        break
      else
        ac_hi=`expr $ac_try - 1`
        ac_try=`expr 2 '*' $ac_try`
      fi
    done
  fi
  while test "x$ac_lo" != "x$ac_hi"; do
    ac_try=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo`
    AC_TRY_COMPILE([$1
#define _expr_ $2
int _array_ [1 - 2 * !((_expr_) <= $ac_try)];
], , ac_result=true, ac_result=false)
    if test $ac_result = true; then
      ac_hi=$ac_try
    else
      ac_lo=`expr $ac_try + 1`
    fi
  done
  AC_CV_NAME=$ac_lo
else
AC_TRY_RUN_NATIVE([$1
int _expr_ = ($2);
#include <stdio.h>
int main ()
{
  FILE *f = fopen("conftestval", "w");
  if (!f) exit(1);
  fprintf(f, "%d\n", _expr_);
  return 0;
}], AC_CV_NAME=`cat conftestval`, AC_CV_NAME=unknown)
fi
])

dnl AC_CHECK_EVAL_INT(INCLUDES, INT-CONSTANT-EXPRESSION, VARIABLE)
AC_DEFUN(AC_CHECK_EVAL_INT,
[changequote(<<, >>)dnl
dnl The cache variable name.
define(<<AC_CV_NAME>>,
<<ac_cv_eval_int_>>dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
patsubst(dnl
translit(<<$2>>,<<(),^ >>,<<{}`$>>),
 <<[!]>>,<<X21>>),
 <<["]>>,<<X22>>),
 <<[%]>>,<<X25>>),
 <<[&]>>,<<X26>>),
 <<[']>>,<<X27>>),
 <<[{]>>,<<X28>>),
 <<[}]>>,<<X29>>),
 <<[*]>>,<<X2A>>),
 <<[+]>>,<<X2B>>),
 <<[`]>>,<<X2C>>),
 <<[-]>>,<<X2D>>),
 <<[.]>>,<<X2E>>),
 <<[/]>>,<<X2F>>),
 <<[:]>>,<<X3A>>),
 <<[<]>>,<<X3C>>),
 <<[=]>>,<<X3D>>),
 <<[>]>>,<<X3E>>),
 <<[?]>>,<<X3F>>),
 <<[$]>>,<<X5E>>),
 <<[|]>>,<<X7C>>),
 <<[~]>>,<<X7E>>))dnl
changequote([, ])dnl
AC_MSG_CHECKING(value of $2)
AC_CACHE_VAL(AC_CV_NAME, [AC_CHECK_EVAL_INT_UNCACHED([$1],[$2])])
AC_MSG_RESULT($AC_CV_NAME)
$3=$AC_CV_NAME
undefine([AC_CV_NAME])dnl
])

dnl AC_CHECK_SIZEOF(TYPE)
AC_DEFUN(AC_CHECK_SIZEOF,
[changequote(<<, >>)dnl
dnl The name to #define.
define(<<AC_TYPE_NAME>>, translit(sizeof_$1, [a-z *], [A-Z_P]))dnl
dnl The cache variable name.
define(<<AC_CV_NAME>>, translit(ac_cv_sizeof_$1, [ *], [_p]))dnl
changequote([, ])dnl
AC_MSG_CHECKING(size of $1)
AC_CACHE_VAL(AC_CV_NAME, [AC_CHECK_EVAL_INT_UNCACHED([], [sizeof($1)])])
AC_MSG_RESULT($AC_CV_NAME)
AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME)
undefine([AC_TYPE_NAME])dnl
undefine([AC_CV_NAME])dnl
])

dnl Examples

AC_CHECK_EVAL_BOOL([#include <stdlib.h>], [sizeof (int) < 3])

AC_CHECK_EVAL_INT([], 5 * 3, foo)
AC_CHECK_EVAL_INT([], ~17, bar)

AC_CHECK_SIZEOF(short)
AC_CHECK_SIZEOF(int)

AC_OUTPUT(Makefile)

Reply via email to