Merge pull request #7351 from Kelimion/compiler-utf8-codepage

Set console codepage to utf-8 (on Windows), and restore old one on exit
This commit is contained in:
Jeroen van Rijn
2026-08-16 18:06:39 +02:00
committed by GitHub
6 changed files with 70 additions and 6 deletions

View File

@@ -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 ---
}

View File

@@ -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
}
}

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -65,6 +65,20 @@ template <typename T> struct TypeIs64BitInteger { enum {value = false}; };
template <> struct TypeIs64BitInteger<u64> { enum {value = true}; };
template <> struct TypeIs64BitInteger<i64> { 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"

View File

@@ -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();