mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-18 03:42:23 -07:00
Merge pull request #1107 from odin-lang/mv/libc-errors
Fix libc errors in Windows and add some tests.
This commit is contained in:
@@ -2,7 +2,11 @@ package libc
|
||||
|
||||
// 7.3 Complex arithmetic
|
||||
|
||||
foreign import libc "system:c"
|
||||
when ODIN_OS == "windows" {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
@(default_calling_convention="c")
|
||||
foreign libc {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package libc
|
||||
|
||||
foreign import libc "system:c"
|
||||
when ODIN_OS == "windows" {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
// 7.4 Character handling
|
||||
|
||||
|
||||
@@ -2,7 +2,11 @@ package libc
|
||||
|
||||
// 7.5 Errors
|
||||
|
||||
foreign import libc "system:c"
|
||||
when ODIN_OS == "windows" {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
// C11 standard only requires the definition of:
|
||||
// EDOM,
|
||||
|
||||
@@ -4,7 +4,11 @@ package libc
|
||||
|
||||
import "core:intrinsics"
|
||||
|
||||
foreign import libc "system:c"
|
||||
when ODIN_OS == "windows" {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
// To support C's tgmath behavior we use Odin's explicit procedure overloading,
|
||||
// but we cannot use the same names as exported by libc so use @(link_name)
|
||||
|
||||
+43
-9
@@ -2,18 +2,52 @@ package libc
|
||||
|
||||
// 7.13 Nonlocal jumps
|
||||
|
||||
foreign import libc "system:c"
|
||||
when ODIN_OS == "windows" {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
when ODIN_OS == "windows" {
|
||||
@(default_calling_convention="c")
|
||||
foreign libc {
|
||||
// 7.13.1 Save calling environment
|
||||
//
|
||||
// NOTE(dweiler): C11 requires setjmp be a macro, which means it won't
|
||||
// necessarily export a symbol named setjmp but rather _setjmp in the case
|
||||
// of musl, glibc, BSD libc, and msvcrt.
|
||||
//
|
||||
/// NOTE(dweiler): UCRT has two implementations of longjmp. One that performs
|
||||
// stack unwinding and one that doesn't. The choice of which to use depends on a
|
||||
// flag which is set inside the jmp_buf structure given to setjmp. The default
|
||||
// behavior is to unwind the stack. Within Odin, we cannot use the stack
|
||||
// unwinding version as the unwinding information isn't present. To opt-in to
|
||||
// the regular non-unwinding version we need a way to set this flag. Since the
|
||||
// location of the flag within the struct is not defined or part of the ABI and
|
||||
// can change between versions of UCRT, we must rely on setjmp to set it. It
|
||||
// turns out that setjmp receives this flag in the RDX register on Win64, this
|
||||
// just so happens to coincide with the second argument of a function in the
|
||||
// Win64 ABI. By giving our setjmp a second argument with the value of zero,
|
||||
// the RDX register will contain zero and correctly set the flag to disable
|
||||
// stack unwinding.
|
||||
@(link_name="_setjmp")
|
||||
setjmp :: proc(env: ^jmp_buf, hack: rawptr = nil) -> int ---;
|
||||
}
|
||||
} else {
|
||||
@(default_calling_convention="c")
|
||||
foreign libc {
|
||||
// 7.13.1 Save calling environment
|
||||
//
|
||||
// NOTE(dweiler): C11 requires setjmp be a macro, which means it won't
|
||||
// necessarily export a symbol named setjmp but rather _setjmp in the case
|
||||
// of musl, glibc, BSD libc, and msvcrt.
|
||||
@(link_name="_setjmp")
|
||||
setjmp :: proc(env: ^jmp_buf) -> int ---;
|
||||
}
|
||||
}
|
||||
|
||||
@(default_calling_convention="c")
|
||||
foreign libc {
|
||||
// 7.13.1 Save calling environment
|
||||
//
|
||||
// NOTE(dweiler): C11 requires setjmp be a macro, which means it won't
|
||||
// necessarily export a symbol named setjmp but rather _setjmp in the case
|
||||
// of musl, glibc, BSD libc, and msvcrt.
|
||||
@(link_name="_setjmp")
|
||||
setjmp :: proc(env: ^jmp_buf) -> int ---;
|
||||
|
||||
// 7.13.2 Restore calling environment
|
||||
longjmp :: proc(env: ^jmp_buf, val: int) -> ! ---;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,11 @@ package libc
|
||||
|
||||
// 7.14 Signal handling
|
||||
|
||||
foreign import libc "system:c"
|
||||
when ODIN_OS == "windows" {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
sig_atomic_t :: distinct atomic_int;
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package libc
|
||||
|
||||
foreign import libc "system:c"
|
||||
when ODIN_OS == "windows" {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
// 7.21 Input/output
|
||||
|
||||
|
||||
@@ -2,7 +2,11 @@ package libc
|
||||
|
||||
// 7.22 General utilities
|
||||
|
||||
foreign import libc "system:c"
|
||||
when ODIN_OS == "windows" {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
when ODIN_OS == "windows" {
|
||||
RAND_MAX :: 0x7fff;
|
||||
@@ -14,7 +18,7 @@ when ODIN_OS == "windows" {
|
||||
}
|
||||
|
||||
MB_CUR_MAX :: #force_inline proc() -> size_t {
|
||||
return ___mb_cur_max_func();
|
||||
return size_t(___mb_cur_max_func());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,11 @@ package libc
|
||||
|
||||
// 7.24 String handling
|
||||
|
||||
foreign import libc "system:c"
|
||||
when ODIN_OS == "windows" {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
foreign libc {
|
||||
// 7.24.2 Copying functions
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package libc_tests
|
||||
|
||||
import "core:c/libc"
|
||||
|
||||
test_stdio :: proc() {
|
||||
c: libc.char = 'C';
|
||||
libc.puts("Hello from puts");
|
||||
libc.printf("Hello from printf in %c\n", c);
|
||||
}
|
||||
test_thread :: proc() {
|
||||
thread_proc :: proc "c" (rawptr) -> libc.int {
|
||||
libc.printf("Hello from thread");
|
||||
return 42;
|
||||
}
|
||||
thread: libc.thrd_t;
|
||||
libc.thrd_create(&thread, thread_proc, nil);
|
||||
result: libc.int;
|
||||
libc.thrd_join(thread, &result);
|
||||
libc.printf(" %d\n", result);
|
||||
}
|
||||
|
||||
jmp: libc.jmp_buf;
|
||||
test_sjlj :: proc() {
|
||||
if libc.setjmp(&jmp) != 0 {
|
||||
libc.printf("Hello from longjmp\n");
|
||||
return;
|
||||
}
|
||||
libc.printf("Hello from setjmp\n");
|
||||
libc.longjmp(&jmp, 1);
|
||||
}
|
||||
test_signal :: proc() {
|
||||
handler :: proc "c" (sig: libc.int) {
|
||||
libc.printf("Hello from signal handler\n");
|
||||
}
|
||||
libc.signal(libc.SIGABRT, handler);
|
||||
libc.raise(libc.SIGABRT);
|
||||
}
|
||||
test_atexit :: proc() {
|
||||
handler :: proc "c" () {
|
||||
libc.printf("Hello from atexit\n");
|
||||
}
|
||||
libc.atexit(handler);
|
||||
}
|
||||
main :: proc() {
|
||||
test_stdio();
|
||||
test_thread();
|
||||
test_sjlj();
|
||||
test_signal();
|
||||
test_atexit();
|
||||
}
|
||||
@@ -6,7 +6,10 @@ thrd_start_t :: proc "c" (rawptr) -> int;
|
||||
tss_dtor_t :: proc "c" (rawptr);
|
||||
|
||||
when ODIN_OS == "windows" {
|
||||
foreign import libc "system:c"
|
||||
foreign import libc {
|
||||
"system:libucrt.lib",
|
||||
"system:msvcprt.lib"
|
||||
}
|
||||
|
||||
thrd_success :: 0; // _Thrd_success
|
||||
thrd_nomem :: 1; // _Thrd_nomem
|
||||
@@ -24,6 +27,7 @@ when ODIN_OS == "windows" {
|
||||
thrd_t :: struct { _: rawptr, _: uint, } // _Thrd_t
|
||||
tss_t :: distinct int; // _Tss_imp_t
|
||||
cnd_t :: distinct rawptr; // _Cnd_imp_t
|
||||
mtx_t :: distinct rawptr; // _Mtx_imp_t
|
||||
|
||||
// MSVCRT does not expose the C11 symbol names as what they are in C11
|
||||
// because they held off implementing <threads.h> and C11 support for so
|
||||
@@ -52,9 +56,9 @@ when ODIN_OS == "windows" {
|
||||
@(link_name="_Mtx_unlock") mtx_unlock :: proc(mtx: ^mtx_t) -> int ---;
|
||||
|
||||
// 7.26.5 Thread functions
|
||||
@(link_name="_Thrd_create") thrd_create :: proc(thr: ^thr_t, func: thrd_start_t, arg: rawptr) -> int ---;
|
||||
@(link_name="_Thrd_create") thrd_create :: proc(thr: ^thrd_t, func: thrd_start_t, arg: rawptr) -> int ---;
|
||||
@(link_name="_Thrd_current") thrd_current :: proc() -> thrd_t ---;
|
||||
@(link_name="_Thrd_detach") thrd_detach :: proc(thr: thr_t) -> int ---;
|
||||
@(link_name="_Thrd_detach") thrd_detach :: proc(thr: thrd_t) -> int ---;
|
||||
@(link_name="_Thrd_equal") thrd_equal :: proc(lhs, rhs: thrd_t) -> int ---;
|
||||
@(link_name="_Thrd_exit") thrd_exit :: proc(res: int) -> ! ---;
|
||||
@(link_name="_Thrd_join") thrd_join :: proc(thr: thrd_t, res: ^int) -> int ---;
|
||||
|
||||
@@ -2,7 +2,11 @@ package libc
|
||||
|
||||
// 7.27 Date and time
|
||||
|
||||
foreign import libc "system:c"
|
||||
when ODIN_OS == "windows" {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
// We enforce 64-bit time_t and timespec as there is no reason to use 32-bit as
|
||||
// we approach the 2038 problem. Windows has defaulted to this since VC8 (2005).
|
||||
|
||||
@@ -2,7 +2,11 @@ package libc
|
||||
|
||||
// 7.28 Unicode utilities
|
||||
|
||||
foreign import libc "system:c"
|
||||
when ODIN_OS == "windows" {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
@(default_calling_convention="c")
|
||||
foreign libc {
|
||||
|
||||
@@ -2,7 +2,11 @@ package libc
|
||||
|
||||
// 7.29 Extended multibyte and wide character utilities
|
||||
|
||||
foreign import libc "system:c"
|
||||
when ODIN_OS == "windows" {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
@(default_calling_convention="c")
|
||||
foreign libc {
|
||||
|
||||
@@ -2,7 +2,11 @@ package libc
|
||||
|
||||
// 7.30 Wide character classification and mapping utilities
|
||||
|
||||
foreign import libc "system:c"
|
||||
when ODIN_OS == "windows" {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
} else {
|
||||
foreign import libc "system:c"
|
||||
}
|
||||
|
||||
when ODIN_OS == "windows" {
|
||||
wctrans_t :: distinct wchar_t;
|
||||
|
||||
Reference in New Issue
Block a user