diff --git a/ChangeLog b/ChangeLog index 364de2477..bfcbca465 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2007-04-15 Richard Frith-Macdonald + + * configure.ac: check for wide character support in printf + * config/config.wprintf.c: ditto + * configure: regenerate + * Headers/Additions/GNUstepBase/config.h.in: regenerate + * Source/NSString.m: Don't use wide char support if we don't have it. + Should fix bug #19587 + 2007-04-15 Richard Frith-Macdonald * Source/NSBundle.m: diff --git a/Headers/Additions/GNUstepBase/config.h.in b/Headers/Additions/GNUstepBase/config.h.in index 299ada32a..cfc20120b 100644 --- a/Headers/Additions/GNUstepBase/config.h.in +++ b/Headers/Additions/GNUstepBase/config.h.in @@ -525,6 +525,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_WCHAR_H +/* Define if register_printf_function supports wide characters */ +#undef HAVE_WIDE_PRINTF_FUNCTION + /* Define to 1 if you have the header file. */ #undef HAVE_WINDOWS_H @@ -558,25 +561,25 @@ /* Define to 1 if the `setpgrp' function takes no argument. */ #undef SETPGRP_VOID -/* The size of a `double', as computed by sizeof. */ +/* The size of `double', as computed by sizeof. */ #undef SIZEOF_DOUBLE -/* The size of a `float', as computed by sizeof. */ +/* The size of `float', as computed by sizeof. */ #undef SIZEOF_FLOAT -/* The size of a `int', as computed by sizeof. */ +/* The size of `int', as computed by sizeof. */ #undef SIZEOF_INT -/* The size of a `long', as computed by sizeof. */ +/* The size of `long', as computed by sizeof. */ #undef SIZEOF_LONG -/* The size of a `long long', as computed by sizeof. */ +/* The size of `long long', as computed by sizeof. */ #undef SIZEOF_LONG_LONG -/* The size of a `short', as computed by sizeof. */ +/* The size of `short', as computed by sizeof. */ #undef SIZEOF_SHORT -/* The size of a `void*', as computed by sizeof. */ +/* The size of `void*', as computed by sizeof. */ #undef SIZEOF_VOIDP /* Define to 1 if you have the ANSI C header files. */ @@ -604,5 +607,5 @@ #undef inline #endif -/* Define to `unsigned' if does not define. */ +/* Define to `unsigned int' if does not define. */ #undef size_t diff --git a/Source/NSString.m b/Source/NSString.m index 6317227cf..541d91507 100644 --- a/Source/NSString.m +++ b/Source/NSString.m @@ -515,6 +515,8 @@ handle_printf_atsign (FILE *stream, string_object = *((id*) ptr); #endif string_object = [string_object description]; + +#if HAVE_WIDE_PRINTF_FUNCTION if (info->wide) { if (sizeof(wchar_t) == 4) @@ -539,6 +541,7 @@ handle_printf_atsign (FILE *stream, } } else +#endif /* HAVE_WIDE_PRINTF_FUNCTION */ { len = fprintf(stream, "%*s", (info->left ? - info->width : info->width), @@ -1084,7 +1087,9 @@ handle_printf_atsign (FILE *stream, f._contents.c = buf; f._capacity = sizeof(buf); f._count = 0; +#if HAVE_WIDE_PRINTF_FUNCTION f._flags.wide = 0; +#endif /* HAVE_WIDE_PRINTF_FUNCTION */ f._flags.free = 0; GSPrivateFormat(&f, fmt, argList, locale); GSPrivateStrExternalize(&f); @@ -1101,11 +1106,13 @@ handle_printf_atsign (FILE *stream, * the temporary buffer) for large strings. For most strings, the * on-stack memory will have been used, so we will get better performance. */ +#if HAVE_WIDE_PRINTF_FUNCTION if (f._flags.wide == 1) { self = [self initWithCharacters: f._contents.u length: f._count]; } else +#endif /* HAVE_WIDE_PRINTF_FUNCTION */ { self = [self initWithCString: (char*)f._contents.c length: f._count]; } diff --git a/config/config.wprintf.c b/config/config.wprintf.c new file mode 100644 index 000000000..8f7d82fe8 --- /dev/null +++ b/config/config.wprintf.c @@ -0,0 +1,79 @@ +/* See if we have a broken register_printf function (e.g. an old version of glibc) */ +/* + Copyright (C) 2005 Free Software Foundation + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. +*/ +#include +#include +#include + +/* , with libc-5.3.9 thinks this + flag PRINTF_ATSIGN_VA_LIST should be 0, but for me, with libc-5.0.9, + it crashes. -mccallum + + Apparently GNU libc 2.xx needs this to be 0 also, along with Linux + libc versions 5.2.xx and higher (including libc6, which is just GNU + libc). -chung */ +#define PRINTF_ATSIGN_VA_LIST \ + (defined(_LINUX_C_LIB_VERSION_MINOR) \ + && _LINUX_C_LIB_VERSION_MAJOR <= 5 \ + && _LINUX_C_LIB_VERSION_MINOR < 2) + +#if ! PRINTF_ATSIGN_VA_LIST +static int +arginfo_func (const struct printf_info *info, size_t n, int *argtypes) +{ + *argtypes = PA_POINTER; + return 1; +} +#endif /* !PRINTF_ATSIGN_VA_LIST */ + +static int +handle_printf_atsign (FILE *stream, + const struct printf_info *info, +#if PRINTF_ATSIGN_VA_LIST + va_list *ap_pointer) +#elif defined(_LINUX_C_LIB_VERSION_MAJOR) \ + && _LINUX_C_LIB_VERSION_MAJOR < 6 + const void **const args) +#else /* GNU libc needs the following. */ + const void *const *args) +#endif +{ +#if ! PRINTF_ATSIGN_VA_LIST + const void *ptr = *args; +#endif + char * string_object; + int len = 0; + + /* xxx This implementation may not pay pay attention to as much + of printf_info as it should. */ + +#if PRINTF_ATSIGN_VA_LIST + string_object = va_arg (*ap_pointer, char *); +#else + string_object = *((char **) ptr); +#endif + if (info->wide == 0) + len = fprintf(stream, "%s", string_object); + return len; +} + +int main() +{ + char *d = "hi there"; + + register_printf_function ('@', + handle_printf_atsign, +#if PRINTF_ATSIGN_VA_LIST + 0); +#else + arginfo_func); +#endif + + printf("test %s = %@\n", d, d); + return 0; +} diff --git a/configure b/configure index 205a93220..5d90b8ad5 100755 --- a/configure +++ b/configure @@ -14652,9 +14652,61 @@ cat >>confdefs.h <<\_ACEOF #define HAVE_REGISTER_PRINTF_FUNCTION 1 _ACEOF + if test "$cross_compiling" = yes; then + wide_register_printf=1 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include "$srcdir/config/config.wprintf.c" +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + wide_register_printf=1 +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +wide_register_printf=0 +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + if test $wide_register_printf = 1; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_WIDE_PRINTF_FUNCTION 1 +_ACEOF + + fi fi fi + #-------------------------------------------------------------------- # This function needed by NSString. #-------------------------------------------------------------------- diff --git a/configure.ac b/configure.ac index 96fffa5db..5a8acfb19 100644 --- a/configure.ac +++ b/configure.ac @@ -1641,9 +1641,17 @@ if test $register_printf = 1; then if test $working_register_printf = 1; then AC_DEFINE(HAVE_REGISTER_PRINTF_FUNCTION,1, [Define if you have the register_printf_function function]) + AC_TRY_RUN([#include "$srcdir/config/config.wprintf.c"], + wide_register_printf=1, wide_register_printf=0, + wide_register_printf=1) + if test $wide_register_printf = 1; then + AC_DEFINE(HAVE_WIDE_PRINTF_FUNCTION,1, + [Define if register_printf_function supports wide characters]) + fi fi fi + #-------------------------------------------------------------------- # This function needed by NSString. #--------------------------------------------------------------------