From 20167d0a5fd7646d101e55e68e282da36ed6463a Mon Sep 17 00:00:00 2001 From: Keith Marshall Date: Sat, 30 Aug 2008 17:27:18 +0000 Subject: Implement conditional replacement for printf() family functions. --- winsup/mingw/ChangeLog | 32 ++++++++++ winsup/mingw/include/_mingw.h | 74 ++++++++++++++++++----- winsup/mingw/include/stdio.h | 132 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 214 insertions(+), 24 deletions(-) diff --git a/winsup/mingw/ChangeLog b/winsup/mingw/ChangeLog index 0d6c2f677..f01c00926 100644 --- a/winsup/mingw/ChangeLog +++ b/winsup/mingw/ChangeLog @@ -1,3 +1,35 @@ +2008-08-30 Keith Marshall + + Implement conditional replacement for printf() family functions. + + * include/_mingw.h (__USE_MINGW_ANSI_STDIO): New macro; define it. + (__MINGW_ANSI_STDIO__): New manifest constant; define as bitmapped + flag for use in user specified __MINGW_FEATURES__ attribute. + (__MINGW_LC_MESSAGES__, __MINGW_LC_ENVVARS__): New manifest constants; + currently unused: reserved as components of... + (__MINGW_LC_EXTENSIONS__): ...this new manifest constant; earmarked as + a __MINGW_FEATURES__ enhancement to setlocale(). + + * include/stdio.h (__mingw_printf, __mingw_vprintf): Prototype them. + (__mingw_fprintf, __mingw_vfprintf): Likewise. + (__mingw_sprintf, __mingw_vsprintf): Likewise. + (__msvcrt_printf, __msvcrt_vprintf): Likewise. + (__msvcrt_fprintf, __msvcrt_vfprintf): Likewise. + (__msvcrt_sprintf, __msvcrt_vsprintf): Likewise. + (printf, vprintf) [!__USE_MINGW_ANSI_STDIO]: Prototype for default + usage; link to DLL import stub, importing from MSVCRT. + (fprintf, vfprintf) [!__USE_MINGW_ANSI_STDIO]: Likewise. + (sprintf, vsprintf) [!__USE_MINGW_ANSI_STDIO]: Likewise. + (printf) [__USE_MINGW_ANSI_STDIO]: Redirect to __mingw_printf; use + locally defined static stub implementation. + (fprintf, sprintf) [__USE_MINGW_ANSI_STDIO]: Likewise; redirect to + __mingw_fprintf and __mingw_sprintf respectively. + (vprintf) [__USE_MINGW_ANSI_STDIO]: Redirect to __mingw_vprintf; use + static inline implementation for C++ and GNU C, or locally defined + static stub otherwise. + (vfprintf, vsprintf) [__USE_MINGW_ANSI_STDIO]: Likewise; redirect to + __mingw_vfprintf and __mingw_vsprintf respectively. + 2008-08-27 Keith Marshall Avoid access violations, passing NULL to printf( "...%s..." ); diff --git a/winsup/mingw/include/_mingw.h b/winsup/mingw/include/_mingw.h index 230727219..65f23a598 100644 --- a/winsup/mingw/include/_mingw.h +++ b/winsup/mingw/include/_mingw.h @@ -1,3 +1,4 @@ +#ifndef __MINGW_H /* * _mingw.h * @@ -19,10 +20,12 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * */ - -#ifndef __MINGW_H #define __MINGW_H +#define __MINGW32_VERSION 3.14 +#define __MINGW32_MAJOR_VERSION 3 +#define __MINGW32_MINOR_VERSION 14 + #if __GNUC__ >= 3 #pragma GCC system_header #endif @@ -30,24 +33,45 @@ /* These are defined by the user (or the compiler) to specify how identifiers are imported from a DLL. - __DECLSPEC_SUPPORTED Defined if dllimport attribute is supported. - __MINGW_IMPORT The attribute definition to specify imported - variables/functions. - _CRTIMP As above. For MS compatibility. - __MINGW32_VERSION Runtime version. - __MINGW32_MAJOR_VERSION Runtime major version. - __MINGW32_MINOR_VERSION Runtime minor version. - __MINGW32_BUILD_DATE Runtime build date. + __DECLSPEC_SUPPORTED Defined if dllimport attribute is supported. + __MINGW_IMPORT The attribute definition to specify imported + variables/functions. + _CRTIMP As above. For MS compatibility. + __MINGW32_VERSION Runtime version. + __MINGW32_MAJOR_VERSION Runtime major version. + __MINGW32_MINOR_VERSION Runtime minor version. + __MINGW32_BUILD_DATE Runtime build date. + + Macros to enable MinGW features which deviate from standard MSVC + compatible behaviour; these may be specified directly in user code, + activated implicitly, (e.g. by specifying _POSIX_C_SOURCE or such), + or by inclusion in __MINGW_FEATURES__: + + __USE_MINGW_ANSI_STDIO Select a more ANSI C99 compatible + implementation of printf() and friends. Other macros: - __int64 define to be long long. Using a typedef doesn't - work for "unsigned __int64" + __int64 define to be long long. Using a typedef + doesn't work for "unsigned __int64" All headers should include this first, and then use __DECLSPEC_SUPPORTED to choose between the old ``__imp__name'' style or __MINGW_IMPORT style declarations. */ + +/* Manifest definitions identifying the flag bits, controlling activation + * of MinGW features, as specified by the user in __MINGW_FEATURES__. + */ +#define __MINGW_ANSI_STDIO__ 0x0000000000000001ULL +/* + * The following three are not yet formally supported; they are + * included here, to document anticipated future usage. + */ +#define __MINGW_LC_EXTENSIONS__ 0x0000000000000050ULL +#define __MINGW_LC_MESSAGES__ 0x0000000000000010ULL +#define __MINGW_LC_ENVVARS__ 0x0000000000000040ULL + /* Try to avoid problems with outdated checks for GCC __attribute__ support. */ #undef __attribute__ @@ -188,8 +212,28 @@ allow GCC to optimize away some EH unwind code, at least in DW2 case. */ # define __MSVCRT_VERSION__ 0x0600 #endif -#define __MINGW32_VERSION 3.14 -#define __MINGW32_MAJOR_VERSION 3 -#define __MINGW32_MINOR_VERSION 14 +/* Activation of MinGW specific extended features: + */ +#ifndef __USE_MINGW_ANSI_STDIO +/* + * If user didn't specify it explicitly... + */ +# if defined __STRICT_ANSI__ || defined _ISOC99_SOURCE \ + || defined _POSIX_SOURCE || defined _POSIX_C_SOURCE \ + || defined _XOPEN_SOURCE || defined _XOPEN_SOURCE_EXTENDED \ + || defined _GNU_SOURCE || defined _BSD_SOURCE \ + || defined _SVID_SOURCE + /* + * but where any of these source code qualifiers are specified, + * then assume ANSI I/O standards are preferred over Microsoft's... + */ +# define __USE_MINGW_ANSI_STDIO 1 +# else + /* + * otherwise use whatever __MINGW_FEATURES__ specifies... + */ +# define __USE_MINGW_ANSI_STDIO (__MINGW_FEATURES__ & __MINGW_ANSI_STDIO__) +# endif +#endif #endif /* __MINGW_H */ diff --git a/winsup/mingw/include/stdio.h b/winsup/mingw/include/stdio.h index c01de5efd..c05b1b1dd 100644 --- a/winsup/mingw/include/stdio.h +++ b/winsup/mingw/include/stdio.h @@ -194,16 +194,130 @@ _CRTIMP void __cdecl __MINGW_NOTHROW setbuf (FILE*, char*); /* * Formatted Output + * + * MSVCRT implementations are not ANSI C99 conformant... + * we offer these conforming alternatives from libmingwex.a + */ +#undef __mingw_stdio_redirect__ +#define __mingw_stdio_redirect__(F) __cdecl __MINGW_NOTHROW __mingw_##F + +extern int __mingw_stdio_redirect__(fprintf)(FILE*, const char*, ...); +extern int __mingw_stdio_redirect__(printf)(const char*, ...); +extern int __mingw_stdio_redirect__(sprintf)(char*, const char*, ...); +extern int __mingw_stdio_redirect__(snprintf)(char*, size_t, const char*, ...); +extern int __mingw_stdio_redirect__(vfprintf)(FILE*, const char*, __VALIST); +extern int __mingw_stdio_redirect__(vprintf)(const char*, __VALIST); +extern int __mingw_stdio_redirect__(vsprintf)(char*, const char*, __VALIST); +extern int __mingw_stdio_redirect__(vsnprintf)(char*, size_t, const char*, __VALIST); + +#if __USE_MINGW_ANSI_STDIO +/* + * User has expressed a preference for C99 conformance... */ +# undef __mingw_stdio_redirect__ +# ifdef __cplusplus +/* + * For C++ we use inline implementations, to avoid interference + * with namespace qualification, which may result from using #defines. + */ +# define __mingw_stdio_redirect__ static inline __cdecl __MINGW_NOTHROW + +# elif defined __GNUC__ +/* + * FIXME: Is there any GCC version prerequisite here? + * + * We also prefer inline implementations for C, when we can be confident + * that the GNU specific __inline__ mechanism is supported. + */ +# define __mingw_stdio_redirect__ static __inline__ __cdecl __MINGW_NOTHROW + +# else +/* + * Can't use inlines; fall back on module local static stubs. + */ +# define __mingw_stdio_redirect__ static __cdecl __MINGW_NOTHROW +# endif + +__mingw_stdio_redirect__ +int fprintf (FILE *__stream, const char *__format, ...) +{ + register int __retval; + __builtin_va_list __argv; __builtin_va_start( __argv, __format ); + __retval = __mingw_vfprintf( __stream, __format, __argv ); + __builtin_va_end( __argv ); + return __retval; +} + +__mingw_stdio_redirect__ +int printf (const char *__format, ...) +{ + register int __retval; + __builtin_va_list __argv; __builtin_va_start( __argv, __format ); + __retval = __mingw_vprintf( __format, __argv ); + __builtin_va_end( __argv ); + return __retval; +} + +__mingw_stdio_redirect__ +int sprintf (char *__stream, const char *__format, ...) +{ + register int __retval; + __builtin_va_list __argv; __builtin_va_start( __argv, __format ); + __retval = __mingw_vsprintf( __stream, __format, __argv ); + __builtin_va_end( __argv ); + return __retval; +} -_CRTIMP int __cdecl __MINGW_NOTHROW fprintf (FILE*, const char*, ...); -_CRTIMP int __cdecl __MINGW_NOTHROW printf (const char*, ...); -_CRTIMP int __cdecl __MINGW_NOTHROW sprintf (char*, const char*, ...); -_CRTIMP int __cdecl __MINGW_NOTHROW _snprintf (char*, size_t, const char*, ...); -_CRTIMP int __cdecl __MINGW_NOTHROW vfprintf (FILE*, const char*, __VALIST); -_CRTIMP int __cdecl __MINGW_NOTHROW vprintf (const char*, __VALIST); -_CRTIMP int __cdecl __MINGW_NOTHROW vsprintf (char*, const char*, __VALIST); -_CRTIMP int __cdecl __MINGW_NOTHROW _vsnprintf (char*, size_t, const char*, __VALIST); +__mingw_stdio_redirect__ +int vfprintf (FILE *__stream, const char *__format, __VALIST __argv) +{ + return __mingw_vfprintf( __stream, __format, __argv ); +} + +__mingw_stdio_redirect__ +int vprintf (const char *__format, __VALIST __argv) +{ + return __mingw_vprintf( __format, __argv ); +} + +__mingw_stdio_redirect__ +int vsprintf (char *__stream, const char *__format, __VALIST __argv) +{ + return __mingw_vsprintf( __stream, __format, __argv ); +} + +#else +/* + * Default configuration: simply direct all calls to MSVCRT... + */ +_CRTIMP int __cdecl __MINGW_NOTHROW fprintf (FILE*, const char*, ...); +_CRTIMP int __cdecl __MINGW_NOTHROW printf (const char*, ...); +_CRTIMP int __cdecl __MINGW_NOTHROW sprintf (char*, const char*, ...); +_CRTIMP int __cdecl __MINGW_NOTHROW vfprintf (FILE*, const char*, __VALIST); +_CRTIMP int __cdecl __MINGW_NOTHROW vprintf (const char*, __VALIST); +_CRTIMP int __cdecl __MINGW_NOTHROW vsprintf (char*, const char*, __VALIST); + +#endif +/* + * Regardless of user preference, always offer these alternative + * entry points, for direct access to the MSVCRT implementations. + */ +#undef __mingw_stdio_redirect__ +#define __mingw_stdio_redirect__(F) __cdecl __MINGW_NOTHROW __msvcrt_##F + +_CRTIMP int __mingw_stdio_redirect__(fprintf)(FILE*, const char*, ...); +_CRTIMP int __mingw_stdio_redirect__(printf)(const char*, ...); +_CRTIMP int __mingw_stdio_redirect__(sprintf)(char*, const char*, ...); +_CRTIMP int __mingw_stdio_redirect__(vfprintf)(FILE*, const char*, __VALIST); +_CRTIMP int __mingw_stdio_redirect__(vprintf)(const char*, __VALIST); +_CRTIMP int __mingw_stdio_redirect__(vsprintf)(char*, const char*, __VALIST); + +#undef __mingw_stdio_redirect__ + +/* The following pair ALWAYS refer to the MSVCRT implementations... + */ +_CRTIMP int __cdecl __MINGW_NOTHROW _snprintf (char*, size_t, const char*, ...); +_CRTIMP int __cdecl __MINGW_NOTHROW _vsnprintf (char*, size_t, const char*, __VALIST); #ifndef __NO_ISOCEXT /* externs in libmingwex.a */ /* @@ -213,7 +327,7 @@ _CRTIMP int __cdecl __MINGW_NOTHROW _vsnprintf (char*, size_t, const char*, __VA * compatible with C99, but the following are; if you want the MSVCRT * behaviour, you *must* use the Microsoft uglified names. */ -int __cdecl __MINGW_NOTHROW snprintf(char *, size_t, const char *, ...); +int __cdecl __MINGW_NOTHROW snprintf (char *, size_t, const char *, ...); int __cdecl __MINGW_NOTHROW vsnprintf (char *, size_t, const char *, __VALIST); int __cdecl __MINGW_NOTHROW vscanf (const char * __restrict__, __VALIST); -- cgit v1.2.3