stdint.m4 16.3 KB
Newer Older
Kai Tietz committed
1 2 3 4 5 6 7 8 9 10 11 12 13
AC_DEFUN([GCC_STDINT_TYPES],
[AC_REQUIRE([AC_TYPE_INT8_T])
AC_REQUIRE([AC_TYPE_INT16_T])
AC_REQUIRE([AC_TYPE_INT32_T])
AC_REQUIRE([AC_TYPE_INT64_T])
AC_REQUIRE([AC_TYPE_INTMAX_T])
AC_REQUIRE([AC_TYPE_INTPTR_T])
AC_REQUIRE([AC_TYPE_UINT8_T])
AC_REQUIRE([AC_TYPE_UINT16_T])
AC_REQUIRE([AC_TYPE_UINT32_T])
AC_REQUIRE([AC_TYPE_UINT64_T])
AC_REQUIRE([AC_TYPE_UINTMAX_T])
AC_REQUIRE([AC_TYPE_UINTPTR_T])])
14

15 16 17 18 19 20
dnl @synopsis GCC_HEADER_STDINT [( HEADER-TO-GENERATE [, HEADERS-TO-CHECK])]
dnl
dnl the "ISO C9X: 7.18 Integer types <stdint.h>" section requires the
dnl existence of an include file <stdint.h> that defines a set of
dnl typedefs, especially uint8_t,int32_t,uintptr_t.
dnl Many older installations will not provide this file, but some will
Joseph Myers committed
21
dnl have the very same definitions in <inttypes.h>. In other environments
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
dnl we can use the inet-types in <sys/types.h> which would define the
dnl typedefs int8_t and u_int8_t respectivly.
dnl
dnl This macros will create a local "_stdint.h" or the headerfile given as
dnl an argument. In many cases that file will pick the definition from a
dnl "#include <stdint.h>" or "#include <inttypes.h>" statement, while
dnl in other environments it will provide the set of basic 'stdint's defined:
dnl int8_t,uint8_t,int16_t,uint16_t,int32_t,uint32_t,intptr_t,uintptr_t
dnl int_least32_t.. int_fast32_t.. intmax_t
dnl which may or may not rely on the definitions of other files.
dnl
dnl Sometimes the stdint.h or inttypes.h headers conflict with sys/types.h,
dnl so we test the headers together with sys/types.h and always include it
dnl into the generated header (to match the tests with the generated file).
dnl Hopefully this is not a big annoyance.
dnl
dnl If your installed header files require the stdint-types you will want to
dnl create an installable file mylib-int.h that all your other installable
dnl header may include. So, for a library package named "mylib", just use
dnl      GCC_HEADER_STDINT(mylib-int.h)
42
dnl in configure.ac and install that header file in Makefile.am along with
43 44 45 46 47 48 49 50
dnl the other headers (mylib.h).  The mylib-specific headers can simply
dnl use "#include <mylib-int.h>" to obtain the stdint-types.
dnl
dnl Remember, if the system already had a valid <stdint.h>, the generated
dnl file will include it directly. No need for fuzzy HAVE_STDINT_H things...
dnl
dnl @author  Guido Draheim <guidod@gmx.de>, Paolo Bonzini <bonzini@gnu.org>

