+2015-12-27 Keith Marshall <keithmarshall@users.sourceforge.net>
+
+ Improve ISO-C conformity in MinGW printf(); cf. MinGW-Bug [#1761]
+
+ * mingwex/ofmtctl.c: New file; it implements...
+ (_mingw_output_format_control): ...this new function; it provides
+ additional MinGW specific printf() format processing options.
+
+ * Makefile.in (libmingwex.a) [prerequisites]: Add ofmtctl.$OBJEXT
+
+ * include/stdio.h (_mingw_output_format_control): Declare it.
+ (_EXPONENT_DIGIT_MASK, _MSVC_PRINTF_QUIRKS, _QUERY_MSVC_PRINTF_QUIRKS)
+ (_ENABLE_MSVC_PRINTF_QUIRKS, _DISABLE_MSVC_PRINTF_QUIRKS): New
+ manifest constant expressions; define them.
+
+ * mingwex/stdio/pformat.c: Revise licensing terms.
+ (__pformat) [%le, %lE, %lf, %lF, %lg, %lG, %lx, %lX]: When...
+ [_mingw_output_format_flag & _MSVC_PRINTF_QUIRKS == 0]: ...ignore `l'
+ modifier; this matches the behaviour specified by ISO-C99, else...
+ [_mingw_output_format_flag & _MSVC_PRINTF_QUIRKS != 0]: ...revert to
+ previous MSVC compatible behaviour, treating it as an `L' modifier.
+ [!_WIN32] (_MSVC_PRINTF_QUIRKS): Force the zero match case.
+
+ * mingwex/ofmt.c (ARGLIST): Subsume references to...
+ (ARGTYPE): ...this now obsolete macro; delete it throughout.
+ (update_output_format_flag): New inline function; it restricts flag
+ operations to affect only Microsoft's exponent digit bits.
+ [FUNCTION == _set_output_format]: Use it.
+ [FUNCTION == _get_output_format]: Likewise.
+
2015-10-23 Keith Marshall <keithmarshall@users.sourceforge.net>
Make atof() and strtod() conform to ISO-C; fix MinGW-Bug [#2273]
# compatibility than their Microsoft equivalents.
#
vpath %.c ${mingwrt_srcdir}/mingwex/stdio
-libmingwex.a: $(addsuffix .$(OBJEXT), btowc fprintf fseeko64 pformat \
- printf snprintf snwprintf sprintf vfprintf vfscanf vfwscanf vprintf \
- vscanf vsnprintf vsnwprintf vsprintf vsscanf vswscanf vwscanf)
+libmingwex.a: $(addsuffix .$(OBJEXT), btowc fprintf fseeko64 ofmtctl pformat \
+ printf snprintf snwprintf sprintf vfprintf vfscanf vfwscanf vprintf vscanf \
+ vsnprintf vsnwprintf vsprintf vsscanf vswscanf vwscanf)
# pformat.$(OBJEXT) needs an explicit build rule, since we need to
# specify an additional header file path.
#endif /* __STRICT_ANSI__ */
_CRTIMP int __cdecl __MINGW_NOTHROW setvbuf (FILE*, char*, int, size_t);
-
_CRTIMP void __cdecl __MINGW_NOTHROW setbuf (FILE*, char*);
-/*
- * Formatted Output
+/* Formatted Output
*
* MSVCRT implementations are not ANSI C99 conformant...
* we offer these conforming alternatives from libmingwex.a
extern int __mingw_stdio_redirect__(vsprintf)(char*, const char*, __VALIST);
extern int __mingw_stdio_redirect__(vsnprintf)(char*, size_t, const char*, __VALIST);
+/* When using these C99 conforming alternatives, we may wish to support
+ * some of Microsoft's quirky formatting options, even when they violate
+ * strict C99 conformance.
+ */
+#define _MSVC_PRINTF_QUIRKS 0x0100U
+#define _QUERY_MSVC_PRINTF_QUIRKS ~0U, 0U
+#define _DISABLE_MSVC_PRINTF_QUIRKS ~_MSVC_PRINTF_QUIRKS, 0U
+#define _ENABLE_MSVC_PRINTF_QUIRKS ~0U, _MSVC_PRINTF_QUIRKS
+
+/* Those quirks which conflict with ANSI C99 specified behaviour are
+ * disabled by default; use the following function, like this:
+ *
+ * _mingw_output_format_control( _ENABLE_MSVC_PRINTF_QUIRKS );
+ *
+ * to enable them, like this:
+ *
+ * state = _mingw_output_format_control( _QUERY_MSVC_PRINTF_QUIRKS )
+ * & _MSVC_PRINTF_QUIRKS;
+ *
+ * to ascertain the currently active enabled state, or like this:
+ *
+ * _mingw_output_format_control( _DISABLE_MSVC_PRINTF_QUIRKS );
+ *
+ * to disable them again.
+ */
+extern unsigned int _mingw_output_format_control( unsigned int, unsigned int );
+
#if __USE_MINGW_ANSI_STDIO
/*
* User has expressed a preference for C99 conformance...
*/
#define _THREE_DIGIT_EXPONENT 0
+/* Once again, unspecified by Microsoft, (and mostly redundant),
+ * it is convenient to specify a combining mask for these.
+ */
+#define _EXPONENT_DIGIT_MASK (_TWO_DIGIT_EXPONENT | _THREE_DIGIT_EXPONENT)
+
unsigned int __cdecl __mingw_get_output_format (void);
unsigned int __cdecl __mingw_set_output_format (unsigned int);
* $Id$
*
* Written by Keith Marshall <keithmarshall@users.sourceforge.net>
- * Copyright (C) 2014, MinGW.org Project
+ * Copyright (C) 2014, 2015, MinGW.org Project
*
*
* Permission is hereby granted, free of charge, to any person obtaining a
*/
extern unsigned int __mingw_output_format_flag;
+static __inline__ __attribute__((__always_inline__))
+unsigned int update_output_format_flag( unsigned int style )
+{ return (__mingw_output_format_flag & ~_EXPONENT_DIGIT_MASK) | style; }
+
#if defined __varofmt__
/*
* Here, we actually allocate the storage for recording the preferred
/* Our replacement function simply returns the current setting of
* the assigned formatting style...
*/
- return __mingw_output_format_flag;
+ return __mingw_output_format_flag & _EXPONENT_DIGIT_MASK;
}
/* ...and, in the case of _set_output_format(), we simply map the
* requisite name to the common function implementation.
* Here, we are wrapping the _set_printf_count_output() function...
*/
# define RTNTYPE int
-# define ARGTYPE int
# define FUNCTION _set_printf_count_output
-# define ARGLIST mode
+# define ARGLIST int mode
#define api_helper_result api_helper( mode )
extern int __mingw_set_printf_count_output_fallback( int );
* ...while here, it is _get_printf_count_output().
*/
# define RTNTYPE int
-# define ARGTYPE void
# define FUNCTION _get_printf_count_output
-# define ARGLIST
+# define ARGLIST void
#define api_helper_result api_helper()
extern int __mingw_get_printf_count_output_fallback( void );
*/
# define RTNTYPE unsigned int
# define FUNCTION _set_output_format
-# define ARGTYPE unsigned int
-# define ARGLIST style
+# define ARGLIST unsigned int style
/* Our replacement function emulates the documented behaviour of
* its MSVCRT counterpart, assigning a new value for the recorded
* to retrieve the previous value for return; thus it is able
* to use a handler in common with _get_output_format()...
*/
- unsigned int retval = api_helper( style );
- __mingw_output_format_flag = style;
+ unsigned int retval = api_helper( style &= _EXPONENT_DIGIT_MASK );
+ __mingw_output_format_flag = update_output_format_flag( style );
return retval;
}
/* ...while declaring its formal prototype as external.
*/
# define RTNTYPE unsigned int
# define FUNCTION _get_output_format
-# define ARGTYPE void
-# define ARGLIST
+# define ARGLIST void
+
+static __inline__ __attribute__((__always_inline__))
+unsigned int api_invoke( unsigned int (*api_helper)( void ) )
+{
+ unsigned int retval = api_helper();
+ __mingw_output_format_flag = update_output_format_flag( retval );
+ return retval;
+}
-#define api_helper_result __mingw_output_format_flag = api_helper()
+#define api_helper_result api_invoke( api_helper )
extern unsigned int __mingw_get_output_format_fallback( void );
#endif
#define __api_name__(FUNCTION) __stringify__(FUNCTION)
#define __stringify__(TEXT) #TEXT
-RTNTYPE __mingw_(FUNCTION)( ARGTYPE ARGLIST )
+RTNTYPE __mingw_(FUNCTION)( ARGLIST )
{
/* Our generic interface maps an indirect call to the API...
*/
- static RTNTYPE (*api_helper)( ARGTYPE ARGLIST ) = NULL;
+ static RTNTYPE (*api_helper)( ARGLIST ) = NULL;
/* ...such that it will prefer an MSVCRT implementation...
*/
--- /dev/null
+/*
+ * ofmtctl.c
+ *
+ * Implementation of a MinGW.org specific helper routine, to manipulate
+ * supplementary output format control flags other than those specified
+ * for the Microsoft output format control API.
+ *
+ * $Id$
+ *
+ * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
+ * Copyright (C) 2015, MinGW.org Project.
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice, this permission notice, and the following
+ * disclaimer shall be included in all copies or substantial portions of
+ * the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+#include <stdio.h>
+
+/* MinGW uses this public symbol to represent both Microsoft's exponent
+ * digit format flag, and supplementary MinGW.org specific flags.
+ */
+extern unsigned int __mingw_output_format_flags;
+
+/* The MinGW.org specific output format flag management API function.
+ * This provides both get and set capabilities for the MinGW specified
+ * flags; it has no effect on the Microsoft specified flags; use their
+ * _get_output_format() and _set_output_format() API functions when it
+ * is desired to manipulate them.
+ */
+unsigned int _mingw_output_format_control
+( unsigned int flags_to_keep, unsigned int flags_to_set )
+{
+ /* Return value is always based on current flag state.
+ */
+ unsigned int retval = __mingw_output_format_flags;
+
+ /* Adjust flags as specified by the mask of flags to keep,
+ * and add in any extra flags to set; always keep the state
+ * of the Microsoft specified flag bits, and decline to set
+ * them to any new state.
+ */
+ __mingw_output_format_flags &= flags_to_keep | _EXPONENT_DIGIT_MASK;
+ __mingw_output_format_flags |= flags_to_set & ~_EXPONENT_DIGIT_MASK;
+
+ /* Finally, exclude the Microsoft specified bits from the
+ * state to be returned, and return the original state of
+ * the MinGW specified bits.
+ */
+ return retval & ~_EXPONENT_DIGIT_MASK;
+}
+
+/* $RCSfile$: end of file */
/* FIXME: to be removed one day; for now we explicitly are not
* prepared to support the POSIX-XSI additions to the C99 standard.
*/
-#undef WITH_XSI_FEATURES
+#undef WITH_XSI_FEATURES
/* pformat.c
*
* to support Microsoft's non-standard format specifications.
*
* Written by Keith Marshall <keithmarshall@users.sourceforge.net>
+ * Copyright (C) 2008, 2009, 2011, 2014, 2015, MinGW.org Project
*
- * This is free software. You may redistribute and/or modify it as you
- * see fit, without restriction of copyright.
*
- * This software is provided "as is", in the hope that it may be useful,
- * but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of
- * MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no
- * time will the author accept any form of liability for any damages,
- * however caused, resulting from the use of this software.
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice, this permission notice, and the following
+ * disclaimer shall be included in all copies or substantial portions of
+ * the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
+ * DEALINGS IN THE SOFTWARE.
*
* The elements of this implementation which deal with the formatting
* of floating point numbers, (i.e. the `%e', `%E', `%f', `%F', `%g'
*/
++fmt;
length = PFORMAT_LENGTH_LLONG;
+ state = PFORMAT_END;
+ break;
}
else
- /* Modifier is `l'; data type is `long' sized...
+ { /* Modifier is `l'; data type is `long' sized...
*/
length = PFORMAT_LENGTH_LONG;
-# ifndef _WIN32
- /*
- * Microsoft's MSVCRT implementation also uses `l'
- * as a modifier for `long double'; if we don't want
- * to support that, we end this case here...
+ /* Microsoft's MSVCRT implementation also uses `l'
+ * as a modifier for `long double'; however, this
+ * conflicts with the usage specified by ISO-C and
+ * POSIX, so we definitely shouldn't support this
+ * anomaly for non-Windows builds...
*/
- state = PFORMAT_END;
- break;
-
- /* otherwise, we simply fall through...
+# ifndef _WIN32
+# undef _MSVC_PRINTF_QUIRKS
+# define _MSVC_PRINTF_QUIRKS 0
+# endif
+ /* ...nor should we support it by default, even in
+ * Windows builds, but we grant the user a mechanism
+ * to enable it via __mingw_output_format_flag.
+ */
+ if( (__mingw_output_format_flag & _MSVC_PRINTF_QUIRKS) == 0 )
+ {
+ /* When support for this Microsoft anomaly is NOT
+ * enabled, we must end this case right here...
+ */
+ state = PFORMAT_END;
+ break;
+ }
+ /* ...otherwise, we simply fall through, considering
+ * the `l' modifier as equivalent to `L`, in the case
+ * of floating point formats...
*/
-# endif
+ }
case 'L':
/*