diff --git a/base/runtime/core_builtin.odin b/base/runtime/core_builtin.odin index 42bf13478..02278a356 100644 --- a/base/runtime/core_builtin.odin +++ b/base/runtime/core_builtin.odin @@ -433,7 +433,6 @@ _make_dynamic_array_len_cap :: proc(array: ^Raw_Dynamic_Array, size_of_elem, ali array.data = raw_data(data) array.len = 0 if use_zero else len array.cap = 0 if use_zero else cap - array.allocator = allocator return } diff --git a/core/math/rand/rand_pcg.odin b/core/math/rand/rand_pcg.odin index 009e139be..79c18acbb 100644 --- a/core/math/rand/rand_pcg.odin +++ b/core/math/rand/rand_pcg.odin @@ -55,16 +55,20 @@ pcg_random_generator_proc :: proc(data: rawptr, mode: runtime.Random_Generator_M intrinsics.unaligned_store((^u64)(raw_data(p)), read_u64(r)) case: // All other cases. - pos := i8(0) - val := u64(0) - for &v in p { - if pos == 0 { - val = read_u64(r) - pos = 8 + n := len(p) / size_of(u64) + buff := ([^]u64)(raw_data(p))[:n] + for &e in buff { + intrinsics.unaligned_store(&e, read_u64(r)) + } + // Handle remaining bytes + rem := len(p) % size_of(u64) + if rem > 0 { + val := read_u64(r) + tail := p[len(p) - rem:] + for &b in tail { + b = byte(val) + val >>= 8 } - v = byte(val) - val >>= 8 - pos -= 1 } } diff --git a/core/math/rand/rand_xoshiro256.odin b/core/math/rand/rand_xoshiro256.odin index 54dd02130..7326ba8d5 100644 --- a/core/math/rand/rand_xoshiro256.odin +++ b/core/math/rand/rand_xoshiro256.odin @@ -74,16 +74,20 @@ xoshiro256_random_generator_proc :: proc(data: rawptr, mode: runtime.Random_Gene intrinsics.unaligned_store((^u64)(raw_data(p)), read_u64(r)) case: // All other cases. - pos := i8(0) - val := u64(0) - for &v in p { - if pos == 0 { - val = read_u64(r) - pos = 8 + n := len(p) / size_of(u64) + buff := ([^]u64)(raw_data(p))[:n] + for &e in buff { + intrinsics.unaligned_store(&e, read_u64(r)) + } + // Handle remaining bytes + rem := len(p) % size_of(u64) + if rem > 0 { + val := read_u64(r) + tail := p[len(p) - rem:] + for &b in tail { + b = byte(val) + val >>= 8 } - v = byte(val) - val >>= 8 - pos -= 1 } } diff --git a/core/sys/darwin/Foundation/NSScreen.odin b/core/sys/darwin/Foundation/NSScreen.odin index 79ab00fbe..8d52b9e1c 100644 --- a/core/sys/darwin/Foundation/NSScreen.odin +++ b/core/sys/darwin/Foundation/NSScreen.odin @@ -3,18 +3,22 @@ package objc_Foundation @(objc_class="NSScreen") Screen :: struct {using _: Object} -@(objc_type=Screen, objc_name="mainScreen") +@(objc_type=Screen, objc_name="mainScreen", objc_is_class_method=true) Screen_mainScreen :: proc "c" () -> ^Screen { return msgSend(^Screen, Screen, "mainScreen") } -@(objc_type=Screen, objc_name="deepestScreen") +@(objc_type=Screen, objc_name="deepestScreen", objc_is_class_method=true) Screen_deepestScreen :: proc "c" () -> ^Screen { return msgSend(^Screen, Screen, "deepestScreen") } -@(objc_type=Screen, objc_name="screens") +@(objc_type=Screen, objc_name="screens", objc_is_class_method=true) Screen_screens :: proc "c" () -> ^Array { return msgSend(^Array, Screen, "screens") } +@(objc_type=Screen, objc_name="screensHaveSeparateSpaces", objc_is_class_method=true) +Screen_screensHaveSeparateSpaces :: proc "c" () -> BOOL { + return msgSend(BOOL, Screen, "screensHaveSeparateSpaces") +} @(objc_type=Screen, objc_name="frame") Screen_frame :: proc "c" (self: ^Screen) -> Rect { return msgSend(Rect, self, "frame") diff --git a/core/sys/darwin/Foundation/NSWindow.odin b/core/sys/darwin/Foundation/NSWindow.odin index f39faca0a..11f8b187e 100644 --- a/core/sys/darwin/Foundation/NSWindow.odin +++ b/core/sys/darwin/Foundation/NSWindow.odin @@ -968,3 +968,23 @@ Window_setTabbingMode :: proc "c" (self: ^Window, mode: WindowTabbingMode) { Window_toggleFullScreen :: proc "c" (self: ^Window, sender: id) { msgSend(nil, self, "toggleFullScreen:", sender) } +@(objc_type = Window, objc_name = "contentRectForFrameRect", objc_is_class_method=true) +Window_contentRectForFrameRectType :: proc "c" (frameRect: Rect, styleMask: WindowStyleMask) -> Rect { + return msgSend(Rect, Window, "contentRectForFrameRect:styleMask:", frameRect, styleMask) +} +@(objc_type = Window, objc_name = "frameRectForContentRect", objc_is_class_method=true) +Window_frameRectForContentRectType :: proc "c" (contentRect: Rect, styleMask: WindowStyleMask) -> Rect { + return msgSend(Rect, Window, "frameRectForContentRect:styleMask:", contentRect, styleMask) +} +@(objc_type = Window, objc_name = "minFrameWidthWithTitle", objc_is_class_method=true) +Window_minFrameWidthWithTitle :: proc "c" (title: ^String, styleMask: WindowStyleMask) -> Float { + return msgSend(Float, Window, "minFrameWidthWithTitle:styleMask:", title, styleMask) +} +@(objc_type = Window, objc_name = "contentRectForFrameRect") +Window_contentRectForFrameRectInstance :: proc "c" (self: ^Window, frameRect: Rect) -> Rect { + return msgSend(Rect, self, "contentRectForFrameRect:", frameRect) +} +@(objc_type = Window, objc_name = "frameRectForContentRect") +Window_frameRectForContentRectInstance :: proc "c" (self: ^Window, contentRect: Rect) -> Rect { + return msgSend(Rect, self, "frameRectForContentRect:", contentRect) +} diff --git a/core/sys/linux/bits.odin b/core/sys/linux/bits.odin index 59383638d..2ca7558a2 100644 --- a/core/sys/linux/bits.odin +++ b/core/sys/linux/bits.odin @@ -2275,3 +2275,34 @@ Eventfd_Flags_Bits :: enum { CLOEXEC = auto_cast Open_Flags_Bits.CLOEXEC, NONBLOCK = auto_cast Open_Flags_Bits.NONBLOCK, } + +Sched_Policy :: enum u32 { + OTHER = 0, + BATCH = 3, + IDLE = 5, + FIFO = 1, + RR = 2, + DEADLINE = 6, +} + +Sched_Flag_Bits :: enum { + RESET_ON_FORK = log2(0x01), + RECLAIM = log2(0x02), + DL_OVERRUN = log2(0x04), + KEEP_POLICY = log2(0x08), + KEEP_PARAMS = log2(0x10), + UTIL_CLAMP_MIN = log2(0x20), + UTIL_CLAMP_MAX = log2(0x40), +} + +Sched_Attr_Flag_Bits :: enum {} + +/* + See `constants.odin` for `MFD_HUGE_16KB`, et al. +*/ +Memfd_Create_Flag_Bits :: enum { + CLOEXEC = log2(0x1), + ALLOW_SEALING = log2(0x2), + HUGETLB = log2(0x4), +} + diff --git a/core/sys/linux/constants.odin b/core/sys/linux/constants.odin index 71a16312e..4de57f40b 100644 --- a/core/sys/linux/constants.odin +++ b/core/sys/linux/constants.odin @@ -395,6 +395,20 @@ MAP_HUGE_1GB :: transmute(Map_Flags)(u32(30) << MAP_HUGE_SHIFT) MAP_HUGE_2GB :: transmute(Map_Flags)(u32(31) << MAP_HUGE_SHIFT) MAP_HUGE_16GB :: transmute(Map_Flags)(u32(34) << MAP_HUGE_SHIFT) +MFD_HUGE_16KB :: transmute(Memfd_Create_Flags)(u32(14) << MAP_HUGE_SHIFT) +MFD_HUGE_64KB :: transmute(Memfd_Create_Flags)(u32(16) << MAP_HUGE_SHIFT) +MFD_HUGE_512KB :: transmute(Memfd_Create_Flags)(u32(19) << MAP_HUGE_SHIFT) +MFD_HUGE_1MB :: transmute(Memfd_Create_Flags)(u32(20) << MAP_HUGE_SHIFT) +MFD_HUGE_2MB :: transmute(Memfd_Create_Flags)(u32(21) << MAP_HUGE_SHIFT) +MFD_HUGE_8MB :: transmute(Memfd_Create_Flags)(u32(23) << MAP_HUGE_SHIFT) +MFD_HUGE_16MB :: transmute(Memfd_Create_Flags)(u32(24) << MAP_HUGE_SHIFT) +MFD_HUGE_32MB :: transmute(Memfd_Create_Flags)(u32(25) << MAP_HUGE_SHIFT) +MFD_HUGE_256MB :: transmute(Memfd_Create_Flags)(u32(28) << MAP_HUGE_SHIFT) +MFD_HUGE_512MB :: transmute(Memfd_Create_Flags)(u32(29) << MAP_HUGE_SHIFT) +MFD_HUGE_1GB :: transmute(Memfd_Create_Flags)(u32(30) << MAP_HUGE_SHIFT) +MFD_HUGE_2GB :: transmute(Memfd_Create_Flags)(u32(31) << MAP_HUGE_SHIFT) +MFD_HUGE_16GB :: transmute(Memfd_Create_Flags)(u32(34) << MAP_HUGE_SHIFT) + /* Get window size */ TIOCGWINSZ :: 0x5413 diff --git a/core/sys/linux/sys.odin b/core/sys/linux/sys.odin index b10759595..392761e1d 100644 --- a/core/sys/linux/sys.odin +++ b/core/sys/linux/sys.odin @@ -2043,22 +2043,71 @@ setpriority :: proc "contextless" (which: Priority_Which, who: i32, prio: i32) - return Errno(-ret) } -// TODO(flysand): sched_setparam - -// TODO(flysand): sched_getparam - -// TODO(flysand): sched_setscheduler - -// TODO(flysand): sched_getscheduler - -// TODO(flysand): sched_get_priority_max - -// TODO(flysand): sched_get_priority_min - -// TODO(flysand): sched_rr_get_interval +/* + Set scheduling parameters. + Available since Linux 2.0. +*/ +sched_setparam :: proc "contextless" (pid: Pid, param: ^Sched_Param) -> (Errno) { + ret := syscall(SYS_sched_setparam, pid, param) + return Errno(-ret) +} /* - Lock and memory. + Get scheduling parameters. + Available since Linux 2.0. +*/ +sched_getparam :: proc "contextless" (pid: Pid, param: ^Sched_Param) -> (Errno) { + ret := syscall(SYS_sched_getparam, pid, param) + return Errno(-ret) +} + +/* + Set scheduling policy/parameters. + Available since Linux 2.0. +*/ +sched_setscheduler :: proc "contextless" (pid: Pid, policy: i32, param: ^Sched_Param) -> (Errno) { + ret := syscall(SYS_sched_setscheduler, pid, policy, param) + return Errno(-ret) +} + +/* + Get scheduling policy/parameters. + Available since Linux 2.0. +*/ +sched_getscheduler :: proc "contextless" (pid: Pid, policy: i32, param: ^Sched_Param) -> (i32, Errno) { + ret := syscall(SYS_sched_getscheduler, pid) + return errno_unwrap(ret, i32) +} + +/* + Get static priority range. + Available since Linux 2.0. +*/ +sched_get_priority_max :: proc "contextless" (policy: i32) -> (i32, Errno) { + ret := syscall(SYS_sched_get_priority_max, policy) + return errno_unwrap(ret, i32) +} + +/* + Get static priority range. + Available since Linux 2.0. +*/ +sched_get_priority_min :: proc "contextless" (policy: i32) -> (i32, Errno) { + ret := syscall(SYS_sched_get_priority_min, policy) + return errno_unwrap(ret, i32) +} + +/* + get the SCHED_RR interval for the named process. + Available since Linux 2.0. +*/ +sched_rr_get_interval :: proc "contextless" (pid: Pid, tp: ^Time_Spec) -> (Errno) { + ret := syscall(SYS_sched_rr_get_interval, pid, tp) + return Errno(-ret) +} + +/* + Lock memory. Available since Linux 2.0. If flags specified, available since Linux 4.4. */ @@ -2560,9 +2609,29 @@ futex :: proc{ futex_wake_bitset, } -// TODO(flysand): sched_setaffinity +/* + Set a thread's CPU affinity mask. + Available since Linux 2.6. + + If you are running on a system with less than 128 cores you can use `linux.Cpu_Set` as the type for the mask argument. + Otherwise use an array of integers. +*/ +sched_setaffinity :: proc "contextless" (pid: Pid, cpusetsize: uint, mask: rawptr) -> (Errno) { + ret := syscall(SYS_sched_setaffinity, pid, cpusetsize, mask) + return Errno(-ret) +} -// TODO(flysand): sched_getaffinity +/* + Get a thread's CPU affinity mask. + Available since Linux 2.6. + + If you are running on a system with less than 128 cores you can use `linux.Cpu_Set` as the type for the mask argument. + Otherwise use an array of integers. +*/ +sched_getaffinity :: proc "contextless" (pid: Pid, cpusetsize: uint, mask: rawptr) -> (Errno) { + ret := syscall(SYS_sched_getaffinity, pid, cpusetsize, mask) + return Errno(-ret) +} // TODO(flysand): set_thread_area @@ -3103,7 +3172,14 @@ sendmmsg :: proc "contextless" (sock: Fd, msg_vec: []MMsg_Hdr, flags: Socket_Msg // TODO(flysand): setns -// TODO(flysand): getcpu +/* + Determine CPU and NUMA node on which the calling thread is running. + Available since Linux 2.6.19. +*/ +getcpu :: proc "contextless" (cpu, node: ^u32) -> (Errno) { + ret := syscall(SYS_getcpu, cpu, node) + return Errno(-ret) +} // TODO(flysand): process_vm_readv @@ -3113,9 +3189,23 @@ sendmmsg :: proc "contextless" (sock: Fd, msg_vec: []MMsg_Hdr, flags: Socket_Msg // TODO(flysand): finit_module -// TODO(flysand): sched_setattr +/* + Set scheduling policy and attributes. + Available since Linux 3.14. +*/ +sched_setattr :: proc "contextless" (pid: Pid, attr: ^Sched_Attr, flags: Sched_Attr_Flags) -> (Errno) { + ret := syscall(SYS_sched_setattr, pid, attr, transmute(u32)flags) + return Errno(-ret) +} -// TODO(flysand): sched_getattr +/* + Get scheduling policy and attributes. + Available since Linux 3.14. +*/ +sched_getattr :: proc "contextless" (pid: Pid, attr: ^Sched_Attr, size: u32, flags: Sched_Attr_Flags) -> (Errno) { + ret := syscall(SYS_sched_getattr, pid, attr, transmute(u32)flags) + return Errno(-ret) +} /* Rename the file with names relative to the specified dirfd's with other options. @@ -3133,7 +3223,14 @@ getrandom :: proc "contextless" (buf: []u8, flags: Get_Random_Flags) -> (int, Er return errno_unwrap(ret, int) } -// TODO(flysand): memfd_create +/* + Create an anonymous file. + Available since Linux 3.17. +*/ +memfd_create :: proc "contextless" (name: cstring, flags: Memfd_Create_Flags) -> (Fd, Errno) { + ret := syscall(SYS_memfd_create, cast(rawptr)name, transmute(u32)flags) + return errno_unwrap(ret, Fd) +} // TODO(flysand): kexec_file_load diff --git a/core/sys/linux/types.odin b/core/sys/linux/types.odin index 01028b9e1..c2334e5b6 100644 --- a/core/sys/linux/types.odin +++ b/core/sys/linux/types.odin @@ -1750,3 +1750,33 @@ Umount2_Flags :: bit_set[Umount2_Flags_Bits; u32] Swap_Flags :: bit_set[Swap_Flags_Bits; u32] Eventfd_Flags :: bit_set[Eventfd_Flags_Bits; i32] + +Cpu_Set :: bit_set[0 ..< 128] + +Sched_Param :: struct { + sched_priority: i32, +} + +Sched_Flags :: bit_set[Sched_Flag_Bits; u32] + +Sched_Attr :: struct { + size: u32, + + sched_policy: Sched_Policy, + sched_flags: Sched_Flags, + sched_nice: i32, + sched_priority: u32, + + /* For the DEADLINE policy */ + sched_runtime: u64, + sched_deadline: u64, + sched_period: u64, + + /* Utilization hints */ + sched_util_min: u32, + sched_util_max: u32, +} + +Sched_Attr_Flags :: bit_set[Sched_Attr_Flag_Bits; u32] + +Memfd_Create_Flags :: bit_set[Memfd_Create_Flag_Bits; u32] diff --git a/core/sys/orca/orca.odin b/core/sys/orca/orca.odin index a36c5fa2a..a0fe0a041 100644 --- a/core/sys/orca/orca.odin +++ b/core/sys/orca/orca.odin @@ -1,15 +1,13 @@ // Bindings for the Orca platform // // See: [[ https://orca-app.dev ]] + package orca import "core:c" char :: c.char -// currently missing in the api.json -window :: distinct u64 - // currently missing in the api.json pool :: struct { arena: arena, @@ -142,17 +140,6 @@ UNICODE_VARIATION_SELECTORS_SUPPLEMENT :: unicode_range { 0xe0100, 239 } UNICODE_SUPPLEMENTARY_PRIVATE_USE_AREA_A :: unicode_range { 0xf0000, 65533 } UNICODE_SUPPLEMENTARY_PRIVATE_USE_AREA_B :: unicode_range { 0x100000, 65533 } -clock_kind :: enum c.int { - MONOTONIC, - UPTIME, - DATE, -} - -@(default_calling_convention="c", link_prefix="oc_") -foreign { - clock_time :: proc(clock: clock_kind) -> f64 --- -} - file_write_slice :: proc(file: file, slice: []char) -> u64 { return file_write(file, u64(len(slice)), raw_data(slice)) } @@ -204,6 +191,26 @@ foreign { mat2x3_rotate :: proc(radians: f32) -> mat2x3 --- // Return a 2x3 matrix representing a translation. mat2x3_translate :: proc(x: f32, y: f32) -> mat2x3 --- + // Return a 2x3 matrix representing a scale. + mat2x3_scale :: proc(x: f32, y: f32) -> mat2x3 --- +} + +//////////////////////////////////////////////////////////////////////////////// +// API for sampling the system clock. +//////////////////////////////////////////////////////////////////////////////// + +clock_kind :: enum u32 { + // A clock incrementing monotonically. + MONOTONIC = 0, + // A clock incrementing monotonically during uptime. + UPTIME = 1, + // A clock driven by the platform time. + DATE = 2, +} + +@(default_calling_convention="c", link_prefix="oc_") +foreign { + clock_time :: proc(clock: clock_kind) -> f64 --- } //////////////////////////////////////////////////////////////////////////////// @@ -354,10 +361,14 @@ foreign { arena_init_with_options :: proc(arena: ^arena, options: ^arena_options) --- // Release all resources allocated to a memory arena. arena_cleanup :: proc(arena: ^arena) --- - // Allocate a block of memory from an arena. + // Allocate a zero initialized block of memory from an arena. arena_push :: proc(arena: ^arena, size: u64) -> rawptr --- - // Allocate an aligned block of memory from an arena. + // Allocate an aligned, zero initialized block of memory from an arena. arena_push_aligned :: proc(arena: ^arena, size: u64, alignment: u32) -> rawptr --- + // Allocate a block of memory from an arena. + arena_push_uninitialized :: proc(arena: ^arena, size: u64) -> rawptr --- + // Allocate an aligned block of memory from an arena. + arena_push_aligned_uninitialized :: proc(arena: ^arena, size: u64, alignment: u32) -> rawptr --- // Reset an arena. All memory that was previously allocated from this arena is released to the arena, and can be reallocated by later calls to `oc_arena_push` and similar functions. No memory is actually released _to the system_. arena_clear :: proc(arena: ^arena) --- // Begin a memory scope. This creates an `oc_arena_scope` object that stores the current offset of the arena. The arena can later be reset to that offset by calling `oc_arena_scope_end`, releasing all memory that was allocated within the scope to the arena. @@ -530,15 +541,15 @@ utf8_status :: enum u32 { // The operation unexpectedly encountered the end of the utf8 sequence. OUT_OF_BOUNDS = 1, // A continuation byte was encountered where a leading byte was expected. - UNEXPECTED_CONTINUATION_BYTE = 3, + UNEXPECTED_CONTINUATION_BYTE = 2, // A leading byte was encountered in the middle of the encoding of utf8 codepoint. - UNEXPECTED_LEADING_BYTE = 4, + UNEXPECTED_LEADING_BYTE = 3, // The utf8 sequence contains an invalid byte. - INVALID_BYTE = 5, + INVALID_BYTE = 4, // The operation encountered an invalid utf8 codepoint. - INVALID_CODEPOINT = 6, + INVALID_CODEPOINT = 5, // The utf8 sequence contains an overlong encoding of a utf8 codepoint. - OVERLONG_ENCODING = 7, + OVERLONG_ENCODING = 6, } // A type representing the result of decoding of utf8-encoded codepoint. @@ -1044,6 +1055,9 @@ file_dialog_result :: struct { selection: str8_list, } +// An opaque handle identifying a window. +window :: distinct u64 + @(default_calling_convention="c", link_prefix="oc_") foreign { // Set the title of the application's window. @@ -1054,8 +1068,93 @@ foreign { request_quit :: proc() --- // Convert a scancode to a keycode, according to current keyboard layout. scancode_to_keycode :: proc(scanCode: scan_code) -> key_code --- +} + +//////////////////////////////////////////////////////////////////////////////// +// Application user input. +//////////////////////////////////////////////////////////////////////////////// + +key_state :: struct { + lastUpdate: u64, + transitionCount: u32, + repeatCount: u32, + down: bool, + sysClicked: bool, + sysDoubleClicked: bool, + sysTripleClicked: bool, +} + +keyboard_state :: struct { + keys: [349]key_state, + mods: keymod_flags, +} + +mouse_state :: struct { + lastUpdate: u64, + posValid: bool, + pos: vec2, + delta: vec2, + wheel: vec2, + using _: struct #raw_union { + buttons: [5]key_state, + using _: struct { + left: key_state, + right: key_state, + middle: key_state, + ext1: key_state, + ext2: key_state, + }, + }, +} + +BACKING_SIZE :: 64 + +text_state :: struct { + lastUpdate: u64, + backing: [64]utf32, + codePoints: str32, +} + +clipboard_state :: struct { + lastUpdate: u64, + pastedText: str8, +} + +input_state :: struct { + frameCounter: u64, + keyboard: keyboard_state, + mouse: mouse_state, + text: text_state, + clipboard: clipboard_state, +} + +@(default_calling_convention="c", link_prefix="oc_") +foreign { + input_process_event :: proc(arena: ^arena, state: ^input_state, event: ^event) --- + input_next_frame :: proc(state: ^input_state) --- + key_down :: proc(state: ^input_state, key: key_code) -> bool --- + key_press_count :: proc(state: ^input_state, key: key_code) -> u8 --- + key_release_count :: proc(state: ^input_state, key: key_code) -> u8 --- + key_repeat_count :: proc(state: ^input_state, key: key_code) -> u8 --- + key_down_scancode :: proc(state: ^input_state, key: scan_code) -> bool --- + key_press_count_scancode :: proc(state: ^input_state, key: scan_code) -> u8 --- + key_release_count_scancode :: proc(state: ^input_state, key: scan_code) -> u8 --- + key_repeat_count_scancode :: proc(state: ^input_state, key: scan_code) -> u8 --- + mouse_down :: proc(state: ^input_state, button: mouse_button) -> bool --- + mouse_pressed :: proc(state: ^input_state, button: mouse_button) -> u8 --- + mouse_released :: proc(state: ^input_state, button: mouse_button) -> u8 --- + mouse_clicked :: proc(state: ^input_state, button: mouse_button) -> bool --- + mouse_double_clicked :: proc(state: ^input_state, button: mouse_button) -> bool --- + mouse_position :: proc(state: ^input_state) -> vec2 --- + mouse_delta :: proc(state: ^input_state) -> vec2 --- + mouse_wheel :: proc(state: ^input_state) -> vec2 --- + input_text_utf32 :: proc(arena: ^arena, state: ^input_state) -> str32 --- + input_text_utf8 :: proc(arena: ^arena, state: ^input_state) -> str8 --- // Put a string in the clipboard. clipboard_set_string :: proc(string: str8) --- + clipboard_pasted :: proc(state: ^input_state) -> bool --- + clipboard_pasted_text :: proc(state: ^input_state) -> str8 --- + key_mods :: proc(state: ^input_state) -> keymod_flags --- } //////////////////////////////////////////////////////////////////////////////// @@ -1073,7 +1172,7 @@ file :: distinct u64 // Flags for the `oc_file_open()` function. file_open_flag :: enum u16 { // Open the file in 'append' mode. All writes append data at the end of the file. - APPEND = 1, + APPEND = 0, // Truncate the file to 0 bytes when opening. TRUNCATE, // Create the file if it does not exist. @@ -1090,7 +1189,7 @@ file_open_flags :: bit_set[file_open_flag; u16] // This enum describes the access permissions of a file handle. file_access_flag :: enum u16 { // The file handle can be used for reading from the file. - READ = 1, + READ = 0, // The file handle can be used for writing to the file. WRITE, } @@ -1242,7 +1341,7 @@ file_type :: enum u32 { // A type describing file permissions. file_perm_flag :: enum u16 { - OTHER_EXEC = 1, + OTHER_EXEC = 0, OTHER_WRITE, OTHER_READ, GROUP_EXEC, @@ -1272,6 +1371,18 @@ file_status :: struct { modificationDate: datestamp, } +// An type describing a list of enumerated files in a given directory. +file_list :: struct { + list: list, + eltCount: u64, +} + +file_listdir_elt :: struct { + listElt: list_elt, + basename: str8, + type: file_type, +} + @(default_calling_convention="c", link_prefix="oc_") foreign { // Send a single I/O request and wait for its completion. @@ -1299,6 +1410,7 @@ foreign { file_get_status :: proc(file: file) -> file_status --- file_size :: proc(file: file) -> u64 --- file_open_with_request :: proc(path: str8, rights: file_access, flags: file_open_flags) -> file --- + file_listdir :: proc(arena: ^arena, directory: str8) -> file_list --- } //////////////////////////////////////////////////////////////////////////////// @@ -1703,87 +1815,6 @@ foreign { // Graphical User Interface API. //////////////////////////////////////////////////////////////////////////////// -key_state :: struct { - lastUpdate: u64, - transitionCount: u32, - repeatCount: u32, - down: bool, - sysClicked: bool, - sysDoubleClicked: bool, - sysTripleClicked: bool, -} - -keyboard_state :: struct { - keys: [349]key_state, - mods: keymod_flags, -} - -mouse_state :: struct { - lastUpdate: u64, - posValid: bool, - pos: vec2, - delta: vec2, - wheel: vec2, - using _: struct #raw_union { - buttons: [5]key_state, - using _: struct { - left: key_state, - right: key_state, - middle: key_state, - ext1: key_state, - ext2: key_state, - }, - }, -} - -BACKING_SIZE :: 64 - -text_state :: struct { - lastUpdate: u64, - backing: [64]utf32, - codePoints: str32, -} - -clipboard_state :: struct { - lastUpdate: u64, - pastedText: str8, -} - -input_state :: struct { - frameCounter: u64, - keyboard: keyboard_state, - mouse: mouse_state, - text: text_state, - clipboard: clipboard_state, -} - -@(default_calling_convention="c", link_prefix="oc_") -foreign { - input_process_event :: proc(arena: ^arena, state: ^input_state, event: ^event) --- - input_next_frame :: proc(state: ^input_state) --- - key_down :: proc(state: ^input_state, key: key_code) -> bool --- - key_press_count :: proc(state: ^input_state, key: key_code) -> u8 --- - key_release_count :: proc(state: ^input_state, key: key_code) -> u8 --- - key_repeat_count :: proc(state: ^input_state, key: key_code) -> u8 --- - key_down_scancode :: proc(state: ^input_state, key: scan_code) -> bool --- - key_press_count_scancode :: proc(state: ^input_state, key: scan_code) -> u8 --- - key_release_count_scancode :: proc(state: ^input_state, key: scan_code) -> u8 --- - key_repeat_count_scancode :: proc(state: ^input_state, key: scan_code) -> u8 --- - mouse_down :: proc(state: ^input_state, button: mouse_button) -> bool --- - mouse_pressed :: proc(state: ^input_state, button: mouse_button) -> u8 --- - mouse_released :: proc(state: ^input_state, button: mouse_button) -> u8 --- - mouse_clicked :: proc(state: ^input_state, button: mouse_button) -> bool --- - mouse_double_clicked :: proc(state: ^input_state, button: mouse_button) -> bool --- - mouse_position :: proc(state: ^input_state) -> vec2 --- - mouse_delta :: proc(state: ^input_state) -> vec2 --- - mouse_wheel :: proc(state: ^input_state) -> vec2 --- - input_text_utf32 :: proc(arena: ^arena, state: ^input_state) -> str32 --- - input_text_utf8 :: proc(arena: ^arena, state: ^input_state) -> str8 --- - clipboard_pasted :: proc(state: ^input_state) -> bool --- - clipboard_pasted_text :: proc(state: ^input_state) -> str8 --- - key_mods :: proc(state: ^input_state) -> keymod_flags --- -} - //////////////////////////////////////////////////////////////////////////////// // Graphical User Interface Core API. //////////////////////////////////////////////////////////////////////////////// @@ -1857,11 +1888,11 @@ ui_attribute_mask :: enum u32 { SIZE_WIDTH = 1, SIZE_HEIGHT = 2, LAYOUT_AXIS = 4, - LAYOUT_ALIGN_X = 64, - LAYOUT_ALIGN_Y = 128, - LAYOUT_SPACING = 32, LAYOUT_MARGIN_X = 8, LAYOUT_MARGIN_Y = 16, + LAYOUT_SPACING = 32, + LAYOUT_ALIGN_X = 64, + LAYOUT_ALIGN_Y = 128, FLOATING_X = 256, FLOATING_Y = 512, FLOAT_TARGET_X = 1024, @@ -1873,10 +1904,10 @@ ui_attribute_mask :: enum u32 { COLOR = 65536, BG_COLOR = 131072, BORDER_COLOR = 262144, - BORDER_SIZE = 2097152, - ROUNDNESS = 4194304, FONT = 524288, FONT_SIZE = 1048576, + BORDER_SIZE = 2097152, + ROUNDNESS = 4194304, DRAW_MASK = 8388608, ANIMATION_TIME = 16777216, ANIMATION_MASK = 33554432, @@ -1898,6 +1929,7 @@ ui_box_size :: [2]ui_size ui_box_floating :: [2]bool +// These bits *disable* the corresponding element when they're set. ui_draw_mask :: enum u32 { BACKGROUND = 1, BORDER = 2, diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 98185b0d3..cd2307c6d 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -11554,6 +11554,15 @@ gb_internal ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast return kind; case_end; + case_ast_node(ht, HelperType, node); + Type *type = check_type(c, ht->type); + if (type != nullptr && type != t_invalid) { + o->mode = Addressing_Type; + o->type = type; + } + return kind; + case_end; + case_ast_node(i, Implicit, node); switch (i->kind) { case Token_context: diff --git a/src/linker.cpp b/src/linker.cpp index c2a3ee928..c68417994 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -737,7 +737,21 @@ try_cross_linking:; } if (build_context.build_mode == BuildMode_StaticLibrary) { - compiler_error("TODO(bill): -build-mode:static on non-windows targets"); + TIME_SECTION("Static Library Creation"); + + gbString ar_command = gb_string_make(heap_allocator(), ""); + defer (gb_string_free(ar_command)); + + ar_command = gb_string_appendc(ar_command, "ar rcs "); + ar_command = gb_string_append_fmt(ar_command, "\"%.*s\" ", LIT(output_filename)); + ar_command = gb_string_appendc(ar_command, object_files); + + result = system_exec_command_line_app("ar", ar_command); + if (result) { + return result; + } + + return result; } // NOTE(dweiler): We use clang as a frontend for the linker as there are