Merge branch 'master' into freestanding_amd64

This commit is contained in:
gingerBill
2022-02-28 12:32:51 +00:00
11 changed files with 356 additions and 341 deletions
+3 -7
View File
@@ -10,7 +10,7 @@ OS=$(shell uname)
ifeq ($(OS), Darwin) ifeq ($(OS), Darwin)
ARCH=$(shell uname -m) ARCH=$(shell uname -m)
LLVM_CONFIG= LLVM_CONFIG=llvm-config
# allow for arm only llvm's with version 13 # allow for arm only llvm's with version 13
ifeq ($(ARCH), arm64) ifeq ($(ARCH), arm64)
@@ -27,9 +27,7 @@ ifeq ($(OS), Darwin)
LLMV_VERSION_PATTERN_REMOVE_SINGLE_STR = $(subst ",,$(LLVM_VERSION_PATTERN_REMOVE_ELEMENTS)) LLMV_VERSION_PATTERN_REMOVE_SINGLE_STR = $(subst ",,$(LLVM_VERSION_PATTERN_REMOVE_ELEMENTS))
LLVM_VERSION_PATTERN = "^(($(LLMV_VERSION_PATTERN_REMOVE_SINGLE_STR)))" LLVM_VERSION_PATTERN = "^(($(LLMV_VERSION_PATTERN_REMOVE_SINGLE_STR)))"
ifneq ($(shell llvm-config --version | grep -E $(LLVM_VERSION_PATTERN)),) ifeq ($(shell $(LLVM_CONFIG) --version | grep -E $(LLVM_VERSION_PATTERN)),)
LLVM_CONFIG=llvm-config
else
ifeq ($(ARCH), arm64) ifeq ($(ARCH), arm64)
$(error "Requirement: llvm-config must be base version 13 for arm64") $(error "Requirement: llvm-config must be base version 13 for arm64")
else else
@@ -48,9 +46,7 @@ ifeq ($(OS), Linux)
else ifneq ($(shell which llvm-config-11-64 2>/dev/null),) else ifneq ($(shell which llvm-config-11-64 2>/dev/null),)
LLVM_CONFIG=llvm-config-11-64 LLVM_CONFIG=llvm-config-11-64
else else
ifneq ($(shell llvm-config --version | grep '^11\.'),) ifeq ($(shell $(LLVM_CONFIG) --version | grep '^11\.'),)
LLVM_CONFIG=llvm-config
else
$(error "Requirement: llvm-config must be version 11") $(error "Requirement: llvm-config must be version 11")
endif endif
endif endif
+11 -1
View File
@@ -108,8 +108,11 @@ read_console :: proc(handle: win32.HANDLE, b: []byte) -> (n: int, err: Errno) {
buf8: [4*BUF_SIZE]u8 buf8: [4*BUF_SIZE]u8
for n < len(b) && err == 0 { 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)) max_read := u32(min(BUF_SIZE, min_read))
if max_read == 0 {
break
}
single_read_length: u32 single_read_length: u32
ok := win32.ReadConsoleW(handle, &buf16[0], max_read, &single_read_length, nil) ok := win32.ReadConsoleW(handle, &buf16[0], max_read, &single_read_length, nil)
@@ -133,6 +136,13 @@ read_console :: proc(handle: win32.HANDLE, b: []byte) -> (n: int, err: Errno) {
if ctrl_z || single_read_length < max_read { if ctrl_z || single_read_length < max_read {
break 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 return
+11 -2
View File
@@ -313,6 +313,7 @@ foreign libc {
@(link_name="getenv") _unix_getenv :: proc(cstring) -> cstring --- @(link_name="getenv") _unix_getenv :: proc(cstring) -> cstring ---
@(link_name="getcwd") _unix_getcwd :: proc(buf: cstring, len: c.size_t) -> 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="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="realpath") _unix_realpath :: proc(path: cstring, resolved_path: rawptr) -> rawptr ---
@(link_name="strerror") _darwin_string_error :: proc(num : c.int) -> cstring --- @(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) { 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)) handle := _unix_open(cstr, i32(flags), u16(mode))
delete(cstr)
if handle == -1 { if handle == -1 {
return INVALID_HANDLE, 1 return INVALID_HANDLE, 1
} }
@@ -670,6 +670,15 @@ set_current_directory :: proc(path: string) -> (err: Errno) {
return ERROR_NONE 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) -> ! { exit :: proc "contextless" (code: int) -> ! {
_unix_exit(i32(code)) _unix_exit(i32(code))
} }
+272 -279
View File
@@ -7,149 +7,149 @@ import "core:runtime"
import "core:strings" import "core:strings"
import "core:c" import "core:c"
Handle :: distinct i32; Handle :: distinct i32
File_Time :: distinct u64; File_Time :: distinct u64
Errno :: distinct i32; Errno :: distinct i32
Syscall :: distinct i32; Syscall :: distinct i32
INVALID_HANDLE :: ~Handle(0); INVALID_HANDLE :: ~Handle(0)
ERROR_NONE: Errno : 0; ERROR_NONE: Errno : 0
EPERM: Errno : 1; EPERM: Errno : 1
ENOENT: Errno : 2; ENOENT: Errno : 2
ESRCH: Errno : 3; ESRCH: Errno : 3
EINTR: Errno : 4; EINTR: Errno : 4
EIO: Errno : 5; EIO: Errno : 5
ENXIO: Errno : 6; ENXIO: Errno : 6
E2BIG: Errno : 7; E2BIG: Errno : 7
ENOEXEC: Errno : 8; ENOEXEC: Errno : 8
EBADF: Errno : 9; EBADF: Errno : 9
ECHILD: Errno : 10; ECHILD: Errno : 10
EBEADLK: Errno : 11; EBEADLK: Errno : 11
ENOMEM: Errno : 12; ENOMEM: Errno : 12
EACCESS: Errno : 13; EACCESS: Errno : 13
EFAULT: Errno : 14; EFAULT: Errno : 14
ENOTBLK: Errno : 15; ENOTBLK: Errno : 15
EBUSY: Errno : 16; EBUSY: Errno : 16
EEXIST: Errno : 17; EEXIST: Errno : 17
EXDEV: Errno : 18; EXDEV: Errno : 18
ENODEV: Errno : 19; ENODEV: Errno : 19
ENOTDIR: Errno : 20; ENOTDIR: Errno : 20
EISDIR: Errno : 21; EISDIR: Errno : 21
EINVAL: Errno : 22; EINVAL: Errno : 22
ENFILE: Errno : 23; ENFILE: Errno : 23
EMFILE: Errno : 24; EMFILE: Errno : 24
ENOTTY: Errno : 25; ENOTTY: Errno : 25
ETXTBSY: Errno : 26; ETXTBSY: Errno : 26
EFBIG: Errno : 27; EFBIG: Errno : 27
ENOSPC: Errno : 28; ENOSPC: Errno : 28
ESPIPE: Errno : 29; ESPIPE: Errno : 29
EROFS: Errno : 30; EROFS: Errno : 30
EMLINK: Errno : 31; EMLINK: Errno : 31
EPIPE: Errno : 32; EPIPE: Errno : 32
EDOM: Errno : 33; EDOM: Errno : 33
ERANGE: Errno : 34; /* Result too large */ ERANGE: Errno : 34 /* Result too large */
EAGAIN: Errno : 35; EAGAIN: Errno : 35
EINPROGRESS: Errno : 36; EINPROGRESS: Errno : 36
EALREADY: Errno : 37; EALREADY: Errno : 37
ENOTSOCK: Errno : 38; ENOTSOCK: Errno : 38
EDESTADDRREQ: Errno : 39; EDESTADDRREQ: Errno : 39
EMSGSIZE: Errno : 40; EMSGSIZE: Errno : 40
EPROTOTYPE: Errno : 41; EPROTOTYPE: Errno : 41
ENOPROTOOPT: Errno : 42; ENOPROTOOPT: Errno : 42
EPROTONOSUPPORT: Errno : 43; EPROTONOSUPPORT: Errno : 43
ESOCKTNOSUPPORT: Errno : 44; ESOCKTNOSUPPORT: Errno : 44
EOPNOTSUPP: Errno : 45; EOPNOTSUPP: Errno : 45
EPFNOSUPPORT: Errno : 46; EPFNOSUPPORT: Errno : 46
EAFNOSUPPORT: Errno : 47; EAFNOSUPPORT: Errno : 47
EADDRINUSE: Errno : 48; EADDRINUSE: Errno : 48
EADDRNOTAVAIL: Errno : 49; EADDRNOTAVAIL: Errno : 49
ENETDOWN: Errno : 50; ENETDOWN: Errno : 50
ENETUNREACH: Errno : 51; ENETUNREACH: Errno : 51
ENETRESET: Errno : 52; ENETRESET: Errno : 52
ECONNABORTED: Errno : 53; ECONNABORTED: Errno : 53
ECONNRESET: Errno : 54; ECONNRESET: Errno : 54
ENOBUFS: Errno : 55; ENOBUFS: Errno : 55
EISCONN: Errno : 56; EISCONN: Errno : 56
ENOTCONN: Errno : 57; ENOTCONN: Errno : 57
ESHUTDOWN: Errno : 58; ESHUTDOWN: Errno : 58
ETIMEDOUT: Errno : 60; ETIMEDOUT: Errno : 60
ECONNREFUSED: Errno : 61; ECONNREFUSED: Errno : 61
ELOOP: Errno : 62; ELOOP: Errno : 62
ENAMETOOLING: Errno : 63; ENAMETOOLING: Errno : 63
EHOSTDOWN: Errno : 64; EHOSTDOWN: Errno : 64
EHOSTUNREACH: Errno : 65; EHOSTUNREACH: Errno : 65
ENOTEMPTY: Errno : 66; ENOTEMPTY: Errno : 66
EPROCLIM: Errno : 67; EPROCLIM: Errno : 67
EUSERS: Errno : 68; EUSERS: Errno : 68
EDQUOT: Errno : 69; EDQUOT: Errno : 69
ESTALE: Errno : 70; ESTALE: Errno : 70
EBADRPC: Errno : 72; EBADRPC: Errno : 72
ERPCMISMATCH: Errno : 73; ERPCMISMATCH: Errno : 73
EPROGUNAVAIL: Errno : 74; EPROGUNAVAIL: Errno : 74
EPROGMISMATCH: Errno : 75; EPROGMISMATCH: Errno : 75
EPROCUNAVAIL: Errno : 76; EPROCUNAVAIL: Errno : 76
ENOLCK: Errno : 77; ENOLCK: Errno : 77
ENOSYS: Errno : 78; ENOSYS: Errno : 78
EFTYPE: Errno : 79; EFTYPE: Errno : 79
EAUTH: Errno : 80; EAUTH: Errno : 80
ENEEDAUTH: Errno : 81; ENEEDAUTH: Errno : 81
EIDRM: Errno : 82; EIDRM: Errno : 82
ENOMSG: Errno : 83; ENOMSG: Errno : 83
EOVERFLOW: Errno : 84; EOVERFLOW: Errno : 84
ECANCELED: Errno : 85; ECANCELED: Errno : 85
EILSEQ: Errno : 86; EILSEQ: Errno : 86
ENOATTR: Errno : 87; ENOATTR: Errno : 87
EDOOFUS: Errno : 88; EDOOFUS: Errno : 88
EBADMSG: Errno : 89; EBADMSG: Errno : 89
EMULTIHOP: Errno : 90; EMULTIHOP: Errno : 90
ENOLINK: Errno : 91; ENOLINK: Errno : 91
EPROTO: Errno : 92; EPROTO: Errno : 92
ENOTCAPABLE: Errno : 93; ENOTCAPABLE: Errno : 93
ECAPMODE: Errno : 94; ECAPMODE: Errno : 94
ENOTRECOVERABLE: Errno : 95; ENOTRECOVERABLE: Errno : 95
EOWNERDEAD: Errno : 96; EOWNERDEAD: Errno : 96
O_RDONLY :: 0x00000; O_RDONLY :: 0x00000
O_WRONLY :: 0x00001; O_WRONLY :: 0x00001
O_RDWR :: 0x00002; O_RDWR :: 0x00002
O_CREATE :: 0x00040; O_CREATE :: 0x00040
O_EXCL :: 0x00080; O_EXCL :: 0x00080
O_NOCTTY :: 0x00100; O_NOCTTY :: 0x00100
O_TRUNC :: 0x00200; O_TRUNC :: 0x00200
O_NONBLOCK :: 0x00800; O_NONBLOCK :: 0x00800
O_APPEND :: 0x00400; O_APPEND :: 0x00400
O_SYNC :: 0x01000; O_SYNC :: 0x01000
O_ASYNC :: 0x02000; O_ASYNC :: 0x02000
O_CLOEXEC :: 0x80000; O_CLOEXEC :: 0x80000
SEEK_SET :: 0; SEEK_SET :: 0
SEEK_CUR :: 1; SEEK_CUR :: 1
SEEK_END :: 2; SEEK_END :: 2
SEEK_DATA :: 3; SEEK_DATA :: 3
SEEK_HOLE :: 4; SEEK_HOLE :: 4
SEEK_MAX :: SEEK_HOLE; SEEK_MAX :: SEEK_HOLE
// NOTE: These are OS specific! // NOTE: These are OS specific!
// Do not mix these up! // Do not mix these up!
RTLD_LAZY :: 0x001; RTLD_LAZY :: 0x001
RTLD_NOW :: 0x002; RTLD_NOW :: 0x002
//RTLD_BINDING_MASK :: 0x3; // Called MODEMASK in dlfcn.h //RTLD_BINDING_MASK :: 0x3 // Called MODEMASK in dlfcn.h
RTLD_GLOBAL :: 0x100; RTLD_GLOBAL :: 0x100
RTLD_LOCAL :: 0x000; RTLD_LOCAL :: 0x000
RTLD_TRACE :: 0x200; RTLD_TRACE :: 0x200
RTLD_NODELETE :: 0x01000; RTLD_NODELETE :: 0x01000
RTLD_NOLOAD :: 0x02000; RTLD_NOLOAD :: 0x02000
args := _alloc_command_line_arguments(); args := _alloc_command_line_arguments()
Unix_File_Time :: struct { Unix_File_Time :: struct {
seconds: i64, seconds: i64,
nanoseconds: c.long, nanoseconds: c.long,
} }
pid_t :: u32; pid_t :: u32
OS_Stat :: struct { OS_Stat :: struct {
device_id: u64, device_id: u64,
@@ -177,297 +177,290 @@ OS_Stat :: struct {
} }
// File type // File type
S_IFMT :: 0o170000; // Type of file mask S_IFMT :: 0o170000 // Type of file mask
S_IFIFO :: 0o010000; // Named pipe (fifo) S_IFIFO :: 0o010000 // Named pipe (fifo)
S_IFCHR :: 0o020000; // Character special S_IFCHR :: 0o020000 // Character special
S_IFDIR :: 0o040000; // Directory S_IFDIR :: 0o040000 // Directory
S_IFBLK :: 0o060000; // Block special S_IFBLK :: 0o060000 // Block special
S_IFREG :: 0o100000; // Regular S_IFREG :: 0o100000 // Regular
S_IFLNK :: 0o120000; // Symbolic link S_IFLNK :: 0o120000 // Symbolic link
S_IFSOCK :: 0o140000; // Socket S_IFSOCK :: 0o140000 // Socket
//S_ISVTX :: 0o001000; // Save swapped text even after use //S_ISVTX :: 0o001000 // Save swapped text even after use
// File mode // File mode
// Read, write, execute/search by owner // Read, write, execute/search by owner
S_IRWXU :: 0o0700; // RWX mask for owner S_IRWXU :: 0o0700 // RWX mask for owner
S_IRUSR :: 0o0400; // R for owner S_IRUSR :: 0o0400 // R for owner
S_IWUSR :: 0o0200; // W for owner S_IWUSR :: 0o0200 // W for owner
S_IXUSR :: 0o0100; // X for owner S_IXUSR :: 0o0100 // X for owner
// Read, write, execute/search by group // Read, write, execute/search by group
S_IRWXG :: 0o0070; // RWX mask for group S_IRWXG :: 0o0070 // RWX mask for group
S_IRGRP :: 0o0040; // R for group S_IRGRP :: 0o0040 // R for group
S_IWGRP :: 0o0020; // W for group S_IWGRP :: 0o0020 // W for group
S_IXGRP :: 0o0010; // X for group S_IXGRP :: 0o0010 // X for group
// Read, write, execute/search by others // Read, write, execute/search by others
S_IRWXO :: 0o0007; // RWX mask for other S_IRWXO :: 0o0007 // RWX mask for other
S_IROTH :: 0o0004; // R for other S_IROTH :: 0o0004 // R for other
S_IWOTH :: 0o0002; // W for other S_IWOTH :: 0o0002 // W for other
S_IXOTH :: 0o0001; // X for other S_IXOTH :: 0o0001 // X for other
S_ISUID :: 0o4000; // Set user id on execution S_ISUID :: 0o4000 // Set user id on execution
S_ISGID :: 0o2000; // Set group id on execution S_ISGID :: 0o2000 // Set group id on execution
S_ISVTX :: 0o1000; // Directory restrcted delete S_ISVTX :: 0o1000 // Directory restrcted delete
S_ISLNK :: #force_inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFLNK; 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_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_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_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_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_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_ISSOCK :: #force_inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFSOCK
F_OK :: 0; // Test for file existance F_OK :: 0 // Test for file existance
X_OK :: 1; // Test for execute permission X_OK :: 1 // Test for execute permission
W_OK :: 2; // Test for write permission W_OK :: 2 // Test for write permission
R_OK :: 4; // Test for read permission R_OK :: 4 // Test for read permission
foreign libc { foreign libc {
@(link_name="__error") __errno_location :: proc() -> ^int ---; @(link_name="__error") __errno_location :: proc() -> ^int ---
@(link_name="syscall") syscall :: proc(number: Syscall, #c_vararg args: ..any) -> 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="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="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="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="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="lseek64") _unix_seek :: proc(fd: Handle, offset: i64, whence: c.int) -> i64 ---
@(link_name="gettid") _unix_gettid :: proc() -> u64 ---; @(link_name="gettid") _unix_gettid :: proc() -> u64 ---
@(link_name="getpagesize") _unix_getpagesize :: proc() -> c.int ---; @(link_name="getpagesize") _unix_getpagesize :: proc() -> c.int ---
@(link_name="stat64") _unix_stat :: proc(path: cstring, stat: ^OS_Stat) -> 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="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="access") _unix_access :: proc(path: cstring, mask: c.int) -> c.int ---
@(link_name="malloc") _unix_malloc :: proc(size: c.size_t) -> rawptr ---; @(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="calloc") _unix_calloc :: proc(num, size: c.size_t) -> rawptr ---
@(link_name="free") _unix_free :: proc(ptr: rawptr) ---; @(link_name="free") _unix_free :: proc(ptr: rawptr) ---
@(link_name="realloc") _unix_realloc :: proc(ptr: rawptr, size: c.size_t) -> rawptr ---; @(link_name="realloc") _unix_realloc :: proc(ptr: rawptr, size: c.size_t) -> rawptr ---
@(link_name="getenv") _unix_getenv :: proc(cstring) -> cstring ---; @(link_name="getenv") _unix_getenv :: proc(cstring) -> cstring ---
@(link_name="getcwd") _unix_getcwd :: proc(buf: cstring, len: c.size_t) -> 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="chdir") _unix_chdir :: proc(buf: cstring) -> c.int ---
@(link_name="exit") _unix_exit :: proc(status: c.int) -> ! ---; @(link_name="exit") _unix_exit :: proc(status: c.int) -> ! ---
} }
foreign dl { foreign dl {
@(link_name="dlopen") _unix_dlopen :: proc(filename: cstring, flags: c.int) -> rawptr ---; @(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="dlsym") _unix_dlsym :: proc(handle: rawptr, symbol: cstring) -> rawptr ---
@(link_name="dlclose") _unix_dlclose :: proc(handle: rawptr) -> c.int ---; @(link_name="dlclose") _unix_dlclose :: proc(handle: rawptr) -> c.int ---
@(link_name="dlerror") _unix_dlerror :: proc() -> cstring ---; @(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 { is_path_separator :: proc(r: rune) -> bool {
return r == '/'; return r == '/'
} }
get_last_error :: proc() -> int { get_last_error :: proc() -> int {
return __errno_location()^; return __errno_location()^
} }
open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, 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, c.int(flags), c.int(mode)); handle := _unix_open(cstr, c.int(flags), c.int(mode))
delete(cstr);
if handle == -1 { 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 { close :: proc(fd: Handle) -> Errno {
result := _unix_close(fd); result := _unix_close(fd)
if result == -1 { 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) { 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 { 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) { write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
if len(data) == 0 { 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 { 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) { 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 { 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) { file_size :: proc(fd: Handle) -> (i64, Errno) {
s, err := fstat(fd); s, err := fstat(fd)
if err != ERROR_NONE { if err != ERROR_NONE {
return -1, err; return -1, err
} }
return s.size, ERROR_NONE; return s.size, ERROR_NONE
} }
stdin: Handle = 0; stdin: Handle = 0
stdout: Handle = 1; stdout: Handle = 1
stderr: Handle = 2; stderr: Handle = 2
last_write_time :: proc(fd: Handle) -> (File_Time, Errno) { last_write_time :: proc(fd: Handle) -> (File_Time, Errno) {
s, err := fstat(fd); s, err := fstat(fd)
if err != ERROR_NONE { if err != ERROR_NONE {
return 0, err; return 0, err
} }
modified := s.modified.seconds * 1_000_000_000 + s.modified.nanoseconds; modified := s.modified.seconds * 1_000_000_000 + s.modified.nanoseconds
return File_Time(modified), ERROR_NONE; return File_Time(modified), ERROR_NONE
} }
last_write_time_by_name :: proc(name: string) -> (File_Time, Errno) { last_write_time_by_name :: proc(name: string) -> (File_Time, Errno) {
s, err := stat(name); s, err := stat(name)
if err != ERROR_NONE { if err != ERROR_NONE {
return 0, err; return 0, err
} }
modified := s.modified.seconds * 1_000_000_000 + s.modified.nanoseconds; modified := s.modified.seconds * 1_000_000_000 + s.modified.nanoseconds
return File_Time(modified), ERROR_NONE; return File_Time(modified), ERROR_NONE
} }
stat :: proc(path: string) -> (OS_Stat, Errno) { stat :: proc(path: string) -> (OS_Stat, Errno) {
cstr := strings.clone_to_cstring(path); cstr := strings.clone_to_cstring(path, context.temp_allocator)
defer delete(cstr); s: OS_Stat
result := _unix_stat(cstr, &s)
s: OS_Stat;
result := _unix_stat(cstr, &s);
if result == -1 { 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) { fstat :: proc(fd: Handle) -> (OS_Stat, Errno) {
s: OS_Stat; s: OS_Stat
result := _unix_fstat(fd, &s); result := _unix_fstat(fd, &s)
if result == -1 { 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) { access :: proc(path: string, mask: int) -> (bool, Errno) {
cstr := strings.clone_to_cstring(path); cstr := strings.clone_to_cstring(path, context.temp_allocator)
defer delete(cstr); result := _unix_access(cstr, c.int(mask))
result := _unix_access(cstr, c.int(mask));
if result == -1 { 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 { heap_alloc :: proc(size: int) -> rawptr {
assert(size >= 0); assert(size >= 0)
return _unix_calloc(1, c.size_t(size)); return _unix_calloc(1, c.size_t(size))
} }
heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr { heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
// NOTE: _unix_realloc doesn't guarantee new memory will be zeroed on // NOTE: _unix_realloc doesn't guarantee new memory will be zeroed on
// POSIX platforms. Ensure your caller takes this into account. // 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) { heap_free :: proc(ptr: rawptr) {
_unix_free(ptr); _unix_free(ptr)
} }
getenv :: proc(name: string) -> (string, bool) { getenv :: proc(name: string) -> (string, bool) {
path_str := strings.clone_to_cstring(name); path_str := strings.clone_to_cstring(name, context.temp_allocator)
defer delete(path_str); cstr := _unix_getenv(path_str)
cstr := _unix_getenv(path_str);
if cstr == nil { if cstr == nil {
return "", false; return "", false
} }
return string(cstr), true; return string(cstr), true
} }
get_current_directory :: proc() -> string { get_current_directory :: proc() -> string {
// NOTE(tetra): I would use PATH_MAX here, but I was not able to find // NOTE(tetra): I would use PATH_MAX here, but I was not able to find
// an authoritative value for it across all systems. // an authoritative value for it across all systems.
// The largest value I could find was 4096, so might as well use the page size. // The largest value I could find was 4096, so might as well use the page size.
page_size := get_page_size(); page_size := get_page_size()
buf := make([dynamic]u8, page_size); buf := make([dynamic]u8, page_size)
#no_bounds_check for { #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 { if cwd != nil {
return string(cwd); return string(cwd)
} }
if Errno(get_last_error()) != ERANGE { 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) { set_current_directory :: proc(path: string) -> (err: Errno) {
cstr := strings.clone_to_cstring(path, context.temp_allocator); cstr := strings.clone_to_cstring(path, context.temp_allocator)
res := _unix_chdir(cstr); res := _unix_chdir(cstr)
if res == -1 do return Errno(get_last_error()); if res == -1 do return Errno(get_last_error())
return ERROR_NONE; return ERROR_NONE
} }
exit :: proc "contextless" (code: int) -> ! { exit :: proc "contextless" (code: int) -> ! {
_unix_exit(c.int(code)); _unix_exit(c.int(code))
} }
current_thread_id :: proc "contextless" () -> int { 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 { dlopen :: proc(filename: string, flags: int) -> rawptr {
cstr := strings.clone_to_cstring(filename); cstr := strings.clone_to_cstring(filename, context.temp_allocator)
defer delete(cstr); handle := _unix_dlopen(cstr, c.int(flags))
handle := _unix_dlopen(cstr, c.int(flags)); return handle
return handle;
} }
dlsym :: proc(handle: rawptr, symbol: string) -> rawptr { dlsym :: proc(handle: rawptr, symbol: string) -> rawptr {
assert(handle != nil); assert(handle != nil)
cstr := strings.clone_to_cstring(symbol); cstr := strings.clone_to_cstring(symbol, context.temp_allocator)
defer delete(cstr); proc_handle := _unix_dlsym(handle, cstr)
proc_handle := _unix_dlsym(handle, cstr); return proc_handle
return proc_handle;
} }
dlclose :: proc(handle: rawptr) -> bool { dlclose :: proc(handle: rawptr) -> bool {
assert(handle != nil); assert(handle != nil)
return _unix_dlclose(handle) == 0; return _unix_dlclose(handle) == 0
} }
dlerror :: proc() -> string { dlerror :: proc() -> string {
return string(_unix_dlerror()); return string(_unix_dlerror())
} }
get_page_size :: proc() -> int { get_page_size :: proc() -> int {
// NOTE(tetra): The page size never changes, so why do anything complicated // NOTE(tetra): The page size never changes, so why do anything complicated
// if we don't have to. // if we don't have to.
@static page_size := -1; @static page_size := -1
if page_size != -1 do return page_size; if page_size != -1 do return page_size
page_size = int(_unix_getpagesize()); page_size = int(_unix_getpagesize())
return page_size; return page_size
} }
_alloc_command_line_arguments :: proc() -> []string { _alloc_command_line_arguments :: proc() -> []string {
res := make([]string, len(runtime.args__)); res := make([]string, len(runtime.args__))
for arg, i in runtime.args__ { for arg, i in runtime.args__ {
res[i] = string(arg); res[i] = string(arg)
} }
return res; return res
} }
+9 -18
View File
@@ -460,9 +460,8 @@ fork :: proc() -> (Pid, Errno) {
} }
open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, 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) handle := _unix_open(cstr, flags, mode)
defer delete(cstr)
if handle < 0 { if handle < 0 {
return INVALID_HANDLE, _get_errno(int(handle)) return INVALID_HANDLE, _get_errno(int(handle))
} }
@@ -610,8 +609,7 @@ last_write_time_by_name :: proc(name: string) -> (File_Time, Errno) {
@private @private
_stat :: proc(path: string) -> (OS_Stat, Errno) { _stat :: proc(path: string) -> (OS_Stat, Errno) {
cstr := strings.clone_to_cstring(path) cstr := strings.clone_to_cstring(path, context.temp_allocator)
defer delete(cstr)
// deliberately uninitialized; the syscall fills this buffer for us // deliberately uninitialized; the syscall fills this buffer for us
s: OS_Stat = --- s: OS_Stat = ---
@@ -624,8 +622,7 @@ _stat :: proc(path: string) -> (OS_Stat, Errno) {
@private @private
_lstat :: proc(path: string) -> (OS_Stat, Errno) { _lstat :: proc(path: string) -> (OS_Stat, Errno) {
cstr := strings.clone_to_cstring(path) cstr := strings.clone_to_cstring(path, context.temp_allocator)
defer delete(cstr)
// deliberately uninitialized; the syscall fills this buffer for us // deliberately uninitialized; the syscall fills this buffer for us
s: OS_Stat = --- s: OS_Stat = ---
@@ -692,8 +689,7 @@ _readdir :: proc(dirp: Dir) -> (entry: Dirent, err: Errno, end_of_stream: bool)
@private @private
_readlink :: proc(path: string) -> (string, Errno) { _readlink :: proc(path: string) -> (string, Errno) {
path_cstr := strings.clone_to_cstring(path) path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
defer delete(path_cstr)
bufsz : uint = 256 bufsz : uint = 256
buf := make([]byte, bufsz) buf := make([]byte, bufsz)
@@ -729,8 +725,7 @@ absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Errno) {
rel = "." rel = "."
} }
rel_cstr := strings.clone_to_cstring(rel) rel_cstr := strings.clone_to_cstring(rel, context.temp_allocator)
defer delete(rel_cstr)
path_ptr := _unix_realpath(rel_cstr, nil) path_ptr := _unix_realpath(rel_cstr, nil)
if path_ptr == 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) { access :: proc(path: string, mask: int) -> (bool, Errno) {
cstr := strings.clone_to_cstring(path) cstr := strings.clone_to_cstring(path, context.temp_allocator)
defer delete(cstr)
result := _unix_access(cstr, mask) result := _unix_access(cstr, mask)
if result < 0 { if result < 0 {
return false, _get_errno(result) return false, _get_errno(result)
@@ -770,8 +764,7 @@ heap_free :: proc(ptr: rawptr) {
} }
getenv :: proc(name: string) -> (string, bool) { getenv :: proc(name: string) -> (string, bool) {
path_str := strings.clone_to_cstring(name) path_str := strings.clone_to_cstring(name, context.temp_allocator)
defer delete(path_str)
cstr := _unix_getenv(path_str) cstr := _unix_getenv(path_str)
if cstr == nil { if cstr == nil {
return "", false return "", false
@@ -817,15 +810,13 @@ current_thread_id :: proc "contextless" () -> int {
} }
dlopen :: proc(filename: string, flags: int) -> rawptr { dlopen :: proc(filename: string, flags: int) -> rawptr {
cstr := strings.clone_to_cstring(filename) cstr := strings.clone_to_cstring(filename, context.temp_allocator)
defer delete(cstr)
handle := _unix_dlopen(cstr, c.int(flags)) handle := _unix_dlopen(cstr, c.int(flags))
return handle return handle
} }
dlsym :: proc(handle: rawptr, symbol: string) -> rawptr { dlsym :: proc(handle: rawptr, symbol: string) -> rawptr {
assert(handle != nil) assert(handle != nil)
cstr := strings.clone_to_cstring(symbol) cstr := strings.clone_to_cstring(symbol, context.temp_allocator)
defer delete(cstr)
proc_handle := _unix_dlsym(handle, cstr) proc_handle := _unix_dlsym(handle, cstr)
return proc_handle return proc_handle
} }
+19
View File
@@ -280,10 +280,29 @@ _split :: proc(s_, sep: string, sep_save, n_: int, allocator := context.allocato
return res[:i+1] 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 { split :: proc(s, sep: string, allocator := context.allocator) -> []string {
return _split(s, sep, 0, -1, allocator) 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 { split_n :: proc(s, sep: string, n: int, allocator := context.allocator) -> []string {
return _split(s, sep, 0, n, allocator) return _split(s, sep, 0, n, allocator)
} }
+10 -20
View File
@@ -91,8 +91,7 @@ sys_open :: proc(path: string, oflag: Open_Flags, mode: Permission) -> (c.int, b
cmode: u32 = 0 cmode: u32 = 0
cflags: u32 = 0 cflags: u32 = 0
cpath: cstring = strings.clone_to_cstring(path) cpath: cstring = strings.clone_to_cstring(path, context.temp_allocator)
defer delete(cpath)
cflags = _sys_permission_mode(mode) 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 { sys_mkdir :: proc(path: string, mode: Permission) -> bool {
cpath: cstring = strings.clone_to_cstring(path) cpath: cstring = strings.clone_to_cstring(path, context.temp_allocator)
defer delete(cpath)
cflags := _sys_permission_mode(mode) cflags := _sys_permission_mode(mode)
return syscall_mkdir(cpath, cflags) != -1 return syscall_mkdir(cpath, cflags) != -1
} }
sys_mkdir_at :: proc(fd: c.int, path: string, mode: Permission) -> bool { sys_mkdir_at :: proc(fd: c.int, path: string, mode: Permission) -> bool {
cpath: cstring = strings.clone_to_cstring(path) cpath: cstring = strings.clone_to_cstring(path, context.temp_allocator)
defer delete(cpath)
cflags := _sys_permission_mode(mode) cflags := _sys_permission_mode(mode)
return syscall_mkdir_at(fd, cpath, cflags) != -1 return syscall_mkdir_at(fd, cpath, cflags) != -1
} }
sys_rmdir :: proc(path: string, mode: Permission) -> bool { sys_rmdir :: proc(path: string, mode: Permission) -> bool {
cpath: cstring = strings.clone_to_cstring(path) cpath: cstring = strings.clone_to_cstring(path, context.temp_allocator)
defer delete(cpath)
cflags := _sys_permission_mode(mode) cflags := _sys_permission_mode(mode)
return syscall_rmdir(cpath, cflags) != -1 return syscall_rmdir(cpath, cflags) != -1
} }
sys_rename :: proc(path: string, new_path: string) -> bool { sys_rename :: proc(path: string, new_path: string) -> bool {
cpath: cstring = strings.clone_to_cstring(path) cpath: cstring = strings.clone_to_cstring(path, context.temp_allocator)
defer delete(cpath) cnpath: cstring = strings.clone_to_cstring(new_path, context.temp_allocator)
cnpath: cstring = strings.clone_to_cstring(new_path)
defer delete(cnpath)
return syscall_rename(cpath, cnpath) != -1 return syscall_rename(cpath, cnpath) != -1
} }
sys_rename_at :: proc(fd: c.int, path: string, to_fd: c.int, new_path: string) -> bool { sys_rename_at :: proc(fd: c.int, path: string, to_fd: c.int, new_path: string) -> bool {
cpath: cstring = strings.clone_to_cstring(path) cpath: cstring = strings.clone_to_cstring(path, context.temp_allocator)
defer delete(cpath) cnpath: cstring = strings.clone_to_cstring(new_path, context.temp_allocator)
cnpath: cstring = strings.clone_to_cstring(new_path)
defer delete(cnpath)
return syscall_rename_at(fd, cpath, to_fd, cnpath) != -1 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 { sys_chmod :: proc(path: string, mode: Permission) -> bool {
cpath: cstring = strings.clone_to_cstring(path) cpath: cstring = strings.clone_to_cstring(path, context.temp_allocator)
defer delete(cpath)
cmode := _sys_permission_mode(mode) cmode := _sys_permission_mode(mode)
return syscall_chmod(cpath, cmode) != -1 return syscall_chmod(cpath, cmode) != -1
} }
sys_lstat :: proc(path: string, status: ^stat) -> bool { sys_lstat :: proc(path: string, status: ^stat) -> bool {
cpath: cstring = strings.clone_to_cstring(path) cpath: cstring = strings.clone_to_cstring(path, context.temp_allocator)
defer delete(cpath)
return syscall_lstat(cpath, status) != -1 return syscall_lstat(cpath, status) != -1
} }
+4
View File
@@ -174,6 +174,10 @@ void check_init_constant(CheckerContext *ctx, Entity *e, Operand *operand) {
return; return;
} }
if (is_type_proc(e->type)) {
error(e->token, "Illegal declaration of a constant procedure value");
}
e->parent_proc_decl = ctx->curr_proc_decl; e->parent_proc_decl = ctx->curr_proc_decl;
e->Constant.value = operand->value; e->Constant.value = operand->value;
+1 -1
View File
@@ -962,7 +962,7 @@ void lb_add_debug_local_variable(lbProcedure *p, LLVMValueRef ptr, Type *type, T
LLVMMetadataRef llvm_debug_loc = lb_debug_location_from_token_pos(p, token.pos); LLVMMetadataRef llvm_debug_loc = lb_debug_location_from_token_pos(p, token.pos);
LLVMMetadataRef llvm_expr = LLVMDIBuilderCreateExpression(m->debug_builder, nullptr, 0); LLVMMetadataRef llvm_expr = LLVMDIBuilderCreateExpression(m->debug_builder, nullptr, 0);
lb_set_llvm_metadata(m, ptr, llvm_expr); lb_set_llvm_metadata(m, ptr, llvm_expr);
LLVMDIBuilderInsertDbgValueAtEnd(m->debug_builder, storage, var_info, llvm_expr, llvm_debug_loc, block); LLVMDIBuilderInsertDeclareAtEnd(m->debug_builder, storage, var_info, llvm_expr, llvm_debug_loc, block);
} }
+10 -8
View File
@@ -572,14 +572,16 @@ void usage(String argv0) {
print_usage_line(0, "Usage:"); print_usage_line(0, "Usage:");
print_usage_line(1, "%.*s command [arguments]", LIT(argv0)); print_usage_line(1, "%.*s command [arguments]", LIT(argv0));
print_usage_line(0, "Commands:"); print_usage_line(0, "Commands:");
print_usage_line(1, "build compile .odin file, or directory of .odin files, as an executable."); print_usage_line(1, "build compile .odin file, or directory of .odin files, as an executable.");
print_usage_line(1, " one must contain the program's entry point, all must be in the same package."); print_usage_line(1, " one must contain the program's entry point, all must be in the same package.");
print_usage_line(1, "run same as 'build', but also then runs the newly compiled executable."); print_usage_line(1, "run same as 'build', but also then runs the newly compiled executable.");
print_usage_line(1, "check parse and type check .odin file"); print_usage_line(1, "check parse, and type check an .odin file, or directory of .odin files");
print_usage_line(1, "query parse, type check, and output a .json file containing information about the program"); print_usage_line(1, "query parse, type check, and output a .json file containing information about the program");
print_usage_line(1, "doc generate documentation .odin file, or directory of .odin files"); print_usage_line(1, "strip-semicolon parse, type check, and remove unneeded semicolons from the entire program");
print_usage_line(1, "version print version"); print_usage_line(1, "test build ands runs procedures with the attribute @(test) in the initial package");
print_usage_line(1, "report print information useful to reporting a bug"); print_usage_line(1, "doc generate documentation .odin file, or directory of .odin files");
print_usage_line(1, "version print version");
print_usage_line(1, "report print information useful to reporting a bug");
print_usage_line(0, ""); print_usage_line(0, "");
print_usage_line(0, "For further details on a command, use -help after the command name"); print_usage_line(0, "For further details on a command, use -help after the command name");
print_usage_line(1, "e.g. odin build -help"); print_usage_line(1, "e.g. odin build -help");
+3 -2
View File
@@ -74,8 +74,9 @@ foreign stbi {
info_from_memory :: proc(buffer: [^]byte, len: c.int, x, y, comp: ^c.int) -> c.int --- info_from_memory :: proc(buffer: [^]byte, len: c.int, x, y, comp: ^c.int) -> c.int ---
info_from_callbacks :: proc(clbk: ^Io_Callbacks, user: rawptr, x, y, comp: ^c.int) -> c.int --- info_from_callbacks :: proc(clbk: ^Io_Callbacks, user: rawptr, x, y, comp: ^c.int) -> c.int ---
is_16_bit :: proc(filename: cstring) -> b32 --- is_16_bit :: proc(filename: cstring) -> b32 ---
is_16_bit_from_file :: proc(f: ^c.FILE) -> b32 --- is_16_bit_from_file :: proc(f: ^c.FILE) -> b32 ---
is_16_bit_from_memory :: proc(buffer: [^]byte, len: c.int) -> c.int ---
// for image formats that explicitly notate that they have premultiplied alpha, // for image formats that explicitly notate that they have premultiplied alpha,
// we just return the colors as stored in the file. set this flag to force // we just return the colors as stored in the file. set this flag to force