From c078b2dd1be617e6687a3a5ffc919a45bbabb5bf Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 4 Aug 2024 15:24:26 +0100 Subject: [PATCH] Add `@(require_results)` --- core/os/dir_windows.odin | 1 + core/os/errors.odin | 6 ++++ core/os/file_windows.odin | 14 ++++++-- core/os/os_darwin.odin | 65 ++++++++++++++++++++++++------------ core/os/os_freebsd.odin | 51 +++++++++++++++++++--------- core/os/os_haiku.odin | 27 ++++++++++----- core/os/os_js.odin | 21 ++++++++++-- core/os/os_linux.odin | 70 ++++++++++++++++++++++++++------------- core/os/os_netbsd.odin | 52 ++++++++++++++++++++--------- core/os/os_openbsd.odin | 50 +++++++++++++++++++--------- core/os/os_wasi.odin | 9 +++-- core/os/os_windows.odin | 28 +++++++++++----- core/os/stat_unix.odin | 9 +++-- core/os/stat_windows.odin | 27 ++++++++------- 14 files changed, 297 insertions(+), 133 deletions(-) diff --git a/core/os/dir_windows.odin b/core/os/dir_windows.odin index f0a1f4ff6..ae3e6922c 100644 --- a/core/os/dir_windows.odin +++ b/core/os/dir_windows.odin @@ -6,6 +6,7 @@ import "base:runtime" @(require_results) read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Error) { + @(require_results) find_data_to_file_info :: proc(base_path: string, d: ^win32.WIN32_FIND_DATAW) -> (fi: File_Info) { // Ignore "." and ".." if d.cFileName[0] == '.' && d.cFileName[1] == 0 { diff --git a/core/os/errors.odin b/core/os/errors.odin index d95c7be51..691397f4b 100644 --- a/core/os/errors.odin +++ b/core/os/errors.odin @@ -139,6 +139,12 @@ _error_string :: proc "contextless" (e: Platform_Error) -> string where intrinsi return "" } + when ODIN_OS == .Darwin { + if s := string(_darwin_string_error(i32(e))); s != "" { + return s + } + } + when ODIN_OS != .Linux { @(require_results) binary_search :: proc "contextless" (array: $A/[]$T, key: T) -> (index: int, found: bool) #no_bounds_check { diff --git a/core/os/file_windows.odin b/core/os/file_windows.odin index aafe247b3..3f6f781aa 100644 --- a/core/os/file_windows.odin +++ b/core/os/file_windows.odin @@ -5,10 +5,12 @@ import "base:intrinsics" import "base:runtime" import "core:unicode/utf16" +@(require_results) is_path_separator :: proc(c: byte) -> bool { return c == '/' || c == '\\' } +@(require_results) open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Error) { if len(path) == 0 { return INVALID_HANDLE, General_Error.Not_Exist @@ -96,7 +98,7 @@ write :: proc(fd: Handle, data: []byte) -> (int, Error) { return int(total_write), nil } -@(private="file") +@(private="file", require_results) read_console :: proc(handle: win32.HANDLE, b: []byte) -> (n: int, err: Error) { if len(b) == 0 { return 0, nil @@ -206,6 +208,7 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) { return i64(hi)<<32 + i64(dw_ptr), nil } +@(require_results) file_size :: proc(fd: Handle) -> (i64, Error) { length: win32.LARGE_INTEGER err: Error @@ -331,6 +334,7 @@ stdout := get_std_handle(uint(win32.STD_OUTPUT_HANDLE)) stderr := get_std_handle(uint(win32.STD_ERROR_HANDLE)) +@(require_results) get_std_handle :: proc "contextless" (h: uint) -> Handle { fd := win32.GetStdHandle(win32.DWORD(h)) return Handle(fd) @@ -345,6 +349,7 @@ exists :: proc(path: string) -> bool { return attribs != win32.INVALID_FILE_ATTRIBUTES } +@(require_results) is_file :: proc(path: string) -> bool { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() wpath := win32.utf8_to_wstring(path, context.temp_allocator) @@ -356,6 +361,7 @@ is_file :: proc(path: string) -> bool { return false } +@(require_results) is_dir :: proc(path: string) -> bool { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() wpath := win32.utf8_to_wstring(path, context.temp_allocator) @@ -370,6 +376,7 @@ is_dir :: proc(path: string) -> bool { // NOTE(tetra): GetCurrentDirectory is not thread safe with SetCurrentDirectory and GetFullPathName @private cwd_lock := win32.SRWLOCK{} // zero is initialized +@(require_results) get_current_directory :: proc(allocator := context.allocator) -> string { win32.AcquireSRWLockExclusive(&cwd_lock) @@ -426,7 +433,7 @@ remove_directory :: proc(path: string) -> (err: Error) { -@(private) +@(private, require_results) is_abs :: proc(path: string) -> bool { if len(path) > 0 && path[0] == '/' { return true @@ -442,7 +449,7 @@ is_abs :: proc(path: string) -> bool { return false } -@(private) +@(private, require_results) fix_long_path :: proc(path: string) -> string { if len(path) < 248 { return path @@ -574,6 +581,7 @@ remove :: proc(name: string) -> Error { } +@(require_results) pipe :: proc() -> (r, w: Handle, err: Error) { sa: win32.SECURITY_ATTRIBUTES sa.nLength = size_of(win32.SECURITY_ATTRIBUTES) diff --git a/core/os/os_darwin.odin b/core/os/os_darwin.odin index 96ef178bb..09cdd84d0 100644 --- a/core/os/os_darwin.odin +++ b/core/os/os_darwin.odin @@ -562,13 +562,13 @@ S_ISUID :: 0o4000 // Set user id on execution S_ISGID :: 0o2000 // Set group id on execution S_ISVTX :: 0o1000 // Directory restrcted delete -S_ISLNK :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFLNK } -S_ISREG :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFREG } -S_ISDIR :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFDIR } -S_ISCHR :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFCHR } -S_ISBLK :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFBLK } -S_ISFIFO :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFIFO } -S_ISSOCK :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFSOCK } +@(require_results) S_ISLNK :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFLNK } +@(require_results) S_ISREG :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFREG } +@(require_results) S_ISDIR :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFDIR } +@(require_results) S_ISCHR :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFCHR } +@(require_results) S_ISBLK :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFBLK } +@(require_results) S_ISFIFO :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFIFO } +@(require_results) S_ISSOCK :: #force_inline proc(m: u16) -> bool { return (m & S_IFMT) == S_IFSOCK } R_OK :: 4 // Test for read permission W_OK :: 2 // Test for write permission @@ -667,11 +667,13 @@ get_last_error :: proc "contextless" () -> Error { return Platform_Error(__error()^) } +@(require_results) get_last_error_string :: proc() -> string { return string(_darwin_string_error(__error()^)) } +@(require_results) open :: proc(path: string, flags: int = O_RDWR, mode: int = 0) -> (handle: Handle, err: Error) { isDir := is_dir_path(path) flags := flags @@ -790,6 +792,7 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) { return final_offset, nil } +@(require_results) file_size :: proc(fd: Handle) -> (i64, Error) { prev, _ := seek(fd, 0, SEEK_CUR) size, err := seek(fd, 0, SEEK_END) @@ -804,12 +807,14 @@ stdin: Handle = 0 // get_std_handle(win32.STD_INPUT_HANDLE); stdout: Handle = 1 // get_std_handle(win32.STD_OUTPUT_HANDLE); stderr: Handle = 2 // get_std_handle(win32.STD_ERROR_HANDLE); +@(require_results) last_write_time :: proc(fd: Handle) -> (time: File_Time, err: Error) { s := _fstat(fd) or_return modified := s.modified.seconds * 1_000_000_000 + s.modified.nanoseconds return File_Time(modified), nil } +@(require_results) last_write_time_by_name :: proc(name: string) -> (time: File_Time, err: Error) { s := _stat(name) or_return modified := s.modified.seconds * 1_000_000_000 + s.modified.nanoseconds @@ -817,10 +822,12 @@ last_write_time_by_name :: proc(name: string) -> (time: File_Time, err: Error) { } +@(require_results) is_path_separator :: proc(r: rune) -> bool { return r == '/' } +@(require_results) is_file_handle :: proc(fd: Handle) -> bool { s, err := _fstat(fd) if err != nil { @@ -829,6 +836,7 @@ is_file_handle :: proc(fd: Handle) -> bool { return S_ISREG(s.mode) } +@(require_results) is_file_path :: proc(path: string, follow_links: bool = true) -> bool { s: OS_Stat err: Error @@ -844,6 +852,7 @@ is_file_path :: proc(path: string, follow_links: bool = true) -> bool { } +@(require_results) is_dir_handle :: proc(fd: Handle) -> bool { s, err := _fstat(fd) if err != nil { @@ -852,6 +861,7 @@ is_dir_handle :: proc(fd: Handle) -> bool { return S_ISDIR(s.mode) } +@(require_results) is_dir_path :: proc(path: string, follow_links: bool = true) -> bool { s: OS_Stat err: Error @@ -869,6 +879,7 @@ is_dir_path :: proc(path: string, follow_links: bool = true) -> bool { is_file :: proc {is_file_path, is_file_handle} is_dir :: proc {is_dir_path, is_dir_handle} +@(require_results) exists :: proc(path: string) -> bool { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cpath := strings.clone_to_cstring(path, context.temp_allocator) @@ -893,7 +904,7 @@ remove :: proc(path: string) -> Error { return nil } -@private +@(private, require_results) _stat :: proc(path: string) -> (OS_Stat, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -906,7 +917,7 @@ _stat :: proc(path: string) -> (OS_Stat, Error) { return s, nil } -@private +@(private, require_results) _lstat :: proc(path: string) -> (OS_Stat, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -919,7 +930,7 @@ _lstat :: proc(path: string) -> (OS_Stat, Error) { return s, nil } -@private +@(private, require_results) _fstat :: proc(fd: Handle) -> (OS_Stat, Error) { s: OS_Stat result := _unix_fstat(fd, &s) @@ -929,7 +940,7 @@ _fstat :: proc(fd: Handle) -> (OS_Stat, Error) { return s, nil } -@private +@(private, require_results) _fdopendir :: proc(fd: Handle) -> (Dir, Error) { dirp := _unix_fdopendir(fd) if dirp == cast(Dir)nil { @@ -938,7 +949,7 @@ _fdopendir :: proc(fd: Handle) -> (Dir, Error) { return dirp, nil } -@private +@(private) _closedir :: proc(dirp: Dir) -> Error { rc := _unix_closedir(dirp) if rc != 0 { @@ -947,12 +958,12 @@ _closedir :: proc(dirp: Dir) -> Error { return nil } -@private +@(private) _rewinddir :: proc(dirp: Dir) { _unix_rewinddir(dirp) } -@private +@(private, require_results) _readdir :: proc(dirp: Dir) -> (entry: Dirent, err: Error, end_of_stream: bool) { result: ^Dirent rc := _unix_readdir_r(dirp, &entry, &result) @@ -971,7 +982,7 @@ _readdir :: proc(dirp: Dir) -> (entry: Dirent, err: Error, end_of_stream: bool) return } -@private +@(private, require_results) _readlink :: proc(path: string) -> (string, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator) path_cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -994,12 +1005,14 @@ _readlink :: proc(path: string) -> (string, Error) { } } +@(require_results) absolute_path_from_handle :: proc(fd: Handle) -> (path: string, err: Error) { buf: [DARWIN_MAXPATHLEN]byte _ = fcntl(int(fd), F_GETPATH, int(uintptr(&buf[0]))) or_return return strings.clone_from_cstring(cstring(&buf[0])) } +@(require_results) absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) { rel := rel if rel == "" { @@ -1031,6 +1044,7 @@ flush :: proc(fd: Handle) -> Error { return cast(Platform_Error)_unix_fsync(fd) } +@(require_results) lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator) path_str := strings.clone_to_cstring(key, context.temp_allocator) @@ -1041,6 +1055,7 @@ lookup_env :: proc(key: string, allocator := context.allocator) -> (value: strin return strings.clone(string(cstr), allocator), true } +@(require_results) get_env :: proc(key: string, allocator := context.allocator) -> (value: string) { value, _ = lookup_env(key, allocator) return @@ -1067,6 +1082,7 @@ unset_env :: proc(key: string) -> Error { return nil } +@(require_results) get_current_directory :: proc() -> string { page_size := get_page_size() // NOTE(tetra): See note in os_linux.odin/get_current_directory. buf := make([dynamic]u8, page_size) @@ -1109,6 +1125,7 @@ exit :: proc "contextless" (code: int) -> ! { _unix_exit(i32(code)) } +@(require_results) current_thread_id :: proc "contextless" () -> int { tid: u64 // NOTE(Oskar): available from OSX 10.6 and iOS 3.2. @@ -1119,12 +1136,14 @@ current_thread_id :: proc "contextless" () -> int { return int(tid) } +@(require_results) dlopen :: proc(filename: string, flags: int) -> rawptr { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(filename, context.temp_allocator) handle := _unix_dlopen(cstr, flags) return handle } +@(require_results) dlsym :: proc(handle: rawptr, symbol: string) -> rawptr { assert(handle != nil) runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() @@ -1140,6 +1159,7 @@ dlerror :: proc() -> string { return string(_unix_dlerror()) } +@(require_results) get_page_size :: proc() -> int { // NOTE(tetra): The page size never changes, so why do anything complicated // if we don't have to. @@ -1152,7 +1172,7 @@ get_page_size :: proc() -> int { return page_size } -@(private) +@(private, require_results) _processor_core_count :: proc() -> int { count : int = 0 count_size := size_of(count) @@ -1165,6 +1185,7 @@ _processor_core_count :: proc() -> int { return 1 } +@(require_results) _alloc_command_line_arguments :: proc() -> []string { res := make([]string, len(runtime.args__)) for _, i in res { @@ -1173,6 +1194,7 @@ _alloc_command_line_arguments :: proc() -> []string { return res } +@(require_results) socket :: proc(domain: int, type: int, protocol: int) -> (Socket, Error) { result := _unix_socket(domain, type, protocol) if result < 0 { @@ -1181,7 +1203,8 @@ socket :: proc(domain: int, type: int, protocol: int) -> (Socket, Error) { return Socket(result), nil } -connect :: proc(sd: Socket, addr: ^SOCKADDR, len: socklen_t) -> (Error) { +@(require_results) +connect :: proc(sd: Socket, addr: ^SOCKADDR, len: socklen_t) -> Error { result := _unix_connect(int(sd), addr, len) if result < 0 { return get_last_error() @@ -1189,7 +1212,7 @@ connect :: proc(sd: Socket, addr: ^SOCKADDR, len: socklen_t) -> (Error) { return nil } -bind :: proc(sd: Socket, addr: ^SOCKADDR, len: socklen_t) -> (Error) { +bind :: proc(sd: Socket, addr: ^SOCKADDR, len: socklen_t) -> Error { result := _unix_bind(int(sd), addr, len) if result < 0 { return get_last_error() @@ -1205,7 +1228,7 @@ accept :: proc(sd: Socket, addr: ^SOCKADDR, len: rawptr) -> (Socket, Error) { return Socket(result), nil } -listen :: proc(sd: Socket, backlog: int) -> (Error) { +listen :: proc(sd: Socket, backlog: int) -> Error { result := _unix_listen(int(sd), backlog) if result < 0 { return get_last_error() @@ -1213,7 +1236,7 @@ listen :: proc(sd: Socket, backlog: int) -> (Error) { return nil } -setsockopt :: proc(sd: Socket, level: int, optname: int, optval: rawptr, optlen: socklen_t) -> (Error) { +setsockopt :: proc(sd: Socket, level: int, optname: int, optval: rawptr, optlen: socklen_t) -> Error { result := _unix_setsockopt(int(sd), level, optname, optval, optlen) if result < 0 { return get_last_error() @@ -1261,7 +1284,7 @@ send :: proc(sd: Socket, data: []byte, flags: int) -> (u32, Error) { return u32(result), nil } -shutdown :: proc(sd: Socket, how: int) -> (Error) { +shutdown :: proc(sd: Socket, how: int) -> Error { result := _unix_shutdown(int(sd), how) if result < 0 { return get_last_error() diff --git a/core/os/os_freebsd.odin b/core/os/os_freebsd.odin index 1a38aa20c..c7955368e 100644 --- a/core/os/os_freebsd.odin +++ b/core/os/os_freebsd.odin @@ -353,13 +353,13 @@ S_ISGID :: 0o2000 // Set group id on execution S_ISVTX :: 0o1000 // Directory restrcted delete -S_ISLNK :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFLNK } -S_ISREG :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFREG } -S_ISDIR :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFDIR } -S_ISCHR :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFCHR } -S_ISBLK :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFBLK } -S_ISFIFO :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFIFO } -S_ISSOCK :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFSOCK } +@(require_results) S_ISLNK :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFLNK } +@(require_results) S_ISREG :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFREG } +@(require_results) S_ISDIR :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFDIR } +@(require_results) S_ISCHR :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFCHR } +@(require_results) S_ISBLK :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFBLK } +@(require_results) S_ISFIFO :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFIFO } +@(require_results) S_ISSOCK :: #force_inline proc(m: mode_t) -> bool { return (m & S_IFMT) == S_IFSOCK } F_OK :: 0 // Test for file existance X_OK :: 1 // Test for execute permission @@ -415,6 +415,7 @@ foreign dl { @(link_name="pthread_getthreadid_np") pthread_getthreadid_np :: proc() -> c.int --- } +@(require_results) is_path_separator :: proc(r: rune) -> bool { return r == '/' } @@ -424,6 +425,7 @@ get_last_error :: proc "contextless" () -> Error { return Platform_Error(__Error_location()^) } +@(require_results) open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -505,6 +507,7 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) { return res, nil } +@(require_results) file_size :: proc(fd: Handle) -> (size: i64, err: Error) { size = -1 s := _fstat(fd) or_return @@ -553,6 +556,7 @@ remove_directory :: proc(path: string) -> Error { return nil } +@(require_results) is_file_handle :: proc(fd: Handle) -> bool { s, err := _fstat(fd) if err != nil { @@ -561,6 +565,7 @@ is_file_handle :: proc(fd: Handle) -> bool { return S_ISREG(s.mode) } +@(require_results) is_file_path :: proc(path: string, follow_links: bool = true) -> bool { s: OS_Stat err: Error @@ -575,6 +580,7 @@ is_file_path :: proc(path: string, follow_links: bool = true) -> bool { return S_ISREG(s.mode) } +@(require_results) is_dir_handle :: proc(fd: Handle) -> bool { s, err := _fstat(fd) if err != nil { @@ -583,6 +589,7 @@ is_dir_handle :: proc(fd: Handle) -> bool { return S_ISDIR(s.mode) } +@(require_results) is_dir_path :: proc(path: string, follow_links: bool = true) -> bool { s: OS_Stat err: Error @@ -610,6 +617,7 @@ stderr: Handle = 2 last_write_time :: proc(fd: Handle) -> File_Time {} last_write_time_by_name :: proc(name: string) -> File_Time {} */ +@(require_results) last_write_time :: proc(fd: Handle) -> (File_Time, Error) { s, err := _fstat(fd) if err != nil { @@ -619,6 +627,7 @@ last_write_time :: proc(fd: Handle) -> (File_Time, Error) { return File_Time(modified), nil } +@(require_results) last_write_time_by_name :: proc(name: string) -> (File_Time, Error) { s, err := _stat(name) if err != nil { @@ -628,7 +637,7 @@ last_write_time_by_name :: proc(name: string) -> (File_Time, Error) { return File_Time(modified), nil } -@private +@(private, require_results) _stat :: proc(path: string) -> (OS_Stat, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -640,7 +649,7 @@ _stat :: proc(path: string) -> (OS_Stat, Error) { return s, nil } -@private +@(private, require_results) _lstat :: proc(path: string) -> (OS_Stat, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -654,7 +663,7 @@ _lstat :: proc(path: string) -> (OS_Stat, Error) { return s, nil } -@private +@(private, require_results) _fstat :: proc(fd: Handle) -> (OS_Stat, Error) { s: OS_Stat = --- result := _unix_fstat(fd, &s) @@ -664,7 +673,7 @@ _fstat :: proc(fd: Handle) -> (OS_Stat, Error) { return s, nil } -@private +@(private, require_results) _fdopendir :: proc(fd: Handle) -> (Dir, Error) { dirp := _unix_fdopendir(fd) if dirp == cast(Dir)nil { @@ -673,7 +682,7 @@ _fdopendir :: proc(fd: Handle) -> (Dir, Error) { return dirp, nil } -@private +@(private) _closedir :: proc(dirp: Dir) -> Error { rc := _unix_closedir(dirp) if rc != 0 { @@ -682,12 +691,12 @@ _closedir :: proc(dirp: Dir) -> Error { return nil } -@private +@(private) _rewinddir :: proc(dirp: Dir) { _unix_rewinddir(dirp) } -@private +@(private, require_results) _readdir :: proc(dirp: Dir) -> (entry: Dirent, err: Error, end_of_stream: bool) { result: ^Dirent rc := _unix_readdir_r(dirp, &entry, &result) @@ -705,7 +714,7 @@ _readdir :: proc(dirp: Dir) -> (entry: Dirent, err: Error, end_of_stream: bool) return } -@private +@(private, require_results) _readlink :: proc(path: string) -> (string, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator) @@ -730,6 +739,7 @@ _readlink :: proc(path: string) -> (string, Error) { return "", Error{} } +@(require_results) absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) { // NOTE(Feoramund): The situation isn't ideal, but this was the best way I // could find to implement this. There are a couple outstanding bug reports @@ -752,6 +762,7 @@ absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) { return path, nil } +@(require_results) absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) { rel := rel if rel == "" { @@ -784,6 +795,7 @@ access :: proc(path: string, mask: int) -> (bool, Error) { return true, nil } +@(require_results) lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator) @@ -795,11 +807,13 @@ lookup_env :: proc(key: string, allocator := context.allocator) -> (value: strin return strings.clone(string(cstr), allocator), true } +@(require_results) get_env :: proc(key: string, allocator := context.allocator) -> (value: string) { value, _ = lookup_env(key, allocator) return } +@(require_results) get_current_directory :: proc() -> string { // NOTE(tetra): I would use PATH_MAX here, but I was not able to find // an authoritative value for it across all systems. @@ -835,16 +849,19 @@ exit :: proc "contextless" (code: int) -> ! { _unix_exit(c.int(code)) } +@(require_results) current_thread_id :: proc "contextless" () -> int { return cast(int) pthread_getthreadid_np() } +@(require_results) dlopen :: proc(filename: string, flags: int) -> rawptr { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(filename, context.temp_allocator) handle := _unix_dlopen(cstr, c.int(flags)) return handle } +@(require_results) dlsym :: proc(handle: rawptr, symbol: string) -> rawptr { assert(handle != nil) runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() @@ -860,6 +877,7 @@ dlerror :: proc() -> string { return string(_unix_dlerror()) } +@(require_results) get_page_size :: proc() -> int { // NOTE(tetra): The page size never changes, so why do anything complicated // if we don't have to. @@ -872,7 +890,7 @@ get_page_size :: proc() -> int { return page_size } -@(private) +@(private, require_results) _processor_core_count :: proc() -> int { count : int = 0 count_size := size_of(count) @@ -886,6 +904,7 @@ _processor_core_count :: proc() -> int { } +@(require_results) _alloc_command_line_arguments :: proc() -> []string { res := make([]string, len(runtime.args__)) for arg, i in runtime.args__ { diff --git a/core/os/os_haiku.odin b/core/os/os_haiku.odin index ffaf12aae..7f1ec7089 100644 --- a/core/os/os_haiku.odin +++ b/core/os/os_haiku.odin @@ -177,6 +177,7 @@ Dirent :: struct { Dir :: distinct rawptr // DIR* +@(require_results) is_path_separator :: proc(r: rune) -> bool { return r == '/' } @@ -186,6 +187,7 @@ get_last_error :: proc "contextless" () -> Error { return Platform_Error(__error()^) } +@(require_results) fork :: proc() -> (Pid, Error) { pid := _unix_fork() if pid == -1 { @@ -194,6 +196,7 @@ fork :: proc() -> (Pid, Error) { return Pid(pid), nil } +@(require_results) open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -274,6 +277,7 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) { return res, nil } +@(require_results) file_size :: proc(fd: Handle) -> (i64, Error) { s, err := _fstat(fd) if err != nil { @@ -285,6 +289,7 @@ file_size :: proc(fd: Handle) -> (i64, Error) { // "Argv" arguments converted to Odin strings args := _alloc_command_line_arguments() +@(require_results) _alloc_command_line_arguments :: proc() -> []string { res := make([]string, len(runtime.args__)) for arg, i in runtime.args__ { @@ -293,7 +298,7 @@ _alloc_command_line_arguments :: proc() -> []string { return res } -@private +@(private, require_results) _stat :: proc(path: string) -> (OS_Stat, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -307,7 +312,7 @@ _stat :: proc(path: string) -> (OS_Stat, Error) { return s, nil } -@private +@(private, require_results) _lstat :: proc(path: string) -> (OS_Stat, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -321,7 +326,7 @@ _lstat :: proc(path: string) -> (OS_Stat, Error) { return s, nil } -@private +@(private, require_results) _fstat :: proc(fd: Handle) -> (OS_Stat, Error) { // deliberately uninitialized s: OS_Stat = --- @@ -332,7 +337,7 @@ _fstat :: proc(fd: Handle) -> (OS_Stat, Error) { return s, nil } -@private +@(private) _fdopendir :: proc(fd: Handle) -> (Dir, Error) { dirp := _unix_fdopendir(fd) if dirp == cast(Dir)nil { @@ -341,7 +346,7 @@ _fdopendir :: proc(fd: Handle) -> (Dir, Error) { return dirp, nil } -@private +@(private) _closedir :: proc(dirp: Dir) -> Error { rc := _unix_closedir(dirp) if rc != 0 { @@ -350,12 +355,12 @@ _closedir :: proc(dirp: Dir) -> Error { return nil } -@private +@(private) _rewinddir :: proc(dirp: Dir) { _unix_rewinddir(dirp) } -@private +@(private, require_results) _readdir :: proc(dirp: Dir) -> (entry: Dirent, err: Error, end_of_stream: bool) { result: ^Dirent rc := _unix_readdir_r(dirp, &entry, &result) @@ -373,7 +378,7 @@ _readdir :: proc(dirp: Dir) -> (entry: Dirent, err: Error, end_of_stream: bool) return } -@private +@(private, require_results) _readlink :: proc(path: string) -> (string, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator) path_cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -395,10 +400,12 @@ _readlink :: proc(path: string) -> (string, Error) { } } +@(require_results) absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) { return "", Error(ENOSYS) } +@(require_results) absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) { rel := rel if rel == "" { @@ -430,6 +437,7 @@ access :: proc(path: string, mask: int) -> (bool, Error) { return true, nil } +@(require_results) lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator) path_str := strings.clone_to_cstring(key, context.temp_allocator) @@ -440,12 +448,13 @@ lookup_env :: proc(key: string, allocator := context.allocator) -> (value: strin return strings.clone(string(cstr), allocator), true } +@(require_results) get_env :: proc(key: string, allocator := context.allocator) -> (value: string) { value, _ = lookup_env(key, allocator) return } -@(private) +@(private, require_results) _processor_core_count :: proc() -> int { info: haiku.system_info haiku.get_system_info(&info) diff --git a/core/os/os_js.odin b/core/os/os_js.odin index a2ae49b6d..eb434c727 100644 --- a/core/os/os_js.odin +++ b/core/os/os_js.odin @@ -3,10 +3,12 @@ package os import "base:runtime" +@(require_results) is_path_separator :: proc(c: byte) -> bool { return c == '/' || c == '\\' } +@(require_results) open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Error) { unimplemented("core:os procedure not supported on JS target") } @@ -38,6 +40,7 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) { unimplemented("core:os procedure not supported on JS target") } +@(require_results) file_size :: proc(fd: Handle) -> (i64, Error) { unimplemented("core:os procedure not supported on JS target") } @@ -65,20 +68,24 @@ write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Error) stdout: Handle = 1 stderr: Handle = 2 +@(require_results) get_std_handle :: proc "contextless" (h: uint) -> Handle { context = runtime.default_context() unimplemented("core:os procedure not supported on JS target") } +@(require_results) exists :: proc(path: string) -> bool { unimplemented("core:os procedure not supported on JS target") } +@(require_results) is_file :: proc(path: string) -> bool { unimplemented("core:os procedure not supported on JS target") } +@(require_results) is_dir :: proc(path: string) -> bool { unimplemented("core:os procedure not supported on JS target") } @@ -86,6 +93,7 @@ is_dir :: proc(path: string) -> bool { // NOTE(tetra): GetCurrentDirectory is not thread safe with SetCurrentDirectory and GetFullPathName //@private cwd_lock := win32.SRWLOCK{} // zero is initialized +@(require_results) get_current_directory :: proc(allocator := context.allocator) -> string { unimplemented("core:os procedure not supported on JS target") } @@ -111,12 +119,12 @@ remove_directory :: proc(path: string) -> (err: Error) { -@(private) +@(private, require_results) is_abs :: proc(path: string) -> bool { unimplemented("core:os procedure not supported on JS target") } -@(private) +@(private, require_results) fix_long_path :: proc(path: string) -> string { unimplemented("core:os procedure not supported on JS target") } @@ -151,10 +159,12 @@ remove :: proc(name: string) -> Error { } +@(require_results) pipe :: proc() -> (r, w: Handle, err: Error) { unimplemented("core:os procedure not supported on JS target") } +@(require_results) read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Error) { unimplemented("core:os procedure not supported on JS target") } @@ -251,20 +261,23 @@ args := _alloc_command_line_arguments() +@(require_results) last_write_time :: proc(fd: Handle) -> (File_Time, Error) { unimplemented("core:os procedure not supported on JS target") } +@(require_results) last_write_time_by_name :: proc(name: string) -> (File_Time, Error) { unimplemented("core:os procedure not supported on JS target") } +@(require_results) get_page_size :: proc() -> int { unimplemented("core:os procedure not supported on JS target") } -@(private) +@(private, require_results) _processor_core_count :: proc() -> int { unimplemented("core:os procedure not supported on JS target") } @@ -276,6 +289,7 @@ exit :: proc "contextless" (code: int) -> ! { +@(require_results) current_thread_id :: proc "contextless" () -> int { context = runtime.default_context() unimplemented("core:os procedure not supported on JS target") @@ -283,6 +297,7 @@ current_thread_id :: proc "contextless" () -> int { +@(require_results) _alloc_command_line_arguments :: proc() -> []string { return nil } diff --git a/core/os/os_linux.odin b/core/os/os_linux.odin index 4aa4f279e..1e110d18f 100644 --- a/core/os/os_linux.odin +++ b/core/os/os_linux.odin @@ -448,13 +448,13 @@ S_ISGID :: 0o2000 // Set group id on execution S_ISVTX :: 0o1000 // Directory restrcted delete -S_ISLNK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFLNK } -S_ISREG :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFREG } -S_ISDIR :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFDIR } -S_ISCHR :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFCHR } -S_ISBLK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFBLK } -S_ISFIFO :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFIFO } -S_ISSOCK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFSOCK } +@(require_results) S_ISLNK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFLNK } +@(require_results) S_ISREG :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFREG } +@(require_results) S_ISDIR :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFDIR } +@(require_results) S_ISCHR :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFCHR } +@(require_results) S_ISBLK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFBLK } +@(require_results) S_ISFIFO :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFIFO } +@(require_results) S_ISSOCK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFSOCK } F_OK :: 0 // Test for file existance X_OK :: 1 // Test for execute permission @@ -506,12 +506,13 @@ foreign dl { @(link_name="freeifaddrs") _freeifaddrs :: proc(ifa: ^ifaddrs) --- } +@(require_results) is_path_separator :: proc(r: rune) -> bool { return r == '/' } // determine errno from syscall return value -@private +@(private, require_results) _get_errno :: proc(res: int) -> Error { if res < 0 && res > -4096 { return Platform_Error(-res) @@ -536,7 +537,7 @@ get_last_error :: proc "contextless" () -> Error { return err } -personality :: proc(persona: u64) -> (Error) { +personality :: proc(persona: u64) -> Error { res := unix.sys_personality(persona) if res == -1 { return _get_errno(res) @@ -544,6 +545,7 @@ personality :: proc(persona: u64) -> (Error) { return nil } +@(require_results) fork :: proc() -> (Pid, Error) { pid := unix.sys_fork() if pid == -1 { @@ -567,6 +569,7 @@ execvp :: proc(path: string, args: []string) -> Error { } +@(require_results) open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0o000) -> (Handle, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -659,6 +662,7 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) { return i64(res), nil } +@(require_results) file_size :: proc(fd: Handle) -> (i64, Error) { // deliberately uninitialized; the syscall fills this buffer for us s: OS_Stat = --- @@ -694,6 +698,7 @@ remove_directory :: proc(path: string) -> Error { return _get_errno(unix.sys_rmdir(path_cstr)) } +@(require_results) is_file_handle :: proc(fd: Handle) -> bool { s, err := _fstat(fd) if err != nil { @@ -702,6 +707,7 @@ is_file_handle :: proc(fd: Handle) -> bool { return S_ISREG(s.mode) } +@(require_results) is_file_path :: proc(path: string, follow_links: bool = true) -> bool { s: OS_Stat err: Error @@ -717,6 +723,7 @@ is_file_path :: proc(path: string, follow_links: bool = true) -> bool { } +@(require_results) is_dir_handle :: proc(fd: Handle) -> bool { s, err := _fstat(fd) if err != nil { @@ -725,6 +732,7 @@ is_dir_handle :: proc(fd: Handle) -> bool { return S_ISDIR(s.mode) } +@(require_results) is_dir_path :: proc(path: string, follow_links: bool = true) -> bool { s: OS_Stat err: Error @@ -742,6 +750,7 @@ is_dir_path :: proc(path: string, follow_links: bool = true) -> bool { is_file :: proc {is_file_path, is_file_handle} is_dir :: proc {is_dir_path, is_dir_handle} +@(require_results) exists :: proc(path: string) -> bool { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cpath := strings.clone_to_cstring(path, context.temp_allocator) @@ -759,19 +768,21 @@ stderr: Handle = 2 last_write_time :: proc(fd: Handle) -> File_Time {} last_write_time_by_name :: proc(name: string) -> File_Time {} */ +@(require_results) last_write_time :: proc(fd: Handle) -> (time: File_Time, err: Error) { s := _fstat(fd) or_return modified := s.modified.seconds * 1_000_000_000 + s.modified.nanoseconds return File_Time(modified), nil } +@(require_results) last_write_time_by_name :: proc(name: string) -> (time: File_Time, err: Error) { s := _stat(name) or_return modified := s.modified.seconds * 1_000_000_000 + s.modified.nanoseconds return File_Time(modified), nil } -@private +@(private, require_results) _stat :: proc(path: string) -> (OS_Stat, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -785,7 +796,7 @@ _stat :: proc(path: string) -> (OS_Stat, Error) { return s, nil } -@private +@(private, require_results) _lstat :: proc(path: string) -> (OS_Stat, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -799,7 +810,7 @@ _lstat :: proc(path: string) -> (OS_Stat, Error) { return s, nil } -@private +@(private, require_results) _fstat :: proc(fd: Handle) -> (OS_Stat, Error) { // deliberately uninitialized; the syscall fills this buffer for us s: OS_Stat = --- @@ -810,7 +821,7 @@ _fstat :: proc(fd: Handle) -> (OS_Stat, Error) { return s, nil } -@private +@(private, require_results) _fdopendir :: proc(fd: Handle) -> (Dir, Error) { dirp := _unix_fdopendir(fd) if dirp == cast(Dir)nil { @@ -819,7 +830,7 @@ _fdopendir :: proc(fd: Handle) -> (Dir, Error) { return dirp, nil } -@private +@(private) _closedir :: proc(dirp: Dir) -> Error { rc := _unix_closedir(dirp) if rc != 0 { @@ -828,12 +839,12 @@ _closedir :: proc(dirp: Dir) -> Error { return nil } -@private +@(private) _rewinddir :: proc(dirp: Dir) { _unix_rewinddir(dirp) } -@private +@(private, require_results) _readdir :: proc(dirp: Dir) -> (entry: Dirent, err: Error, end_of_stream: bool) { result: ^Dirent rc := _unix_readdir_r(dirp, &entry, &result) @@ -853,7 +864,7 @@ _readdir :: proc(dirp: Dir) -> (entry: Dirent, err: Error, end_of_stream: bool) return } -@private +@(private, require_results) _readlink :: proc(path: string) -> (string, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator) path_cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -876,6 +887,7 @@ _readlink :: proc(path: string) -> (string, Error) { } } +@(require_results) absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) { buf : [256]byte fd_str := strconv.itoa( buf[:], cast(int)fd ) @@ -886,6 +898,7 @@ absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) { return _readlink(procfs_path) } +@(require_results) absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) { rel := rel if rel == "" { @@ -916,6 +929,7 @@ access :: proc(path: string, mask: int) -> (bool, Error) { return true, nil } +@(require_results) lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator) path_str := strings.clone_to_cstring(key, context.temp_allocator) @@ -927,6 +941,7 @@ lookup_env :: proc(key: string, allocator := context.allocator) -> (value: strin return strings.clone(string(cstr), allocator), true } +@(require_results) get_env :: proc(key: string, allocator := context.allocator) -> (value: string) { value, _ = lookup_env(key, allocator) return @@ -954,6 +969,7 @@ unset_env :: proc(key: string) -> Error { return nil } +@(require_results) get_current_directory :: proc() -> string { // NOTE(tetra): I would use PATH_MAX here, but I was not able to find // an authoritative value for it across all systems. @@ -990,16 +1006,19 @@ exit :: proc "contextless" (code: int) -> ! { _unix_exit(c.int(code)) } +@(require_results) current_thread_id :: proc "contextless" () -> int { return unix.sys_gettid() } +@(require_results) dlopen :: proc(filename: string, flags: int) -> rawptr { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(filename, context.temp_allocator) handle := _unix_dlopen(cstr, c.int(flags)) return handle } +@(require_results) dlsym :: proc(handle: rawptr, symbol: string) -> rawptr { assert(handle != nil) runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() @@ -1015,6 +1034,7 @@ dlerror :: proc() -> string { return string(_unix_dlerror()) } +@(require_results) get_page_size :: proc() -> int { // NOTE(tetra): The page size never changes, so why do anything complicated // if we don't have to. @@ -1027,11 +1047,12 @@ get_page_size :: proc() -> int { return page_size } -@(private) +@(private, require_results) _processor_core_count :: proc() -> int { return int(_unix_get_nprocs()) } +@(require_results) _alloc_command_line_arguments :: proc() -> []string { res := make([]string, len(runtime.args__)) for arg, i in runtime.args__ { @@ -1040,6 +1061,7 @@ _alloc_command_line_arguments :: proc() -> []string { return res } +@(require_results) socket :: proc(domain: int, type: int, protocol: int) -> (Socket, Error) { result := unix.sys_socket(domain, type, protocol) if result < 0 { @@ -1048,7 +1070,7 @@ socket :: proc(domain: int, type: int, protocol: int) -> (Socket, Error) { return Socket(result), nil } -bind :: proc(sd: Socket, addr: ^SOCKADDR, len: socklen_t) -> (Error) { +bind :: proc(sd: Socket, addr: ^SOCKADDR, len: socklen_t) -> Error { result := unix.sys_bind(int(sd), addr, len) if result < 0 { return _get_errno(result) @@ -1057,7 +1079,7 @@ bind :: proc(sd: Socket, addr: ^SOCKADDR, len: socklen_t) -> (Error) { } -connect :: proc(sd: Socket, addr: ^SOCKADDR, len: socklen_t) -> (Error) { +connect :: proc(sd: Socket, addr: ^SOCKADDR, len: socklen_t) -> Error { result := unix.sys_connect(int(sd), addr, len) if result < 0 { return _get_errno(result) @@ -1073,7 +1095,7 @@ accept :: proc(sd: Socket, addr: ^SOCKADDR, len: rawptr) -> (Socket, Error) { return Socket(result), nil } -listen :: proc(sd: Socket, backlog: int) -> (Error) { +listen :: proc(sd: Socket, backlog: int) -> Error { result := unix.sys_listen(int(sd), backlog) if result < 0 { return _get_errno(result) @@ -1081,7 +1103,7 @@ listen :: proc(sd: Socket, backlog: int) -> (Error) { return nil } -setsockopt :: proc(sd: Socket, level: int, optname: int, optval: rawptr, optlen: socklen_t) -> (Error) { +setsockopt :: proc(sd: Socket, level: int, optname: int, optval: rawptr, optlen: socklen_t) -> Error { result := unix.sys_setsockopt(int(sd), level, optname, optval, optlen) if result < 0 { return _get_errno(result) @@ -1123,7 +1145,7 @@ send :: proc(sd: Socket, data: []byte, flags: int) -> (u32, Error) { return u32(result), nil } -shutdown :: proc(sd: Socket, how: int) -> (Error) { +shutdown :: proc(sd: Socket, how: int) -> Error { result := unix.sys_shutdown(int(sd), how) if result < 0 { return _get_errno(result) @@ -1139,6 +1161,7 @@ fcntl :: proc(fd: int, cmd: int, arg: int) -> (int, Error) { return result, nil } +@(require_results) poll :: proc(fds: []pollfd, timeout: int) -> (int, Error) { result := unix.sys_poll(raw_data(fds), uint(len(fds)), timeout) if result < 0 { @@ -1147,6 +1170,7 @@ poll :: proc(fds: []pollfd, timeout: int) -> (int, Error) { return result, nil } +@(require_results) ppoll :: proc(fds: []pollfd, timeout: ^unix.timespec, sigmask: ^sigset_t) -> (int, Error) { result := unix.sys_ppoll(raw_data(fds), uint(len(fds)), timeout, sigmask, size_of(sigset_t)) if result < 0 { diff --git a/core/os/os_netbsd.odin b/core/os/os_netbsd.odin index 7905a7d4e..c41dc6aa6 100644 --- a/core/os/os_netbsd.odin +++ b/core/os/os_netbsd.odin @@ -407,13 +407,13 @@ S_ISUID :: 0o4000 // Set user id on execution S_ISGID :: 0o2000 // Set group id on execution S_ISVTX :: 0o1000 // Directory restrcted delete -S_ISLNK :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFLNK } -S_ISREG :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFREG } -S_ISDIR :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFDIR } -S_ISCHR :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFCHR } -S_ISBLK :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFBLK } -S_ISFIFO :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFIFO } -S_ISSOCK :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFSOCK } +@(require_results) S_ISLNK :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFLNK } +@(require_results) S_ISREG :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFREG } +@(require_results) S_ISDIR :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFDIR } +@(require_results) S_ISCHR :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFCHR } +@(require_results) S_ISBLK :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFBLK } +@(require_results) S_ISFIFO :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFIFO } +@(require_results) S_ISSOCK :: #force_inline proc "contextless" (m: mode_t) -> bool { return (m & S_IFMT) == S_IFSOCK } F_OK :: 0 // Test for file existance X_OK :: 1 // Test for execute permission @@ -561,6 +561,7 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) { return res, nil } +@(require_results) file_size :: proc(fd: Handle) -> (size: i64, err: Error) { size = -1 s := _fstat(fd) or_return @@ -609,6 +610,7 @@ remove_directory :: proc(path: string) -> Error { return nil } +@(require_results) is_file_handle :: proc(fd: Handle) -> bool { s, err := _fstat(fd) if err != nil { @@ -617,6 +619,7 @@ is_file_handle :: proc(fd: Handle) -> bool { return S_ISREG(s.mode) } +@(require_results) is_file_path :: proc(path: string, follow_links: bool = true) -> bool { s: OS_Stat err: Error @@ -631,6 +634,7 @@ is_file_path :: proc(path: string, follow_links: bool = true) -> bool { return S_ISREG(s.mode) } +@(require_results) is_dir_handle :: proc(fd: Handle) -> bool { s, err := _fstat(fd) if err != nil { @@ -639,6 +643,7 @@ is_dir_handle :: proc(fd: Handle) -> bool { return S_ISDIR(s.mode) } +@(require_results) is_dir_path :: proc(path: string, follow_links: bool = true) -> bool { s: OS_Stat err: Error @@ -656,6 +661,7 @@ is_dir_path :: proc(path: string, follow_links: bool = true) -> bool { is_file :: proc {is_file_path, is_file_handle} is_dir :: proc {is_dir_path, is_dir_handle} +@(require_results) exists :: proc(path: string) -> bool { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cpath := strings.clone_to_cstring(path, context.temp_allocator) @@ -663,6 +669,7 @@ exists :: proc(path: string) -> bool { return res == 0 } +@(require_results) fcntl :: proc(fd: int, cmd: int, arg: int) -> (int, Error) { result := _unix_fcntl(Handle(fd), c.int(cmd), uintptr(arg)) if result < 0 { @@ -677,19 +684,21 @@ stdin: Handle = 0 stdout: Handle = 1 stderr: Handle = 2 +@(require_results) last_write_time :: proc(fd: Handle) -> (time: File_Time, err: Error) { s := _fstat(fd) or_return modified := s.modified.seconds * 1_000_000_000 + s.modified.nanoseconds return File_Time(modified), nil } +@(require_results) last_write_time_by_name :: proc(name: string) -> (time: File_Time, err: Error) { s := _stat(name) or_return modified := s.modified.seconds * 1_000_000_000 + s.modified.nanoseconds return File_Time(modified), nil } -@private +@(private, require_results) _stat :: proc(path: string) -> (OS_Stat, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -701,7 +710,7 @@ _stat :: proc(path: string) -> (OS_Stat, Error) { return s, nil } -@private +@(private, require_results) _lstat :: proc(path: string) -> (OS_Stat, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -715,7 +724,7 @@ _lstat :: proc(path: string) -> (OS_Stat, Error) { return s, nil } -@private +@(private, require_results) _fstat :: proc(fd: Handle) -> (OS_Stat, Error) { s: OS_Stat = --- result := _unix_fstat(fd, &s) @@ -725,7 +734,7 @@ _fstat :: proc(fd: Handle) -> (OS_Stat, Error) { return s, nil } -@private +@(private, require_results) _fdopendir :: proc(fd: Handle) -> (Dir, Error) { dirp := _unix_fdopendir(fd) if dirp == cast(Dir)nil { @@ -734,7 +743,7 @@ _fdopendir :: proc(fd: Handle) -> (Dir, Error) { return dirp, nil } -@private +@(private) _closedir :: proc(dirp: Dir) -> Error { rc := _unix_closedir(dirp) if rc != 0 { @@ -743,12 +752,12 @@ _closedir :: proc(dirp: Dir) -> Error { return nil } -@private +@(private) _rewinddir :: proc(dirp: Dir) { _unix_rewinddir(dirp) } -@private +@(private, require_results) _readdir :: proc(dirp: Dir) -> (entry: Dirent, err: Error, end_of_stream: bool) { result: ^Dirent rc := _unix_readdir_r(dirp, &entry, &result) @@ -767,7 +776,7 @@ _readdir :: proc(dirp: Dir) -> (entry: Dirent, err: Error, end_of_stream: bool) return } -@private +@(private, require_results) _readlink :: proc(path: string) -> (string, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator) @@ -792,12 +801,14 @@ _readlink :: proc(path: string) -> (string, Error) { return "", Error{} } +@(require_results) absolute_path_from_handle :: proc(fd: Handle) -> (path: string, err: Error) { buf: [MAX_PATH]byte _ = fcntl(int(fd), F_GETPATH, int(uintptr(&buf[0]))) or_return return strings.clone_from_cstring(cstring(&buf[0])) } +@(require_results) absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) { rel := rel if rel == "" { @@ -829,6 +840,7 @@ access :: proc(path: string, mask: int) -> (bool, Error) { return true, nil } +@(require_results) lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator) @@ -840,11 +852,13 @@ lookup_env :: proc(key: string, allocator := context.allocator) -> (value: strin return strings.clone(string(cstr), allocator), true } +@(require_results) get_env :: proc(key: string, allocator := context.allocator) -> (value: string) { value, _ = lookup_env(key, allocator) return } +@(require_results) get_current_directory :: proc() -> string { // NOTE(tetra): I would use PATH_MAX here, but I was not able to find // an authoritative value for it across all systems. @@ -880,10 +894,12 @@ exit :: proc "contextless" (code: int) -> ! { _unix_exit(c.int(code)) } +@(require_results) current_thread_id :: proc "contextless" () -> int { return int(_lwp_self()) } +@(require_results) dlopen :: proc(filename: string, flags: int) -> rawptr { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(filename, context.temp_allocator) @@ -891,6 +907,7 @@ dlopen :: proc(filename: string, flags: int) -> rawptr { return handle } +@(require_results) dlsym :: proc(handle: rawptr, symbol: string) -> rawptr { assert(handle != nil) runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() @@ -904,10 +921,12 @@ dlclose :: proc(handle: rawptr) -> bool { return _unix_dlclose(handle) == 0 } +@(require_results) dlerror :: proc() -> string { return string(_unix_dlerror()) } +@(require_results) get_page_size :: proc() -> int { // NOTE(tetra): The page size never changes, so why do anything complicated // if we don't have to. @@ -920,7 +939,7 @@ get_page_size :: proc() -> int { return page_size } -@(private) +@(private, require_results) _processor_core_count :: proc() -> int { count : int = 0 count_size := size_of(count) @@ -933,6 +952,7 @@ _processor_core_count :: proc() -> int { return 1 } +@(require_results) _alloc_command_line_arguments :: proc() -> []string { res := make([]string, len(runtime.args__)) for arg, i in runtime.args__ { diff --git a/core/os/os_openbsd.odin b/core/os/os_openbsd.odin index 1c2e652b0..1cd26211e 100644 --- a/core/os/os_openbsd.odin +++ b/core/os/os_openbsd.odin @@ -322,13 +322,13 @@ S_ISUID :: 0o4000 // Set user id on execution S_ISGID :: 0o2000 // Set group id on execution S_ISTXT :: 0o1000 // Sticky bit -S_ISLNK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFLNK } -S_ISREG :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFREG } -S_ISDIR :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFDIR } -S_ISCHR :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFCHR } -S_ISBLK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFBLK } -S_ISFIFO :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFIFO } -S_ISSOCK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFSOCK } +@(require_results) S_ISLNK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFLNK } +@(require_results) S_ISREG :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFREG } +@(require_results) S_ISDIR :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFDIR } +@(require_results) S_ISCHR :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFCHR } +@(require_results) S_ISBLK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFBLK } +@(require_results) S_ISFIFO :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFIFO } +@(require_results) S_ISSOCK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFSOCK } F_OK :: 0x00 // Test for file existance X_OK :: 0x01 // Test for execute permission @@ -489,6 +489,7 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) { return res, nil } +@(require_results) file_size :: proc(fd: Handle) -> (size: i64, err: Error) { size = -1 s := _fstat(fd) or_return @@ -537,6 +538,7 @@ remove_directory :: proc(path: string) -> Error { return nil } +@(require_results) is_file_handle :: proc(fd: Handle) -> bool { s, err := _fstat(fd) if err != nil { @@ -545,6 +547,7 @@ is_file_handle :: proc(fd: Handle) -> bool { return S_ISREG(s.mode) } +@(require_results) is_file_path :: proc(path: string, follow_links: bool = true) -> bool { s: OS_Stat err: Error @@ -559,6 +562,7 @@ is_file_path :: proc(path: string, follow_links: bool = true) -> bool { return S_ISREG(s.mode) } +@(require_results) is_dir_handle :: proc(fd: Handle) -> bool { s, err := _fstat(fd) if err != nil { @@ -567,6 +571,7 @@ is_dir_handle :: proc(fd: Handle) -> bool { return S_ISDIR(s.mode) } +@(require_results) is_dir_path :: proc(path: string, follow_links: bool = true) -> bool { s: OS_Stat err: Error @@ -594,19 +599,21 @@ stderr: Handle = 2 last_write_time :: proc(fd: Handle) -> File_Time {} last_write_time_by_name :: proc(name: string) -> File_Time {} */ +@(require_results) last_write_time :: proc(fd: Handle) -> (time: File_Time, err: Error) { s := _fstat(fd) or_return modified := s.modified.seconds * 1_000_000_000 + s.modified.nanoseconds return File_Time(modified), nil } +@(require_results) last_write_time_by_name :: proc(name: string) -> (time: File_Time, err: Error) { s := _stat(name) or_return modified := s.modified.seconds * 1_000_000_000 + s.modified.nanoseconds return File_Time(modified), nil } -@private +@(private, require_results) _stat :: proc(path: string) -> (OS_Stat, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -620,7 +627,7 @@ _stat :: proc(path: string) -> (OS_Stat, Error) { return s, nil } -@private +@(private, require_results) _lstat :: proc(path: string) -> (OS_Stat, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -634,7 +641,7 @@ _lstat :: proc(path: string) -> (OS_Stat, Error) { return s, nil } -@private +@(private, require_results) _fstat :: proc(fd: Handle) -> (OS_Stat, Error) { // deliberately uninitialized s: OS_Stat = --- @@ -645,7 +652,7 @@ _fstat :: proc(fd: Handle) -> (OS_Stat, Error) { return s, nil } -@private +@(private, require_results) _fdopendir :: proc(fd: Handle) -> (Dir, Error) { dirp := _unix_fdopendir(fd) if dirp == cast(Dir)nil { @@ -654,7 +661,7 @@ _fdopendir :: proc(fd: Handle) -> (Dir, Error) { return dirp, nil } -@private +@(private) _closedir :: proc(dirp: Dir) -> Error { rc := _unix_closedir(dirp) if rc != 0 { @@ -663,12 +670,12 @@ _closedir :: proc(dirp: Dir) -> Error { return nil } -@private +@(private) _rewinddir :: proc(dirp: Dir) { _unix_rewinddir(dirp) } -@private +@(private, require_results) _readdir :: proc(dirp: Dir) -> (entry: Dirent, err: Error, end_of_stream: bool) { result: ^Dirent rc := _unix_readdir_r(dirp, &entry, &result) @@ -687,7 +694,7 @@ _readdir :: proc(dirp: Dir) -> (entry: Dirent, err: Error, end_of_stream: bool) return } -@private +@(private, require_results) _readlink :: proc(path: string) -> (string, Error) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator) path_cstr := strings.clone_to_cstring(path, context.temp_allocator) @@ -710,10 +717,12 @@ _readlink :: proc(path: string) -> (string, Error) { } // XXX OpenBSD +@(require_results) absolute_path_from_handle :: proc(fd: Handle) -> (string, Error) { return "", Error(ENOSYS) } +@(require_results) absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Error) { rel := rel if rel == "" { @@ -744,6 +753,7 @@ access :: proc(path: string, mask: int) -> (bool, Error) { return true, nil } +@(require_results) lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator) path_str := strings.clone_to_cstring(key, context.temp_allocator) @@ -754,11 +764,13 @@ lookup_env :: proc(key: string, allocator := context.allocator) -> (value: strin return strings.clone(string(cstr), allocator), true } +@(require_results) get_env :: proc(key: string, allocator := context.allocator) -> (value: string) { value, _ = lookup_env(key, allocator) return } +@(require_results) get_current_directory :: proc() -> string { buf := make([dynamic]u8, MAX_PATH) for { @@ -790,16 +802,19 @@ exit :: proc "contextless" (code: int) -> ! { _unix_exit(c.int(code)) } +@(require_results) current_thread_id :: proc "contextless" () -> int { return _unix_getthrid() } +@(require_results) dlopen :: proc(filename: string, flags: int) -> rawptr { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() cstr := strings.clone_to_cstring(filename, context.temp_allocator) handle := _unix_dlopen(cstr, c.int(flags)) return handle } +@(require_results) dlsym :: proc(handle: rawptr, symbol: string) -> rawptr { assert(handle != nil) runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() @@ -811,10 +826,12 @@ dlclose :: proc(handle: rawptr) -> bool { assert(handle != nil) return _unix_dlclose(handle) == 0 } +@(require_results) dlerror :: proc() -> string { return string(_unix_dlerror()) } +@(require_results) get_page_size :: proc() -> int { // NOTE(tetra): The page size never changes, so why do anything complicated // if we don't have to. @@ -829,11 +846,12 @@ get_page_size :: proc() -> int { _SC_NPROCESSORS_ONLN :: 503 -@(private) +@(private, require_results) _processor_core_count :: proc() -> int { return int(_sysconf(_SC_NPROCESSORS_ONLN)) } +@(require_results) _alloc_command_line_arguments :: proc() -> []string { res := make([]string, len(runtime.args__)) for arg, i in runtime.args__ { diff --git a/core/os/os_wasi.odin b/core/os/os_wasi.odin index 992c00f21..28f470357 100644 --- a/core/os/os_wasi.odin +++ b/core/os/os_wasi.odin @@ -27,6 +27,7 @@ stderr: Handle = 2 args := _alloc_command_line_arguments() +@(require_results) _alloc_command_line_arguments :: proc() -> (args: []string) { args = make([]string, len(runtime.args__)) for &arg, i in args { @@ -91,8 +92,9 @@ init_preopens :: proc() { preopens = dyn_preopens[:] } +@(require_results) wasi_match_preopen :: proc(path: string) -> (wasi.fd_t, string, bool) { - + @(require_results) prefix_matches :: proc(prefix, path: string) -> bool { // Empty is valid for any relative path. if len(prefix) == 0 && len(path) > 0 && path[0] != '/' { @@ -163,6 +165,7 @@ read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) { n, err := wasi.fd_pread(wasi.fd_t(fd), {iovs}, wasi.filesize_t(offset)) return int(n), Platform_Error(err) } +@(require_results) open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Errno) { oflags: wasi.oflags_t if mode & O_CREATE == O_CREATE { @@ -215,14 +218,16 @@ seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) { n, err := wasi.fd_seek(wasi.fd_t(fd), wasi.filedelta_t(offset), wasi.whence_t(whence)) return i64(n), Platform_Error(err) } +@(require_results) current_thread_id :: proc "contextless" () -> int { return 0 } -@(private) +@(private, require_results) _processor_core_count :: proc() -> int { return 1 } +@(require_results) file_size :: proc(fd: Handle) -> (size: i64, err: Errno) { stat := wasi.fd_filestat_get(wasi.fd_t(fd)) or_return size = i64(stat.size) diff --git a/core/os/os_windows.odin b/core/os/os_windows.odin index 5a080e18c..273fe5af0 100644 --- a/core/os/os_windows.odin +++ b/core/os/os_windows.odin @@ -153,7 +153,7 @@ get_page_size :: proc() -> int { return page_size } -@(private) +@(private, require_results) _processor_core_count :: proc() -> int { length : win32.DWORD = 0 result := win32.GetLogicalProcessorInformation(nil, &length) @@ -184,12 +184,14 @@ exit :: proc "contextless" (code: int) -> ! { +@(require_results) current_thread_id :: proc "contextless" () -> int { return int(win32.GetCurrentThreadId()) } +@(require_results) _alloc_command_line_arguments :: proc() -> []string { arg_count: i32 arg_list_ptr := win32.CommandLineToArgvW(win32.GetCommandLineW(), &arg_count) @@ -223,44 +225,52 @@ _alloc_command_line_arguments :: proc() -> []string { */ WINDOWS_11_BUILD_CUTOFF :: 22_000 -get_windows_version_w :: proc() -> win32.OSVERSIONINFOEXW { +@(require_results) +get_windows_version_w :: proc "contextless" () -> win32.OSVERSIONINFOEXW { osvi : win32.OSVERSIONINFOEXW osvi.dwOSVersionInfoSize = size_of(win32.OSVERSIONINFOEXW) win32.RtlGetVersion(&osvi) return osvi } -is_windows_xp :: proc() -> bool { +@(require_results) +is_windows_xp :: proc "contextless" () -> bool { osvi := get_windows_version_w() return (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) } -is_windows_vista :: proc() -> bool { +@(require_results) +is_windows_vista :: proc "contextless" () -> bool { osvi := get_windows_version_w() return (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0) } -is_windows_7 :: proc() -> bool { +@(require_results) +is_windows_7 :: proc "contextless" () -> bool { osvi := get_windows_version_w() return (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 1) } -is_windows_8 :: proc() -> bool { +@(require_results) +is_windows_8 :: proc "contextless" () -> bool { osvi := get_windows_version_w() return (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 2) } -is_windows_8_1 :: proc() -> bool { +@(require_results) +is_windows_8_1 :: proc "contextless" () -> bool { osvi := get_windows_version_w() return (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 3) } -is_windows_10 :: proc() -> bool { +@(require_results) +is_windows_10 :: proc "contextless" () -> bool { osvi := get_windows_version_w() return (osvi.dwMajorVersion == 10 && osvi.dwMinorVersion == 0 && osvi.dwBuildNumber < WINDOWS_11_BUILD_CUTOFF) } -is_windows_11 :: proc() -> bool { +@(require_results) +is_windows_11 :: proc "contextless" () -> bool { osvi := get_windows_version_w() return (osvi.dwMajorVersion == 10 && osvi.dwMinorVersion == 0 && osvi.dwBuildNumber >= WINDOWS_11_BUILD_CUTOFF) } diff --git a/core/os/stat_unix.odin b/core/os/stat_unix.odin index 189f32743..8e89bee4f 100644 --- a/core/os/stat_unix.odin +++ b/core/os/stat_unix.odin @@ -50,14 +50,14 @@ File_Info :: struct { } */ -@private +@(private, require_results) _make_time_from_unix_file_time :: proc(uft: Unix_File_Time) -> time.Time { return time.Time{ _nsec = uft.nanoseconds + uft.seconds * 1_000_000_000, } } -@private +@(private) _fill_file_info_from_stat :: proc(fi: ^File_Info, s: OS_Stat) { fi.size = s.size fi.mode = cast(File_Mode)s.mode @@ -71,7 +71,7 @@ _fill_file_info_from_stat :: proc(fi: ^File_Info, s: OS_Stat) { } -@private +@(private, require_results) path_base :: proc(path: string) -> string { is_separator :: proc(c: byte) -> bool { return c == '/' @@ -100,6 +100,7 @@ path_base :: proc(path: string) -> string { } +@(require_results) lstat :: proc(name: string, allocator := context.allocator) -> (fi: File_Info, err: Error) { context.allocator = allocator @@ -110,6 +111,7 @@ lstat :: proc(name: string, allocator := context.allocator) -> (fi: File_Info, e return } +@(require_results) stat :: proc(name: string, allocator := context.allocator) -> (fi: File_Info, err: Error) { context.allocator = allocator @@ -120,6 +122,7 @@ stat :: proc(name: string, allocator := context.allocator) -> (fi: File_Info, er return } +@(require_results) fstat :: proc(fd: Handle, allocator := context.allocator) -> (fi: File_Info, err: Error) { context.allocator = allocator diff --git a/core/os/stat_windows.odin b/core/os/stat_windows.odin index 0c0bf51a3..ca4f87668 100644 --- a/core/os/stat_windows.odin +++ b/core/os/stat_windows.odin @@ -4,7 +4,7 @@ import "core:time" import "base:runtime" import win32 "core:sys/windows" -@(private) +@(private, require_results) full_path_from_name :: proc(name: string, allocator := context.allocator) -> (path: string, err: Errno) { context.allocator = allocator @@ -30,7 +30,7 @@ full_path_from_name :: proc(name: string, allocator := context.allocator) -> (pa return } -@(private) +@(private, require_results) _stat :: proc(name: string, create_file_attributes: u32, allocator := context.allocator) -> (fi: File_Info, e: Errno) { if len(name) == 0 { return {}, ERROR_PATH_NOT_FOUND @@ -72,17 +72,20 @@ _stat :: proc(name: string, create_file_attributes: u32, allocator := context.al } +@(require_results) lstat :: proc(name: string, allocator := context.allocator) -> (File_Info, Errno) { attrs := win32.FILE_FLAG_BACKUP_SEMANTICS attrs |= win32.FILE_FLAG_OPEN_REPARSE_POINT return _stat(name, attrs, allocator) } +@(require_results) stat :: proc(name: string, allocator := context.allocator) -> (File_Info, Errno) { attrs := win32.FILE_FLAG_BACKUP_SEMANTICS return _stat(name, attrs, allocator) } +@(require_results) fstat :: proc(fd: Handle, allocator := context.allocator) -> (fi: File_Info, err: Errno) { if fd == 0 { err = ERROR_INVALID_HANDLE @@ -108,7 +111,7 @@ fstat :: proc(fd: Handle, allocator := context.allocator) -> (fi: File_Info, err } -@(private) +@(private, require_results) cleanpath_strip_prefix :: proc(buf: []u16) -> []u16 { buf := buf N := 0 @@ -133,13 +136,13 @@ cleanpath_strip_prefix :: proc(buf: []u16) -> []u16 { return buf } -@(private) +@(private, require_results) cleanpath_from_handle :: proc(fd: Handle) -> (s: string, err: Errno) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == context.allocator) buf := cleanpath_from_handle_u16(fd, context.temp_allocator) or_return return win32.utf16_to_utf8(buf, context.allocator) } -@(private) +@(private, require_results) cleanpath_from_handle_u16 :: proc(fd: Handle, allocator: runtime.Allocator) -> ([]u16, Errno) { if fd == 0 { return nil, ERROR_INVALID_HANDLE @@ -154,14 +157,14 @@ cleanpath_from_handle_u16 :: proc(fd: Handle, allocator: runtime.Allocator) -> ( buf_len := win32.GetFinalPathNameByHandleW(h, raw_data(buf), n, 0) return buf[:buf_len], nil } -@(private) +@(private, require_results) cleanpath_from_buf :: proc(buf: []u16) -> string { buf := buf buf = cleanpath_strip_prefix(buf) return win32.utf16_to_utf8(buf, context.allocator) or_else "" } -@(private) +@(private, require_results) basename :: proc(name: string) -> (base: string) { name := name if len(name) > 3 && name[:3] == `\\?` { @@ -187,7 +190,7 @@ basename :: proc(name: string) -> (base: string) { return name } -@(private) +@(private, require_results) file_type_mode :: proc(h: win32.HANDLE) -> File_Mode { switch win32.GetFileType(h) { case win32.FILE_TYPE_PIPE: @@ -199,7 +202,7 @@ file_type_mode :: proc(h: win32.HANDLE) -> File_Mode { } -@(private) +@(private, require_results) file_mode_from_file_attributes :: proc(FileAttributes: win32.DWORD, h: win32.HANDLE, ReparseTag: win32.DWORD) -> (mode: File_Mode) { if FileAttributes & win32.FILE_ATTRIBUTE_READONLY != 0 { mode |= 0o444 @@ -236,7 +239,7 @@ windows_set_file_info_times :: proc(fi: ^File_Info, d: ^$T) { fi.access_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime)) } -@(private) +@(private, require_results) file_info_from_win32_file_attribute_data :: proc(d: ^win32.WIN32_FILE_ATTRIBUTE_DATA, name: string) -> (fi: File_Info, e: Errno) { fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow) @@ -251,7 +254,7 @@ file_info_from_win32_file_attribute_data :: proc(d: ^win32.WIN32_FILE_ATTRIBUTE_ return } -@(private) +@(private, require_results) file_info_from_win32_find_data :: proc(d: ^win32.WIN32_FIND_DATAW, name: string) -> (fi: File_Info, e: Errno) { fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow) @@ -266,7 +269,7 @@ file_info_from_win32_find_data :: proc(d: ^win32.WIN32_FIND_DATAW, name: string) return } -@(private) +@(private, require_results) file_info_from_get_file_information_by_handle :: proc(path: string, h: win32.HANDLE) -> (File_Info, Errno) { d: win32.BY_HANDLE_FILE_INFORMATION if !win32.GetFileInformationByHandle(h, &d) {