This makes things closer match how this works in MSVC. A few minor details still differ though: In MS UCRT headers, the __local_stdio_{printf,scanf}_options functions are inline in the public headers. I don't see any technical advantage in doing that (and getting that kind of inline correct in C is tricky).
This makes it possible to set the flags at runtime, by assigning to _CRT_INTERNAL_LOCAL_PRINTF_OPTIONS. This also makes it possible to affect the flags of our non-inline UCRT stdio functions, like stdio/ucrt_printf.c and similar ones. In MSVC, these flags are adjustable in many different ways. I haven't found any docs that explicitly describe which mechanisms are intended to be used, and which ones should be avoided: 1. One can define e.g. _CRT_INTERNAL_LOCAL_PRINTF_OPTIONS to a different constant value while compiling. In MSVC, this does affect all functions (as all are defined inline in headers). In the mingw-w64 headers, this only affects the functions that are defined inline (currently mostly the wide char functions). 2. One can assign to e.g. _CRT_INTERNAL_LOCAL_PRINTF_OPTIONS at runtime. Previously this wasn't supported in mingw-w64, now it becomes supported. Doing this now affects the non-inline functions too. 3. In MSVC, one can define _CRT_STDIO_ISO_WIDE_SPECIFIERS or _CRT_STDIO_LEGACY_WIDE_SPECIFIERS while compiling. This adds directives, pulling in an extra library, which adds a constructor function, which on startup sets or clears bits in _CRT_INTERNAL_LOCAL_PRINTF_OPTIONS, depending on the choice. This is the mechanism that is closest to being documented (it was mentioned in a blog post [1], although the behaviour change advertised in that blog post was later reverted before release). We currently don't have anything corresponding to this. 4. One can also call e.g. __local_stdio_printf_options directly and assign to it. We should now be fully compatible with this. It's unclear how many projects attempt to do any of this at all; if they do, it's probably most plausible that they do 3 or 2. In MSVC, the options flags are statically initialized to zero, while another startup routine (__scrt_initialize_default_local_stdio_options) sets their initial values. Here we just statically initialize them to their default values. [1] https://devblogs.microsoft.com/cppblog/c-runtime-crt-features-fixes-and-breaking-changes-in-visual-studio-14-ctp1/ Signed-off-by: Martin Storsjö <mar...@martin.st> --- mingw-w64-crt/Makefile.am | 2 ++ .../stdio/ucrt___local_stdio_printf_options.c | 15 +++++++++++++++ .../stdio/ucrt___local_stdio_scanf_options.c | 15 +++++++++++++++ mingw-w64-headers/crt/corecrt_stdio_config.h | 14 ++++++++++++-- 4 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 mingw-w64-crt/stdio/ucrt___local_stdio_printf_options.c create mode 100644 mingw-w64-crt/stdio/ucrt___local_stdio_scanf_options.c diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am index f2f1e6f81..345eac0aa 100644 --- a/mingw-w64-crt/Makefile.am +++ b/mingw-w64-crt/Makefile.am @@ -401,6 +401,8 @@ src_ucrtbase=\ misc/_onexit.c \ misc/output_format.c \ misc/ucrt-access.c \ + stdio/ucrt___local_stdio_printf_options.c \ + stdio/ucrt___local_stdio_scanf_options.c \ stdio/ucrt_fprintf.c \ stdio/ucrt_fscanf.c \ stdio/ucrt_ms_fprintf.c \ diff --git a/mingw-w64-crt/stdio/ucrt___local_stdio_printf_options.c b/mingw-w64-crt/stdio/ucrt___local_stdio_printf_options.c new file mode 100644 index 000000000..986c4fd10 --- /dev/null +++ b/mingw-w64-crt/stdio/ucrt___local_stdio_printf_options.c @@ -0,0 +1,15 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#undef __MSVCRT_VERSION__ +#define _UCRT +#include <corecrt_stdio_config.h> + +static unsigned __int64 options = _CRT_INTERNAL_PRINTF_LEGACY_WIDE_SPECIFIERS | _CRT_INTERNAL_PRINTF_STANDARD_ROUNDING; + +unsigned __int64* __local_stdio_printf_options(void) { + return &options; +} diff --git a/mingw-w64-crt/stdio/ucrt___local_stdio_scanf_options.c b/mingw-w64-crt/stdio/ucrt___local_stdio_scanf_options.c new file mode 100644 index 000000000..2dbd32456 --- /dev/null +++ b/mingw-w64-crt/stdio/ucrt___local_stdio_scanf_options.c @@ -0,0 +1,15 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#undef __MSVCRT_VERSION__ +#define _UCRT +#include <corecrt_stdio_config.h> + +static unsigned __int64 options = _CRT_INTERNAL_SCANF_LEGACY_WIDE_SPECIFIERS; + +unsigned __int64* __local_stdio_scanf_options(void) { + return &options; +} diff --git a/mingw-w64-headers/crt/corecrt_stdio_config.h b/mingw-w64-headers/crt/corecrt_stdio_config.h index 3028d92e1..7ac0e6e03 100644 --- a/mingw-w64-headers/crt/corecrt_stdio_config.h +++ b/mingw-w64-headers/crt/corecrt_stdio_config.h @@ -9,6 +9,13 @@ #include <corecrt.h> +#ifdef __cplusplus +extern "C" { +#endif + +unsigned __int64* __local_stdio_printf_options(void); +unsigned __int64* __local_stdio_scanf_options(void); + #define _CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION 0x0001ULL #define _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR 0x0002ULL #define _CRT_INTERNAL_PRINTF_LEGACY_WIDE_SPECIFIERS 0x0004ULL @@ -21,11 +28,14 @@ #define _CRT_INTERNAL_SCANF_LEGACY_MSVCRT_COMPATIBILITY 0x0004ULL #ifndef _CRT_INTERNAL_LOCAL_PRINTF_OPTIONS -#define _CRT_INTERNAL_LOCAL_PRINTF_OPTIONS (_CRT_INTERNAL_PRINTF_LEGACY_WIDE_SPECIFIERS | _CRT_INTERNAL_PRINTF_STANDARD_ROUNDING) +#define _CRT_INTERNAL_LOCAL_PRINTF_OPTIONS (*__local_stdio_printf_options()) #endif #ifndef _CRT_INTERNAL_LOCAL_SCANF_OPTIONS -#define _CRT_INTERNAL_LOCAL_SCANF_OPTIONS _CRT_INTERNAL_SCANF_LEGACY_WIDE_SPECIFIERS +#define _CRT_INTERNAL_LOCAL_SCANF_OPTIONS (*__local_stdio_scanf_options()) #endif +#ifdef __cplusplus +} +#endif #endif /* _STDIO_CONFIG_DEFINED */ -- 2.43.0 _______________________________________________ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public