headers, crt: Convert the UCRT stdio options to a mutable state
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ö <martin@martin.st>
4 files changed