1# Check for the presence of C99 features.  Generally the check will fail
2# if the feature isn't present (a C99 compiler isn't that much to ask,
3# right?).
4
5# Check C99-style variadic macros (required):
6#
7#  #define PRINTF(msg, ...) (printf(msg, __VA_ARGS__)
8#
9AC_DEFUN([AC_C99_VARIADIC_MACROS],
10[
11  dnl Check for variadic macros
12  AC_CACHE_CHECK([for C99 variadic macros],
13    [ac_cv_c99_variadic_macros],
14     [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>
15           #define MSG(...) fprintf(stderr, __VA_ARGS__)
16          ]], [[MSG("foo");
17           MSG("%s", "foo");
18           MSG("%s%d", "foo", 1);]])],[ac_cv_c99_variadic_macros=yes],[ac_cv_c99_variadic_macros=no])])
19  if test "x${ac_cv_c99_variadic_macros}" != "xyes"; then
20    AC_MSG_ERROR([A compiler supporting C99 variadic macros is required])
21  fi
22])
23
24# Check C99-style variable-sized arrays (required):
25#
26#   char concat_str[strlen(s1) + strlen(s2) + 1];
27#
28AC_DEFUN([AC_C99_VARIABLE_ARRAYS],
29[
30  dnl Check for variable arrays
31  AC_CACHE_CHECK([for C99 variable arrays],
32    [ac_cv_c99_variable_arrays],
33    [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
34#include <string.h>
35#include <stdio.h>
36]], [[char *s1 = "foo", *s2 = "bar";
37         char s3[strlen(s1) + strlen(s2) + 1];
38         sprintf(s3, "%s%s", s1, s2);]])],[ac_cv_c99_variable_arrays=yes],[ac_cv_c99_variable_arrays=no])])
39  if test "x${ac_cv_c99_variable_arrays}" != "xyes"; then
40    AC_MSG_ERROR([A compiler supporting C99 variable arrays is required])
41  fi
42])
43
44# Check C99-style initializers (required):
45#
46# Examples:
47#   struct timeval tv = {.tv_sec = 0, .tv_usec = 500000};
48#   int fibonacci[6] = {[0] = 0, [1] = 1, [2] = 1, [3] = 2, [4] = 3, [5] = 5};
49# Note we do not check for multi-field initializers like
50#   struct { struct { int b; } a; } = {.a.b = 5}
51# which are not supported by many compilers.  It is best to avoid this
52# problem by writing these using nesting.  The above case becomes
53#   struct { struct { int b; } a; } = {.a = {.b = 5}}
54AC_DEFUN([AC_C99_INITIALIZERS],
55[
56  dnl Check for C99 initializers
57  AC_CACHE_CHECK([for C99 initializers],
58    [ac_cv_c99_initializers],
59    [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[struct foo {
60           int an_integer;
61           char *a_string;
62           int an_array[5];
63           union {int x, y;} a_union;
64         };
65        ]], [[struct foo bar = {.an_array = {0, [3] = 2, [2] = 1, [4] = 3},
66                           .an_integer = 999,
67                           .a_string = "does it work?",
68                           .a_union = {.y = 243}};]])],[ac_cv_c99_initializers=yes],[ac_cv_c99_initializers=no])])
69  if test "${ac_cv_c99_initializers}" != "yes"; then
70    AC_MSG_ERROR([A compiler supporting C99 initializers is required])
71  fi
72])
73
74# Check C99-style stdint.h (required)
75AC_DEFUN([AC_C99_STDINT_H],
76[
77  AC_CHECK_HEADERS([stdint.h])
78  dnl Check for C99 stdint.h
79  AC_CACHE_CHECK([for C99 stdint.h],
80    [ac_cv_c99_stdint_h],
81    [ac_cv_c99_stdint_h=$ac_cv_header_stdint_h])
82  if test "${ac_cv_c99_stdint_h}" != "yes"; then
83    AC_MSG_ERROR([A compiler supporting C99's stdint.h is required])
84  fi
85])
86
87# Check that token concenation works as we expect
88#
89AC_DEFUN([FC_C99_TOKEN_CONCENATION],
90[
91AC_CACHE_CHECK([whether preprocessor token concenation works],
92  [ac_cv_c99_token_concenation],
93  [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#define COMBINE(a, b) a ## b
94  #define CALLER(...) COMBINE(, __VA_ARGS__)]],
95    [[CALLER();
96    char *text = CALLER("string");]])],
97  [ac_cv_c99_token_concenation=yes],[ac_cv_c99_token_concenation=no])])
98  if test "x${ac_cv_c99_token_concenation}" != "xyes" ; then
99    AC_MSG_ERROR([A preprocessor supporting token concenation is required])
100  fi
101])
102