51
AC_DEFUN([GCC_HEADER_STDINT],
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
[m4_define(_GCC_STDINT_H, m4_ifval($1, $1, _stdint.h))

inttype_headers=`echo inttypes.h sys/inttypes.h $2 | sed -e 's/,/ /g'`

acx_cv_header_stdint=stddef.h
acx_cv_header_stdint_kind="(already complete)"
for i in stdint.h $inttype_headers; do
  unset ac_cv_type_uintptr_t
  unset ac_cv_type_uintmax_t
  unset ac_cv_type_int_least32_t
  unset ac_cv_type_int_fast32_t
  unset ac_cv_type_uint64_t
  _AS_ECHO_N([looking for a compliant stdint.h in $i, ])
  AC_CHECK_TYPE(uintmax_t,[acx_cv_header_stdint=$i],continue,[#include <sys/types.h>
#include <$i>])
  AC_CHECK_TYPE(uintptr_t,,[acx_cv_header_stdint_kind="(mostly complete)"], [#include <sys/types.h>
#include <$i>])
  AC_CHECK_TYPE(int_least32_t,,[acx_cv_header_stdint_kind="(mostly complete)"], [#include <sys/types.h>
#include <$i>])
  AC_CHECK_TYPE(int_fast32_t,,[acx_cv_header_stdint_kind="(mostly complete)"], [#include <sys/types.h>
#include <$i>])
  AC_CHECK_TYPE(uint64_t,,[acx_cv_header_stdint_kind="(lacks uint64_t)"], [#include <sys/types.h>
#include <$i>])
  break
done
if test "$acx_cv_header_stdint" = stddef.h; then
  acx_cv_header_stdint_kind="(lacks uintmax_t)"
  for i in stdint.h $inttype_headers; do
    unset ac_cv_type_uintptr_t
    unset ac_cv_type_uint32_t
    unset ac_cv_type_uint64_t
    _AS_ECHO_N([looking for an incomplete stdint.h in $i, ])
    AC_CHECK_TYPE(uint32_t,[acx_cv_header_stdint=$i],continue,[#include <sys/types.h>
#include <$i>])
    AC_CHECK_TYPE(uint64_t,,,[#include <sys/types.h>
#include <$i>])
    AC_CHECK_TYPE(uintptr_t,,,[#include <sys/types.h>
#include <$i>])
    break
  done
fi
if test "$acx_cv_header_stdint" = stddef.h; then
  acx_cv_header_stdint_kind="(u_intXX_t style)"
  for i in sys/types.h $inttype_headers; do
    unset ac_cv_type_u_int32_t
    unset ac_cv_type_u_int64_t
    _AS_ECHO_N([looking for u_intXX_t types in $i, ])
    AC_CHECK_TYPE(u_int32_t,[acx_cv_header_stdint=$i],continue,[#include <sys/types.h>
#include <$i>])
    AC_CHECK_TYPE(u_int64_t,,,[#include <sys/types.h>
#include <$i>])
    break
  done
fi
if test "$acx_cv_header_stdint" = stddef.h; then
  acx_cv_header_stdint_kind="(using manual detection)"
fi

test -z "$ac_cv_type_uintptr_t" && ac_cv_type_uintptr_t=no
test -z "$ac_cv_type_uint64_t" && ac_cv_type_uint64_t=no
test -z "$ac_cv_type_u_int64_t" && ac_cv_type_u_int64_t=no
test -z "$ac_cv_type_int_least32_t" && ac_cv_type_int_least32_t=no
test -z "$ac_cv_type_int_fast32_t" && ac_cv_type_int_fast32_t=no

# ----------------- Summarize what we found so far

AC_MSG_CHECKING([what to include in _GCC_STDINT_H])

case `AS_BASENAME(_GCC_STDINT_H)` in
  stdint.h) AC_MSG_WARN([are you sure you want it there?]) ;;
  inttypes.h) AC_MSG_WARN([are you sure you want it there?]) ;;
  *) ;;
esac

AC_MSG_RESULT($acx_cv_header_stdint $acx_cv_header_stdint_kind)

# ----------------- done included file, check C basic types --------

# Lacking an uintptr_t?  Test size of void *
case "$acx_cv_header_stdint:$ac_cv_type_uintptr_t" in
  stddef.h:* | *:no) AC_CHECK_SIZEOF(void *) ;;
esac

# Lacking an uint64_t?  Test size of long
case "$acx_cv_header_stdint:$ac_cv_type_uint64_t:$ac_cv_type_u_int64_t" in
  stddef.h:*:* | *:no:no) AC_CHECK_SIZEOF(long) ;;
esac

if test $acx_cv_header_stdint = stddef.h; then
  # Lacking a good header?  Test size of everything and deduce all types.
  AC_CHECK_SIZEOF(int)
  AC_CHECK_SIZEOF(short)
  AC_CHECK_SIZEOF(char)

  AC_MSG_CHECKING(for type equivalent to int8_t)
  case "$ac_cv_sizeof_char" in
    1) acx_cv_type_int8_t=char ;;
149
    *) AC_MSG_ERROR([no 8-bit type, please report a bug])
150 151 152 153 154 155 156
  esac
  AC_MSG_RESULT($acx_cv_type_int8_t)

  AC_MSG_CHECKING(for type equivalent to int16_t)
  case "$ac_cv_sizeof_int:$ac_cv_sizeof_short" in
    2:*) acx_cv_type_int16_t=int ;;
    *:2) acx_cv_type_int16_t=short ;;
157
    *) AC_MSG_ERROR([no 16-bit type, please report a bug])
158 159 160 161 162 163 164
  esac
  AC_MSG_RESULT($acx_cv_type_int16_t)

  AC_MSG_CHECKING(for type equivalent to int32_t)
  case "$ac_cv_sizeof_int:$ac_cv_sizeof_long" in
    4:*) acx_cv_type_int32_t=int ;;
    *:4) acx_cv_type_int32_t=long ;;
165
    *) AC_MSG_ERROR([no 32-bit type, please report a bug])
166 167 168 169 170
  esac
  AC_MSG_RESULT($acx_cv_type_int32_t)
fi

# These tests are here to make the output prettier
171

172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
if test "$ac_cv_type_uint64_t" != yes && test "$ac_cv_type_u_int64_t" != yes; then
  case "$ac_cv_sizeof_long" in
    8) acx_cv_type_int64_t=long ;;
  esac
  AC_MSG_CHECKING(for type equivalent to int64_t)
  AC_MSG_RESULT(${acx_cv_type_int64_t-'using preprocessor symbols'})
fi

# Now we can use the above types

if test "$ac_cv_type_uintptr_t" != yes; then
  AC_MSG_CHECKING(for type equivalent to intptr_t)
  case $ac_cv_sizeof_void_p in
    2) acx_cv_type_intptr_t=int16_t ;;
    4) acx_cv_type_intptr_t=int32_t ;;
    8) acx_cv_type_intptr_t=int64_t ;;
188
    *) AC_MSG_ERROR([no equivalent for intptr_t, please report a bug])
189 190 191 192 193
  esac
  AC_MSG_RESULT($acx_cv_type_intptr_t)
fi

# ----------------- done all checks, emit header -------------
194
AC_CONFIG_COMMANDS(_GCC_STDINT_H, [
195 196 197 198 199 200 201 202 203 204 205 206
if test "$GCC" = yes; then
  echo "/* generated for " `$CC --version | sed 1q` "*/" > tmp-stdint.h
else
  echo "/* generated for $CC */" > tmp-stdint.h
fi

sed 's/^ *//' >> tmp-stdint.h <<EOF

  #ifndef GCC_GENERATED_STDINT_H
  #define GCC_GENERATED_STDINT_H 1

  #include <sys/types.h>
207 208
EOF

209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
if test "$acx_cv_header_stdint" != stdint.h; then
  echo "#include <stddef.h>" >> tmp-stdint.h
fi
if test "$acx_cv_header_stdint" != stddef.h; then
  echo "#include <$acx_cv_header_stdint>" >> tmp-stdint.h
fi

sed 's/^ *//' >> tmp-stdint.h <<EOF
  /* glibc uses these symbols as guards to prevent redefinitions.  */
  #ifdef __int8_t_defined
  #define _INT8_T
  #define _INT16_T
  #define _INT32_T
  #endif
  #ifdef __uint32_t_defined
  #define _UINT32_T
  #endif

EOF

# ----------------- done header, emit basic int types -------------
if test "$acx_cv_header_stdint" = stddef.h; then
  sed 's/^ *//' >> tmp-stdint.h <<EOF

    #ifndef _UINT8_T
    #define _UINT8_T
    #ifndef __uint8_t_defined
    #define __uint8_t_defined
237
    #ifndef uint8_t
238 239 240
    typedef unsigned $acx_cv_type_int8_t uint8_t;
    #endif
    #endif
241
    #endif
242 243 244 245 246

    #ifndef _UINT16_T
    #define _UINT16_T
    #ifndef __uint16_t_defined
    #define __uint16_t_defined
247
    #ifndef uint16_t
248 249 250
    typedef unsigned $acx_cv_type_int16_t uint16_t;
    #endif
    #endif
251
    #endif
252 253 254 255 256

    #ifndef _UINT32_T
    #define _UINT32_T
    #ifndef __uint32_t_defined
    #define __uint32_t_defined
257
    #ifndef uint32_t
258 259 260
    typedef unsigned $acx_cv_type_int32_t uint32_t;
    #endif
    #endif
261
    #endif
262 263 264 265 266

    #ifndef _INT8_T
    #define _INT8_T
    #ifndef __int8_t_defined
    #define __int8_t_defined
267
    #ifndef int8_t
268 269 270
    typedef $acx_cv_type_int8_t int8_t;
    #endif
    #endif
271
    #endif
272 273 274 275 276

    #ifndef _INT16_T
    #define _INT16_T
    #ifndef __int16_t_defined
    #define __int16_t_defined
277
    #ifndef int16_t
278 279 280
    typedef $acx_cv_type_int16_t int16_t;
    #endif
    #endif
281
    #endif
282 283 284 285 286

    #ifndef _INT32_T
    #define _INT32_T
    #ifndef __int32_t_defined
    #define __int32_t_defined
287
    #ifndef int32_t
288 289 290
    typedef $acx_cv_type_int32_t int32_t;
    #endif
    #endif
291
    #endif
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
EOF
elif test "$ac_cv_type_u_int32_t" = yes; then
  sed 's/^ *//' >> tmp-stdint.h <<EOF

    /* int8_t int16_t int32_t defined by inet code, we do the u_intXX types */
    #ifndef _INT8_T
    #define _INT8_T
    #endif
    #ifndef _INT16_T
    #define _INT16_T
    #endif
    #ifndef _INT32_T
    #define _INT32_T
    #endif

    #ifndef _UINT8_T
    #define _UINT8_T
    #ifndef __uint8_t_defined
    #define __uint8_t_defined
311
    #ifndef uint8_t
312 313 314
    typedef u_int8_t uint8_t;
    #endif
    #endif
315
    #endif
316 317 318 319 320

    #ifndef _UINT16_T
    #define _UINT16_T
    #ifndef __uint16_t_defined
    #define __uint16_t_defined
321
    #ifndef uint16_t
322 323 324
    typedef u_int16_t uint16_t;
    #endif
    #endif
325
    #endif
326 327 328 329 330

    #ifndef _UINT32_T
    #define _UINT32_T
    #ifndef __uint32_t_defined
    #define __uint32_t_defined
331
    #ifndef uint32_t
332 333 334
    typedef u_int32_t uint32_t;
    #endif
    #endif
335
    #endif
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
EOF
else
  sed 's/^ *//' >> tmp-stdint.h <<EOF

    /* Some systems have guard macros to prevent redefinitions, define them.  */
    #ifndef _INT8_T
    #define _INT8_T
    #endif
    #ifndef _INT16_T
    #define _INT16_T
    #endif
    #ifndef _INT32_T
    #define _INT32_T
    #endif
    #ifndef _UINT8_T
    #define _UINT8_T
    #endif
    #ifndef _UINT16_T
    #define _UINT16_T
    #endif
    #ifndef _UINT32_T
    #define _UINT32_T
    #endif
EOF
fi

# ------------- done basic int types, emit int64_t types ------------
if test "$ac_cv_type_uint64_t" = yes; then
  sed 's/^ *//' >> tmp-stdint.h <<EOF

    /* system headers have good uint64_t and int64_t */
    #ifndef _INT64_T
    #define _INT64_T
    #endif
    #ifndef _UINT64_T
    #define _UINT64_T
    #endif
EOF
elif test "$ac_cv_type_u_int64_t" = yes; then
  sed 's/^ *//' >> tmp-stdint.h <<EOF

    /* system headers have an u_int64_t (and int64_t) */
    #ifndef _INT64_T
    #define _INT64_T
    #endif
    #ifndef _UINT64_T
    #define _UINT64_T
    #ifndef __uint64_t_defined
    #define __uint64_t_defined
385
    #ifndef uint64_t
386 387 388
    typedef u_int64_t uint64_t;
    #endif
    #endif
389
    #endif
390 391 392 393 394 395 396
EOF
elif test -n "$acx_cv_type_int64_t"; then
  sed 's/^ *//' >> tmp-stdint.h <<EOF

    /* architecture has a 64-bit type, $acx_cv_type_int64_t */
    #ifndef _INT64_T
    #define _INT64_T
397
    #ifndef int64_t
398 399
    typedef $acx_cv_type_int64_t int64_t;
    #endif
400
    #endif
401 402 403 404
    #ifndef _UINT64_T
    #define _UINT64_T
    #ifndef __uint64_t_defined
    #define __uint64_t_defined
405
    #ifndef uint64_t
406 407 408
    typedef unsigned $acx_cv_type_int64_t uint64_t;
    #endif
    #endif
409
    #endif
410 411 412 413 414 415 416 417 418
EOF
else
  sed 's/^ *//' >> tmp-stdint.h <<EOF

    /* some common heuristics for int64_t, using compiler-specific tests */
    #if defined __STDC_VERSION__ && (__STDC_VERSION__-0) >= 199901L
    #ifndef _INT64_T
    #define _INT64_T
    #ifndef __int64_t_defined
419
    #ifndef int64_t
420 421 422
    typedef long long int64_t;
    #endif
    #endif
423
    #endif
424 425
    #ifndef _UINT64_T
    #define _UINT64_T
426
    #ifndef uint64_t
427 428
    typedef unsigned long long uint64_t;
    #endif
429
    #endif
430 431 432 433 434 435 436 437 438 439 440

    #elif defined __GNUC__ && defined (__STDC__) && __STDC__-0
    /* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and
       does not implement __extension__.  But that compiler doesn't define
       __GNUC_MINOR__.  */
    # if __GNUC__ < 2 || (__NeXT__ && !__GNUC_MINOR__)
    # define __extension__
    # endif

    # ifndef _INT64_T
    # define _INT64_T
441
    # ifndef int64_t
442 443
    __extension__ typedef long long int64_t;
    # endif
444
    # endif
445 446
    # ifndef _UINT64_T
    # define _UINT64_T
447
    # ifndef uint64_t
448 449
    __extension__ typedef unsigned long long uint64_t;
    # endif
450
    # endif
451 452 453 454 455 456

    #elif !defined __STRICT_ANSI__
    # if defined _MSC_VER || defined __WATCOMC__ || defined __BORLANDC__

    #  ifndef _INT64_T
    #  define _INT64_T
457
    #  ifndef int64_t
458 459
    typedef __int64 int64_t;
    #  endif
460
    #  endif
461 462
    #  ifndef _UINT64_T
    #  define _UINT64_T
463
    #  ifndef uint64_t
464 465
    typedef unsigned __int64 uint64_t;
    #  endif
466
    #  endif
467 468 469 470 471 472 473 474 475 476 477 478
    # endif /* compiler */

    #endif /* ANSI version */
EOF
fi

# ------------- done int64_t types, emit intptr types ------------
if test "$ac_cv_type_uintptr_t" != yes; then
  sed 's/^ *//' >> tmp-stdint.h <<EOF

    /* Define intptr_t based on sizeof(void*) = $ac_cv_sizeof_void_p */
    #ifndef __uintptr_t_defined
479
    #ifndef uintptr_t
480 481
    typedef u$acx_cv_type_intptr_t uintptr_t;
    #endif
482
    #endif
483
    #ifndef __intptr_t_defined
484
    #ifndef intptr_t
485 486
    typedef $acx_cv_type_intptr_t  intptr_t;
    #endif
487
    #endif
488 489 490 491
EOF
fi

# ------------- done intptr types, emit int_least types ------------
492
if test "$ac_cv_type_int_least32_t" != yes; then
493
  sed 's/^ *//' >> tmp-stdint.h <<EOF
494 495 496 497 498

    /* Define int_least types */
    typedef int8_t     int_least8_t;
    typedef int16_t    int_least16_t;
    typedef int32_t    int_least32_t;
499
    #ifdef _INT64_T
500
    typedef int64_t    int_least64_t;
501
    #endif
502 503 504 505

    typedef uint8_t    uint_least8_t;
    typedef uint16_t   uint_least16_t;
    typedef uint32_t   uint_least32_t;
506
    #ifdef _UINT64_T
507
    typedef uint64_t   uint_least64_t;
508
    #endif
509 510 511
EOF
fi

512
# ------------- done intptr types, emit int_fast types ------------
513 514 515
if test "$ac_cv_type_int_fast32_t" != yes; then
  dnl NOTE: The following code assumes that sizeof (int) > 1.
  dnl Fix when strange machines are reported.
516
  sed 's/^ *//' >> tmp-stdint.h <<EOF
517 518 519 520 521

    /* Define int_fast types.  short is often slow */
    typedef int8_t       int_fast8_t;
    typedef int          int_fast16_t;
    typedef int32_t      int_fast32_t;
522
    #ifdef _INT64_T
523
    typedef int64_t      int_fast64_t;
524
    #endif
525 526 527 528

    typedef uint8_t      uint_fast8_t;
    typedef unsigned int uint_fast16_t;
    typedef uint32_t     uint_fast32_t;
529
    #ifdef _UINT64_T
530
    typedef uint64_t     uint_fast64_t;
531
    #endif
532 533 534
EOF
fi

535 536 537 538
if test "$ac_cv_type_uintmax_t" != yes; then
  sed 's/^ *//' >> tmp-stdint.h <<EOF

    /* Define intmax based on what we found */
539
    #ifndef intmax_t
540 541 542 543 544
    #ifdef _INT64_T
    typedef int64_t       intmax_t;
    #else
    typedef long          intmax_t;
    #endif
545 546
    #endif
    #ifndef uintmax_t
547 548 549 550 551
    #ifdef _UINT64_T
    typedef uint64_t      uintmax_t;
    #else
    typedef unsigned long uintmax_t;
    #endif
552
    #endif
553 554 555 556 557 558 559
EOF
fi

sed 's/^ *//' >> tmp-stdint.h <<EOF

  #endif /* GCC_GENERATED_STDINT_H */
EOF
560

561 562
if test -r ]_GCC_STDINT_H[ && cmp -s tmp-stdint.h ]_GCC_STDINT_H[; then
  rm -f tmp-stdint.h
563
else
564
  mv -f tmp-stdint.h ]_GCC_STDINT_H[
565 566 567
fi

], [
568 569 570 571 572 573 574 575 576 577 578 579 580
GCC="$GCC"
CC="$CC"
acx_cv_header_stdint="$acx_cv_header_stdint"
acx_cv_type_int8_t="$acx_cv_type_int8_t"
acx_cv_type_int16_t="$acx_cv_type_int16_t"
acx_cv_type_int32_t="$acx_cv_type_int32_t"
acx_cv_type_int64_t="$acx_cv_type_int64_t"
acx_cv_type_intptr_t="$acx_cv_type_intptr_t"
ac_cv_type_uintmax_t="$ac_cv_type_uintmax_t"
ac_cv_type_uintptr_t="$ac_cv_type_uintptr_t"
ac_cv_type_uint64_t="$ac_cv_type_uint64_t"
ac_cv_type_u_int64_t="$ac_cv_type_u_int64_t"
ac_cv_type_u_int32_t="$ac_cv_type_u_int32_t"
581 582
ac_cv_type_int_least32_t="$ac_cv_type_int_least32_t"
ac_cv_type_int_fast32_t="$ac_cv_type_int_fast32_t"
583
ac_cv_sizeof_void_p="$ac_cv_sizeof_void_p"
584 585 586
])

])