diff --git a/base/runtime/core.odin b/base/runtime/core.odin index 41d620bdd..0453583c0 100644 --- a/base/runtime/core.odin +++ b/base/runtime/core.odin @@ -945,5 +945,25 @@ default_assertion_contextless_failure_proc :: proc "contextless" (prefix, messag print_byte('\n') } } + when ODIN_CODEPAGE_MAGIC { + SetConsoleOutputCP(old_console_codepage) + } trap() } + +ODIN_CODEPAGE_MAGIC :: ODIN_OS == .Windows && #config(ODIN_CODEPAGE_MAGIC, !ODIN_BEDROCK) + +when ODIN_CODEPAGE_MAGIC { + @(private) + old_console_codepage: u32 + + @(private) + UTF_8 :: 65001 +} + +foreign import kernel32 "system:Kernel32.lib" +@(default_calling_convention="system") +foreign kernel32 { + GetConsoleOutputCP :: proc() -> u32 --- + SetConsoleOutputCP :: proc(codepage: u32) -> b32 --- +} \ No newline at end of file diff --git a/base/runtime/entry_windows.odin b/base/runtime/entry_windows.odin index d3b38bc9c..5e7753d6a 100644 --- a/base/runtime/entry_windows.odin +++ b/base/runtime/entry_windows.odin @@ -17,9 +17,14 @@ when ODIN_BUILD_MODE == .Dynamic { switch dll_forward_reason { case .Process_Attach: when !ODIN_BEDROCK { #force_no_inline _startup_runtime() } + when ODIN_CODEPAGE_MAGIC { + old_console_codepage = GetConsoleOutputCP() + SetConsoleOutputCP(UTF_8) + } intrinsics.__entry_point() case .Process_Detach: when !ODIN_BEDROCK { #force_no_inline _cleanup_runtime() } + when ODIN_CODEPAGE_MAGIC { SetConsoleOutputCP(old_console_codepage) } case .Thread_Attach: break case .Thread_Detach: @@ -36,8 +41,13 @@ when ODIN_BUILD_MODE == .Dynamic { args__ = argv[:argc] context = default_context() when !ODIN_BEDROCK { #force_no_inline _startup_runtime() } + when ODIN_CODEPAGE_MAGIC { + old_console_codepage = GetConsoleOutputCP() + SetConsoleOutputCP(UTF_8) + } intrinsics.__entry_point() - when !ODIN_BEDROCK { #force_no_inline _cleanup_runtime() } + when !ODIN_BEDROCK { #force_no_inline _cleanup_runtime() } + when ODIN_CODEPAGE_MAGIC { SetConsoleOutputCP(old_console_codepage) } return 0 } } else when ODIN_NO_CRT { @@ -45,8 +55,13 @@ when ODIN_BUILD_MODE == .Dynamic { mainCRTStartup :: proc "system" () -> i32 { context = default_context() when !ODIN_BEDROCK { #force_no_inline _startup_runtime() } + when ODIN_CODEPAGE_MAGIC { + old_console_codepage = GetConsoleOutputCP() + SetConsoleOutputCP(UTF_8) + } intrinsics.__entry_point() - when !ODIN_BEDROCK { #force_no_inline _cleanup_runtime() } + when !ODIN_BEDROCK { #force_no_inline _cleanup_runtime() } + when ODIN_CODEPAGE_MAGIC { SetConsoleOutputCP(old_console_codepage) } return 0 } } else { @@ -55,8 +70,13 @@ when ODIN_BUILD_MODE == .Dynamic { args__ = argv[:argc] context = default_context() when !ODIN_BEDROCK { #force_no_inline _startup_runtime() } + when ODIN_CODEPAGE_MAGIC { + old_console_codepage = GetConsoleOutputCP() + SetConsoleOutputCP(UTF_8) + } intrinsics.__entry_point() - when !ODIN_BEDROCK { #force_no_inline _cleanup_runtime() } + when !ODIN_BEDROCK { #force_no_inline _cleanup_runtime() } + when ODIN_CODEPAGE_MAGIC { SetConsoleOutputCP(old_console_codepage) } return 0 } } diff --git a/base/runtime/procs_windows_amd64.odin b/base/runtime/procs_windows_amd64.odin index 81d2cfb5d..cedbc2bd8 100644 --- a/base/runtime/procs_windows_amd64.odin +++ b/base/runtime/procs_windows_amd64.odin @@ -11,8 +11,9 @@ foreign kernel32 { windows_trap_array_bounds :: proc "contextless" () -> ! { EXCEPTION_ARRAY_BOUNDS_EXCEEDED :: 0xC000008C - - + when ODIN_CODEPAGE_MAGIC { + SetConsoleOutputCP(old_console_codepage) + } RaiseException(EXCEPTION_ARRAY_BOUNDS_EXCEEDED, 0, 0, nil) } diff --git a/base/runtime/procs_windows_i386.odin b/base/runtime/procs_windows_i386.odin index 99c314228..9dd97116d 100644 --- a/base/runtime/procs_windows_i386.odin +++ b/base/runtime/procs_windows_i386.odin @@ -15,7 +15,9 @@ windows_trap_array_bounds :: proc "contextless" () -> ! { foreign kernel32 { RaiseException :: proc "system" (dwExceptionCode, dwExceptionFlags, nNumberOfArguments: DWORD, lpArguments: ^ULONG_PTR) -> ! --- } - + when ODIN_CODEPAGE_MAGIC { + SetConsoleOutputCP(old_console_codepage) + } RaiseException(EXCEPTION_ARRAY_BOUNDS_EXCEEDED, 0, 0, nil) } diff --git a/src/common.cpp b/src/common.cpp index 8338ec707..3b4557cde 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -65,6 +65,20 @@ template struct TypeIs64BitInteger { enum {value = false}; }; template <> struct TypeIs64BitInteger { enum {value = true}; }; template <> struct TypeIs64BitInteger { enum {value = true}; }; +#if defined(GB_SYSTEM_WINDOWS) +uint32_t old_console_codepage = 0; +void set_utf8_codepage() { + old_console_codepage = GetConsoleOutputCP(); +} + +void restore_old_codepage() { + // Nothing we can do if this fails, so we're not asserting or anything. + SetConsoleOutputCP(old_console_codepage); +} +#else +void set_utf8_codepage() {} +void restore_old_codepage() {} +#endif #include "unicode.cpp" diff --git a/src/main.cpp b/src/main.cpp index 74900587f..7d2f4d713 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3794,6 +3794,13 @@ int main(int arg_count, char const **arg_ptr) { defer (timings_destroy(&global_timings)); MAIN_TIME_SECTION("initialization"); + // NOTE(Jeroen): Set codepage to UTF-8 (Windows only) and restore on exit. + // Keep in mind this is for the compiler's own output only. + // Like error messages on lines containing unicode. + // Child processes will inherit the default codepage, + // and so must do their own codepage management if they want. + set_utf8_codepage(); + defer (restore_old_codepage()); init_string_interner(); init_global_error_collector();