aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2022-02-28 12:32:51 +0000
committergingerBill <bill@gingerbill.org>2022-02-28 12:32:51 +0000
commit45124e4d5c19d477c2fc80282e153cc0bb7ac6ff (patch)
treeb5bd3d72b4b5f7909f67d65358e6e3ad25fb8714 /core
parent32988b03632912bbdb788e3dc319592a1dab9bfe (diff)
parent7681c43b144015278b75b2788b824a5630f6ccd6 (diff)
Merge branch 'master' into freestanding_amd64
Diffstat (limited to 'core')
-rw-r--r--core/os/file_windows.odin18
-rw-r--r--core/os/os_darwin.odin13
-rw-r--r--core/os/os_freebsd.odin567
-rw-r--r--core/os/os_linux.odin27
-rw-r--r--core/strings/strings.odin19
-rw-r--r--core/sys/darwin/xnu_system_call_helpers.odin30
6 files changed, 343 insertions, 331 deletions
diff --git a/core/os/file_windows.odin b/core/os/file_windows.odin
index 5368f51cf..4c8d385f2 100644
--- a/core/os/file_windows.odin
+++ b/core/os/file_windows.odin
@@ -106,20 +106,23 @@ read_console :: proc(handle: win32.HANDLE, b: []byte) -> (n: int, err: Errno) {
BUF_SIZE :: 386
buf16: [BUF_SIZE]u16
buf8: [4*BUF_SIZE]u8
-
+
for n < len(b) && err == 0 {
- min_read := max(min(len(b), 4), len(b)/4)
+ min_read := max(len(b)/4, 1 if len(b) > 0 else 0)
max_read := u32(min(BUF_SIZE, min_read))
+ if max_read == 0 {
+ break
+ }
single_read_length: u32
ok := win32.ReadConsoleW(handle, &buf16[0], max_read, &single_read_length, nil)
if !ok {
err = Errno(win32.GetLastError())
}
-
+
buf8_len := utf16.decode_to_utf8(buf8[:], buf16[:single_read_length])
src := buf8[:buf8_len]
-
+
ctrl_z := false
for i := 0; i < len(src) && n+i < len(b); i += 1 {
x := src[i]
@@ -133,6 +136,13 @@ read_console :: proc(handle: win32.HANDLE, b: []byte) -> (n: int, err: Errno) {
if ctrl_z || single_read_length < max_read {
break
}
+
+ // NOTE(bill): if the last two values were a newline, then it is expected that
+ // this is the end of the input
+ if n >= 2 && single_read_length == max_read && string(b[n-2:n]) == "\r\n" {
+ break
+ }
+
}
return
diff --git a/core/os/os_darwin.odin b/core/os/os_darwin.odin
index a011fa58a..4365842b0 100644
--- a/core/os/os_darwin.odin
+++ b/core/os/os_darwin.odin
@@ -313,6 +313,7 @@ foreign libc {
@(link_name="getenv") _unix_getenv :: proc(cstring) -> cstring ---
@(link_name="getcwd") _unix_getcwd :: proc(buf: cstring, len: c.size_t) -> cstring ---
@(link_name="chdir") _unix_chdir :: proc(buf: cstring) -> c.int ---
+ @(link_name="mkdir") _unix_mkdir :: proc(buf: cstring, mode: u32) -> c.int ---
@(link_name="realpath") _unix_realpath :: proc(path: cstring, resolved_path: rawptr) -> rawptr ---
@(link_name="strerror") _darwin_string_error :: proc(num : c.int) -> cstring ---
@@ -344,9 +345,8 @@ get_last_error_string :: proc() -> string {
}
open :: proc(path: string, flags: int = O_RDWR, mode: int = 0) -> (Handle, Errno) {
- cstr := strings.clone_to_cstring(path)
+ cstr := strings.clone_to_cstring(path, context.temp_allocator)
handle := _unix_open(cstr, i32(flags), u16(mode))
- delete(cstr)
if handle == -1 {
return INVALID_HANDLE, 1
}
@@ -670,6 +670,15 @@ set_current_directory :: proc(path: string) -> (err: Errno) {
return ERROR_NONE
}
+make_directory :: proc(path: string, mode: u32 = 0o775) -> Errno {
+ path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
+ res := _unix_mkdir(path_cstr, mode)
+ if res == -1 {
+ return Errno(get_last_error())
+ }
+ return ERROR_NONE
+}
+
exit :: proc "contextless" (code: int) -> ! {
_unix_exit(i32(code))
}
diff --git a/core/os/os_freebsd.odin b/core/os/os_freebsd.odin
index 82317532d..e31eb31bb 100644
--- a/core/os/os_freebsd.odin
+++ b/core/os/os_freebsd.odin
@@ -7,149 +7,149 @@ import "core:runtime"
import "core:strings"
import "core:c"
-Handle :: distinct i32;
-File_Time :: distinct u64;
-Errno :: distinct i32;
-Syscall :: distinct i32;
-
-INVALID_HANDLE :: ~Handle(0);
-
-ERROR_NONE: Errno : 0;
-EPERM: Errno : 1;
-ENOENT: Errno : 2;
-ESRCH: Errno : 3;
-EINTR: Errno : 4;
-EIO: Errno : 5;
-ENXIO: Errno : 6;
-E2BIG: Errno : 7;
-ENOEXEC: Errno : 8;
-EBADF: Errno : 9;
-ECHILD: Errno : 10;
-EBEADLK: Errno : 11;
-ENOMEM: Errno : 12;
-EACCESS: Errno : 13;
-EFAULT: Errno : 14;
-ENOTBLK: Errno : 15;
-EBUSY: Errno : 16;
-EEXIST: Errno : 17;
-EXDEV: Errno : 18;
-ENODEV: Errno : 19;
-ENOTDIR: Errno : 20;
-EISDIR: Errno : 21;
-EINVAL: Errno : 22;
-ENFILE: Errno : 23;
-EMFILE: Errno : 24;
-ENOTTY: Errno : 25;
-ETXTBSY: Errno : 26;
-EFBIG: Errno : 27;
-ENOSPC: Errno : 28;
-ESPIPE: Errno : 29;
-EROFS: Errno : 30;
-EMLINK: Errno : 31;
-EPIPE: Errno : 32;
-EDOM: Errno : 33;
-ERANGE: Errno : 34; /* Result too large */
-EAGAIN: Errno : 35;
-EINPROGRESS: Errno : 36;
-EALREADY: Errno : 37;
-ENOTSOCK: Errno : 38;
-EDESTADDRREQ: Errno : 39;
-EMSGSIZE: Errno : 40;
-EPROTOTYPE: Errno : 41;
-ENOPROTOOPT: Errno : 42;
-EPROTONOSUPPORT: Errno : 43;
-ESOCKTNOSUPPORT: Errno : 44;
-EOPNOTSUPP: Errno : 45;
-EPFNOSUPPORT: Errno : 46;
-EAFNOSUPPORT: Errno : 47;
-EADDRINUSE: Errno : 48;
-EADDRNOTAVAIL: Errno : 49;
-ENETDOWN: Errno : 50;
-ENETUNREACH: Errno : 51;
-ENETRESET: Errno : 52;
-ECONNABORTED: Errno : 53;
-ECONNRESET: Errno : 54;
-ENOBUFS: Errno : 55;
-EISCONN: Errno : 56;
-ENOTCONN: Errno : 57;
-ESHUTDOWN: Errno : 58;
-ETIMEDOUT: Errno : 60;
-ECONNREFUSED: Errno : 61;
-ELOOP: Errno : 62;
-ENAMETOOLING: Errno : 63;
-EHOSTDOWN: Errno : 64;
-EHOSTUNREACH: Errno : 65;
-ENOTEMPTY: Errno : 66;
-EPROCLIM: Errno : 67;
-EUSERS: Errno : 68;
-EDQUOT: Errno : 69;
-ESTALE: Errno : 70;
-EBADRPC: Errno : 72;
-ERPCMISMATCH: Errno : 73;
-EPROGUNAVAIL: Errno : 74;
-EPROGMISMATCH: Errno : 75;
-EPROCUNAVAIL: Errno : 76;
-ENOLCK: Errno : 77;
-ENOSYS: Errno : 78;
-EFTYPE: Errno : 79;
-EAUTH: Errno : 80;
-ENEEDAUTH: Errno : 81;
-EIDRM: Errno : 82;
-ENOMSG: Errno : 83;
-EOVERFLOW: Errno : 84;
-ECANCELED: Errno : 85;
-EILSEQ: Errno : 86;
-ENOATTR: Errno : 87;
-EDOOFUS: Errno : 88;
-EBADMSG: Errno : 89;
-EMULTIHOP: Errno : 90;
-ENOLINK: Errno : 91;
-EPROTO: Errno : 92;
-ENOTCAPABLE: Errno : 93;
-ECAPMODE: Errno : 94;
-ENOTRECOVERABLE: Errno : 95;
-EOWNERDEAD: Errno : 96;
-
-O_RDONLY :: 0x00000;
-O_WRONLY :: 0x00001;
-O_RDWR :: 0x00002;
-O_CREATE :: 0x00040;
-O_EXCL :: 0x00080;
-O_NOCTTY :: 0x00100;
-O_TRUNC :: 0x00200;
-O_NONBLOCK :: 0x00800;
-O_APPEND :: 0x00400;
-O_SYNC :: 0x01000;
-O_ASYNC :: 0x02000;
-O_CLOEXEC :: 0x80000;
-
-
-SEEK_SET :: 0;
-SEEK_CUR :: 1;
-SEEK_END :: 2;
-SEEK_DATA :: 3;
-SEEK_HOLE :: 4;
-SEEK_MAX :: SEEK_HOLE;
+Handle :: distinct i32
+File_Time :: distinct u64
+Errno :: distinct i32
+Syscall :: distinct i32
+
+INVALID_HANDLE :: ~Handle(0)
+
+ERROR_NONE: Errno : 0
+EPERM: Errno : 1
+ENOENT: Errno : 2
+ESRCH: Errno : 3
+EINTR: Errno : 4
+EIO: Errno : 5
+ENXIO: Errno : 6
+E2BIG: Errno : 7
+ENOEXEC: Errno : 8
+EBADF: Errno : 9
+ECHILD: Errno : 10
+EBEADLK: Errno : 11
+ENOMEM: Errno : 12
+EACCESS: Errno : 13
+EFAULT: Errno : 14
+ENOTBLK: Errno : 15
+EBUSY: Errno : 16
+EEXIST: Errno : 17
+EXDEV: Errno : 18
+ENODEV: Errno : 19
+ENOTDIR: Errno : 20
+EISDIR: Errno : 21
+EINVAL: Errno : 22
+ENFILE: Errno : 23
+EMFILE: Errno : 24
+ENOTTY: Errno : 25
+ETXTBSY: Errno : 26
+EFBIG: Errno : 27
+ENOSPC: Errno : 28
+ESPIPE: Errno : 29
+EROFS: Errno : 30
+EMLINK: Errno : 31
+EPIPE: Errno : 32
+EDOM: Errno : 33
+ERANGE: Errno : 34 /* Result too large */
+EAGAIN: Errno : 35
+EINPROGRESS: Errno : 36
+EALREADY: Errno : 37
+ENOTSOCK: Errno : 38
+EDESTADDRREQ: Errno : 39
+EMSGSIZE: Errno : 40
+EPROTOTYPE: Errno : 41
+ENOPROTOOPT: Errno : 42
+EPROTONOSUPPORT: Errno : 43
+ESOCKTNOSUPPORT: Errno : 44
+EOPNOTSUPP: Errno : 45
+EPFNOSUPPORT: Errno : 46
+EAFNOSUPPORT: Errno : 47
+EADDRINUSE: Errno : 48
+EADDRNOTAVAIL: Errno : 49
+ENETDOWN: Errno : 50
+ENETUNREACH: Errno : 51
+ENETRESET: Errno : 52
+ECONNABORTED: Errno : 53
+ECONNRESET: Errno : 54
+ENOBUFS: Errno : 55
+EISCONN: Errno : 56
+ENOTCONN: Errno : 57
+ESHUTDOWN: Errno : 58
+ETIMEDOUT: Errno : 60
+ECONNREFUSED: Errno : 61
+ELOOP: Errno : 62
+ENAMETOOLING: Errno : 63
+EHOSTDOWN: Errno : 64
+EHOSTUNREACH: Errno : 65
+ENOTEMPTY: Errno : 66
+EPROCLIM: Errno : 67
+EUSERS: Errno : 68
+EDQUOT: Errno : 69
+ESTALE: Errno : 70
+EBADRPC: Errno : 72
+ERPCMISMATCH: Errno : 73
+EPROGUNAVAIL: Errno : 74
+EPROGMISMATCH: Errno : 75
+EPROCUNAVAIL: Errno : 76
+ENOLCK: Errno : 77
+ENOSYS: Errno : 78
+EFTYPE: Errno : 79
+EAUTH: Errno : 80
+ENEEDAUTH: Errno : 81
+EIDRM: Errno : 82
+ENOMSG: Errno : 83
+EOVERFLOW: Errno : 84
+ECANCELED: Errno : 85
+EILSEQ: Errno : 86
+ENOATTR: Errno : 87
+EDOOFUS: Errno : 88
+EBADMSG: Errno : 89
+EMULTIHOP: Errno : 90
+ENOLINK: Errno : 91
+EPROTO: Errno : 92
+ENOTCAPABLE: Errno : 93
+ECAPMODE: Errno : 94
+ENOTRECOVERABLE: Errno : 95
+EOWNERDEAD: Errno : 96
+
+O_RDONLY :: 0x00000
+O_WRONLY :: 0x00001
+O_RDWR :: 0x00002
+O_CREATE :: 0x00040
+O_EXCL :: 0x00080
+O_NOCTTY :: 0x00100
+O_TRUNC :: 0x00200
+O_NONBLOCK :: 0x00800
+O_APPEND :: 0x00400
+O_SYNC :: 0x01000
+O_ASYNC :: 0x02000
+O_CLOEXEC :: 0x80000
+
+
+SEEK_SET :: 0
+SEEK_CUR :: 1
+SEEK_END :: 2
+SEEK_DATA :: 3
+SEEK_HOLE :: 4
+SEEK_MAX :: SEEK_HOLE
// NOTE: These are OS specific!
// Do not mix these up!
-RTLD_LAZY :: 0x001;
-RTLD_NOW :: 0x002;
-//RTLD_BINDING_MASK :: 0x3; // Called MODEMASK in dlfcn.h
-RTLD_GLOBAL :: 0x100;
-RTLD_LOCAL :: 0x000;
-RTLD_TRACE :: 0x200;
-RTLD_NODELETE :: 0x01000;
-RTLD_NOLOAD :: 0x02000;
+RTLD_LAZY :: 0x001
+RTLD_NOW :: 0x002
+//RTLD_BINDING_MASK :: 0x3 // Called MODEMASK in dlfcn.h
+RTLD_GLOBAL :: 0x100
+RTLD_LOCAL :: 0x000
+RTLD_TRACE :: 0x200
+RTLD_NODELETE :: 0x01000
+RTLD_NOLOAD :: 0x02000
-args := _alloc_command_line_arguments();
+args := _alloc_command_line_arguments()
Unix_File_Time :: struct {
seconds: i64,
nanoseconds: c.long,
}
-pid_t :: u32;
+pid_t :: u32
OS_Stat :: struct {
device_id: u64,
@@ -177,297 +177,290 @@ OS_Stat :: struct {
}
// File type
-S_IFMT :: 0o170000; // Type of file mask
-S_IFIFO :: 0o010000; // Named pipe (fifo)
-S_IFCHR :: 0o020000; // Character special
-S_IFDIR :: 0o040000; // Directory
-S_IFBLK :: 0o060000; // Block special
-S_IFREG :: 0o100000; // Regular
-S_IFLNK :: 0o120000; // Symbolic link
-S_IFSOCK :: 0o140000; // Socket
-//S_ISVTX :: 0o001000; // Save swapped text even after use
+S_IFMT :: 0o170000 // Type of file mask
+S_IFIFO :: 0o010000 // Named pipe (fifo)
+S_IFCHR :: 0o020000 // Character special
+S_IFDIR :: 0o040000 // Directory
+S_IFBLK :: 0o060000 // Block special
+S_IFREG :: 0o100000 // Regular
+S_IFLNK :: 0o120000 // Symbolic link
+S_IFSOCK :: 0o140000 // Socket
+//S_ISVTX :: 0o001000 // Save swapped text even after use
// File mode
// Read, write, execute/search by owner
-S_IRWXU :: 0o0700; // RWX mask for owner
-S_IRUSR :: 0o0400; // R for owner
-S_IWUSR :: 0o0200; // W for owner
-S_IXUSR :: 0o0100; // X for owner
+S_IRWXU :: 0o0700 // RWX mask for owner
+S_IRUSR :: 0o0400 // R for owner
+S_IWUSR :: 0o0200 // W for owner
+S_IXUSR :: 0o0100 // X for owner
// Read, write, execute/search by group
-S_IRWXG :: 0o0070; // RWX mask for group
-S_IRGRP :: 0o0040; // R for group
-S_IWGRP :: 0o0020; // W for group
-S_IXGRP :: 0o0010; // X for group
+S_IRWXG :: 0o0070 // RWX mask for group
+S_IRGRP :: 0o0040 // R for group
+S_IWGRP :: 0o0020 // W for group
+S_IXGRP :: 0o0010 // X for group
// Read, write, execute/search by others
-S_IRWXO :: 0o0007; // RWX mask for other
-S_IROTH :: 0o0004; // R for other
-S_IWOTH :: 0o0002; // W for other
-S_IXOTH :: 0o0001; // X for other
+S_IRWXO :: 0o0007 // RWX mask for other
+S_IROTH :: 0o0004 // R for other
+S_IWOTH :: 0o0002 // W for other
+S_IXOTH :: 0o0001 // X for other
-S_ISUID :: 0o4000; // Set user id on execution
-S_ISGID :: 0o2000; // Set group id on execution
-S_ISVTX :: 0o1000; // Directory restrcted delete
+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: u32) -> bool do return (m & S_IFMT) == S_IFLNK;
-S_ISREG :: #force_inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFREG;
-S_ISDIR :: #force_inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFDIR;
-S_ISCHR :: #force_inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFCHR;
-S_ISBLK :: #force_inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFBLK;
-S_ISFIFO :: #force_inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFIFO;
-S_ISSOCK :: #force_inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFSOCK;
+S_ISLNK :: #force_inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFLNK
+S_ISREG :: #force_inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFREG
+S_ISDIR :: #force_inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFDIR
+S_ISCHR :: #force_inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFCHR
+S_ISBLK :: #force_inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFBLK
+S_ISFIFO :: #force_inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFIFO
+S_ISSOCK :: #force_inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFSOCK
-F_OK :: 0; // Test for file existance
-X_OK :: 1; // Test for execute permission
-W_OK :: 2; // Test for write permission
-R_OK :: 4; // Test for read permission
+F_OK :: 0 // Test for file existance
+X_OK :: 1 // Test for execute permission
+W_OK :: 2 // Test for write permission
+R_OK :: 4 // Test for read permission
foreign libc {
- @(link_name="__error") __errno_location :: proc() -> ^int ---;
- @(link_name="syscall") syscall :: proc(number: Syscall, #c_vararg args: ..any) -> int ---;
-
- @(link_name="open") _unix_open :: proc(path: cstring, flags: c.int, mode: c.int) -> Handle ---;
- @(link_name="close") _unix_close :: proc(fd: Handle) -> c.int ---;
- @(link_name="read") _unix_read :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---;
- @(link_name="write") _unix_write :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---;
- @(link_name="lseek64") _unix_seek :: proc(fd: Handle, offset: i64, whence: c.int) -> i64 ---;
- @(link_name="gettid") _unix_gettid :: proc() -> u64 ---;
- @(link_name="getpagesize") _unix_getpagesize :: proc() -> c.int ---;
- @(link_name="stat64") _unix_stat :: proc(path: cstring, stat: ^OS_Stat) -> c.int ---;
- @(link_name="fstat") _unix_fstat :: proc(fd: Handle, stat: ^OS_Stat) -> c.int ---;
- @(link_name="access") _unix_access :: proc(path: cstring, mask: c.int) -> c.int ---;
-
- @(link_name="malloc") _unix_malloc :: proc(size: c.size_t) -> rawptr ---;
- @(link_name="calloc") _unix_calloc :: proc(num, size: c.size_t) -> rawptr ---;
- @(link_name="free") _unix_free :: proc(ptr: rawptr) ---;
- @(link_name="realloc") _unix_realloc :: proc(ptr: rawptr, size: c.size_t) -> rawptr ---;
- @(link_name="getenv") _unix_getenv :: proc(cstring) -> cstring ---;
- @(link_name="getcwd") _unix_getcwd :: proc(buf: cstring, len: c.size_t) -> cstring ---;
- @(link_name="chdir") _unix_chdir :: proc(buf: cstring) -> c.int ---;
-
- @(link_name="exit") _unix_exit :: proc(status: c.int) -> ! ---;
+ @(link_name="__error") __errno_location :: proc() -> ^int ---
+ @(link_name="syscall") syscall :: proc(number: Syscall, #c_vararg args: ..any) -> int ---
+
+ @(link_name="open") _unix_open :: proc(path: cstring, flags: c.int, mode: c.int) -> Handle ---
+ @(link_name="close") _unix_close :: proc(fd: Handle) -> c.int ---
+ @(link_name="read") _unix_read :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---
+ @(link_name="write") _unix_write :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---
+ @(link_name="lseek64") _unix_seek :: proc(fd: Handle, offset: i64, whence: c.int) -> i64 ---
+ @(link_name="gettid") _unix_gettid :: proc() -> u64 ---
+ @(link_name="getpagesize") _unix_getpagesize :: proc() -> c.int ---
+ @(link_name="stat64") _unix_stat :: proc(path: cstring, stat: ^OS_Stat) -> c.int ---
+ @(link_name="fstat") _unix_fstat :: proc(fd: Handle, stat: ^OS_Stat) -> c.int ---
+ @(link_name="access") _unix_access :: proc(path: cstring, mask: c.int) -> c.int ---
+
+ @(link_name="malloc") _unix_malloc :: proc(size: c.size_t) -> rawptr ---
+ @(link_name="calloc") _unix_calloc :: proc(num, size: c.size_t) -> rawptr ---
+ @(link_name="free") _unix_free :: proc(ptr: rawptr) ---
+ @(link_name="realloc") _unix_realloc :: proc(ptr: rawptr, size: c.size_t) -> rawptr ---
+ @(link_name="getenv") _unix_getenv :: proc(cstring) -> cstring ---
+ @(link_name="getcwd") _unix_getcwd :: proc(buf: cstring, len: c.size_t) -> cstring ---
+ @(link_name="chdir") _unix_chdir :: proc(buf: cstring) -> c.int ---
+
+ @(link_name="exit") _unix_exit :: proc(status: c.int) -> ! ---
}
foreign dl {
- @(link_name="dlopen") _unix_dlopen :: proc(filename: cstring, flags: c.int) -> rawptr ---;
- @(link_name="dlsym") _unix_dlsym :: proc(handle: rawptr, symbol: cstring) -> rawptr ---;
- @(link_name="dlclose") _unix_dlclose :: proc(handle: rawptr) -> c.int ---;
- @(link_name="dlerror") _unix_dlerror :: proc() -> cstring ---;
+ @(link_name="dlopen") _unix_dlopen :: proc(filename: cstring, flags: c.int) -> rawptr ---
+ @(link_name="dlsym") _unix_dlsym :: proc(handle: rawptr, symbol: cstring) -> rawptr ---
+ @(link_name="dlclose") _unix_dlclose :: proc(handle: rawptr) -> c.int ---
+ @(link_name="dlerror") _unix_dlerror :: proc() -> cstring ---
- @(link_name="pthread_getthreadid_np") pthread_getthreadid_np :: proc() -> c.int ---;
+ @(link_name="pthread_getthreadid_np") pthread_getthreadid_np :: proc() -> c.int ---
}
is_path_separator :: proc(r: rune) -> bool {
- return r == '/';
+ return r == '/'
}
get_last_error :: proc() -> int {
- return __errno_location()^;
+ return __errno_location()^
}
open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Errno) {
- cstr := strings.clone_to_cstring(path);
- handle := _unix_open(cstr, c.int(flags), c.int(mode));
- delete(cstr);
+ cstr := strings.clone_to_cstring(path, context.temp_allocator)
+ handle := _unix_open(cstr, c.int(flags), c.int(mode))
if handle == -1 {
- return INVALID_HANDLE, Errno(get_last_error());
+ return INVALID_HANDLE, Errno(get_last_error())
}
- return handle, ERROR_NONE;
+ return handle, ERROR_NONE
}
close :: proc(fd: Handle) -> Errno {
- result := _unix_close(fd);
+ result := _unix_close(fd)
if result == -1 {
- return Errno(get_last_error());
+ return Errno(get_last_error())
}
- return ERROR_NONE;
+ return ERROR_NONE
}
read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
- bytes_read := _unix_read(fd, &data[0], c.size_t(len(data)));
+ bytes_read := _unix_read(fd, &data[0], c.size_t(len(data)))
if bytes_read == -1 {
- return -1, Errno(get_last_error());
+ return -1, Errno(get_last_error())
}
- return int(bytes_read), ERROR_NONE;
+ return int(bytes_read), ERROR_NONE
}
write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
if len(data) == 0 {
- return 0, ERROR_NONE;
+ return 0, ERROR_NONE
}
- bytes_written := _unix_write(fd, &data[0], c.size_t(len(data)));
+ bytes_written := _unix_write(fd, &data[0], c.size_t(len(data)))
if bytes_written == -1 {
- return -1, Errno(get_last_error());
+ return -1, Errno(get_last_error())
}
- return int(bytes_written), ERROR_NONE;
+ return int(bytes_written), ERROR_NONE
}
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
- res := _unix_seek(fd, offset, c.int(whence));
+ res := _unix_seek(fd, offset, c.int(whence))
if res == -1 {
- return -1, Errno(get_last_error());
+ return -1, Errno(get_last_error())
}
- return res, ERROR_NONE;
+ return res, ERROR_NONE
}
file_size :: proc(fd: Handle) -> (i64, Errno) {
- s, err := fstat(fd);
+ s, err := fstat(fd)
if err != ERROR_NONE {
- return -1, err;
+ return -1, err
}
- return s.size, ERROR_NONE;
+ return s.size, ERROR_NONE
}
-stdin: Handle = 0;
-stdout: Handle = 1;
-stderr: Handle = 2;
+stdin: Handle = 0
+stdout: Handle = 1
+stderr: Handle = 2
last_write_time :: proc(fd: Handle) -> (File_Time, Errno) {
- s, err := fstat(fd);
+ s, err := fstat(fd)
if err != ERROR_NONE {
- return 0, err;
+ return 0, err
}
- modified := s.modified.seconds * 1_000_000_000 + s.modified.nanoseconds;
- return File_Time(modified), ERROR_NONE;
+ modified := s.modified.seconds * 1_000_000_000 + s.modified.nanoseconds
+ return File_Time(modified), ERROR_NONE
}
last_write_time_by_name :: proc(name: string) -> (File_Time, Errno) {
- s, err := stat(name);
+ s, err := stat(name)
if err != ERROR_NONE {
- return 0, err;
+ return 0, err
}
- modified := s.modified.seconds * 1_000_000_000 + s.modified.nanoseconds;
- return File_Time(modified), ERROR_NONE;
+ modified := s.modified.seconds * 1_000_000_000 + s.modified.nanoseconds
+ return File_Time(modified), ERROR_NONE
}
stat :: proc(path: string) -> (OS_Stat, Errno) {
- cstr := strings.clone_to_cstring(path);
- defer delete(cstr);
-
- s: OS_Stat;
- result := _unix_stat(cstr, &s);
+ cstr := strings.clone_to_cstring(path, context.temp_allocator)
+ s: OS_Stat
+ result := _unix_stat(cstr, &s)
if result == -1 {
- return s, Errno(get_last_error());
+ return s, Errno(get_last_error())
}
- return s, ERROR_NONE;
+ return s, ERROR_NONE
}
fstat :: proc(fd: Handle) -> (OS_Stat, Errno) {
- s: OS_Stat;
- result := _unix_fstat(fd, &s);
+ s: OS_Stat
+ result := _unix_fstat(fd, &s)
if result == -1 {
- return s, Errno(get_last_error());
+ return s, Errno(get_last_error())
}
- return s, ERROR_NONE;
+ return s, ERROR_NONE
}
access :: proc(path: string, mask: int) -> (bool, Errno) {
- cstr := strings.clone_to_cstring(path);
- defer delete(cstr);
- result := _unix_access(cstr, c.int(mask));
+ cstr := strings.clone_to_cstring(path, context.temp_allocator)
+ result := _unix_access(cstr, c.int(mask))
if result == -1 {
- return false, Errno(get_last_error());
+ return false, Errno(get_last_error())
}
- return true, ERROR_NONE;
+ return true, ERROR_NONE
}
heap_alloc :: proc(size: int) -> rawptr {
- assert(size >= 0);
- return _unix_calloc(1, c.size_t(size));
+ assert(size >= 0)
+ return _unix_calloc(1, c.size_t(size))
}
heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
// NOTE: _unix_realloc doesn't guarantee new memory will be zeroed on
// POSIX platforms. Ensure your caller takes this into account.
- return _unix_realloc(ptr, c.size_t(new_size));
+ return _unix_realloc(ptr, c.size_t(new_size))
}
heap_free :: proc(ptr: rawptr) {
- _unix_free(ptr);
+ _unix_free(ptr)
}
getenv :: proc(name: string) -> (string, bool) {
- path_str := strings.clone_to_cstring(name);
- defer delete(path_str);
- cstr := _unix_getenv(path_str);
+ path_str := strings.clone_to_cstring(name, context.temp_allocator)
+ cstr := _unix_getenv(path_str)
if cstr == nil {
- return "", false;
+ return "", false
}
- return string(cstr), true;
+ return string(cstr), true
}
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.
// The largest value I could find was 4096, so might as well use the page size.
- page_size := get_page_size();
- buf := make([dynamic]u8, page_size);
+ page_size := get_page_size()
+ buf := make([dynamic]u8, page_size)
#no_bounds_check for {
- cwd := _unix_getcwd(cstring(&buf[0]), c.size_t(len(buf)));
+ cwd := _unix_getcwd(cstring(&buf[0]), c.size_t(len(buf)))
if cwd != nil {
- return string(cwd);
+ return string(cwd)
}
if Errno(get_last_error()) != ERANGE {
- return "";
+ return ""
}
- resize(&buf, len(buf)+page_size);
+ resize(&buf, len(buf)+page_size)
}
- unreachable();
+ unreachable()
}
set_current_directory :: proc(path: string) -> (err: Errno) {
- cstr := strings.clone_to_cstring(path, context.temp_allocator);
- res := _unix_chdir(cstr);
- if res == -1 do return Errno(get_last_error());
- return ERROR_NONE;
+ cstr := strings.clone_to_cstring(path, context.temp_allocator)
+ res := _unix_chdir(cstr)
+ if res == -1 do return Errno(get_last_error())
+ return ERROR_NONE
}
exit :: proc "contextless" (code: int) -> ! {
- _unix_exit(c.int(code));
+ _unix_exit(c.int(code))
}
current_thread_id :: proc "contextless" () -> int {
- return cast(int) pthread_getthreadid_np();
+ return cast(int) pthread_getthreadid_np()
}
dlopen :: proc(filename: string, flags: int) -> rawptr {
- cstr := strings.clone_to_cstring(filename);
- defer delete(cstr);
- handle := _unix_dlopen(cstr, c.int(flags));
- return handle;
+ cstr := strings.clone_to_cstring(filename, context.temp_allocator)
+ handle := _unix_dlopen(cstr, c.int(flags))
+ return handle
}
dlsym :: proc(handle: rawptr, symbol: string) -> rawptr {
- assert(handle != nil);
- cstr := strings.clone_to_cstring(symbol);
- defer delete(cstr);
- proc_handle := _unix_dlsym(handle, cstr);
- return proc_handle;
+ assert(handle != nil)
+ cstr := strings.clone_to_cstring(symbol, context.temp_allocator)
+ proc_handle := _unix_dlsym(handle, cstr)
+ return proc_handle
}
dlclose :: proc(handle: rawptr) -> bool {
- assert(handle != nil);
- return _unix_dlclose(handle) == 0;
+ assert(handle != nil)
+ return _unix_dlclose(handle) == 0
}
dlerror :: proc() -> string {
- return string(_unix_dlerror());
+ return string(_unix_dlerror())
}
get_page_size :: proc() -> int {
// NOTE(tetra): The page size never changes, so why do anything complicated
// if we don't have to.
- @static page_size := -1;
- if page_size != -1 do return page_size;
+ @static page_size := -1
+ if page_size != -1 do return page_size
- page_size = int(_unix_getpagesize());
- return page_size;
+ page_size = int(_unix_getpagesize())
+ return page_size
}
_alloc_command_line_arguments :: proc() -> []string {
- res := make([]string, len(runtime.args__));
+ res := make([]string, len(runtime.args__))
for arg, i in runtime.args__ {
- res[i] = string(arg);
+ res[i] = string(arg)
}
- return res;
+ return res
}
diff --git a/core/os/os_linux.odin b/core/os/os_linux.odin
index 4edfa46da..200d6d68d 100644
--- a/core/os/os_linux.odin
+++ b/core/os/os_linux.odin
@@ -460,9 +460,8 @@ fork :: proc() -> (Pid, Errno) {
}
open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Errno) {
- cstr := strings.clone_to_cstring(path)
+ cstr := strings.clone_to_cstring(path, context.temp_allocator)
handle := _unix_open(cstr, flags, mode)
- defer delete(cstr)
if handle < 0 {
return INVALID_HANDLE, _get_errno(int(handle))
}
@@ -610,8 +609,7 @@ last_write_time_by_name :: proc(name: string) -> (File_Time, Errno) {
@private
_stat :: proc(path: string) -> (OS_Stat, Errno) {
- cstr := strings.clone_to_cstring(path)
- defer delete(cstr)
+ cstr := strings.clone_to_cstring(path, context.temp_allocator)
// deliberately uninitialized; the syscall fills this buffer for us
s: OS_Stat = ---
@@ -624,8 +622,7 @@ _stat :: proc(path: string) -> (OS_Stat, Errno) {
@private
_lstat :: proc(path: string) -> (OS_Stat, Errno) {
- cstr := strings.clone_to_cstring(path)
- defer delete(cstr)
+ cstr := strings.clone_to_cstring(path, context.temp_allocator)
// deliberately uninitialized; the syscall fills this buffer for us
s: OS_Stat = ---
@@ -692,8 +689,7 @@ _readdir :: proc(dirp: Dir) -> (entry: Dirent, err: Errno, end_of_stream: bool)
@private
_readlink :: proc(path: string) -> (string, Errno) {
- path_cstr := strings.clone_to_cstring(path)
- defer delete(path_cstr)
+ path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
bufsz : uint = 256
buf := make([]byte, bufsz)
@@ -729,8 +725,7 @@ absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Errno) {
rel = "."
}
- rel_cstr := strings.clone_to_cstring(rel)
- defer delete(rel_cstr)
+ rel_cstr := strings.clone_to_cstring(rel, context.temp_allocator)
path_ptr := _unix_realpath(rel_cstr, nil)
if path_ptr == nil {
@@ -745,8 +740,7 @@ absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Errno) {
}
access :: proc(path: string, mask: int) -> (bool, Errno) {
- cstr := strings.clone_to_cstring(path)
- defer delete(cstr)
+ cstr := strings.clone_to_cstring(path, context.temp_allocator)
result := _unix_access(cstr, mask)
if result < 0 {
return false, _get_errno(result)
@@ -770,8 +764,7 @@ heap_free :: proc(ptr: rawptr) {
}
getenv :: proc(name: string) -> (string, bool) {
- path_str := strings.clone_to_cstring(name)
- defer delete(path_str)
+ path_str := strings.clone_to_cstring(name, context.temp_allocator)
cstr := _unix_getenv(path_str)
if cstr == nil {
return "", false
@@ -817,15 +810,13 @@ current_thread_id :: proc "contextless" () -> int {
}
dlopen :: proc(filename: string, flags: int) -> rawptr {
- cstr := strings.clone_to_cstring(filename)
- defer delete(cstr)
+ cstr := strings.clone_to_cstring(filename, context.temp_allocator)
handle := _unix_dlopen(cstr, c.int(flags))
return handle
}
dlsym :: proc(handle: rawptr, symbol: string) -> rawptr {
assert(handle != nil)
- cstr := strings.clone_to_cstring(symbol)
- defer delete(cstr)
+ cstr := strings.clone_to_cstring(symbol, context.temp_allocator)
proc_handle := _unix_dlsym(handle, cstr)
return proc_handle
}
diff --git a/core/strings/strings.odin b/core/strings/strings.odin
index 4daa0bacd..670da166b 100644
--- a/core/strings/strings.odin
+++ b/core/strings/strings.odin
@@ -280,10 +280,29 @@ _split :: proc(s_, sep: string, sep_save, n_: int, allocator := context.allocato
return res[:i+1]
}
+/*
+ Splits a string into parts, based on a separator.
+ Returned strings are substrings of 's'.
+ ```
+ s := "aaa.bbb.ccc.ddd.eee" // 5 parts
+ ss := split(s, ".")
+ fmt.println(ss) // [aaa, bbb, ccc, ddd, eee]
+ ```
+*/
split :: proc(s, sep: string, allocator := context.allocator) -> []string {
return _split(s, sep, 0, -1, allocator)
}
+/*
+ Splits a string into a total of 'n' parts, based on a separator.
+ Returns fewer parts if there wasn't enough occurrences of the separator.
+ Returned strings are substrings of 's'.
+ ```
+ s := "aaa.bbb.ccc.ddd.eee" // 5 parts present
+ ss := split_n(s, ".", 3) // total of 3 wanted
+ fmt.println(ss) // [aaa, bbb, ccc.ddd.eee]
+ ```
+*/
split_n :: proc(s, sep: string, n: int, allocator := context.allocator) -> []string {
return _split(s, sep, 0, n, allocator)
}
diff --git a/core/sys/darwin/xnu_system_call_helpers.odin b/core/sys/darwin/xnu_system_call_helpers.odin
index 5b060cfd3..94fe0bf47 100644
--- a/core/sys/darwin/xnu_system_call_helpers.odin
+++ b/core/sys/darwin/xnu_system_call_helpers.odin
@@ -91,8 +91,7 @@ sys_open :: proc(path: string, oflag: Open_Flags, mode: Permission) -> (c.int, b
cmode: u32 = 0
cflags: u32 = 0
- cpath: cstring = strings.clone_to_cstring(path)
- defer delete(cpath)
+ cpath: cstring = strings.clone_to_cstring(path, context.temp_allocator)
cflags = _sys_permission_mode(mode)
@@ -124,39 +123,32 @@ sys_open :: proc(path: string, oflag: Open_Flags, mode: Permission) -> (c.int, b
}
sys_mkdir :: proc(path: string, mode: Permission) -> bool {
- cpath: cstring = strings.clone_to_cstring(path)
- defer delete(cpath)
+ cpath: cstring = strings.clone_to_cstring(path, context.temp_allocator)
cflags := _sys_permission_mode(mode)
return syscall_mkdir(cpath, cflags) != -1
}
sys_mkdir_at :: proc(fd: c.int, path: string, mode: Permission) -> bool {
- cpath: cstring = strings.clone_to_cstring(path)
- defer delete(cpath)
+ cpath: cstring = strings.clone_to_cstring(path, context.temp_allocator)
cflags := _sys_permission_mode(mode)
return syscall_mkdir_at(fd, cpath, cflags) != -1
}
sys_rmdir :: proc(path: string, mode: Permission) -> bool {
- cpath: cstring = strings.clone_to_cstring(path)
- defer delete(cpath)
+ cpath: cstring = strings.clone_to_cstring(path, context.temp_allocator)
cflags := _sys_permission_mode(mode)
return syscall_rmdir(cpath, cflags) != -1
}
sys_rename :: proc(path: string, new_path: string) -> bool {
- cpath: cstring = strings.clone_to_cstring(path)
- defer delete(cpath)
- cnpath: cstring = strings.clone_to_cstring(new_path)
- defer delete(cnpath)
+ cpath: cstring = strings.clone_to_cstring(path, context.temp_allocator)
+ cnpath: cstring = strings.clone_to_cstring(new_path, context.temp_allocator)
return syscall_rename(cpath, cnpath) != -1
}
sys_rename_at :: proc(fd: c.int, path: string, to_fd: c.int, new_path: string) -> bool {
- cpath: cstring = strings.clone_to_cstring(path)
- defer delete(cpath)
- cnpath: cstring = strings.clone_to_cstring(new_path)
- defer delete(cnpath)
+ cpath: cstring = strings.clone_to_cstring(path, context.temp_allocator)
+ cnpath: cstring = strings.clone_to_cstring(new_path, context.temp_allocator)
return syscall_rename_at(fd, cpath, to_fd, cnpath) != -1
}
@@ -165,14 +157,12 @@ sys_lseek :: proc(fd: c.int, offset: i64, whence: Offset_From) -> i64 {
}
sys_chmod :: proc(path: string, mode: Permission) -> bool {
- cpath: cstring = strings.clone_to_cstring(path)
- defer delete(cpath)
+ cpath: cstring = strings.clone_to_cstring(path, context.temp_allocator)
cmode := _sys_permission_mode(mode)
return syscall_chmod(cpath, cmode) != -1
}
sys_lstat :: proc(path: string, status: ^stat) -> bool {
- cpath: cstring = strings.clone_to_cstring(path)
- defer delete(cpath)
+ cpath: cstring = strings.clone_to_cstring(path, context.temp_allocator)
return syscall_lstat(cpath, status) != -1
}