From: Alex Smith Date: Tue, 7 Sep 2010 19:54:44 +0000 (+0100) Subject: Let configure check for the varargs/_Bool interaction X-Git-Tag: 0.29~26 X-Git-Url: http://thyrsus.com/gitweb/?a=commitdiff_plain;h=3923d6eba0c5071b1c73a4d3e02f6ae0b6b1c365;p=intercal.git Let configure check for the varargs/_Bool interaction According to the C standard, passing _Bool via varargs is undefined behaviour. This lets autoconf check to see whether it actually works, and casts to int in the relevant location if it doesn't. (Recent gcc will compile an attempt to access a boolean via varargs into an illegal instruction.) --- diff --git a/configure.ac b/configure.ac index 948e331..4f2cf61 100644 --- a/configure.ac +++ b/configure.ac @@ -53,6 +53,51 @@ AC_TYPE_SIZE_T AC_TYPE_UINT16_T AC_TYPE_UINT32_T +# Some compilers (correctly according to the standard, but dubiously for +# actual use in code) dislike mixing _Bool and varargs. +if test "x$ac_cv_type__Bool" == "xyes" +then +AC_MSG_CHECKING([[whether booleans can be passed via varargs]]) +AC_RUN_IFELSE([AC_LANG_PROGRAM([[ +#include +#ifdef HAVE_STDARG_H +#include +void test(int x, ...) +#else +#include +void test(va_alist) va_dcl +#endif +{ + int y,z; + _Bool b; + va_list ap; +#ifdef HAVE_STDARG_H + va_start(ap, x); + y = x; +#else + va_start(ap); + y = va_arg(ap, int); +#endif + b = va_arg(ap, _Bool); + z = va_arg(ap, int); + if(b && x != z) exit(2); + if(!b && x == z) exit(3); +} +]],[[ +_Bool match = (_Bool)1; +_Bool nomatch = (_Bool) 0; +test(12345,match,12345); +test(23456,nomatch,1234); +exit(0); +]])],[AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no) +AC_DEFINE([BOOL_VARARGS_BROKEN],[],dnl +[Define if _Bool works but cannot be passed via varargs.]) +],[AC_MSG_RESULT([[unknown in a cross-compile, assuming no]]) +AC_DEFINE([BOOL_VARARGS_BROKEN],[],dnl +[Define if _Bool works but cannot be passed via varargs.]) +]) +fi + AC_MSG_CHECKING([[whether yyrestart() is needed]]) # Write a lex program that will cause an error if yyrestart exists. echo '%% diff --git a/src/cesspool.c b/src/cesspool.c index e1129b3..eb55b1f 100644 --- a/src/cesspool.c +++ b/src/cesspool.c @@ -632,7 +632,11 @@ void ick_resize(va_alist) va_dcl type = va_arg(ap, unsigned int); #endif a = va_arg(ap, ick_array*); +#ifdef BOOL_VARARGS_BROKEN + forget = (bool)va_arg(ap, int); +#else forget = va_arg(ap, bool); +#endif /* AIS: a->dims is no longer initialised. So initialise it here if it isn't already initialised, with an annotation to explain that diff --git a/src/feh2.c b/src/feh2.c index 99b4be5..3eb7148 100644 --- a/src/feh2.c +++ b/src/feh2.c @@ -2099,8 +2099,13 @@ void emit(tuple *tn, FILE *fp) dim++; (void) fprintf(fp, "\t""ick_resize("); prvar(np->lval, fp, 1); +#ifdef BOOL_VARARGS_BROKEN + (void) fprintf(fp, ", (int)%s[%lu]", nameof(np->lval->opcode, forgetbits), + np->lval->constant); +#else (void) fprintf(fp, ", %s[%lu]", nameof(np->lval->opcode, forgetbits), np->lval->constant); +#endif (void) fprintf(fp, ", %d", dim); for (sp = np->rval; sp; sp = sp->rval) { (void) fprintf(fp, ", (size_t)");