| # va_copy.m4 serial 1 (js-1.6.20070208) |
| |
| dnl ## |
| dnl ## Check for C99 va_copy() implementation |
| dnl ## (and provide fallback implementation if neccessary) |
| dnl ## |
| dnl ## configure.in: |
| dnl ## AC_CHECK_VA_COPY |
| dnl ## foo.c: |
| dnl ## #include "config.h" |
| dnl ## [...] |
| dnl ## va_copy(d,s) |
| dnl ## |
| dnl ## This check is rather complex: first because we really have to |
| dnl ## try various possible implementations in sequence and second, we |
| dnl ## cannot define a macro in config.h with parameters directly. |
| dnl ## |
| |
| dnl # test program for va_copy() implementation |
| changequote(<<,>>) |
| m4_define(__va_copy_test, <<[ |
| #include <stdlib.h> |
| #include <stdarg.h> |
| #include <string.h> |
| #define DO_VA_COPY(d, s) $1 |
| void test(char *str, ...) |
| { |
| va_list ap, ap2; |
| int i; |
| va_start(ap, str); |
| DO_VA_COPY(ap2, ap); |
| for (i = 1; i <= 9; i++) { |
| int k = (int)va_arg(ap, int); |
| if (k != i) |
| abort(); |
| } |
| DO_VA_COPY(ap, ap2); |
| for (i = 1; i <= 9; i++) { |
| int k = (int)va_arg(ap, int); |
| if (k != i) |
| abort(); |
| } |
| va_end(ap); |
| } |
| int main(int argc, char *argv[]) |
| { |
| test("test", 1, 2, 3, 4, 5, 6, 7, 8, 9); |
| exit(0); |
| } |
| ]>>) |
| changequote([,]) |
| |
| dnl # test driver for va_copy() implementation |
| m4_define(__va_copy_check, [ |
| AH_VERBATIM($1, |
| [/* Predefined possible va_copy() implementation (id: $1) */ |
| #define __VA_COPY_USE_$1(d, s) $2]) |
| if test ".$ac_cv_va_copy" = .; then |
| AC_TRY_RUN(__va_copy_test($2), [ac_cv_va_copy="$1"]) |
| fi |
| ]) |
| |
| dnl # Autoconf check for va_copy() implementation checking |
| AC_DEFUN([AC_CHECK_VA_COPY],[ |
| dnl # provide Autoconf display check message |
| AC_MSG_CHECKING(for va_copy() function) |
| dnl # check for various implementations in priorized sequence |
| AC_CACHE_VAL(ac_cv_va_copy, [ |
| ac_cv_va_copy="" |
| dnl # 1. check for standardized C99 macro |
| __va_copy_check(C99, [va_copy((d), (s))]) |
| dnl # 2. check for alternative/deprecated GCC macro |
| __va_copy_check(GCM, [VA_COPY((d), (s))]) |
| dnl # 3. check for internal GCC macro (high-level define) |
| __va_copy_check(GCH, [__va_copy((d), (s))]) |
| dnl # 4. check for internal GCC macro (built-in function) |
| __va_copy_check(GCB, [__builtin_va_copy((d), (s))]) |
| dnl # 5. check for assignment approach (assuming va_list is a struct) |
| __va_copy_check(ASS, [do { (d) = (s); } while (0)]) |
| dnl # 6. check for assignment approach (assuming va_list is a pointer) |
| __va_copy_check(ASP, [do { *(d) = *(s); } while (0)]) |
| dnl # 7. check for memory copying approach (assuming va_list is a struct) |
| __va_copy_check(CPS, [memcpy((void *)&(d), (void *)&(s)), sizeof((s))]) |
| dnl # 8. check for memory copying approach (assuming va_list is a pointer) |
| __va_copy_check(CPP, [memcpy((void *)(d), (void *)(s)), sizeof(*(s))]) |
| if test ".$ac_cv_va_copy" = .; then |
| AC_ERROR([no working implementation found]) |
| fi |
| ]) |
| dnl # optionally activate the fallback implementation |
| if test ".$ac_cv_va_copy" = ".C99"; then |
| AC_DEFINE(HAVE_VA_COPY, 1, [Define if va_copy() macro exists (and no fallback implementation is required)]) |
| fi |
| dnl # declare which fallback implementation to actually use |
| AC_DEFINE_UNQUOTED([__VA_COPY_USE], [__VA_COPY_USE_$ac_cv_va_copy], |
| [Define to id of used va_copy() implementation]) |
| dnl # provide activation hook for fallback implementation |
| AH_VERBATIM([__VA_COPY_ACTIVATION], |
| [/* Optional va_copy() implementation activation */ |
| #ifndef HAVE_VA_COPY |
| #define va_copy(d, s) __VA_COPY_USE(d, s) |
| #endif |
| ]) |
| dnl # provide Autoconf display result message |
| if test ".$ac_cv_va_copy" = ".C99"; then |
| AC_MSG_RESULT([yes]) |
| else |
| AC_MSG_RESULT([no (using fallback implementation)]) |
| fi |
| ]) |
| |