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

Reply via email to