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