Merge remote-tracking branch 'offical/master'

This commit is contained in:
ed
2025-01-11 22:06:08 -05:00
88 changed files with 2043 additions and 546 deletions
+6
View File
@@ -208,6 +208,12 @@ jobs:
run: | run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin test tests/internal -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true odin test tests/internal -all-packages -vet -strict-style -disallow-do -define:ODIN_TEST_FANCY=false -define:ODIN_TEST_FAIL_ON_BAD_MEMORY=true
- name: Check issues
shell: cmd
run: |
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
cd tests/issues
call run.bat
- name: Check benchmarks - name: Check benchmarks
shell: cmd shell: cmd
run: | run: |
+1 -1
View File
@@ -115,7 +115,7 @@ OpenBSD)
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)" LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
;; ;;
Haiku) Haiku)
CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags) -I/system/develop/headers/private/shared -I/system/develop/headers/private/kernel" CXXFLAGS="$CXXFLAGS -D_GNU_SOURCE $($LLVM_CONFIG --cxxflags --ldflags) -I/system/develop/headers/private/shared -I/system/develop/headers/private/kernel"
LDFLAGS="$LDFLAGS -liconv" LDFLAGS="$LDFLAGS -liconv"
LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)" LDFLAGS="$LDFLAGS $($LLVM_CONFIG --libs core native --system-libs)"
;; ;;
+8 -7
View File
@@ -88,14 +88,15 @@ when ODIN_OS == .Haiku {
_get_errno :: proc() -> ^int --- _get_errno :: proc() -> ^int ---
} }
@(private="file") _HAIKU_USE_POSITIVE_POSIX_ERRORS :: #config(HAIKU_USE_POSITIVE_POSIX_ERRORS, false)
B_GENERAL_ERROR_BASE :: min(i32) _POSIX_ERROR_FACTOR :: -1 when _HAIKU_USE_POSITIVE_POSIX_ERRORS else 1
@(private="file")
B_POSIX_ERROR_BASE :: B_GENERAL_ERROR_BASE + 0x7000
EDOM :: B_POSIX_ERROR_BASE + 16 @(private="file") _GENERAL_ERROR_BASE :: min(int)
EILSEQ :: B_POSIX_ERROR_BASE + 38 @(private="file") _POSIX_ERROR_BASE :: _GENERAL_ERROR_BASE + 0x7000
ERANGE :: B_POSIX_ERROR_BASE + 17
EDOM :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 16)
EILSEQ :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 38)
ERANGE :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 17)
} }
when ODIN_OS == .JS { when ODIN_OS == .JS {
+1 -1
View File
@@ -110,7 +110,7 @@ when ODIN_OS == .Windows {
} }
} }
when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Windows { when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Haiku || ODIN_OS == .Windows {
LC_ALL :: 0 LC_ALL :: 0
LC_COLLATE :: 1 LC_COLLATE :: 1
+15
View File
@@ -42,6 +42,21 @@ when ODIN_OS == .Linux {
} }
} }
when ODIN_OS == .Haiku {
RAND_MAX :: 0x7fffffff
// GLIBC and MUSL only
@(private="file")
@(default_calling_convention="c")
foreign libc {
__ctype_get_mb_cur_max :: proc() -> ushort ---
}
MB_CUR_MAX :: #force_inline proc() -> size_t {
return size_t(__ctype_get_mb_cur_max())
}
}
when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .OpenBSD { when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .OpenBSD {
RAND_MAX :: 0x7fffffff RAND_MAX :: 0x7fffffff
+1 -1
View File
@@ -95,7 +95,7 @@ when ODIN_OS == .Linux || ODIN_OS == .FreeBSD || ODIN_OS == .Darwin || ODIN_OS =
time_t :: distinct i64 time_t :: distinct i64
when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD { when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .Haiku {
clock_t :: distinct int32_t clock_t :: distinct int32_t
} else { } else {
clock_t :: distinct long clock_t :: distinct long
+41 -9
View File
@@ -34,12 +34,18 @@ Tracking_Allocator_Bad_Free_Entry :: struct {
location: runtime.Source_Code_Location, location: runtime.Source_Code_Location,
} }
/*
Callback type for when tracking allocator runs into a bad free.
*/
Tracking_Allocator_Bad_Free_Callback :: proc(t: ^Tracking_Allocator, memory: rawptr, location: runtime.Source_Code_Location)
/* /*
Tracking allocator data. Tracking allocator data.
*/ */
Tracking_Allocator :: struct { Tracking_Allocator :: struct {
backing: Allocator, backing: Allocator,
allocation_map: map[rawptr]Tracking_Allocator_Entry, allocation_map: map[rawptr]Tracking_Allocator_Entry,
bad_free_callback: Tracking_Allocator_Bad_Free_Callback,
bad_free_array: [dynamic]Tracking_Allocator_Bad_Free_Entry, bad_free_array: [dynamic]Tracking_Allocator_Bad_Free_Entry,
mutex: sync.Mutex, mutex: sync.Mutex,
clear_on_free_all: bool, clear_on_free_all: bool,
@@ -61,6 +67,7 @@ allocate the tracked data.
tracking_allocator_init :: proc(t: ^Tracking_Allocator, backing_allocator: Allocator, internals_allocator := context.allocator) { tracking_allocator_init :: proc(t: ^Tracking_Allocator, backing_allocator: Allocator, internals_allocator := context.allocator) {
t.backing = backing_allocator t.backing = backing_allocator
t.allocation_map.allocator = internals_allocator t.allocation_map.allocator = internals_allocator
t.bad_free_callback = tracking_allocator_bad_free_callback_panic
t.bad_free_array.allocator = internals_allocator t.bad_free_array.allocator = internals_allocator
if .Free_All in query_features(t.backing) { if .Free_All in query_features(t.backing) {
t.clear_on_free_all = true t.clear_on_free_all = true
@@ -109,6 +116,33 @@ tracking_allocator_reset :: proc(t: ^Tracking_Allocator) {
sync.mutex_unlock(&t.mutex) sync.mutex_unlock(&t.mutex)
} }
/*
Default behavior for a bad free: Crash with error message that says where the
bad free happened.
Override Tracking_Allocator.bad_free_callback to have something else happen. For
example, you can use tracking_allocator_bad_free_callback_add_to_array to return
the tracking allocator to the old behavior, where the bad_free_array was used.
*/
tracking_allocator_bad_free_callback_panic :: proc(t: ^Tracking_Allocator, memory: rawptr, location: runtime.Source_Code_Location) {
runtime.print_caller_location(location)
runtime.print_string(" Tracking allocator error: Bad free of pointer ")
runtime.print_uintptr(uintptr(memory))
runtime.print_string("\n")
runtime.trap()
}
/*
Alternative behavior for a bad free: Store in `bad_free_array`. If you use this,
then you must make sure to check Tracking_Allocator.bad_free_array at some point.
*/
tracking_allocator_bad_free_callback_add_to_array :: proc(t: ^Tracking_Allocator, memory: rawptr, location: runtime.Source_Code_Location) {
append(&t.bad_free_array, Tracking_Allocator_Bad_Free_Entry {
memory = memory,
location = location,
})
}
/* /*
Tracking allocator. Tracking allocator.
@@ -116,8 +150,10 @@ The tracking allocator is an allocator wrapper that tracks memory allocations.
This allocator stores all the allocations in a map. Whenever a pointer that's This allocator stores all the allocations in a map. Whenever a pointer that's
not inside of the map is freed, the `bad_free_array` entry is added. not inside of the map is freed, the `bad_free_array` entry is added.
An example of how to use the `Tracking_Allocator` to track subsequent allocations Here follows an example of how to use the `Tracking_Allocator` to track
in your program and report leaks and bad frees: subsequent allocations in your program and report leaks. By default, the
tracking allocator will crash on bad frees. You can override that behavior by
overriding `track.bad_free_callback`.
Example: Example:
@@ -137,9 +173,6 @@ Example:
for _, leak in track.allocation_map { for _, leak in track.allocation_map {
fmt.printf("%v leaked %m\n", leak.location, leak.size) fmt.printf("%v leaked %m\n", leak.location, leak.size)
} }
for bad_free in track.bad_free_array {
fmt.printf("%v allocation %p was freed badly\n", bad_free.location, bad_free.memory)
}
} }
*/ */
@(require_results) @(require_results)
@@ -191,10 +224,9 @@ tracking_allocator_proc :: proc(
} }
if mode == .Free && old_memory != nil && old_memory not_in data.allocation_map { if mode == .Free && old_memory != nil && old_memory not_in data.allocation_map {
append(&data.bad_free_array, Tracking_Allocator_Bad_Free_Entry{ if data.bad_free_callback != nil {
memory = old_memory, data.bad_free_callback(data, old_memory, loc)
location = loc, }
})
} else { } else {
result = data.backing.procedure(data.backing.data, mode, size, alignment, old_memory, old_size, loc) or_return result = data.backing.procedure(data.backing.data, mode, size, alignment, old_memory, old_size, loc) or_return
} }
+5 -2
View File
@@ -432,10 +432,13 @@ Range_Stmt :: struct {
reverse: bool, reverse: bool,
} }
Inline_Range_Stmt :: struct { Inline_Range_Stmt :: Unroll_Range_Stmt
Unroll_Range_Stmt :: struct {
using node: Stmt, using node: Stmt,
label: ^Expr, label: ^Expr,
inline_pos: tokenizer.Pos, unroll_pos: tokenizer.Pos,
args: []^Expr,
for_pos: tokenizer.Pos, for_pos: tokenizer.Pos,
val0: ^Expr, val0: ^Expr,
val1: ^Expr, val1: ^Expr,
+2 -1
View File
@@ -242,8 +242,9 @@ clone_node :: proc(node: ^Node) -> ^Node {
r.vals = clone(r.vals) r.vals = clone(r.vals)
r.expr = clone(r.expr) r.expr = clone(r.expr)
r.body = clone(r.body) r.body = clone(r.body)
case ^Inline_Range_Stmt: case ^Unroll_Range_Stmt:
r.label = clone(r.label) r.label = clone(r.label)
r.args = clone(r.args)
r.val0 = clone(r.val0) r.val0 = clone(r.val0)
r.val1 = clone(r.val1) r.val1 = clone(r.val1)
r.expr = clone(r.expr) r.expr = clone(r.expr)
+41 -2
View File
@@ -1262,11 +1262,49 @@ parse_foreign_decl :: proc(p: ^Parser) -> ^ast.Decl {
parse_unrolled_for_loop :: proc(p: ^Parser, inline_tok: tokenizer.Token) -> ^ast.Stmt { parse_unrolled_for_loop :: proc(p: ^Parser, inline_tok: tokenizer.Token) -> ^ast.Stmt {
for_tok := expect_token(p, .For)
val0, val1: ^ast.Expr val0, val1: ^ast.Expr
in_tok: tokenizer.Token in_tok: tokenizer.Token
expr: ^ast.Expr expr: ^ast.Expr
body: ^ast.Stmt body: ^ast.Stmt
args: [dynamic]^ast.Expr
if allow_token(p, .Open_Paren) {
p.expr_level += 1
if p.curr_tok.kind == .Close_Paren {
error(p, p.curr_tok.pos, "#unroll expected at least 1 argument, got 0")
} else {
args = make([dynamic]^ast.Expr)
for p.curr_tok.kind != .Close_Paren &&
p.curr_tok.kind != .EOF {
arg := parse_value(p)
if p.curr_tok.kind == .Eq {
eq := expect_token(p, .Eq)
if arg != nil {
if _, ok := arg.derived.(^ast.Ident); !ok {
error(p, arg.pos, "expected an identifier for 'key=value'")
}
}
value := parse_value(p)
fv := ast.new(ast.Field_Value, arg.pos, value)
fv.field = arg
fv.sep = eq.pos
fv.value = value
arg = fv
}
append(&args, arg)
allow_token(p, .Comma) or_break
}
}
p.expr_level -= 1
_ = expect_token_after(p, .Close_Paren, "#unroll")
}
for_tok := expect_token(p, .For)
bad_stmt := false bad_stmt := false
@@ -1309,7 +1347,8 @@ parse_unrolled_for_loop :: proc(p: ^Parser, inline_tok: tokenizer.Token) -> ^ast
} }
range_stmt := ast.new(ast.Inline_Range_Stmt, inline_tok.pos, body) range_stmt := ast.new(ast.Inline_Range_Stmt, inline_tok.pos, body)
range_stmt.inline_pos = inline_tok.pos range_stmt.unroll_pos = inline_tok.pos
range_stmt.args = args[:]
range_stmt.for_pos = for_tok.pos range_stmt.for_pos = for_tok.pos
range_stmt.val0 = val0 range_stmt.val0 = val0
range_stmt.val1 = val1 range_stmt.val1 = val1
+1 -1
View File
@@ -1,4 +1,4 @@
#+build darwin, linux, netbsd, freebsd, openbsd #+build darwin, linux, netbsd, freebsd, openbsd, haiku
package os package os
import "core:strings" import "core:strings"
+8
View File
@@ -624,6 +624,14 @@ is_dir_path :: proc(path: string, follow_links: bool = true) -> bool {
is_file :: proc {is_file_path, is_file_handle} is_file :: proc {is_file_path, is_file_handle}
is_dir :: proc {is_dir_path, is_dir_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)
res := _unix_access(cpath, O_RDONLY)
return res == 0
}
// NOTE(bill): Uses startup to initialize it // NOTE(bill): Uses startup to initialize it
stdin: Handle = 0 stdin: Handle = 0
+25 -9
View File
@@ -1,11 +1,13 @@
package os package os
foreign import libc "system:c" foreign import lib "system:c"
import "base:runtime" import "base:runtime"
import "core:c" import "core:c"
import "core:c/libc"
import "core:strings" import "core:strings"
import "core:sys/haiku" import "core:sys/haiku"
import "core:sys/posix"
Handle :: i32 Handle :: i32
Pid :: i32 Pid :: i32
@@ -14,7 +16,7 @@ _Platform_Error :: haiku.Errno
MAX_PATH :: haiku.PATH_MAX MAX_PATH :: haiku.PATH_MAX
ENOSYS :: _Platform_Error(i32(haiku.Errno.POSIX_ERROR_BASE) + 9) ENOSYS :: _Platform_Error(haiku.Errno.ENOSYS)
INVALID_HANDLE :: ~Handle(0) INVALID_HANDLE :: ~Handle(0)
@@ -117,14 +119,13 @@ 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_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 } S_ISSOCK :: #force_inline proc(m: u32) -> bool { return (m & S_IFMT) == S_IFSOCK }
__error :: libc.errno
_unix_open :: posix.open
foreign libc { foreign lib {
@(link_name="_errorp") __error :: proc() -> ^c.int ---
@(link_name="fork") _unix_fork :: proc() -> pid_t --- @(link_name="fork") _unix_fork :: proc() -> pid_t ---
@(link_name="getthrid") _unix_getthrid :: proc() -> int --- @(link_name="getthrid") _unix_getthrid :: proc() -> int ---
@(link_name="open") _unix_open :: proc(path: cstring, flags: c.int, #c_vararg mode: ..u16) -> 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="pread") _unix_pread :: proc(fd: Handle, buf: rawptr, size: c.size_t, offset: i64) -> c.ssize_t --- @(link_name="pread") _unix_pread :: proc(fd: Handle, buf: rawptr, size: c.size_t, offset: i64) -> c.ssize_t ---
@@ -150,6 +151,7 @@ foreign libc {
@(link_name="closedir") _unix_closedir :: proc(dirp: Dir) -> c.int --- @(link_name="closedir") _unix_closedir :: proc(dirp: Dir) -> c.int ---
@(link_name="rewinddir") _unix_rewinddir :: proc(dirp: Dir) --- @(link_name="rewinddir") _unix_rewinddir :: proc(dirp: Dir) ---
@(link_name="readdir_r") _unix_readdir_r :: proc(dirp: Dir, entry: ^Dirent, result: ^^Dirent) -> c.int --- @(link_name="readdir_r") _unix_readdir_r :: proc(dirp: Dir, entry: ^Dirent, result: ^^Dirent) -> c.int ---
@(link_name="dup") _unix_dup :: proc(fd: Handle) -> Handle ---
@(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 ---
@@ -157,7 +159,7 @@ foreign libc {
@(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="realpath") _unix_realpath :: proc(path: cstring, resolved_path: rawptr) -> rawptr --- @(link_name="realpath") _unix_realpath :: proc(path: cstring, resolved_path: [^]byte = nil) -> cstring ---
@(link_name="exit") _unix_exit :: proc(status: c.int) -> ! --- @(link_name="exit") _unix_exit :: proc(status: c.int) -> ! ---
@@ -203,7 +205,7 @@ fork :: proc() -> (Pid, Error) {
open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Error) { open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Error) {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
cstr := strings.clone_to_cstring(path, context.temp_allocator) cstr := strings.clone_to_cstring(path, context.temp_allocator)
handle := _unix_open(cstr, c.int(flags), u16(mode)) handle := cast(Handle)_unix_open(cstr, transmute(posix.O_Flags)i32(flags), transmute(posix.mode_t)i32(mode))
if handle == -1 { if handle == -1 {
return INVALID_HANDLE, get_last_error() return INVALID_HANDLE, get_last_error()
} }
@@ -444,7 +446,7 @@ absolute_path_from_relative :: proc(rel: string, allocator := context.allocator)
if path_ptr == nil { if path_ptr == nil {
return "", get_last_error() return "", get_last_error()
} }
defer _unix_free(path_ptr) defer _unix_free(rawptr(path_ptr))
path_cstr := cstring(path_ptr) path_cstr := cstring(path_ptr)
return strings.clone(string(path_cstr), allocator) return strings.clone(string(path_cstr), allocator)
@@ -488,3 +490,17 @@ exit :: proc "contextless" (code: int) -> ! {
runtime._cleanup_runtime_contextless() runtime._cleanup_runtime_contextless()
_unix_exit(i32(code)) _unix_exit(i32(code))
} }
@(require_results)
current_thread_id :: proc "contextless" () -> int {
return int(haiku.find_thread(nil))
}
@(private, require_results)
_dup :: proc(fd: Handle) -> (Handle, Error) {
dup := _unix_dup(fd)
if dup == -1 {
return INVALID_HANDLE, get_last_error()
}
return dup, nil
}
+1 -1
View File
@@ -53,7 +53,7 @@ File_Info :: struct {
@(private, require_results) @(private, require_results)
_make_time_from_unix_file_time :: proc(uft: Unix_File_Time) -> time.Time { _make_time_from_unix_file_time :: proc(uft: Unix_File_Time) -> time.Time {
return time.Time{ return time.Time{
_nsec = uft.nanoseconds + uft.seconds * 1_000_000_000, _nsec = i64(uft.nanoseconds) + i64(uft.seconds) * 1_000_000_000,
} }
} }
+1 -1
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, freebsd, openbsd, netbsd #+build linux, darwin, freebsd, openbsd, netbsd, haiku
package filepath package filepath
import "base:runtime" import "base:runtime"
+11 -5
View File
@@ -89,6 +89,7 @@ intern_get_cstring :: proc(m: ^Intern, text: string) -> (str: cstring, err: runt
entry := _intern_get_entry(m, text) or_return entry := _intern_get_entry(m, text) or_return
return cstring(&entry.str[0]), nil return cstring(&entry.str[0]), nil
} }
/* /*
Internal function to lookup whether the text string exists in the map, returns the entry Internal function to lookup whether the text string exists in the map, returns the entry
Sets and allocates the entry if it wasn't set yet Sets and allocates the entry if it wasn't set yet
@@ -104,13 +105,15 @@ Returns:
- err: An allocator error if one occured, `nil` otherwise - err: An allocator error if one occured, `nil` otherwise
*/ */
_intern_get_entry :: proc(m: ^Intern, text: string) -> (new_entry: ^Intern_Entry, err: runtime.Allocator_Error) #no_bounds_check { _intern_get_entry :: proc(m: ^Intern, text: string) -> (new_entry: ^Intern_Entry, err: runtime.Allocator_Error) #no_bounds_check {
if prev, ok := m.entries[text]; ok {
return prev, nil
}
if m.allocator.procedure == nil { if m.allocator.procedure == nil {
m.allocator = context.allocator m.allocator = context.allocator
} }
key_ptr, val_ptr, inserted := map_entry(&m.entries, text) or_return
if !inserted {
return val_ptr^, nil
}
entry_size := int(offset_of(Intern_Entry, str)) + len(text) + 1 entry_size := int(offset_of(Intern_Entry, str)) + len(text) + 1
bytes := runtime.mem_alloc(entry_size, align_of(Intern_Entry), m.allocator) or_return bytes := runtime.mem_alloc(entry_size, align_of(Intern_Entry), m.allocator) or_return
new_entry = (^Intern_Entry)(raw_data(bytes)) new_entry = (^Intern_Entry)(raw_data(bytes))
@@ -120,6 +123,9 @@ _intern_get_entry :: proc(m: ^Intern, text: string) -> (new_entry: ^Intern_Entry
new_entry.str[new_entry.len] = 0 new_entry.str[new_entry.len] = 0
key := string(new_entry.str[:new_entry.len]) key := string(new_entry.str[:new_entry.len])
m.entries[key] = new_entry
return new_entry, nil key_ptr^ = key
val_ptr^ = new_entry
return
} }
+24 -26
View File
@@ -1,14 +1,13 @@
#+private #+private
package sync package sync
import "core:c"
import "core:sys/haiku" import "core:sys/haiku"
import "core:sys/unix" import "core:sys/posix"
import "core:time" import "core:time"
@(private="file") @(private="file")
Wait_Node :: struct { Wait_Node :: struct {
thread: unix.pthread_t, thread: posix.pthread_t,
futex: ^Futex, futex: ^Futex,
prev, next: ^Wait_Node, prev, next: ^Wait_Node,
} }
@@ -58,7 +57,7 @@ _futex_wait :: proc "contextless" (f: ^Futex, expect: u32) -> (ok: bool) {
head := &waitq.list head := &waitq.list
waiter := Wait_Node{ waiter := Wait_Node{
thread = unix.pthread_self(), thread = posix.pthread_self(),
futex = f, futex = f,
prev = head, prev = head,
next = head.next, next = head.next,
@@ -67,25 +66,24 @@ _futex_wait :: proc "contextless" (f: ^Futex, expect: u32) -> (ok: bool) {
waiter.prev.next = &waiter waiter.prev.next = &waiter
waiter.next.prev = &waiter waiter.next.prev = &waiter
old_mask, mask: haiku.sigset_t old_mask, mask: posix.sigset_t
haiku.sigemptyset(&mask) posix.sigemptyset(&mask)
haiku.sigaddset(&mask, haiku.SIGCONT) posix.sigaddset(&mask, .SIGCONT)
unix.pthread_sigmask(haiku.SIG_BLOCK, &mask, &old_mask) posix.pthread_sigmask(.BLOCK, &mask, &old_mask)
if u32(atomic_load_explicit(f, .Acquire)) == expect { if u32(atomic_load_explicit(f, .Acquire)) == expect {
waitq_unlock(waitq) waitq_unlock(waitq)
defer waitq_lock(waitq) defer waitq_lock(waitq)
sig: c.int sig: posix.Signal
haiku.sigwait(&mask, &sig) errno := posix.sigwait(&mask, &sig)
errno := haiku.errno() ok = errno == nil
ok = errno == .OK
} }
waiter.prev.next = waiter.next waiter.prev.next = waiter.next
waiter.next.prev = waiter.prev waiter.next.prev = waiter.prev
_ = unix.pthread_sigmask(haiku.SIG_SETMASK, &old_mask, nil) _ = posix.pthread_sigmask(.SETMASK, &old_mask, nil)
// FIXME: Add error handling! // FIXME: Add error handling!
return return
@@ -101,7 +99,7 @@ _futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expect: u32, duration
head := &waitq.list head := &waitq.list
waiter := Wait_Node{ waiter := Wait_Node{
thread = unix.pthread_self(), thread = posix.pthread_self(),
futex = f, futex = f,
prev = head, prev = head,
next = head.next, next = head.next,
@@ -110,29 +108,29 @@ _futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expect: u32, duration
waiter.prev.next = &waiter waiter.prev.next = &waiter
waiter.next.prev = &waiter waiter.next.prev = &waiter
old_mask, mask: haiku.sigset_t old_mask, mask: posix.sigset_t
haiku.sigemptyset(&mask) posix.sigemptyset(&mask)
haiku.sigaddset(&mask, haiku.SIGCONT) posix.sigaddset(&mask, .SIGCONT)
unix.pthread_sigmask(haiku.SIG_BLOCK, &mask, &old_mask) posix.pthread_sigmask(.BLOCK, &mask, &old_mask)
if u32(atomic_load_explicit(f, .Acquire)) == expect { if u32(atomic_load_explicit(f, .Acquire)) == expect {
waitq_unlock(waitq) waitq_unlock(waitq)
defer waitq_lock(waitq) defer waitq_lock(waitq)
info: haiku.siginfo_t info: posix.siginfo_t
ts := unix.timespec{ ts := posix.timespec{
tv_sec = i64(duration / 1e9), tv_sec = posix.time_t(i64(duration / 1e9)),
tv_nsec = i64(duration % 1e9), tv_nsec = i64(duration % 1e9),
} }
haiku.sigtimedwait(&mask, &info, &ts) haiku.sigtimedwait(&mask, &info, &ts)
errno := haiku.errno() errno := posix.errno()
ok = errno == .EAGAIN || errno == .OK ok = errno == .EAGAIN || errno == nil
} }
waiter.prev.next = waiter.next waiter.prev.next = waiter.next
waiter.next.prev = waiter.prev waiter.next.prev = waiter.prev
unix.pthread_sigmask(haiku.SIG_SETMASK, &old_mask, nil) posix.pthread_sigmask(.SETMASK, &old_mask, nil)
// FIXME: Add error handling! // FIXME: Add error handling!
return return
@@ -146,7 +144,7 @@ _futex_signal :: proc "contextless" (f: ^Futex) {
head := &waitq.list head := &waitq.list
for waiter := head.next; waiter != head; waiter = waiter.next { for waiter := head.next; waiter != head; waiter = waiter.next {
if waiter.futex == f { if waiter.futex == f {
unix.pthread_kill(waiter.thread, haiku.SIGCONT) posix.pthread_kill(waiter.thread, .SIGCONT)
break break
} }
} }
@@ -160,7 +158,7 @@ _futex_broadcast :: proc "contextless" (f: ^Futex) {
head := &waitq.list head := &waitq.list
for waiter := head.next; waiter != head; waiter = waiter.next { for waiter := head.next; waiter != head; waiter = waiter.next {
if waiter.futex == f { if waiter.futex == f {
unix.pthread_kill(waiter.thread, haiku.SIGCONT) posix.pthread_kill(waiter.thread, .SIGCONT)
} }
} }
} }
@@ -1,26 +1,31 @@
#+build haiku #+build haiku
package sys_haiku package sys_haiku
import "core:c" import "core:sys/posix"
Errno :: enum c.int { foreign import libroot "system:c"
// Error baselines
GENERAL_ERROR_BASE = min(c.int),
OS_ERROR_BASE = GENERAL_ERROR_BASE + 0x1000,
APP_ERROR_BASE = GENERAL_ERROR_BASE + 0x2000,
INTERFACE_ERROR_BASE = GENERAL_ERROR_BASE + 0x3000,
MEDIA_ERROR_BASE = GENERAL_ERROR_BASE + 0x4000,
TRANSLATION_ERROR_BASE = GENERAL_ERROR_BASE + 0x4800,
MIDI_ERROR_BASE = GENERAL_ERROR_BASE + 0x5000,
STORAGE_ERROR_BASE = GENERAL_ERROR_BASE + 0x6000,
POSIX_ERROR_BASE = GENERAL_ERROR_BASE + 0x7000,
MAIL_ERROR_BASE = GENERAL_ERROR_BASE + 0x8000,
PRINT_ERROR_BASE = GENERAL_ERROR_BASE + 0x9000,
DEVICE_ERROR_BASE = GENERAL_ERROR_BASE + 0xa000,
// Developer-defined errors start at (ERRORS_END+1) USE_POSITIVE_POSIX_ERRORS :: posix._HAIKU_USE_POSITIVE_POSIX_ERRORS
ERRORS_END = GENERAL_ERROR_BASE + 0xffff, POSIX_ERROR_FACTOR :: posix._POSIX_ERROR_FACTOR
// Error baselines
GENERAL_ERROR_BASE :: min(i32)
OS_ERROR_BASE :: GENERAL_ERROR_BASE + 0x1000
APP_ERROR_BASE :: GENERAL_ERROR_BASE + 0x2000
INTERFACE_ERROR_BASE :: GENERAL_ERROR_BASE + 0x3000
MEDIA_ERROR_BASE :: GENERAL_ERROR_BASE + 0x4000
TRANSLATION_ERROR_BASE :: GENERAL_ERROR_BASE + 0x4800
MIDI_ERROR_BASE :: GENERAL_ERROR_BASE + 0x5000
STORAGE_ERROR_BASE :: GENERAL_ERROR_BASE + 0x6000
POSIX_ERROR_BASE :: GENERAL_ERROR_BASE + 0x7000
MAIL_ERROR_BASE :: GENERAL_ERROR_BASE + 0x8000
PRINT_ERROR_BASE :: GENERAL_ERROR_BASE + 0x9000
DEVICE_ERROR_BASE :: GENERAL_ERROR_BASE + 0xA000
// Developer-defined errors start at (ERRORS_END+1)
ERRORS_END :: GENERAL_ERROR_BASE + 0xFFFF
Errno :: enum i32 {
// General Errors // General Errors
NO_MEMORY = GENERAL_ERROR_BASE + 0, NO_MEMORY = GENERAL_ERROR_BASE + 0,
IO_ERROR = GENERAL_ERROR_BASE + 1, IO_ERROR = GENERAL_ERROR_BASE + 1,
@@ -107,31 +112,95 @@ Errno :: enum c.int {
PARTIAL_READ = STORAGE_ERROR_BASE + 16, PARTIAL_READ = STORAGE_ERROR_BASE + 16,
PARTIAL_WRITE = STORAGE_ERROR_BASE + 17, PARTIAL_WRITE = STORAGE_ERROR_BASE + 17,
// Some POSIX errors EIO = posix.EIO,
E2BIG = POSIX_ERROR_BASE + 1, EACCES = posix.EACCES,
EFBIG = POSIX_ERROR_BASE + 4, EINVAL = posix.EINVAL,
ENODEV = POSIX_ERROR_BASE + 7, ETIMEDOUT = posix.ETIMEDOUT,
ERANGE = POSIX_ERROR_BASE + 17, EINTR = posix.EINTR,
EOVERFLOW = POSIX_ERROR_BASE + 41, EAGAIN = posix.EAGAIN,
EOPNOTSUPP = POSIX_ERROR_BASE + 43, EWOULDBLOCK = posix.EWOULDBLOCK,
EBUSY = posix.EBUSY,
ENOSYS = POSIX_ERROR_BASE + 9, EPERM = posix.EPERM,
EAGAIN = WOULD_BLOCK, EFAULT = posix.EFAULT,
ENOEXEC = posix.ENOEXEC,
EBADF = posix.EBADF,
EEXIST = posix.EEXIST,
ENOENT = posix.ENOENT,
ENAMETOOLONG = posix.ENAMETOOLONG,
ENOTDIR = posix.ENOTDIR,
ENOTEMPTY = posix.ENOTEMPTY,
ENOSPC = posix.ENOSPC,
EROFS = posix.EROFS,
EISDIR = posix.EISDIR,
EMFILE = posix.EMFILE,
EXDEV = posix.EXDEV,
ELOOP = posix.ELOOP,
EPIPE = posix.EPIPE,
ENOMEM = posix.ENOMEM,
E2BIG = posix.E2BIG,
ECHILD = posix.ECHILD,
EDEADLK = posix.EDEADLK,
EFBIG = posix.EFBIG,
EMLINK = posix.EMLINK,
ENFILE = posix.ENFILE,
ENODEV = posix.ENODEV,
ENOLCK = posix.ENOLCK,
ENOSYS = posix.ENOSYS,
ENOTTY = posix.ENOTTY,
ENXIO = posix.ENXIO,
ESPIPE = posix.ESPIPE,
ESRCH = posix.ESRCH,
EDOM = posix.EDOM,
ERANGE = posix.ERANGE,
EPROTOTYPE = posix.EPROTOTYPE,
EPROTONOSUPPORT = posix.EPROTONOSUPPORT,
EAFNOSUPPORT = posix.EAFNOSUPPORT,
EADDRINUSE = posix.EADDRINUSE,
EADDRNOTAVAIL = posix.EADDRNOTAVAIL,
ENETDOWN = posix.ENETDOWN,
ENETUNREACH = posix.ENETUNREACH,
ENETRESET = posix.ENETRESET,
ECONNABORTED = posix.ECONNABORTED,
ECONNRESET = posix.ECONNRESET,
EISCONN = posix.EISCONN,
ENOTCONN = posix.ENOTCONN,
ECONNREFUSED = posix.ECONNREFUSED,
EHOSTUNREACH = posix.EHOSTUNREACH,
ENOPROTOOPT = posix.ENOPROTOOPT,
ENOBUFS = posix.ENOBUFS,
EINPROGRESS = posix.EINPROGRESS,
EALREADY = posix.EALREADY,
EILSEQ = posix.EILSEQ,
ENOMSG = posix.ENOMSG,
ESTALE = posix.ESTALE,
EOVERFLOW = posix.EOVERFLOW,
EMSGSIZE = posix.EMSGSIZE,
EOPNOTSUPP = posix.EOPNOTSUPP,
ENOTSOCK = posix.ENOTSOCK,
EBADMSG = posix.EBADMSG,
ECANCELED = posix.ECANCELED,
EDESTADDRREQ = posix.EDESTADDRREQ,
EDQUOT = posix.EDQUOT,
EIDRM = posix.EIDRM,
EMULTIHOP = posix.EMULTIHOP,
ENODATA = posix.ENODATA,
ENOLINK = posix.ENOLINK,
ENOSR = posix.ENOSR,
ENOSTR = posix.ENOSTR,
ENOTSUP = posix.ENOTSUP,
EPROTO = posix.EPROTO,
ETIME = posix.ETIME,
ETXTBSY = posix.ETXTBSY,
ENOTRECOVERABLE = posix.ENOTRECOVERABLE,
EOWNERDEAD = posix.EOWNERDEAD,
// New error codes that can be mapped to POSIX errors // New error codes that can be mapped to POSIX errors
TOO_MANY_ARGS_NEG = E2BIG, TOO_MANY_ARGS = POSIX_ERROR_FACTOR * E2BIG,
FILE_TOO_LARGE_NEG = EFBIG, FILE_TOO_LARGE = POSIX_ERROR_FACTOR * EFBIG,
DEVICE_NOT_FOUND_NEG = ENODEV, DEVICE_NOT_FOUND = POSIX_ERROR_FACTOR * ENODEV,
RESULT_NOT_REPRESENTABLE_NEG = ERANGE, RESULT_NOT_REPRESENTABLE = POSIX_ERROR_FACTOR * ERANGE,
BUFFER_OVERFLOW_NEG = EOVERFLOW, BUFFER_OVERFLOW = POSIX_ERROR_FACTOR * EOVERFLOW,
NOT_SUPPORTED_NEG = EOPNOTSUPP, NOT_SUPPORTED = POSIX_ERROR_FACTOR * EOPNOTSUPP,
TOO_MANY_ARGS_POS = -E2BIG,
FILE_TOO_LARGE_POS = -EFBIG,
DEVICE_NOT_FOUND_POS = -ENODEV,
RESULT_NOT_REPRESENTABLE_POS = -ERANGE,
BUFFER_OVERFLOW_POS = -EOVERFLOW,
NOT_SUPPORTED_POS = -EOPNOTSUPP,
// Media Kit Errors // Media Kit Errors
STREAM_NOT_FOUND = MEDIA_ERROR_BASE + 0, STREAM_NOT_FOUND = MEDIA_ERROR_BASE + 0,
@@ -226,14 +295,8 @@ Errno :: enum c.int {
ILLEGAL_DATA = TRANSLATION_ERROR_BASE + 2, ILLEGAL_DATA = TRANSLATION_ERROR_BASE + 2,
} }
errno :: #force_inline proc "contextless" () -> Errno { @(default_calling_convention="c")
return Errno(_errnop()^)
}
foreign import libroot "system:c"
foreign libroot { foreign libroot {
_to_positive_error :: proc(error: c.int) -> c.int --- _to_positive_error :: proc(error: i32) -> i32 ---
_to_negative_error :: proc(error: c.int) -> c.int --- _to_negative_error :: proc(error: i32) -> i32 ---
_errnop :: proc() -> ^c.int ---
} }
+23 -20
View File
@@ -1,9 +1,11 @@
#+build haiku #+build haiku
package sys_haiku package sys_haiku
import "core:c" import "base:intrinsics"
directory_which :: enum c.int { foreign import libroot "system:c"
directory_which :: enum i32 {
// Per volume directories // Per volume directories
DESKTOP_DIRECTORY = 0, DESKTOP_DIRECTORY = 0,
TRASH_DIRECTORY, TRASH_DIRECTORY,
@@ -110,17 +112,18 @@ directory_which :: enum c.int {
BEOS_SOUNDS_DIRECTORY, BEOS_SOUNDS_DIRECTORY,
} }
find_path_flags :: enum c.int { find_path_flag :: enum u32 {
CREATE_DIRECTORY = 0x0001, CREATE_DIRECTORY = intrinsics.constant_log2(0x0001),
CREATE_PARENT_DIRECTORY = 0x0002, CREATE_PARENT_DIRECTORY = intrinsics.constant_log2(0x0002),
EXISTING_ONLY = 0x0004, EXISTING_ONLY = intrinsics.constant_log2(0x0004),
// find_paths() only! // find_paths() only
SYSTEM_ONLY = 0x0010, SYSTEM_ONLY = intrinsics.constant_log2(0x0010),
USER_ONLY = 0x0020, USER_ONLY = intrinsics.constant_log2(0x0020),
} }
find_path_flags :: distinct bit_set[find_path_flag; u32]
path_base_directory :: enum c.int { path_base_directory :: enum i32 {
INSTALLATION_LOCATION_DIRECTORY, INSTALLATION_LOCATION_DIRECTORY,
ADD_ONS_DIRECTORY, ADD_ONS_DIRECTORY,
APPS_DIRECTORY, APPS_DIRECTORY,
@@ -146,7 +149,7 @@ path_base_directory :: enum c.int {
TRANSLATORS_DIRECTORY, TRANSLATORS_DIRECTORY,
VAR_DIRECTORY, VAR_DIRECTORY,
// find_path() only! // find_path() only
IMAGE_PATH = 1000, IMAGE_PATH = 1000,
PACKAGE_PATH, PACKAGE_PATH,
} }
@@ -154,15 +157,15 @@ path_base_directory :: enum c.int {
// value that can be used instead of a pointer to a symbol in the program image // value that can be used instead of a pointer to a symbol in the program image
APP_IMAGE_SYMBOL :: rawptr(addr_t(0)) APP_IMAGE_SYMBOL :: rawptr(addr_t(0))
// pointer to a symbol in the callers image (same as B_CURRENT_IMAGE_SYMBOL) // pointer to a symbol in the callers image (same as B_CURRENT_IMAGE_SYMBOL)
current_image_symbol :: proc() -> rawptr { return rawptr(current_image_symbol) } current_image_symbol :: proc "contextless" () -> rawptr { return rawptr(current_image_symbol) }
foreign import libroot "system:c" @(default_calling_convention="c")
foreign libroot { foreign libroot {
find_directory :: proc(which: directory_which, volume: dev_t, createIt: bool, pathString: [^]c.char, length: i32) -> status_t --- find_directory :: proc(which: directory_which, volume: dev_t, createIt: bool, pathString: [^]byte, length: i32) -> status_t ---
find_path :: proc(codePointer: rawptr, baseDirectory: path_base_directory, subPath: cstring, pathBuffer: [^]c.char, bufferSize: c.size_t) -> status_t --- find_path :: proc(codePointer: rawptr, baseDirectory: path_base_directory, subPath: cstring, pathBuffer: [^]byte, bufferSize: uint) -> status_t ---
find_path_etc :: proc(codePointer: rawptr, dependency: cstring, architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, pathBuffer: [^]c.char, bufferSize: c.size_t) -> status_t --- find_path_etc :: proc(codePointer: rawptr, dependency: cstring, architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, pathBuffer: [^]byte, bufferSize: uint) -> status_t ---
find_path_for_path :: proc(path: cstring, baseDirectory: path_base_directory, subPath: cstring, pathBuffer: [^]c.char, bufferSize: c.size_t) -> status_t --- find_path_for_path :: proc(path: cstring, baseDirectory: path_base_directory, subPath: cstring, pathBuffer: [^]byte, bufferSize: uint) -> status_t ---
find_path_for_path_etc :: proc(path: cstring, dependency: cstring, architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, pathBuffer: [^]c.char, bufferSize: c.size_t) -> status_t --- find_path_for_path_etc :: proc(path: cstring, dependency: cstring, architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, pathBuffer: [^]byte, bufferSize: uint) -> status_t ---
find_paths :: proc(baseDirectory: path_base_directory, subPath: cstring, _paths: ^[^][^]c.char, _pathCount: ^c.size_t) -> status_t --- find_paths :: proc(baseDirectory: path_base_directory, subPath: cstring, _paths: ^[^][^]byte, _pathCount: ^uint) -> status_t ---
find_paths_etc :: proc(architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, _paths: ^[^][^]c.char, _pathCount: ^c.size_t) -> status_t --- find_paths_etc :: proc(architecture: cstring, baseDirectory: path_base_directory, subPath: cstring, flags: find_path_flags, _paths: ^[^][^]byte, _pathCount: ^uint) -> status_t ---
} }
+141 -145
View File
@@ -1,8 +1,8 @@
#+build haiku #+build haiku
package sys_haiku package sys_haiku
import "core:c" import "base:intrinsics"
import "core:sys/unix" import "core:sys/posix"
foreign import libroot "system:c" foreign import libroot "system:c"
@@ -18,8 +18,8 @@ OS_NAME_LENGTH :: 32
area_info :: struct { area_info :: struct {
area: area_id, area: area_id,
name: [OS_NAME_LENGTH]c.char, name: [OS_NAME_LENGTH]byte,
size: c.size_t, size: uint,
lock: u32, lock: u32,
protection: u32, protection: u32,
team: team_id, team: team_id,
@@ -31,11 +31,11 @@ area_info :: struct {
} }
area_locking :: enum u32 { area_locking :: enum u32 {
NO_LOCK = 0, NO_LOCK = 0,
LAZY_LOCK = 1, LAZY_LOCK = 1,
FULL_LOCK = 2, FULL_LOCK = 2,
CONTIGUOUS = 3, CONTIGUOUS = 3,
LOMEM = 4, // CONTIGUOUS, < 16 MB physical address LOMEM = 4, // CONTIGUOUS, < 16 MB physical address
_32_BIT_FULL_LOCK = 5, // FULL_LOCK, < 4 GB physical addresses _32_BIT_FULL_LOCK = 5, // FULL_LOCK, < 4 GB physical addresses
_32_BIT_CONTIGUOUS = 6, // CONTIGUOUS, < 4 GB physical address _32_BIT_CONTIGUOUS = 6, // CONTIGUOUS, < 4 GB physical address
} }
@@ -52,27 +52,29 @@ address_spec :: enum u32 {
RANDOMIZED_BASE_ADDRESS = 7, RANDOMIZED_BASE_ADDRESS = 7,
} }
area_protection_flags :: enum u32 { area_protection_flag :: enum u32 {
READ_AREA = 1 << 0, READ_AREA = 0,
WRITE_AREA = 1 << 1, WRITE_AREA = 1,
EXECUTE_AREA = 1 << 2, EXECUTE_AREA = 2,
// "stack" protection is not available on most platforms - it's used // "stack" protection is not available on most platforms - it's used
// to only commit memory as needed, and have guard pages at the // to only commit memory as needed, and have guard pages at the
// bottom of the stack. // bottom of the stack.
STACK_AREA = 1 << 3, STACK_AREA = 3,
CLONEABLE_AREA = 1 << 8, CLONEABLE_AREA = 8,
} }
area_protection_flags :: distinct bit_set[area_protection_flag; u32]
@(default_calling_convention="c")
foreign libroot { foreign libroot {
create_area :: proc(name: cstring, startAddress: ^rawptr, addressSpec: address_spec, size: c.size_t, lock: area_locking, protection: area_protection_flags) -> area_id --- create_area :: proc(name: cstring, startAddress: ^rawptr, addressSpec: address_spec, size: uint, lock: area_locking, protection: area_protection_flags) -> area_id ---
clone_area :: proc(name: cstring, destAddress: ^rawptr, addressSpec: address_spec, protection: area_protection_flags, source: area_id) -> area_id --- clone_area :: proc(name: cstring, destAddress: ^rawptr, addressSpec: address_spec, protection: area_protection_flags, source: area_id) -> area_id ---
find_area :: proc(name: cstring) -> area_id --- find_area :: proc(name: cstring) -> area_id ---
area_for :: proc(address: rawptr) -> area_id --- area_for :: proc(address: rawptr) -> area_id ---
delete_area :: proc(id: area_id) -> status_t --- delete_area :: proc(id: area_id) -> status_t ---
resize_area :: proc(id: area_id, newSize: c.size_t) -> status_t --- resize_area :: proc(id: area_id, newSize: uint) -> status_t ---
set_area_protection :: proc(id: area_id, newProtection: area_protection_flags) -> status_t --- set_area_protection :: proc(id: area_id, newProtection: area_protection_flags) -> status_t ---
_get_area_info :: proc(id: area_id, areaInfo: ^area_info, size: c.size_t) -> status_t --- _get_area_info :: proc(id: area_id, areaInfo: ^area_info, size: uint) -> status_t ---
_get_next_area_info :: proc(team: team_id, cookie: ^c.ssize_t, areaInfo: ^area_info, size: c.size_t) -> status_t --- _get_next_area_info :: proc(team: team_id, cookie: ^int, areaInfo: ^area_info, size: uint) -> status_t ---
} }
// Ports // Ports
@@ -80,33 +82,35 @@ foreign libroot {
port_info :: struct { port_info :: struct {
port: port_id, port: port_id,
team: team_id, team: team_id,
name: [OS_NAME_LENGTH]c.char, name: [OS_NAME_LENGTH]byte,
capacity: i32, // queue depth capacity: i32, // queue depth
queue_count: i32, // # msgs waiting to be read queue_count: i32, // # msgs waiting to be read
total_count: i32, // total # msgs read so far total_count: i32, // total # msgs read so far
} }
port_flags :: enum u32 { port_flag :: enum u32 {
USE_USER_MEMCPY = 0x80000000, USE_USER_MEMCPY = intrinsics.constant_log2(0x80000000),
// read the message, but don't remove it; kernel-only; memory must be locked // read the message, but don't remove it; kernel-only; memory must be locked
PEEK_PORT_MESSAGE = 0x100, PEEK_PORT_MESSAGE = intrinsics.constant_log2(0x100),
} }
port_flags :: distinct bit_set[port_flag; u32]
@(default_calling_convention="c")
foreign libroot { foreign libroot {
create_port :: proc(capacity: i32, name: cstring) -> port_id --- create_port :: proc(capacity: i32, name: cstring) -> port_id ---
find_port :: proc(name: cstring) -> port_id --- find_port :: proc(name: cstring) -> port_id ---
read_port :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: c.size_t) -> c.ssize_t --- read_port :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: uint) -> int ---
read_port_etc :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: c.size_t, flags: port_flags, timeout: bigtime_t) -> c.ssize_t --- read_port_etc :: proc(port: port_id, code: ^i32, buffer: rawptr, bufferSize: uint, flags: port_flags, timeout: bigtime_t) -> int ---
write_port :: proc(port: port_id, code: i32, buffer: rawptr, bufferSize: c.size_t) -> status_t --- write_port :: proc(port: port_id, code: i32, buffer: rawptr, bufferSize: uint) -> status_t ---
write_port_etc :: proc(port: port_id, code: i32, buffer: rawptr, bufferSize: c.size_t, flags: port_flags, timeout: bigtime_t) -> status_t --- write_port_etc :: proc(port: port_id, code: i32, buffer: rawptr, bufferSize: uint, flags: port_flags, timeout: bigtime_t) -> status_t ---
close_port :: proc(port: port_id) -> status_t --- close_port :: proc(port: port_id) -> status_t ---
delete_port :: proc(port: port_id) -> status_t --- delete_port :: proc(port: port_id) -> status_t ---
port_buffer_size :: proc(port: port_id) -> c.ssize_t --- port_buffer_size :: proc(port: port_id) -> int ---
port_buffer_size_etc :: proc(port: port_id, flags: port_flags, timeout: bigtime_t) -> c.ssize_t --- port_buffer_size_etc :: proc(port: port_id, flags: port_flags, timeout: bigtime_t) -> int ---
port_count :: proc(port: port_id) -> c.ssize_t --- port_count :: proc(port: port_id) -> int ---
set_port_owner :: proc(port: port_id, team: team_id) -> status_t --- set_port_owner :: proc(port: port_id, team: team_id) -> status_t ---
_get_port_info :: proc(port: port_id, portInfo: ^port_info, portInfoSize: c.size_t) -> status_t --- _get_port_info :: proc(port: port_id, portInfo: ^port_info, portInfoSize: uint) -> status_t ---
_get_next_port_info :: proc(team: team_id, cookie: ^i32, portInfo: ^port_info, portInfoSize: c.size_t) -> status_t --- _get_next_port_info :: proc(team: team_id, cookie: ^i32, portInfo: ^port_info, portInfoSize: uint) -> status_t ---
} }
// Semaphores // Semaphores
@@ -114,22 +118,24 @@ foreign libroot {
sem_info :: struct { sem_info :: struct {
sem: sem_id, sem: sem_id,
team: team_id, team: team_id,
name: [OS_NAME_LENGTH]c.char, name: [OS_NAME_LENGTH]byte,
count: i32, count: i32,
latest_holder: thread_id, latest_holder: thread_id,
} }
semaphore_flags :: enum u32 { semaphore_flag :: enum u32 {
CAN_INTERRUPT = 0x01, // acquisition of the semaphore can be interrupted (system use only) CAN_INTERRUPT = intrinsics.constant_log2(0x01), // acquisition of the semaphore can be interrupted (system use only)
CHECK_PERMISSION = 0x04, // ownership will be checked (system use only) CHECK_PERMISSION = intrinsics.constant_log2(0x04), // ownership will be checked (system use only)
KILL_CAN_INTERRUPT = 0x20, // acquisition of the semaphore can be interrupted by SIGKILL[THR], even if not CAN_INTERRUPT (system use only) KILL_CAN_INTERRUPT = intrinsics.constant_log2(0x20), // acquisition of the semaphore can be interrupted by SIGKILL[THR], even if not CAN_INTERRUPT (system use only)
// release_sem_etc() only flags // release_sem_etc() only flags
DO_NOT_RESCHEDULE = 0x02, // thread is not rescheduled DO_NOT_RESCHEDULE = intrinsics.constant_log2(0x02), // thread is not rescheduled
RELEASE_ALL = 0x08, // all waiting threads will be woken up, count will be zeroed RELEASE_ALL = intrinsics.constant_log2(0x08), // all waiting threads will be woken up, count will be zeroed
RELEASE_IF_WAITING_ONLY = 0x10, // release count only if there are any threads waiting RELEASE_IF_WAITING_ONLY = intrinsics.constant_log2(0x10), // release count only if there are any threads waiting
} }
semaphore_flags :: distinct bit_set[semaphore_flag; u32]
@(default_calling_convention="c")
foreign libroot { foreign libroot {
create_sem :: proc(count: i32, name: cstring) -> sem_id --- create_sem :: proc(count: i32, name: cstring) -> sem_id ---
delete_sem :: proc(id: sem_id) -> status_t --- delete_sem :: proc(id: sem_id) -> status_t ---
@@ -141,8 +147,8 @@ foreign libroot {
switch_sem_etc :: proc(semToBeReleased: sem_id, id: sem_id, count: i32, flags: semaphore_flags, timeout: bigtime_t) -> status_t --- switch_sem_etc :: proc(semToBeReleased: sem_id, id: sem_id, count: i32, flags: semaphore_flags, timeout: bigtime_t) -> status_t ---
get_sem_count :: proc(id: sem_id, threadCount: ^i32) -> status_t --- get_sem_count :: proc(id: sem_id, threadCount: ^i32) -> status_t ---
set_sem_owner :: proc(id: sem_id, team: team_id) -> status_t --- set_sem_owner :: proc(id: sem_id, team: team_id) -> status_t ---
_get_sem_info :: proc(id: sem_id, info: ^sem_info, infoSize: c.size_t) -> status_t --- _get_sem_info :: proc(id: sem_id, info: ^sem_info, infoSize: uint) -> status_t ---
_get_next_sem_info :: proc(team: team_id, cookie: ^i32, info: ^sem_info, infoSize: c.size_t) -> status_t --- _get_next_sem_info :: proc(team: team_id, cookie: ^i32, info: ^sem_info, infoSize: uint) -> status_t ---
} }
// Teams // Teams
@@ -155,7 +161,7 @@ team_info :: struct {
debugger_nub_thread: thread_id, debugger_nub_thread: thread_id,
debugger_nub_port: port_id, debugger_nub_port: port_id,
argc: i32, argc: i32,
args: [64]c.char, args: [64]byte,
uid: uid_t, uid: uid_t,
gid: gid_t, gid: gid_t,
@@ -165,7 +171,7 @@ team_info :: struct {
group_id: pid_t, group_id: pid_t,
session_id: pid_t, session_id: pid_t,
parent: team_id, parent: team_id,
name: [OS_NAME_LENGTH]c.char, name: [OS_NAME_LENGTH]byte,
start_time: bigtime_t, start_time: bigtime_t,
} }
@@ -183,17 +189,18 @@ team_usage_who :: enum i32 {
CHILDREN = -1, CHILDREN = -1,
} }
@(default_calling_convention="c")
foreign libroot { foreign libroot {
// see also: send_signal() // see also: send_signal()
kill_team :: proc(team: team_id) -> status_t --- kill_team :: proc(team: team_id) -> status_t ---
_get_team_info :: proc(id: team_id, info: ^team_info, size: c.size_t) -> status_t --- _get_team_info :: proc(id: team_id, info: ^team_info, size: uint) -> status_t ---
_get_next_team_info :: proc(cookie: ^i32, info: ^team_info, size: c.size_t) -> status_t --- _get_next_team_info :: proc(cookie: ^i32, info: ^team_info, size: uint) -> status_t ---
_get_team_usage_info :: proc(id: team_id, who: team_usage_who, info: ^team_usage_info, size: c.size_t) -> status_t --- _get_team_usage_info :: proc(id: team_id, who: team_usage_who, info: ^team_usage_info, size: uint) -> status_t ---
} }
// Threads // Threads
thread_state :: enum c.int { thread_state :: enum i32 {
RUNNING = 1, RUNNING = 1,
READY, READY,
RECEIVING, RECEIVING,
@@ -205,7 +212,7 @@ thread_state :: enum c.int {
thread_info :: struct { thread_info :: struct {
thread: thread_id, thread: thread_id,
team: team_id, team: team_id,
name: [OS_NAME_LENGTH]c.char, name: [OS_NAME_LENGTH]byte,
state: thread_state, state: thread_state,
priority: thread_priority, priority: thread_priority,
sem: sem_id, sem: sem_id,
@@ -234,6 +241,7 @@ SYSTEM_TIMEBASE :: 0
thread_func :: #type proc "c" (rawptr) -> status_t thread_func :: #type proc "c" (rawptr) -> status_t
@(default_calling_convention="c")
foreign libroot { foreign libroot {
spawn_thread :: proc(thread_func, name: cstring, priority: thread_priority, data: rawptr) -> thread_id --- spawn_thread :: proc(thread_func, name: cstring, priority: thread_priority, data: rawptr) -> thread_id ---
kill_thread :: proc(thread: thread_id) -> status_t --- kill_thread :: proc(thread: thread_id) -> status_t ---
@@ -247,24 +255,25 @@ foreign libroot {
wait_for_thread_etc :: proc(id: thread_id, flags: u32, timeout: bigtime_t, _returnCode: ^status_t) -> status_t --- wait_for_thread_etc :: proc(id: thread_id, flags: u32, timeout: bigtime_t, _returnCode: ^status_t) -> status_t ---
on_exit_thread :: proc(callback: proc "c" (rawptr), data: rawptr) -> status_t --- on_exit_thread :: proc(callback: proc "c" (rawptr), data: rawptr) -> status_t ---
find_thread :: proc(name: cstring) -> thread_id --- find_thread :: proc(name: cstring) -> thread_id ---
send_data :: proc(thread: thread_id, code: i32, buffer: rawptr, bufferSize: c.size_t) -> status_t --- send_data :: proc(thread: thread_id, code: i32, buffer: rawptr, bufferSize: uint) -> status_t ---
receive_data :: proc(sender: ^thread_id, buffer: rawptr, bufferSize: c.size_t) -> i32 --- receive_data :: proc(sender: ^thread_id, buffer: rawptr, bufferSize: uint) -> i32 ---
has_data :: proc(thread: thread_id) -> bool --- has_data :: proc(thread: thread_id) -> bool ---
snooze :: proc(amount: bigtime_t) -> status_t --- snooze :: proc(amount: bigtime_t) -> status_t ---
// FIXME: Find and define those flags. // FIXME: Find and define those flags.
snooze_etc :: proc(amount: bigtime_t, timeBase: c.int, flags: u32) -> status_t --- snooze_etc :: proc(amount: bigtime_t, timeBase: i32, flags: u32) -> status_t ---
snooze_until :: proc(time: bigtime_t, timeBase: c.int) -> status_t --- snooze_until :: proc(time: bigtime_t, timeBase: i32) -> status_t ---
_get_thread_info :: proc(id: thread_id, info: ^thread_info, size: c.size_t) -> status_t --- _get_thread_info :: proc(id: thread_id, info: ^thread_info, size: uint) -> status_t ---
_get_next_thread_info :: proc(team: team_id, cookie: ^i32, info: ^thread_info, size: c.size_t) -> status_t --- _get_next_thread_info :: proc(team: team_id, cookie: ^i32, info: ^thread_info, size: uint) -> status_t ---
// bridge to the pthread API // bridge to the pthread API
get_pthread_thread_id :: proc(thread: pthread_t) -> thread_id --- get_pthread_thread_id :: proc(thread: pthread_t) -> thread_id ---
} }
// Time // Time
@(default_calling_convention="c")
foreign libroot { foreign libroot {
real_time_clock :: proc() -> c.ulong --- real_time_clock :: proc() -> uint ---
set_real_time_clock :: proc(secsSinceJan1st1970: c.ulong) --- set_real_time_clock :: proc(secsSinceJan1st1970: uint) ---
real_time_clock_usecs :: proc() -> bigtime_t --- real_time_clock_usecs :: proc() -> bigtime_t ---
// time since booting in microseconds // time since booting in microseconds
system_time :: proc() -> bigtime_t --- system_time :: proc() -> bigtime_t ---
@@ -280,12 +289,14 @@ alarm_mode :: enum u32 {
PERIODIC_ALARM, // "when" specifies the period PERIODIC_ALARM, // "when" specifies the period
} }
@(default_calling_convention="c")
foreign libroot { foreign libroot {
set_alarm :: proc(_when: bigtime_t, mode: alarm_mode) -> bigtime_t --- set_alarm :: proc(_when: bigtime_t, mode: alarm_mode) -> bigtime_t ---
} }
// Debugger // Debugger
@(default_calling_convention="c")
foreign libroot { foreign libroot {
debugger :: proc(message: cstring) --- debugger :: proc(message: cstring) ---
/* /*
@@ -296,7 +307,7 @@ foreign libroot {
to re-enable the default debugger pass a zero. to re-enable the default debugger pass a zero.
*/ */
disable_debugger :: proc(state: c.int) -> c.int --- disable_debugger :: proc(state: i32) -> i32 ---
} }
// System information // System information
@@ -338,15 +349,15 @@ system_info :: struct {
max_teams: u32, max_teams: u32,
used_teams: u32, used_teams: u32,
kernel_name: [FILE_NAME_LENGTH]c.char, kernel_name: [FILE_NAME_LENGTH]byte,
kernel_build_date: [OS_NAME_LENGTH]c.char, kernel_build_date: [OS_NAME_LENGTH]byte,
kernel_build_time: [OS_NAME_LENGTH]c.char, kernel_build_time: [OS_NAME_LENGTH]byte,
kernel_version: i64, kernel_version: i64,
abi: u32, // the system API abi: u32, // the system API
} }
topology_level_type :: enum c.int { topology_level_type :: enum i32 {
UNKNOWN, UNKNOWN,
ROOT, ROOT,
SMT, SMT,
@@ -354,7 +365,7 @@ topology_level_type :: enum c.int {
PACKAGE, PACKAGE,
} }
cpu_platform :: enum c.int { cpu_platform :: enum i32 {
UNKNOWN, UNKNOWN,
x86, x86,
x86_64, x86_64,
@@ -370,7 +381,7 @@ cpu_platform :: enum c.int {
RISC_V, RISC_V,
} }
cpu_vendor :: enum c.int { cpu_vendor :: enum i32 {
UNKNOWN, UNKNOWN,
AMD, AMD,
CYRIX, CYRIX,
@@ -408,95 +419,80 @@ cpu_topology_node_info :: struct {
}, },
} }
// FIXME: Add cpuid_info when bit fields are ready. when ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 {
cpuid_info :: struct #raw_union {
eax_0: struct {
max_eax: u32,
vendor_id: [12]byte,
},
eax_1: struct {
using _: bit_field u32 {
stepping: u32 | 4,
model: u32 | 4,
family: u32 | 4,
type: u32 | 2,
reserved_0: u32 | 2,
extended_model: u32 | 4,
extended_family: u32 | 8,
reserved_1: u32 | 4,
},
using _: bit_field u32 {
brand_index: u32 | 8,
clflush: u32 | 8,
logical_cpus: u32 | 8,
apic_id: u32 | 8,
},
features: u32,
extended_features: u32,
},
eax_2: struct {
call_num: u8,
cache_descriptors: [15]u8,
},
eax_3: struct {
reserved: [2]u32,
serial_number_high: u32,
serial_number_low: u32,
},
as_chars: [16]byte,
regs: struct {
eax: u32,
ebx: u32,
edx: u32,
ecx: u32,
},
}
}
@(default_calling_convention="c")
foreign libroot { foreign libroot {
get_system_info :: proc(info: ^system_info) -> status_t --- get_system_info :: proc(info: ^system_info) -> status_t ---
_get_cpu_info_etc :: proc(firstCPU: u32, cpuCount: u32, info: ^cpu_info, size: c.size_t) -> status_t --- _get_cpu_info_etc :: proc(firstCPU: u32, cpuCount: u32, info: ^cpu_info, size: uint) -> status_t ---
get_cpu_topology_info :: proc(topologyInfos: [^]cpu_topology_node_info, topologyInfoCount: ^u32) -> status_t --- get_cpu_topology_info :: proc(topologyInfos: [^]cpu_topology_node_info, topologyInfoCount: ^u32) -> status_t ---
is_computer_on :: proc() -> i32 --- when ODIN_ARCH == .amd64 || ODIN_ARCH == .i386 {
is_computer_on_fire :: proc() -> f64 --- get_cpuid :: proc(info: ^cpuid_info, eaxRegister: u32, cpuNum: u32) -> status_t ---
}
is_computer_on :: proc() -> i32 ---
is_computer_on_fire :: proc() -> f64 ---
} }
// Signal.h // POSIX signals
SIG_BLOCK :: 1
SIG_UNBLOCK :: 2
SIG_SETMASK :: 3
/*
* The list of all defined signals:
*
* The numbering of signals for Haiku attempts to maintain
* some consistency with UN*X conventions so that things
* like "kill -9" do what you expect.
*/
SIGHUP :: 1 // hangup -- tty is gone!
SIGINT :: 2 // interrupt
SIGQUIT :: 3 // `quit' special character typed in tty
SIGILL :: 4 // illegal instruction
SIGCHLD :: 5 // child process exited
SIGABRT :: 6 // abort() called, dont' catch
SIGPIPE :: 7 // write to a pipe w/no readers
SIGFPE :: 8 // floating point exception
SIGKILL :: 9 // kill a team (not catchable)
SIGSTOP :: 10 // suspend a thread (not catchable)
SIGSEGV :: 11 // segmentation violation (read: invalid pointer)
SIGCONT :: 12 // continue execution if suspended
SIGTSTP :: 13 // `stop' special character typed in tty
SIGALRM :: 14 // an alarm has gone off (see alarm())
SIGTERM :: 15 // termination requested
SIGTTIN :: 16 // read of tty from bg process
SIGTTOU :: 17 // write to tty from bg process
SIGUSR1 :: 18 // app defined signal 1
SIGUSR2 :: 19 // app defined signal 2
SIGWINCH :: 20 // tty window size changed
SIGKILLTHR :: 21 // be specific: kill just the thread, not team
SIGTRAP :: 22 // Trace/breakpoint trap
SIGPOLL :: 23 // Pollable event
SIGPROF :: 24 // Profiling timer expired
SIGSYS :: 25 // Bad system call
SIGURG :: 26 // High bandwidth data is available at socket
SIGVTALRM :: 27 // Virtual timer expired
SIGXCPU :: 28 // CPU time limit exceeded
SIGXFSZ :: 29 // File size limit exceeded
SIGBUS :: 30 // access to undefined portion of a memory object
sigval :: struct #raw_union {
sival_int: c.int,
sival_ptr: rawptr,
}
siginfo_t :: struct {
si_signo: c.int, // signal number
si_code: c.int, // signal code
si_errno: c.int, // if non zero, an error number associated with this signal
si_pid: pid_t, // sending process ID
si_uid: uid_t, // real user ID of sending process
si_addr: rawptr, // address of faulting instruction
si_status: c.int, // exit value or signal
si_band: c.long, // band event for SIGPOLL
si_value: sigval, // signal value
}
@(default_calling_convention="c")
foreign libroot { foreign libroot {
// signal set (sigset_t) manipulation /*
sigemptyset :: proc(set: ^sigset_t) -> c.int --- Wait for queued signals.
sigfillset :: proc(set: ^sigset_t) -> c.int ---
sigaddset :: proc(set: ^sigset_t, _signal: c.int) -> c.int ---
sigdelset :: proc(set: ^sigset_t, _signal: c.int) -> c.int ---
sigismember :: proc(set: ^sigset_t, _signal: c.int) -> c.int ---
// querying and waiting for signals
sigpending :: proc(set: ^sigset_t) -> c.int ---
sigsuspend :: proc(mask: ^sigset_t) -> c.int ---
sigpause :: proc(_signal: c.int) -> c.int ---
sigwait :: proc(set: ^sigset_t, _signal: ^c.int) -> c.int ---
sigwaitinfo :: proc(set: ^sigset_t, info: ^siginfo_t) -> c.int ---
sigtimedwait :: proc(set: ^sigset_t, info: ^siginfo_t, timeout: ^unix.timespec) -> c.int ---
send_signal :: proc(threadID: thread_id, signal: c.uint) -> c.int --- [[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigtimedwait.html ]]
set_signal_stack :: proc(base: rawptr, size: c.size_t) --- */
sigtimedwait :: proc(set: ^posix.sigset_t, info: ^posix.siginfo_t, timeout: ^posix.timespec) -> posix.result ---
} }
+8 -6
View File
@@ -1,9 +1,7 @@
#+build haiku #+build haiku
package sys_haiku package sys_haiku
import "core:c" status_t :: Errno
status_t :: i32
bigtime_t :: i64 bigtime_t :: i64
nanotime_t :: i64 nanotime_t :: i64
type_code :: u32 type_code :: u32
@@ -37,16 +35,20 @@ mode_t :: u32
umode_t :: u32 umode_t :: u32
nlink_t :: i32 nlink_t :: i32
caddr_t :: ^c.char caddr_t :: [^]byte
addr_t :: phys_addr_t addr_t :: phys_addr_t
key_t :: i32 key_t :: i32
clockid_t :: i32 clockid_t :: i32
time_t :: i64 when ODIN_ARCH == .amd64 || ODIN_ARCH == .arm64 else i32 time_t :: int
timespec :: struct {
tv_sec: time_t,
tv_nsec: int,
}
sig_atomic_t :: c.int sig_atomic_t :: i32
sigset_t :: u64 sigset_t :: u64
image_id :: i32 image_id :: i32
+3 -1
View File
@@ -1,10 +1,12 @@
#+build darwin, linux, freebsd, openbsd, netbsd #+build darwin, linux, freebsd, openbsd, netbsd, haiku
package posix package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System.framework"
} else when ODIN_OS == .Haiku {
foreign import lib "system:network"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+19 -8
View File
@@ -1,4 +1,4 @@
#+build darwin, linux, freebsd, openbsd, netbsd #+build darwin, linux, freebsd, openbsd, netbsd, haiku
package posix package posix
import "core:c" import "core:c"
@@ -219,12 +219,23 @@ when ODIN_OS == .Darwin {
} else when ODIN_OS == .Linux { } else when ODIN_OS == .Linux {
dirent :: struct { dirent :: struct {
d_ino: u64, /* [PSX] file number of entry */ d_ino: u64, /* [PSX] file number of entry */
d_off: i64, /* directory offset of the next entry */ d_off: i64, /* directory offset of the next entry */
d_reclen: u16, /* length of this record */ d_reclen: u16, /* length of this record */
d_type: D_Type, /* file type */ d_type: D_Type, /* file type */
d_name: [256]c.char `fmt:"s,0"`, /* [PSX] entry name */ d_name: [256]c.char `fmt:"s,0"`, /* [PSX] entry name */
} }
} else when ODIN_OS == .Haiku {
dirent :: struct {
d_dev: dev_t, /* device */
d_pdev: dev_t, /* parent device (only for queries) */
d_ino: ino_t, /* inode number */
d_pino: ino_t, /* parent inode (only for queries) */
d_reclen: c.ushort, /* length of this record, not the name */
d_name: [0]c.char `fmt:"s,0"`, /* name of the entry (null byte terminated) */
}
} }
+88 -1
View File
@@ -1,4 +1,4 @@
#+build windows, darwin, linux, freebsd, openbsd, netbsd #+build windows, darwin, linux, freebsd, openbsd, netbsd, haiku
package posix package posix
import "core:c" import "core:c"
@@ -536,5 +536,92 @@ when ODIN_OS == .Darwin {
ETXTBSY :: 139 ETXTBSY :: 139
EWOULDBLOCK :: 140 EWOULDBLOCK :: 140
EXDEV :: 18 EXDEV :: 18
} else when ODIN_OS == .Haiku {
_HAIKU_USE_POSITIVE_POSIX_ERRORS :: libc._HAIKU_USE_POSITIVE_POSIX_ERRORS
_POSIX_ERROR_FACTOR :: libc._POSIX_ERROR_FACTOR
_GENERAL_ERROR_BASE :: min(c.int)
_OS_ERROR_BASE :: _GENERAL_ERROR_BASE + 0x1000
_STORAGE_ERROR_BASE :: _GENERAL_ERROR_BASE + 0x6000
_POSIX_ERROR_BASE :: _GENERAL_ERROR_BASE + 0x7000
EIO :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 1) // B_IO_ERROR
EACCES :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 2) // B_PERMISSION_DENIED
EINVAL :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 5) // B_BAD_VALUE
ETIMEDOUT :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 9) // B_TIMED_OUT
EINTR :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 10) // B_INTERRUPTED
EAGAIN :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 11) // B_WOULD_BLOCK /* SysV compatibility */
EWOULDBLOCK :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 11) // B_WOULD_BLOCK /* BSD compatibility */
EBUSY :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 14) // B_BUSY
EPERM :: _POSIX_ERROR_FACTOR * (_GENERAL_ERROR_BASE + 15) // B_NOT_ALLOWED
EFAULT :: _POSIX_ERROR_FACTOR * (_OS_ERROR_BASE + 0x301) // B_BAD_ADDRESS
ENOEXEC :: _POSIX_ERROR_FACTOR * (_OS_ERROR_BASE + 0x302) // B_NOT_AN_EXECUTABLE
EBADF :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 0) // B_FILE_ERROR
EEXIST :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 2) // B_FILE_EXISTS
ENOENT :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 3) // B_ENTRY_NOT_FOUND
ENAMETOOLONG :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 4) // B_NAME_TOO_LONG
ENOTDIR :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 5) // B_NOT_A_DIRECTORY
ENOTEMPTY :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 6) // B_DIRECTORY_NOT_EMPTY
ENOSPC :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 7) // B_DEVICE_FULL
EROFS :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 8) // B_READ_ONLY_DEVICE
EISDIR :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 9) // B_IS_A_DIRECTORY
EMFILE :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 10) // B_NO_MORE_FDS
EXDEV :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 11) // B_CROSS_DEVICE_LINK
ELOOP :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 12) // B_LINK_LIMIT
EPIPE :: _POSIX_ERROR_FACTOR * (_STORAGE_ERROR_BASE + 13) // B_BUSTED_PIPE
ENOMEM :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 0) when _HAIKU_USE_POSITIVE_POSIX_ERRORS else (_GENERAL_ERROR_BASE + 0) // B_NO_MEMORY
E2BIG :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 1)
ECHILD :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 2)
EDEADLK :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 3)
EFBIG :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 4)
EMLINK :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 5)
ENFILE :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 6)
ENODEV :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 7)
ENOLCK :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 8)
ENOSYS :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 9)
ENOTTY :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 10)
ENXIO :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 11)
ESPIPE :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 12)
ESRCH :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 13)
EPROTOTYPE :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 18)
EPROTONOSUPPORT :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 19)
EAFNOSUPPORT :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 21)
EADDRINUSE :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 22)
EADDRNOTAVAIL :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 23)
ENETDOWN :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 24)
ENETUNREACH :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 25)
ENETRESET :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 26)
ECONNABORTED :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 27)
ECONNRESET :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 28)
EISCONN :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 29)
ENOTCONN :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 30)
ECONNREFUSED :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 32)
EHOSTUNREACH :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 33)
ENOPROTOOPT :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 34)
ENOBUFS :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 35)
EINPROGRESS :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 36)
EALREADY :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 37)
ENOMSG :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 39)
ESTALE :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 40)
EOVERFLOW :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 41)
EMSGSIZE :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 42)
EOPNOTSUPP :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 43)
ENOTSOCK :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 44)
EBADMSG :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 46)
ECANCELED :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 47)
EDESTADDRREQ :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 48)
EDQUOT :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 49)
EIDRM :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 50)
EMULTIHOP :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 51)
ENODATA :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 52)
ENOLINK :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 53)
ENOSR :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 54)
ENOSTR :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 55)
ENOTSUP :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 56)
EPROTO :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 57)
ETIME :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 58)
ETXTBSY :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 59)
ENOTRECOVERABLE :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 61)
EOWNERDEAD :: _POSIX_ERROR_FACTOR * (_POSIX_ERROR_BASE + 62)
} }
+68 -1
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, openbsd, freebsd, netbsd #+build linux, darwin, openbsd, freebsd, netbsd, haiku
package posix package posix
import "core:c" import "core:c"
@@ -343,6 +343,7 @@ when ODIN_OS == .Darwin {
l_type: Lock_Type, /* [PSX] type of lock */ l_type: Lock_Type, /* [PSX] type of lock */
l_whence: c.short, /* [PSX] flag (Whence) of starting offset */ l_whence: c.short, /* [PSX] flag (Whence) of starting offset */
} }
} else when ODIN_OS == .OpenBSD { } else when ODIN_OS == .OpenBSD {
off_t :: distinct c.int64_t off_t :: distinct c.int64_t
@@ -408,6 +409,72 @@ when ODIN_OS == .Darwin {
l_whence: c.short, /* [PSX] flag (Whence) of starting offset */ l_whence: c.short, /* [PSX] flag (Whence) of starting offset */
} }
} else when ODIN_OS == .Haiku {
off_t :: distinct c.int64_t
pid_t :: distinct c.int32_t
/* commands that can be passed to fcntl() */
F_DUPFD :: 0x0001 /* duplicate fd */
F_GETFD :: 0x0002 /* get fd flags */
F_SETFD :: 0x0004 /* set fd flags */
F_GETFL :: 0x0008 /* get file status flags and access mode */
F_SETFL :: 0x0010 /* set file status flags */
F_GETLK :: 0x0020 /* get locking information */
F_SETLK :: 0x0080 /* set locking information */
F_SETLKW :: 0x0100 /* as above, but waits if blocked */
F_DUPFD_CLOEXEC :: 0x0200 /* duplicate fd with close on exec set */
F_GETOWN :: -1 // NOTE: Not supported.
F_SETOWN :: -1 // NOTE: Not supported.
/* advisory locking types */
F_RDLCK :: 0x0040 /* read or shared lock */
F_UNLCK :: 0x0200 /* unlock */
F_WRLCK :: 0x0400 /* write or exclusive lock */
/* file descriptor flags for fcntl() */
FD_CLOEXEC :: 1
O_CLOEXEC :: 0x00000040
O_CREAT :: 0x0200
O_DIRECTORY :: 0x00200000
O_EXCL :: 0x0100
O_NOCTTY :: 0x1000
O_NOFOLLOW :: 0x00080000
O_TRUNC :: 0x0400
_O_TTY_INIT :: 0
O_TTY_INIT :: O_Flags{} // NOTE: not defined in the headers
O_APPEND :: 0x0800
O_DSYNC :: 0x040000
O_NONBLOCK :: 0x0080
O_SYNC :: 0x010000
O_RSYNC :: 0x020000
O_EXEC :: 0x04000000 // NOTE: not defined in the headers
O_RDONLY :: 0
O_RDWR :: 0x0002
O_WRONLY :: 0x0001
_O_SEARCH :: 0
O_SEARCH :: O_Flags{} // NOTE: not defined in the headers
AT_FDCWD: FD: -100
AT_EACCESS :: 0x08
AT_SYMLINK_NOFOLLOW :: 0x01
AT_SYMLINK_FOLLOW :: 0x02
AT_REMOVEDIR :: 0x04
flock :: struct {
l_type: Lock_Type, /* [PSX] type of lock */
l_whence: c.short, /* [PSX] flag (Whence) of starting offset */
l_start: off_t, /* [PSX] relative offset in bytes */
l_len: off_t, /* [PSX] size; if 0 then until EOF */
l_pid: pid_t, /* [PSX] process ID of the process holding the lock */
}
} else when ODIN_OS == .Linux { } else when ODIN_OS == .Linux {
off_t :: distinct c.int64_t off_t :: distinct c.int64_t
+2 -2
View File
@@ -1,4 +1,4 @@
#+build darwin, linux, openbsd, freebsd, netbsd #+build darwin, linux, openbsd, freebsd, netbsd, haiku
package posix package posix
import "core:c" import "core:c"
@@ -46,7 +46,7 @@ FNM_Flag_Bits :: enum c.int {
} }
FNM_Flags :: bit_set[FNM_Flag_Bits; c.int] FNM_Flags :: bit_set[FNM_Flag_Bits; c.int]
when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD { when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Haiku {
FNM_NOMATCH :: 1 FNM_NOMATCH :: 1
+3 -3
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c" import "core:c"
@@ -109,7 +109,7 @@ when ODIN_OS == .Darwin {
GLOB_NOMATCH :: -3 GLOB_NOMATCH :: -3
GLOB_NOSPACE :: -1 GLOB_NOSPACE :: -1
} else when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD { } else when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .Haiku {
glob_t :: struct { glob_t :: struct {
gl_pathc: c.size_t, /* [PSX] count of paths matched by pattern */ gl_pathc: c.size_t, /* [PSX] count of paths matched by pattern */
@@ -134,7 +134,7 @@ when ODIN_OS == .Darwin {
GLOB_ERR :: 0x0004 GLOB_ERR :: 0x0004
GLOB_MARK :: 0x0008 GLOB_MARK :: 0x0008
GLOB_NOCHECK :: 0x0010 GLOB_NOCHECK :: 0x0010
GLOB_NOESCAPE :: 0x2000 when ODIN_OS == .FreeBSD else 0x0100 GLOB_NOESCAPE :: 0x2000 when ODIN_OS == .FreeBSD || ODIN_OS == .Haiku else 0x0100
GLOB_NOSORT :: 0x0020 GLOB_NOSORT :: 0x0020
GLOB_ABORTED :: -2 GLOB_ABORTED :: -2
+2 -2
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c" import "core:c"
@@ -115,7 +115,7 @@ foreign lib {
getgrnam_r :: proc(name: cstring, grp: ^group, buffer: [^]byte, bufsize: c.size_t, result: ^^group) -> Errno --- getgrnam_r :: proc(name: cstring, grp: ^group, buffer: [^]byte, bufsize: c.size_t, result: ^^group) -> Errno ---
} }
when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Haiku || ODIN_OS == .Linux {
gid_t :: distinct c.uint32_t gid_t :: distinct c.uint32_t
+3 -3
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c" import "core:c"
@@ -143,7 +143,7 @@ nl_item :: enum nl_item_t {
CRNCYSTR = CRNCYSTR, CRNCYSTR = CRNCYSTR,
} }
when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD { when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .Haiku {
// NOTE: declared with `_t` so we can enumerate the real `nl_info`. // NOTE: declared with `_t` so we can enumerate the real `nl_info`.
nl_item_t :: distinct c.int nl_item_t :: distinct c.int
@@ -210,7 +210,7 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD {
YESEXPR :: 52 YESEXPR :: 52
NOEXPR :: 53 NOEXPR :: 53
CRNCYSTR :: 56 CRNCYSTR :: 54 when ODIN_OS == .Haiku else 56
} else when ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD { } else when ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD {
+1 -1
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
+1 -1
View File
@@ -1,4 +1,4 @@
#+build windows, linux, darwin, netbsd, openbsd, freebsd #+build windows, linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c/libc" import "core:c/libc"
+1 -1
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c" import "core:c"
+19 -2
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c" import "core:c"
@@ -319,7 +319,7 @@ Info_Errno :: enum c.int {
OVERFLOW = EAI_OVERFLOW, OVERFLOW = EAI_OVERFLOW,
} }
when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku {
hostent :: struct { hostent :: struct {
h_name: cstring, /* [PSX] official name of host */ h_name: cstring, /* [PSX] official name of host */
@@ -431,6 +431,23 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
NI_NUMERICSCOPE :: 0x100 NI_NUMERICSCOPE :: 0x100
NI_DGRAM :: 16 NI_DGRAM :: 16
} else when ODIN_OS == .Haiku {
AI_PASSIVE :: 0x001
AI_CANONNAME :: 0x002
AI_NUMERICHOST :: 0x004
AI_NUMERICSERV :: 0x008
AI_V4MAPPED :: 0x800
AI_ALL :: 0x100
AI_ADDRCONFIG :: 0x400
NI_NOFQDN :: 0x01
NI_NUMERICHOST :: 0x02
NI_NAMEREQD :: 0x04
NI_NUMERICSERV :: 0x08
NI_DGRAM :: 0x10
NI_NUMERICSCOPE :: 0x40
} }
when ODIN_OS == .OpenBSD { when ODIN_OS == .OpenBSD {
+45 -16
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c" import "core:c"
@@ -31,20 +31,31 @@ Protocol :: enum c.int {
UDP = IPPROTO_UDP, UDP = IPPROTO_UDP,
} }
when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku {
in_addr :: struct { in_addr :: struct {
s_addr: in_addr_t, /* [PSX] big endian address */ s_addr: in_addr_t, /* [PSX] big endian address */
} }
in6_addr :: struct { when ODIN_OS == .Haiku {
using _: struct #raw_union { in6_addr :: struct #packed {
s6_addr: [16]c.uint8_t, /* [PSX] big endian address */ using _: struct #raw_union {
__u6_addr16: [8]c.uint16_t, s6_addr: [16]c.uint8_t, /* [PSX] big endian address */
__u6_addr32: [4]c.uint32_t, __u6_addr16: [8]c.uint16_t,
}, __u6_addr32: [4]c.uint32_t,
},
}
} else {
in6_addr :: struct {
using _: struct #raw_union {
s6_addr: [16]c.uint8_t, /* [PSX] big endian address */
__u6_addr16: [8]c.uint16_t,
__u6_addr32: [4]c.uint32_t,
},
}
} }
when ODIN_OS == .Linux { when ODIN_OS == .Linux {
sockaddr_in :: struct { sockaddr_in :: struct {
@@ -77,12 +88,20 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
} else { } else {
when ODIN_OS == .Haiku {
@(private)
_SIN_ZEROSIZE :: 24
} else {
@(private)
_SIN_ZEROSIZE :: 8
}
sockaddr_in :: struct { sockaddr_in :: struct {
sin_len: c.uint8_t, sin_len: c.uint8_t,
sin_family: sa_family_t, /* [PSX] AF_INET (but a smaller size) */ sin_family: sa_family_t, /* [PSX] AF_INET (but a smaller size) */
sin_port: in_port_t, /* [PSX] port number */ sin_port: in_port_t, /* [PSX] port number */
sin_addr: in_addr, /* [PSX] IP address */ sin_addr: in_addr, /* [PSX] IP address */
sin_zero: [8]c.char, sin_zero: [_SIN_ZEROSIZE]c.char,
} }
sockaddr_in6 :: struct { sockaddr_in6 :: struct {
@@ -99,13 +118,23 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
ipv6mr_interface: c.uint, /* [PSX] interface index */ ipv6mr_interface: c.uint, /* [PSX] interface index */
} }
IPV6_JOIN_GROUP :: 12 when ODIN_OS == .Haiku {
IPV6_LEAVE_GROUP :: 13 IPV6_JOIN_GROUP :: 28
IPV6_MULTICAST_HOPS :: 10 IPV6_LEAVE_GROUP :: 29
IPV6_MULTICAST_IF :: 9 IPV6_MULTICAST_HOPS :: 25
IPV6_MULTICAST_LOOP :: 11 IPV6_MULTICAST_IF :: 24
IPV6_UNICAST_HOPS :: 4 IPV6_MULTICAST_LOOP :: 26
IPV6_V6ONLY :: 27 IPV6_UNICAST_HOPS :: 27
IPV6_V6ONLY :: 30
} else {
IPV6_JOIN_GROUP :: 12
IPV6_LEAVE_GROUP :: 13
IPV6_MULTICAST_HOPS :: 10
IPV6_MULTICAST_IF :: 9
IPV6_MULTICAST_LOOP :: 11
IPV6_UNICAST_HOPS :: 4
IPV6_V6ONLY :: 27
}
} }
+36 -13
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "base:intrinsics" import "base:intrinsics"
@@ -25,7 +25,11 @@ foreign lib {
poll :: proc(fds: [^]pollfd, nfds: nfds_t, timeout: c.int) -> c.int --- poll :: proc(fds: [^]pollfd, nfds: nfds_t, timeout: c.int) -> c.int ---
} }
nfds_t :: c.uint when ODIN_OS == .Haiku {
nfds_t :: c.ulong
} else {
nfds_t :: c.uint
}
Poll_Event_Bits :: enum c.short { Poll_Event_Bits :: enum c.short {
// Data other than high-priority data may be read without blocking. // Data other than high-priority data may be read without blocking.
@@ -53,7 +57,7 @@ Poll_Event_Bits :: enum c.short {
} }
Poll_Event :: bit_set[Poll_Event_Bits; c.short] Poll_Event :: bit_set[Poll_Event_Bits; c.short]
when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD { when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Haiku {
pollfd :: struct { pollfd :: struct {
fd: FD, /* [PSX] the following descriptor being polled */ fd: FD, /* [PSX] the following descriptor being polled */
@@ -61,17 +65,36 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
revents: Poll_Event, /* [PSX] the output event flags */ revents: Poll_Event, /* [PSX] the output event flags */
} }
POLLIN :: 0x0001 when ODIN_OS == .Haiku {
POLLRDNORM :: 0x0040
POLLRDBAND :: 0x0080 POLLIN :: 0x0001 /* any readable data available */
POLLPRI :: 0x0002 POLLOUT :: 0x0002 /* file descriptor is writeable */
POLLOUT :: 0x0004 POLLRDNORM :: POLLIN
POLLWRNORM :: POLLOUT POLLWRNORM :: POLLOUT
POLLWRBAND :: 0x0100 POLLRDBAND :: 0x0008 /* priority readable data */
POLLWRBAND :: 0x0010 /* priority data can be written */
POLLPRI :: 0x0020 /* high priority readable data */
POLLERR :: 0x0004 /* errors pending */
POLLHUP :: 0x0080 /* disconnected */
POLLNVAL :: 0x1000 /* invalid file descriptor */
} else {
POLLIN :: 0x0001
POLLRDNORM :: 0x0040
POLLRDBAND :: 0x0080
POLLPRI :: 0x0002
POLLOUT :: 0x0004
POLLWRNORM :: POLLOUT
POLLWRBAND :: 0x0100
POLLERR :: 0x0008
POLLHUP :: 0x0010
POLLNVAL :: 0x0020
}
POLLERR :: 0x0008
POLLHUP :: 0x0010
POLLNVAL :: 0x0020
} else when ODIN_OS == .Linux { } else when ODIN_OS == .Linux {
+51 -1
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c" import "core:c"
@@ -554,6 +554,56 @@ when ODIN_OS == .Darwin {
sched_priority: c.int, /* [PSX] process or thread execution scheduling priority */ sched_priority: c.int, /* [PSX] process or thread execution scheduling priority */
} }
} else when ODIN_OS == .Haiku {
PTHREAD_CANCEL_ASYNCHRONOUS :: 2
PTHREAD_CANCEL_DEFERRED :: 0
PTHREAD_CANCEL_DISABLE :: 1
PTHREAD_CANCEL_ENABLE :: 0
PTHREAD_CANCELED :: rawptr(uintptr(1))
PTHREAD_CREATE_DETACHED :: 0x1
PTHREAD_CREATE_JOINABLE :: 0
PTHREAD_EXPLICIT_SCHED :: 0
PTHREAD_INHERIT_SCHED :: 0x4
PTHREAD_PRIO_INHERIT :: 1
PTHREAD_PRIO_NONE :: 0
PTHREAD_PRIO_PROTECT :: 2
PTHREAD_PROCESS_SHARED :: 1
PTHREAD_PROCESS_PRIVATE :: 0
PTHREAD_SCOPE_PROCESS :: 0
PTHREAD_SCOPE_SYSTEM :: 0x2
pthread_t :: distinct rawptr
pthread_attr_t :: distinct rawptr
pthread_key_t :: distinct c.int
pthread_mutex_t :: struct {
flags: u32,
lock: i32,
unused: i32,
owner: i32,
owner_count: i32,
}
pthread_cond_t :: struct {
flags: u32,
unused: i32,
mutex: ^pthread_mutex_t,
waiter_count: i32,
lock: i32,
}
sched_param :: struct {
sched_priority: c.int, /* [PSX] process or thread execution scheduling priority */
}
} else when ODIN_OS == .Linux { } else when ODIN_OS == .Linux {
PTHREAD_CANCEL_DEFERRED :: 0 PTHREAD_CANCEL_DEFERRED :: 0
+13 -1
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c" import "core:c"
@@ -176,4 +176,16 @@ when ODIN_OS == .Darwin || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD {
pw_shell: cstring, /* Shell program. */ pw_shell: cstring, /* Shell program. */
} }
} else when ODIN_OS == .Haiku {
passwd :: struct {
pw_name: cstring, /* [PSX] user name */
pw_passwd: cstring, /* encrypted password */
pw_uid: uid_t, /* [PSX] user uid */
pw_gid: gid_t, /* [PSX] user gid */
pw_dir: cstring, /* Home directory. */
pw_shell: cstring, /* Shell program. */
pw_gecos: cstring, /* Real name. */
}
} }
+8 -1
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c" import "core:c"
@@ -101,4 +101,11 @@ when ODIN_OS == .Darwin {
SCHED_FIFO :: 1 SCHED_FIFO :: 1
SCHED_RR :: 2 SCHED_RR :: 2
} else when ODIN_OS == .Haiku {
SCHED_FIFO :: 1
SCHED_RR :: 2
// SCHED_SPORADIC :: 3 NOTE: not a thing on freebsd, netbsd and probably others, leaving it out
SCHED_OTHER :: 4
} }
+148 -1
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "base:intrinsics" import "base:intrinsics"
@@ -1180,4 +1180,151 @@ when ODIN_OS == .Darwin {
SI_TIMER :: -2 SI_TIMER :: -2
SI_MESGQ :: -3 SI_MESGQ :: -3
SI_ASYNCIO :: -4 SI_ASYNCIO :: -4
} else when ODIN_OS == .Haiku {
// Request that signal be held
SIG_HOLD :: rawptr(uintptr(3))
uid_t :: distinct c.uint32_t
sigset_t :: distinct u64
SIGHUP :: 1 // hangup -- tty is gone!
//SIGINT :: 2 // interrupt
SIGQUIT :: 3 // `quit' special character typed in tty
//SIGILL :: 4 // illegal instruction
SIGCHLD :: 5 // child process exited
//SIGABRT :: 6 // abort() called, dont' catch
SIGPIPE :: 7 // write to a pipe w/no readers
//SIGFPE :: 8 // floating point exception
SIGKILL :: 9 // kill a team (not catchable)
SIGSTOP :: 10 // suspend a thread (not catchable)
//SIGSEGV :: 11 // segmentation violation (read: invalid pointer)
SIGCONT :: 12 // continue execution if suspended
SIGTSTP :: 13 // `stop' special character typed in tty
SIGALRM :: 14 // an alarm has gone off (see alarm())
//SIGTERM :: 15 // termination requested
SIGTTIN :: 16 // read of tty from bg process
SIGTTOU :: 17 // write to tty from bg process
SIGUSR1 :: 18 // app defined signal 1
SIGUSR2 :: 19 // app defined signal 2
SIGWINCH :: 20 // tty window size changed
SIGKILLTHR :: 21 // be specific: kill just the thread, not team
SIGTRAP :: 22 // Trace/breakpoint trap
SIGPOLL :: 23 // Pollable event
SIGPROF :: 24 // Profiling timer expired
SIGSYS :: 25 // Bad system call
SIGURG :: 26 // High bandwidth data is available at socket
SIGVTALRM :: 27 // Virtual timer expired
SIGXCPU :: 28 // CPU time limit exceeded
SIGXFSZ :: 29 // File size limit exceeded
SIGBUS :: 30 // access to undefined portion of a memory object
// NOTE: this is actually defined as `sigaction`, but due to the function with the same name
// `_t` has been added.
sigaction_t :: struct {
using _: struct #raw_union {
sa_handler: proc "c" (Signal), /* [PSX] signal-catching function or one of the SIG_IGN or SIG_DFL */
sa_sigaction: proc "c" (Signal, ^siginfo_t, rawptr), /* [PSX] signal-catching function */
},
sa_mask: sigset_t, /* [PSX] set of signals to be blocked during execution of the signal handling function */
sa_flags: SA_Flags, /* [PSX] special flags */
sa_userdata: rawptr, /* will be passed to the signal handler, BeOS extension */
}
SIG_BLOCK :: 1
SIG_UNBLOCK :: 2
SIG_SETMASK :: 3
SA_NOCLDSTOP :: 0x01
SA_NOCLDWAIT :: 0x02
SA_RESETHAND :: 0x04
SA_NODEFER :: 0x08
SA_RESTART :: 0x10
SA_ONSTACK :: 0x20
SA_SIGINFO :: 0x40
SS_ONSTACK :: 1
SS_DISABLE :: 2
MINSIGSTKSZ :: 8192
SIGSTKSZ :: 16384
stack_t :: struct {
ss_sp: rawptr, /* [PSX] stack base or pointer */
ss_size: c.size_t, /* [PSX] stack size */
ss_flags: SS_Flags, /* [PSX] flags */
}
siginfo_t :: struct {
si_signo: Signal, /* [PSX] signal number */
si_code: struct #raw_union { /* [PSX] specific more detailed codes per signal */
ill: ILL_Code,
fpe: FPE_Code,
segv: SEGV_Code,
bus: BUS_Code,
trap: TRAP_Code,
chld: CLD_Code,
poll: POLL_Code,
any: Any_Code,
},
si_errno: Errno, /* [PSX] errno value associated with this signal */
si_pid: pid_t, /* sending process ID */
si_uid: uid_t, /* real user ID of sending process */
si_addr: rawptr, /* address of faulting instruction */
si_status: c.int, /* exit value or signal */
si_band: c.long, /* band event for SIGPOLL */
si_value: sigval, /* signal value */
}
/* any signal */
SI_USER :: 0 /* signal sent by user */
SI_QUEUE :: 1 /* signal sent by sigqueue() */
SI_TIMER :: 2 /* signal sent on timer_settime() timeout */
SI_ASYNCIO :: 3 /* signal sent on asynchronous I/O completion */
SI_MESGQ :: 4 /* signal sent on arrival of message on empty message queue */
/* SIGILL */
ILL_ILLOPC :: 10 /* illegal opcode */
ILL_ILLOPN :: 11 /* illegal operand */
ILL_ILLADR :: 12 /* illegal addressing mode */
ILL_ILLTRP :: 13 /* illegal trap */
ILL_PRVOPC :: 14 /* privileged opcode */
ILL_PRVREG :: 15 /* privileged register */
ILL_COPROC :: 16 /* coprocessor error */
ILL_BADSTK :: 17 /* internal stack error */
/* SIGFPE */
FPE_INTDIV :: 20 /* integer division by zero */
FPE_INTOVF :: 21 /* integer overflow */
FPE_FLTDIV :: 22 /* floating-point division by zero */
FPE_FLTOVF :: 23 /* floating-point overflow */
FPE_FLTUND :: 24 /* floating-point underflow */
FPE_FLTRES :: 25 /* floating-point inexact result */
FPE_FLTINV :: 26 /* invalid floating-point operation */
FPE_FLTSUB :: 27 /* subscript out of range */
/* SIGSEGV */
SEGV_MAPERR :: 30 /* address not mapped to object */
SEGV_ACCERR :: 31 /* invalid permissions for mapped object */
/* SIGBUS */
BUS_ADRALN :: 40 /* invalid address alignment */
BUS_ADRERR :: 41 /* nonexistent physical address */
BUS_OBJERR :: 42 /* object-specific hardware error */
/* SIGTRAP */
TRAP_BRKPT :: 50 /* process breakpoint */
TRAP_TRACE :: 51 /* process trace trap. */
/* SIGCHLD */
CLD_EXITED :: 60 /* child exited */
CLD_KILLED :: 61 /* child terminated abnormally without core dump */
CLD_DUMPED :: 62 /* child terminated abnormally with core dump */
CLD_TRAPPED :: 63 /* traced child trapped */
CLD_STOPPED :: 64 /* child stopped */
CLD_CONTINUED :: 65 /* stopped child continued */
/* SIGPOLL */
POLL_IN :: 70 /* input available */
POLL_OUT :: 71 /* output available */
POLL_MSG :: 72 /* input message available */
POLL_ERR :: 73 /* I/O error */
POLL_PRI :: 74 /* high priority input available */
POLL_HUP :: 75 /* device disconnected */
} }
+1 -1
View File
@@ -1,4 +1,4 @@
#+build linux, windows, darwin, netbsd, openbsd, freebsd #+build linux, windows, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "base:intrinsics" import "base:intrinsics"
+1 -1
View File
@@ -1,4 +1,4 @@
#+build linux, windows, linux, darwin, netbsd, openbsd, freebsd #+build linux, windows, linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c" import "core:c"
+1 -1
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "base:intrinsics" import "base:intrinsics"
+1 -1
View File
@@ -1,4 +1,4 @@
#+build linux, windows, darwin, netbsd, openbsd, freebsd #+build linux, windows, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "base:intrinsics" import "base:intrinsics"
+1 -1
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c" import "core:c"
+1 -1
View File
@@ -1,4 +1,4 @@
#+build linux, windows, darwin, netbsd, openbsd, freebsd #+build linux, windows, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
when ODIN_OS == .Windows { when ODIN_OS == .Windows {
+24 -1
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c" import "core:c"
@@ -111,4 +111,27 @@ when ODIN_OS == .Darwin {
IPC_SET :: 1 IPC_SET :: 1
IPC_STAT :: 2 IPC_STAT :: 2
} else when ODIN_OS == .Haiku {
key_t :: distinct c.int32_t
ipc_perm :: struct {
key: key_t,
uid: uid_t, /* [PSX] owner's user ID */
gid: gid_t, /* [PSX] owner's group ID */
cuid: uid_t, /* [PSX] creator's user ID */
cgid: gid_t, /* [PSX] creator's group ID */
mode: mode_t, /* [PSX] read/write perms */
}
IPC_CREAT :: 0o01000
IPC_EXCL :: 0o02000
IPC_NOWAIT :: 0o04000
IPC_PRIVATE :: key_t(0)
IPC_RMID :: 0
IPC_SET :: 1
IPC_STAT :: 2
} }
+19 -1
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c" import "core:c"
@@ -171,4 +171,22 @@ when ODIN_OS == .Darwin {
__unused: [2]c.ulong, __unused: [2]c.ulong,
} }
} else when ODIN_OS == .Haiku {
msgqnum_t :: distinct c.uint32_t
msglen_t :: distinct c.uint32_t
MSG_NOERROR :: 0o10000
msqid_ds :: struct {
msg_perm: ipc_perm, /* [PSX] operation permission structure */
msg_qnum: msgqnum_t, /* [PSX] number of messages currently on queue */
msg_qbytes: msglen_t, /* [PSX] maximum number of bytes allowed on queue */
msg_lspid: pid_t, /* [PSX] process ID of last msgsnd() */
msg_lrpid: pid_t, /* [PSX] process ID of last msgrcv() */
msg_stime: time_t, /* [PSX] time of last msgsnd() */
msg_rtime: time_t, /* [PSX] time of last msgrcv() */
msg_ctime: time_t, /* [PSX] time of last change */
}
} }
+37 -16
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c" import "core:c"
@@ -96,15 +96,26 @@ when ODIN_OS == .NetBSD {
@(private) LGETRUSAGE :: "getrusage" @(private) LGETRUSAGE :: "getrusage"
} }
when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku {
PRIO_PROCESS :: 0 PRIO_PROCESS :: 0
PRIO_PGRP :: 1 PRIO_PGRP :: 1
PRIO_USER :: 2 PRIO_USER :: 2
rlim_t :: distinct c.uint64_t when ODIN_OS == .Haiku {
rlim_t :: distinct c.ulong
} else {
rlim_t :: distinct c.uint64_t
}
RLIM_INFINITY :: ~rlim_t(0) when ODIN_OS == .Linux else (rlim_t(1) << 63) - 1 when ODIN_OS == .Haiku {
RLIM_INFINITY :: rlim_t(0xFFFFFFFF)
} else when ODIN_OS == .Linux {
RLIM_INFINITY :: ~rlim_t(0)
} else {
RLIM_INFINITY :: (rlim_t(1) << 63) - 1
}
RLIM_SAVED_MAX :: RLIM_INFINITY RLIM_SAVED_MAX :: RLIM_INFINITY
RLIM_SAVED_CUR :: RLIM_INFINITY RLIM_SAVED_CUR :: RLIM_INFINITY
@@ -140,19 +151,29 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
ru_nivcsw: c.long, /* involuntary " */ ru_nivcsw: c.long, /* involuntary " */
} }
RLIMIT_CORE :: 4 when ODIN_OS == .Haiku {
RLIMIT_CPU :: 0 RLIMIT_CORE :: 0
RLIMIT_DATA :: 2 RLIMIT_CPU :: 1
RLIMIT_FSIZE :: 1 RLIMIT_DATA :: 2
RLIMIT_NOFILE :: 7 when ODIN_OS == .Linux else 8 RLIMIT_FSIZE :: 3
RLIMIT_STACK :: 3 RLIMIT_NOFILE :: 4
RLIMIT_STACK :: 5
when ODIN_OS == .Linux { RLIMIT_AS :: 6
RLIMIT_AS :: 9
} else when ODIN_OS == .Darwin || ODIN_OS == .OpenBSD {
RLIMIT_AS :: 5
} else { } else {
RLIMIT_AS :: 10 RLIMIT_CORE :: 4
RLIMIT_CPU :: 0
RLIMIT_DATA :: 2
RLIMIT_FSIZE :: 1
RLIMIT_NOFILE :: 7 when ODIN_OS == .Linux else 8
RLIMIT_STACK :: 3
when ODIN_OS == .Linux {
RLIMIT_AS :: 9
} else when ODIN_OS == .Darwin || ODIN_OS == .OpenBSD {
RLIMIT_AS :: 5
} else {
RLIMIT_AS :: 10
}
} }
} }
+11 -5
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "base:intrinsics" import "base:intrinsics"
@@ -56,9 +56,9 @@ when ODIN_OS == .NetBSD {
LSELECT :: "select" LSELECT :: "select"
} }
when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku {
suseconds_t :: distinct (c.int32_t when ODIN_OS == .Darwin || ODIN_OS == .NetBSD else c.long) suseconds_t :: distinct (c.int32_t when ODIN_OS == .Darwin || ODIN_OS == .NetBSD || ODIN_OS == .Haiku else c.long)
timeval :: struct { timeval :: struct {
tv_sec: time_t, /* [PSX] seconds */ tv_sec: time_t, /* [PSX] seconds */
@@ -75,8 +75,14 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
@(private) @(private)
ALIGN :: align_of(c.long) when ODIN_OS == .FreeBSD || ODIN_OS == .Linux else align_of(c.int32_t) ALIGN :: align_of(c.long) when ODIN_OS == .FreeBSD || ODIN_OS == .Linux else align_of(c.int32_t)
fd_set :: struct #align(ALIGN) { when ODIN_OS == .Haiku {
fds_bits: [(FD_SETSIZE / __NFDBITS) when (FD_SETSIZE % __NFDBITS) == 0 else (FD_SETSIZE / __NFDBITS) + 1]c.int32_t, fd_set :: struct #align(ALIGN) {
fds_bits: [(FD_SETSIZE + (__NFDBITS - 1)) / __NFDBITS]c.int32_t,
}
} else {
fd_set :: struct #align(ALIGN) {
fds_bits: [(FD_SETSIZE / __NFDBITS) when (FD_SETSIZE % __NFDBITS) == 0 else (FD_SETSIZE / __NFDBITS) + 1]c.int32_t,
}
} }
@(private) @(private)
+27 -1
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c" import "core:c"
@@ -154,4 +154,30 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
sem_flg: c.short, /* [PSX] operation flags */ sem_flg: c.short, /* [PSX] operation flags */
} }
} else when ODIN_OS == .Haiku {
SEM_UNDO :: 10 // undo the operation on exit
// Commands for `semctl'.
GETPID :: 3
GETVAL :: 4
GETALL :: 5
GETNCNT :: 6
GETZCNT :: 7
SETVAL :: 8
SETALL :: 9
semid_ds :: struct {
sem_perm: ipc_perm, // [PSX] operation permission structure
sem_nsems: c.ushort, // [PSX] number of semaphores in set
sem_otime: time_t, // [PSX] last semop()
sem_ctime: time_t, // [PSX] last time changed by semctl()
}
sembuf :: struct {
sem_num: c.ushort, /* [PSX] semaphore number */
sem_op: c.short, /* [PSX] semaphore operation */
sem_flg: c.short, /* [PSX] operation flags */
}
} }
+56 -10
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c" import "core:c"
@@ -328,24 +328,32 @@ when ODIN_OS == .NetBSD {
@(private) LSOCKET :: "socket" @(private) LSOCKET :: "socket"
} }
when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku {
socklen_t :: distinct c.uint socklen_t :: distinct c.uint
when ODIN_OS == .Haiku {
@(private)
_SA_DATASIZE :: 30
} else {
@(private)
_SA_DATASIZE :: 14
}
when ODIN_OS == .Linux { when ODIN_OS == .Linux {
_sa_family_t :: distinct c.ushort _sa_family_t :: distinct c.ushort
sockaddr :: struct { sockaddr :: struct {
sa_family: sa_family_t, /* [PSX] address family */ sa_family: sa_family_t, /* [PSX] address family */
sa_data: [14]c.char, /* [PSX] socket address */ sa_data: [_SA_DATASIZE]c.char, /* [PSX] socket address */
} }
} else { } else {
_sa_family_t :: distinct c.uint8_t _sa_family_t :: distinct c.uint8_t
sockaddr :: struct { sockaddr :: struct {
sa_len: c.uint8_t, /* total length */ sa_len: c.uint8_t, /* total length */
sa_family: sa_family_t, /* [PSX] address family */ sa_family: sa_family_t, /* [PSX] address family */
sa_data: [14]c.char, /* [PSX] socket address */ sa_data: [_SA_DATASIZE]c.char, /* [PSX] socket address */
} }
} }
@@ -355,6 +363,11 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
_SS_PAD1SIZE :: 6 _SS_PAD1SIZE :: 6
@(private) @(private)
_SS_PAD2SIZE :: 240 _SS_PAD2SIZE :: 240
} else when ODIN_OS == .Haiku {
@(private)
_SS_PAD1SIZE :: 6
@(private)
_SS_PAD2SIZE :: 112
} else when ODIN_OS == .Linux { } else when ODIN_OS == .Linux {
@(private) @(private)
_SS_SIZE :: 128 _SS_SIZE :: 128
@@ -486,6 +499,26 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
SO_RCVTIMEO :: 66 SO_RCVTIMEO :: 66
SO_SNDTIMEO :: 67 SO_SNDTIMEO :: 67
} else when ODIN_OS == .Haiku {
SOL_SOCKET :: -1
SO_ACCEPTCONN :: 0x00000001
SO_BROADCAST :: 0x00000002
SO_DEBUG :: 0x00000004
SO_DONTROUTE :: 0x00000008
SO_ERROR :: 0x40000007
SO_KEEPALIVE :: 0x00000010
SO_OOBINLINE :: 0x00000020
SO_RCVBUF :: 0x40000004
SO_RCVLOWAT :: 0x40000005
SO_REUSEADDR :: 0x00000040
SO_SNDBUF :: 0x40000001
SO_SNDLOWAT :: 0x40000002
SO_TYPE :: 0x40000008
SO_LINGER :: 0x00000200
SO_RCVTIMEO :: 0x40000006
SO_SNDTIMEO :: 0x40000003
} else { } else {
SOL_SOCKET :: 0xffff SOL_SOCKET :: 0xffff
@@ -523,7 +556,11 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
} }
// The maximum backlog queue length for listen(). // The maximum backlog queue length for listen().
SOMAXCONN :: 128 when ODIN_OS == .Haiku {
SOMAXCONN :: 32
} else {
SOMAXCONN :: 128
}
when ODIN_OS == .Linux { when ODIN_OS == .Linux {
MSG_CTRUNC :: 0x008 MSG_CTRUNC :: 0x008
@@ -549,11 +586,18 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
MSG_NOSIGNAL :: 0x00020000 MSG_NOSIGNAL :: 0x00020000
} else when ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD { } else when ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD {
MSG_NOSIGNAL :: 0x0400 MSG_NOSIGNAL :: 0x0400
} else when ODIN_OS == .Haiku {
MSG_NOSIGNAL :: 0x800
} }
} }
AF_INET :: 2 when ODIN_OS == .Haiku {
AF_UNIX :: 1 AF_INET :: 1
AF_UNIX :: 9
} else {
AF_INET :: 2
AF_UNIX :: 1
}
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
AF_INET6 :: 30 AF_INET6 :: 30
@@ -563,6 +607,8 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
AF_INET6 :: 24 AF_INET6 :: 24
} else when ODIN_OS == .Linux { } else when ODIN_OS == .Linux {
AF_INET6 :: 10 AF_INET6 :: 10
} else when ODIN_OS == .Haiku {
AF_INET6 :: 5
} }
SHUT_RD :: 0 SHUT_RD :: 0
+31 -1
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c" import "core:c"
@@ -428,6 +428,36 @@ when ODIN_OS == .Darwin {
UTIME_NOW :: -2 UTIME_NOW :: -2
UTIME_OMIT :: -1 UTIME_OMIT :: -1
} else when ODIN_OS == .Haiku {
dev_t :: distinct c.int32_t
nlink_t :: distinct c.int32_t
_mode_t :: distinct c.uint32_t
blkcnt_t :: distinct c.int64_t
blksize_t :: distinct c.int32_t
ino_t :: distinct c.int64_t
stat_t :: struct {
st_dev: dev_t, /* [PSX] ID of device containing file */
st_ino: ino_t, /* [PSX] file serial number */
st_mode: mode_t, /* [PSX] mode of file */
st_nlink: nlink_t, /* [PSX] number of hard links */
st_uid: uid_t, /* [PSX] user ID of the file */
st_gid: gid_t, /* [PSX] group ID of the file */
st_size: off_t, /* [PSX] file size, in bytes */
st_rdev: dev_t, /* [PSX] device ID */
st_blksize: blksize_t, /* [PSX] optimal blocksize for I/O */
st_atim: timespec, /* [PSX] time of last access */
st_mtim: timespec, /* [PSX] time of last data modification */
st_ctim: timespec, /* [PSX] time of last status change */
st_crtim: timespec, /* [PSX] time of last status change */
st_type: c.uint32_t,
st_blocks: blkcnt_t, /* [PSX] blocks allocated for file */
}
UTIME_NOW :: 1000000000
UTIME_OMIT :: 1000000001
} else when ODIN_OS == .Linux { } else when ODIN_OS == .Linux {
dev_t :: distinct u64 dev_t :: distinct u64
+12 -1
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c" import "core:c"
@@ -78,4 +78,15 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
ITIMER_VIRTUAL :: 1 ITIMER_VIRTUAL :: 1
ITIMER_PROF :: 2 ITIMER_PROF :: 2
} else when ODIN_OS == .Haiku {
itimerval :: struct {
it_interval: timeval, /* [PSX] timer interval */
it_value: timeval, /* [PSX] current value */
}
ITIMER_REAL :: 1
ITIMER_VIRTUAL :: 2
ITIMER_PROF :: 3
} }
+2 -2
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
@@ -25,7 +25,7 @@ when ODIN_OS == .NetBSD {
@(private) LTIMES :: "times" @(private) LTIMES :: "times"
} }
when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku {
tms :: struct { tms :: struct {
tms_utime: clock_t, /* [PSX] user CPU time */ tms_utime: clock_t, /* [PSX] user CPU time */
+2 -2
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c" import "core:c"
@@ -31,7 +31,7 @@ foreign libc {
writev :: proc(fildes: FD, iov: [^]iovec, iovcnt: c.int) -> c.ssize_t --- writev :: proc(fildes: FD, iov: [^]iovec, iovcnt: c.int) -> c.ssize_t ---
} }
when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku {
iovec :: struct { iovec :: struct {
iov_base: rawptr, /* [PSX] base address of I/O memory region */ iov_base: rawptr, /* [PSX] base address of I/O memory region */
+9 -1
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c" import "core:c"
@@ -20,4 +20,12 @@ when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS
sun_path: [108]c.char, /* [PSX] socket pathname */ sun_path: [108]c.char, /* [PSX] socket pathname */
} }
} else when ODIN_OS == .Haiku {
sockaddr_un :: struct {
sun_len: c.uint8_t,
sun_family: sa_family_t, /* [PSX] address family */
sun_path: [126]c.char, /* [PSX] socket pathname */
}
} }
+3 -3
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c" import "core:c"
@@ -38,10 +38,10 @@ foreign lib {
uname :: proc(uname: ^utsname) -> c.int --- uname :: proc(uname: ^utsname) -> c.int ---
} }
when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD { when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Haiku {
@(private) @(private)
_SYS_NAMELEN :: 256 _SYS_NAMELEN :: 32 when ODIN_OS == .Haiku else 256
utsname :: struct { utsname :: struct {
sysname: [_SYS_NAMELEN]c.char `fmt:"s,0"`, /* [PSX] name of OS */ sysname: [_SYS_NAMELEN]c.char `fmt:"s,0"`, /* [PSX] name of OS */
+53 -1
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c" import "core:c"
@@ -442,4 +442,56 @@ when ODIN_OS == .Darwin {
_WIFCONTINUED :: #force_inline proc "contextless" (x: c.int) -> bool { _WIFCONTINUED :: #force_inline proc "contextless" (x: c.int) -> bool {
return x == 0xffff return x == 0xffff
} }
} else when ODIN_OS == .Haiku {
id_t :: distinct c.int32_t
WCONTINUED :: 0x04
WNOHANG :: 0x01
WUNTRACED :: 0x02
WEXITED :: 0x08
WNOWAIT :: 0x20
WSTOPPED :: 0x10
_P_ALL :: 0
_P_PID :: 1
_P_PGID :: 2
@(private)
_WIFEXITED :: #force_inline proc "contextless" (x: c.int) -> bool {
return (x & ~(c.int)(0xff)) == 0
}
@(private)
_WEXITSTATUS :: #force_inline proc "contextless" (x: c.int) -> c.int {
return x & 0xff
}
@(private)
_WIFSIGNALED :: #force_inline proc "contextless" (x: c.int) -> bool {
return ((x >> 8) & 0xff) != 0
}
@(private)
_WTERMSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
return Signal((x >> 8) & 0xff)
}
@(private)
_WIFSTOPPED :: #force_inline proc "contextless" (x: c.int) -> bool {
return ((x >> 16) & 0xff) != 0
}
@(private)
_WSTOPSIG :: #force_inline proc "contextless" (x: c.int) -> Signal {
return Signal((x >> 16) & 0xff)
}
@(private)
_WIFCONTINUED :: #force_inline proc "contextless" (x: c.int) -> bool {
return (x & 0x20000) != 0
}
} }
+172 -12
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c" import "core:c"
@@ -138,17 +138,30 @@ CLocal_Flag_Bits :: enum tcflag_t {
} }
CLocal_Flags :: bit_set[CLocal_Flag_Bits; tcflag_t] CLocal_Flags :: bit_set[CLocal_Flag_Bits; tcflag_t]
CControl_Flag_Bits :: enum tcflag_t { when ODIN_OS == .Haiku {
// CS5 = log2(CS5), /* 5 bits (pseudo) (default) */ CControl_Flag_Bits :: enum tcflag_t {
CS6 = log2(CS6), /* 6 bits */ // CS7 = log2(CS7), /* 7 bits (default) */
CS7 = log2(CS7), /* 7 bits */ CS8 = log2(CS8), /* 8 bits */
CS8 = log2(CS8), /* 8 bits */ CSTOPB = log2(CSTOPB), /* send 2 stop bits */
CSTOPB = log2(CSTOPB), /* send 2 stop bits */ CREAD = log2(CREAD), /* enable receiver */
CREAD = log2(CREAD), /* enable receiver */ PARENB = log2(PARENB), /* parity enable */
PARENB = log2(PARENB), /* parity enable */ PARODD = log2(PARODD), /* odd parity, else even */
PARODD = log2(PARODD), /* odd parity, else even */ HUPCL = log2(HUPCL), /* hang up on last close */
HUPCL = log2(HUPCL), /* hang up on last close */ CLOCAL = log2(CLOCAL), /* ignore modem status lines */
CLOCAL = log2(CLOCAL), /* ignore modem status lines */ }
} else {
CControl_Flag_Bits :: enum tcflag_t {
// CS5 = log2(CS5), /* 5 bits (pseudo) (default) */
CS6 = log2(CS6), /* 6 bits */
CS7 = log2(CS7), /* 7 bits */
CS8 = log2(CS8), /* 8 bits */
CSTOPB = log2(CSTOPB), /* send 2 stop bits */
CREAD = log2(CREAD), /* enable receiver */
PARENB = log2(PARENB), /* parity enable */
PARODD = log2(PARODD), /* odd parity, else even */
HUPCL = log2(HUPCL), /* hang up on last close */
CLOCAL = log2(CLOCAL), /* ignore modem status lines */
}
} }
CControl_Flags :: bit_set[CControl_Flag_Bits; tcflag_t] CControl_Flags :: bit_set[CControl_Flag_Bits; tcflag_t]
@@ -597,4 +610,151 @@ when ODIN_OS == .Darwin {
TCOOFF :: 0 TCOOFF :: 0
TCOON :: 1 TCOON :: 1
} else when ODIN_OS == .Haiku {
cc_t :: distinct c.uchar
_speed_t :: distinct c.uint32_t
tcflag_t :: distinct c.uint16_t
// Same as speed_t, but 16-bit.
CSpeed :: enum tcflag_t {
B0 = B0,
B50 = B50,
B75 = B75,
B110 = B110,
B134 = B134,
B150 = B150,
B200 = B200,
B300 = B300,
B600 = B600,
B1200 = B1200,
B1800 = B1800,
B2400 = B2400,
B4800 = B4800,
B9600 = B9600,
B19200 = B19200,
B38400 = B38400,
}
termios :: struct {
c_iflag: CInput_Flags, /* [XBD] input flags */
c_ispeed: CSpeed, /* input speed */
c_oflag: COutput_Flags, /* [XBD] output flags */
c_ospeed: CSpeed, /* output speed */
c_cflag: CControl_Flags, /* [XBD] control flags */
c_ispeed_high: tcflag_t, /* high word of input baudrate */
c_lflag: CLocal_Flags, /* [XBD] local flag */
c_ospeed_high: tcflag_t, /* high word of output baudrate */
c_line: c.char,
_padding: c.uchar,
_padding2: c.uchar,
c_cc: [NCCS]cc_t,
}
NCCS :: 11
VINTR :: 0
VQUIT :: 1
VERASE :: 2
VKILL :: 3
VEOF :: 4
VEOL :: 5
VMIN :: 4
VTIME :: 5
VEOL2 :: 6
VSWTCH :: 7
VSTART :: 8
VSTOP :: 9
VSUSP :: 10
IGNBRK :: 0x01 /* ignore break condition */
BRKINT :: 0x02 /* break sends interrupt */
IGNPAR :: 0x04 /* ignore characters with parity errors */
PARMRK :: 0x08 /* mark parity errors */
INPCK :: 0x10 /* enable input parity checking */
ISTRIP :: 0x20 /* strip high bit from characters */
INLCR :: 0x40 /* maps newline to CR on input */
IGNCR :: 0x80 /* ignore carriage returns */
ICRNL :: 0x100 /* map CR to newline on input */
IXON :: 0x400 /* enable input SW flow control */
IXANY :: 0x800 /* any character will restart input */
IXOFF :: 0x1000 /* enable output SW flow control */
OPOST :: 0x01 /* enable postprocessing of output */
ONLCR :: 0x04 /* map NL to CR-NL on output */
OCRNL :: 0x08 /* map CR to NL on output */
ONOCR :: 0x10 /* no CR output when at column 0 */
ONLRET :: 0x20 /* newline performs CR function */
OFILL :: 0x40 /* use fill characters for delays */
OFDEL :: 0x80 /* Fills are DEL, otherwise NUL */
_NLDLY :: 0x100 /* Newline delays: */
NL0 :: 0x000
NL1 :: 0x100
_CRDLY :: 0x600 /* Carriage return delays: */
CR0 :: 0x000
CR1 :: 0x200
CR2 :: 0x400
CR3 :: 0x600
_TABDLY :: 0x1800 /* Tab delays: */
TAB0 :: 0x0000
TAB1 :: 0x0800
TAB3 :: 0x1800
_BSDLY :: 0x2000 /* Backspace delays: */
BS0 :: 0x0000
BS1 :: 0x2000
_VTDLY :: 0x4000 /* Vertical tab delays: */
VT0 :: 0x0000
VT1 :: 0x4000
_FFDLY :: 0x8000 /* Form feed delays: */
FF0 :: 0x0000
FF1 :: 0x8000
B0 :: 0x00 /* hang up */
B50 :: 0x01 /* 50 baud */
B75 :: 0x02
B110 :: 0x03
B134 :: 0x04
B150 :: 0x05
B200 :: 0x06
B300 :: 0x07
B600 :: 0x08
B1200 :: 0x09
B1800 :: 0x0A
B2400 :: 0x0B
B4800 :: 0x0C
B9600 :: 0x0D
B19200 :: 0x0E
B38400 :: 0x0F
_CSIZE :: 0x20 /* character size */
//CS5 :: 0x00 /* only 7 and 8 bits supported */
//CS6 :: 0x00 /* Note, it was not very wise to set all of these */
//CS7 :: 0x00 /* to zero, but there is not much we can do about it*/
CS8 :: 0x20
CSTOPB :: 0x40 /* send 2 stop bits, not 1 */
CREAD :: 0x80 /* enable receiver */
PARENB :: 0x100 /* parity enable */
PARODD :: 0x200 /* odd parity, else even */
HUPCL :: 0x400 /* hangs up on last close */
CLOCAL :: 0x800 /* indicates local line */
ISIG :: 0x01 /* enable signals */
ICANON :: 0x02 /* Canonical input */
ECHO :: 0x08 /* Enable echo */
ECHOE :: 0x10 /* Echo erase as bs-sp-bs */
ECHOK :: 0x20 /* Echo nl after kill */
ECHONL :: 0x40 /* Echo nl */
NOFLSH :: 0x80 /* Disable flush after int or quit */
TOSTOP :: 0x100 /* stop bg processes that write to tty */
IEXTEN :: 0x200 /* implementation defined extensions */
TCIFLUSH :: 1
TCOFLUSH :: 2
TCIOFLUSH :: 3
TCIOFF :: 0x04
TCION :: 0x08
TCOOFF :: 0x01
TCOON :: 0x02
} }
+12 -1
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c" import "core:c"
@@ -230,6 +230,17 @@ when ODIN_OS == .Darwin {
getdate_err: Errno = .ENOSYS // NOTE: looks like it's not a thing on OpenBSD. getdate_err: Errno = .ENOSYS // NOTE: looks like it's not a thing on OpenBSD.
} else when ODIN_OS == .Haiku {
clockid_t :: distinct c.int32_t
CLOCK_MONOTONIC :: 0
CLOCK_PROCESS_CPUTIME_ID :: -2
CLOCK_REALTIME :: -1
CLOCK_THREAD_CPUTIME_ID :: -3
getdate_err: Errno = .ENOSYS // NOTE: looks like it's not a thing on Haiku.
} else when ODIN_OS == .Linux { } else when ODIN_OS == .Linux {
clockid_t :: distinct c.int clockid_t :: distinct c.int
+172 -2
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c" import "core:c"
@@ -1852,7 +1852,7 @@ when ODIN_OS == .Darwin {
_PC_ALLOC_SIZE_MIN :: 19 _PC_ALLOC_SIZE_MIN :: 19
_PC_SYMLINK_MAX :: 20 _PC_SYMLINK_MAX :: 20
_PC_2_SYMLINK :: 21 _PC_2_SYMLINK :: 21
_SC_ARG_MAX :: 1 _SC_ARG_MAX :: 1
_SC_CHILD_MAX :: 2 _SC_CHILD_MAX :: 2
_SC_CLK_TCK :: 3 _SC_CLK_TCK :: 3
@@ -1992,4 +1992,174 @@ when ODIN_OS == .Darwin {
// NOTE: Not implemented. // NOTE: Not implemented.
_POSIX_VDISABLE :: 0 _POSIX_VDISABLE :: 0
} else when ODIN_OS == .Haiku {
_F_OK :: 0
X_OK :: 1
W_OK :: 2
R_OK :: 4
F_LOCK :: 1
F_TEST :: 3
F_TLOCK :: 2
F_ULOCK :: 0
_CS_PATH :: 1
_CS_POSIX_V6_WIDTH_RESTRICTED_ENVS :: 0 // Undefined.
_CS_POSIX_V6_ILP32_OFF32_CFLAGS :: 0 // Undefined.
_CS_POSIX_V6_ILP32_OFF32_LDFLAGS :: 0 // Undefined.
_CS_POSIX_V6_ILP32_OFF32_LIBS :: 0 // Undefined.
_CS_POSIX_V6_ILP32_OFFBIG_CFLAGS :: 0 // Undefined.
_CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS :: 0 // Undefined.
_CS_POSIX_V6_ILP32_OFFBIG_LIBS :: 0 // Undefined.
_CS_POSIX_V6_LP64_OFF64_CFLAGS :: 0 // Undefined.
_CS_POSIX_V6_LP64_OFF64_LDFLAGS :: 0 // Undefined.
_CS_POSIX_V6_LP64_OFF64_LIBS :: 0 // Undefined.
_CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS :: 0 // Undefined.
_CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS :: 0 // Undefined.
_CS_POSIX_V6_LPBIG_OFFBIG_LIBS :: 0 // Undefined.
_SC_ASYNCHRONOUS_IO :: 0 // Undefined.
_SC_RAW_SOCKETS :: 0 // Undefined.
_SC_SS_REPL_MAX :: 0 // Undefined.
_SC_TRACE_EVENT_NAME_MAX :: 0 // Undefined.
_SC_TRACE_NAME_MAX :: 0 // Undefined.
_SC_TRACE_SYS_MAX :: 0 // Undefined.
_SC_TRACE_USER_EVENT_MAX :: 0 // Undefined.
_PC_CHOWN_RESTRICTED :: 1
_PC_MAX_CANON :: 2
_PC_MAX_INPUT :: 3
_PC_NAME_MAX :: 4
_PC_NO_TRUNC :: 5
_PC_PATH_MAX :: 6
_PC_PIPE_BUF :: 7
_PC_VDISABLE :: 8
_PC_LINK_MAX :: 25
_PC_SYNC_IO :: 26
_PC_ASYNC_IO :: 27
_PC_PRIO_IO :: 28
_PC_FILESIZEBITS :: 30
_PC_REC_INCR_XFER_SIZE :: 31
_PC_REC_MAX_XFER_SIZE :: 32
_PC_REC_MIN_XFER_SIZE :: 33
_PC_REC_XFER_ALIGN :: 34
_PC_ALLOC_SIZE_MIN :: 35
_PC_SYMLINK_MAX :: 36
_PC_2_SYMLINK :: 37
_SC_ARG_MAX :: 15
_SC_CHILD_MAX :: 16
_SC_CLK_TCK :: 17
_SC_JOB_CONTROL :: 18
_SC_NGROUPS_MAX :: 19
_SC_OPEN_MAX :: 20
_SC_SAVED_IDS :: 21
_SC_STREAM_MAX :: 22
_SC_TZNAME_MAX :: 23
_SC_VERSION :: 24
_SC_GETGR_R_SIZE_MAX :: 25
_SC_GETPW_R_SIZE_MAX :: 26
_SC_PAGE_SIZE :: 27
_SC_PAGESIZE :: _SC_PAGE_SIZE
_SC_SEM_NSEMS_MAX :: 28
_SC_SEM_VALUE_MAX :: 29
_SC_SEMAPHORES :: 30
_SC_THREADS :: 31
_SC_IOV_MAX :: 32
_SC_NPROCESSORS_CONF :: 34
_SC_NPROCESSORS_ONLN :: 35
_SC_ATEXIT_MAX :: 37
_SC_MAPPED_FILES :: 45
_SC_THREAD_PROCESS_SHARED :: 46
_SC_THREAD_STACK_MIN :: 47
_SC_THREAD_ATTR_STACKADDR :: 48
_SC_THREAD_ATTR_STACKSIZE :: 49
_SC_THREAD_PRIORITY_SCHEDULING :: 50
_SC_REALTIME_SIGNALS :: 51
_SC_MEMORY_PROTECTION :: 52
_SC_SIGQUEUE_MAX :: 53
_SC_RTSIG_MAX :: 54
_SC_MONOTONIC_CLOCK :: 55
_SC_DELAYTIMER_MAX :: 56
_SC_TIMER_MAX :: 57
_SC_TIMERS :: 58
_SC_CPUTIME :: 59
_SC_THREAD_CPUTIME :: 60
_SC_HOST_NAME_MAX :: 61
_SC_REGEXP :: 62
_SC_SYMLOOP_MAX :: 63
_SC_SHELL :: 64
_SC_TTY_NAME_MAX :: 65
_SC_ADVISORY_INFO :: 66
_SC_BARRIERS :: 67
_SC_CLOCK_SELECTION :: 68
_SC_FSYNC :: 69
_SC_IPV6 :: 70
_SC_MEMLOCK :: 71
_SC_MEMLOCK_RANGE :: 72
_SC_MESSAGE_PASSING :: 73
_SC_PRIORITIZED_IO :: 74
_SC_PRIORITY_SCHEDULING :: 75
_SC_READER_WRITER_LOCKS :: 76
_SC_SHARED_MEMORY_OBJECTS :: 77
_SC_SPAWN :: 78
_SC_SPIN_LOCKS :: 79
_SC_SPORADIC_SERVER :: 80
_SC_SYNCHRONIZED_IO :: 81
_SC_THREAD_PRIO_INHERIT :: 82
_SC_THREAD_PRIO_PROTECT :: 83
_SC_THREAD_SAFE_FUNCTIONS :: 86
_SC_THREAD_SPORADIC_SERVER :: 87
_SC_TIMEOUTS :: 88
_SC_TRACE :: 89
_SC_TRACE_EVENT_FILTER :: 90
_SC_TRACE_INHERIT :: 91
_SC_TRACE_LOG :: 92
_SC_TYPED_MEMORY_OBJECTS :: 93
_SC_V6_ILP32_OFF32 :: 94
_SC_V6_ILP32_OFFBIG :: 95
_SC_V6_LP64_OFF64 :: 96
_SC_V6_LPBIG_OFFBIG :: 97
_SC_2_C_BIND :: 102
_SC_2_C_DEV :: 103
_SC_2_CHAR_TERM :: 104
_SC_2_FORT_DEV :: 105
_SC_2_FORT_RUN :: 106
_SC_2_LOCALEDEF :: 107
_SC_2_PBS :: 108
_SC_2_PBS_ACCOUNTING :: 109
_SC_2_PBS_CHECKPOINT :: 110
_SC_2_PBS_LOCATE :: 111
_SC_2_PBS_MESSAGE :: 112
_SC_2_PBS_TRACK :: 113
_SC_2_SW_DEV :: 114
_SC_2_UPE :: 115
_SC_2_VERSION :: 116
_SC_XOPEN_CRYPT :: 117
_SC_XOPEN_ENH_I18N :: 118
_SC_XOPEN_REALTIME :: 119
_SC_XOPEN_REALTIME_THREADS :: 120
_SC_XOPEN_SHM :: 121
_SC_XOPEN_STREAMS :: 122
_SC_XOPEN_UNIX :: 123
_SC_XOPEN_VERSION :: 125
_SC_AIO_LISTIO_MAX :: 126
_SC_AIO_MAX :: 127
_SC_AIO_PRIO_DELTA_MAX :: 128
_SC_BC_BASE_MAX :: 129
_SC_BC_DIM_MAX :: 130
_SC_BC_SCALE_MAX :: 131
_SC_BC_STRING_MAX :: 132
_SC_COLL_WEIGHTS_MAX :: 133
_SC_EXPR_NEST_MAX :: 134
_SC_LINE_MAX :: 135
_SC_LOGIN_NAME_MAX :: 136
_SC_MQ_OPEN_MAX :: 137
_SC_MQ_PRIO_MAX :: 138
_SC_THREAD_DESTRUCTOR_ITERATIONS :: 139
_SC_THREAD_KEYS_MAX :: 140
_SC_THREAD_THREADS_MAX :: 141
_SC_RE_DUP_MAX :: 142
} }
+1 -1
View File
@@ -1,4 +1,4 @@
#+build linux, windows, darwin, netbsd, openbsd, freebsd #+build linux, windows, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
import "core:c" import "core:c"
+2 -2
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
package posix package posix
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
@@ -25,7 +25,7 @@ when ODIN_OS == .NetBSD {
@(private) LUTIME :: "utime" @(private) LUTIME :: "utime"
} }
when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux { when ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .OpenBSD || ODIN_OS == .Linux || ODIN_OS == .Haiku {
utimbuf :: struct { utimbuf :: struct {
actime: time_t, /* [PSX] access time (seconds since epoch) */ actime: time_t, /* [PSX] access time (seconds since epoch) */
+4 -1
View File
@@ -110,7 +110,10 @@ class WasmMemoryInterface {
} }
loadCstring(ptr) { loadCstring(ptr) {
const start = this.loadPtr(ptr); return this.loadCstringDirect(this.loadPtr(ptr));
}
loadCstringDirect(start) {
if (start == 0) { if (start == 0) {
return null; return null;
} }
+1
View File
@@ -6,4 +6,5 @@ foreign import "system:Comctl32.lib"
@(default_calling_convention="system") @(default_calling_convention="system")
foreign Comctl32 { foreign Comctl32 {
LoadIconWithScaleDown :: proc(hinst: HINSTANCE, pszName: PCWSTR, cx: c_int, cy: c_int, phico: ^HICON) -> HRESULT --- LoadIconWithScaleDown :: proc(hinst: HINSTANCE, pszName: PCWSTR, cx: c_int, cy: c_int, phico: ^HICON) -> HRESULT ---
SetWindowSubclass :: proc(hwnd: HWND, pfnSubclass: SUBCLASSPROC, uIdSubclass: UINT_PTR, dwRefData: DWORD_PTR) ---
} }
+1 -1
View File
@@ -15,7 +15,7 @@ MINIDUMP_DIRECTORY :: struct {
Location: MINIDUMP_LOCATION_DESCRIPTOR, Location: MINIDUMP_LOCATION_DESCRIPTOR,
} }
MINIDUMP_EXCEPTION_INFORMATION :: struct { MINIDUMP_EXCEPTION_INFORMATION :: struct #max_field_align(4) {
ThreadId: DWORD, ThreadId: DWORD,
ExceptionPointers: ^EXCEPTION_POINTERS, ExceptionPointers: ^EXCEPTION_POINTERS,
ClientPointers: BOOL, ClientPointers: BOOL,
+2
View File
@@ -796,6 +796,8 @@ TIMERPROC :: #type proc "system" (HWND, UINT, UINT_PTR, DWORD)
WNDPROC :: #type proc "system" (HWND, UINT, WPARAM, LPARAM) -> LRESULT WNDPROC :: #type proc "system" (HWND, UINT, WPARAM, LPARAM) -> LRESULT
SUBCLASSPROC :: #type proc "system" (HWND, UINT, WPARAM, LPARAM, UINT_PTR, DWORD_PTR) -> LRESULT
HOOKPROC :: #type proc "system" (code: c_int, wParam: WPARAM, lParam: LPARAM) -> LRESULT HOOKPROC :: #type proc "system" (code: c_int, wParam: WPARAM, lParam: LPARAM) -> LRESULT
WINEVENTPROC :: #type proc "system" ( WINEVENTPROC :: #type proc "system" (
+4 -1
View File
@@ -2,6 +2,7 @@
package sys_windows package sys_windows
import "base:intrinsics" import "base:intrinsics"
import "core:c"
foreign import user32 "system:User32.lib" foreign import user32 "system:User32.lib"
@(default_calling_convention="system") @(default_calling_convention="system")
@@ -32,6 +33,8 @@ foreign user32 {
RegisterClassExW :: proc(^WNDCLASSEXW) -> ATOM --- RegisterClassExW :: proc(^WNDCLASSEXW) -> ATOM ---
UnregisterClassW :: proc(lpClassName: LPCWSTR, hInstance: HINSTANCE) -> BOOL --- UnregisterClassW :: proc(lpClassName: LPCWSTR, hInstance: HINSTANCE) -> BOOL ---
RegisterHotKey :: proc(hnwd: HWND, id: c.int, fsModifiers: UINT, vk: UINT) -> BOOL ---
CreateWindowExW :: proc( CreateWindowExW :: proc(
dwExStyle: DWORD, dwExStyle: DWORD,
lpClassName: LPCWSTR, lpClassName: LPCWSTR,
@@ -553,7 +556,7 @@ MOUSE_ATTRIBUTES_CHANGED :: 0x04
MOUSE_MOVE_NOCOALESCE :: 0x08 MOUSE_MOVE_NOCOALESCE :: 0x08
RI_MOUSE_BUTTON_1_DOWN :: 0x0001 RI_MOUSE_BUTTON_1_DOWN :: 0x0001
RI_MOUSE_LEFT_BUTTON_DOWNS :: RI_MOUSE_BUTTON_1_DOWN RI_MOUSE_LEFT_BUTTON_DOWN :: RI_MOUSE_BUTTON_1_DOWN
RI_MOUSE_BUTTON_1_UP :: 0x0002 RI_MOUSE_BUTTON_1_UP :: 0x0002
RI_MOUSE_LEFT_BUTTON_UP :: RI_MOUSE_BUTTON_1_UP RI_MOUSE_LEFT_BUTTON_UP :: RI_MOUSE_BUTTON_1_UP
RI_MOUSE_BUTTON_2_DOWN :: 0x0004 RI_MOUSE_BUTTON_2_DOWN :: 0x0004
+1
View File
@@ -391,6 +391,7 @@ runner :: proc(internal_tests: []Internal_Test) -> bool {
fmt.assertf(alloc_error == nil, "Error allocating memory for task allocator #%i: %v", i, alloc_error) fmt.assertf(alloc_error == nil, "Error allocating memory for task allocator #%i: %v", i, alloc_error)
when TRACKING_MEMORY { when TRACKING_MEMORY {
mem.tracking_allocator_init(&task_memory_trackers[i], mem.rollback_stack_allocator(&task_allocators[i])) mem.tracking_allocator_init(&task_memory_trackers[i], mem.rollback_stack_allocator(&task_allocators[i]))
task_memory_trackers[i].bad_free_callback = mem.tracking_allocator_bad_free_callback_add_to_array
} }
} }
+1 -1
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, netbsd, openbsd, freebsd #+build linux, darwin, netbsd, openbsd, freebsd, haiku
#+private #+private
package testing package testing
+1
View File
@@ -9,6 +9,7 @@
#+build !wasi #+build !wasi
#+build !windows #+build !windows
#+build !orca #+build !orca
#+build !haiku
package time package time
_IS_SUPPORTED :: false _IS_SUPPORTED :: false
+1 -1
View File
@@ -1,5 +1,5 @@
#+private #+private
#+build darwin, freebsd, openbsd, netbsd #+build darwin, freebsd, openbsd, netbsd, haiku
package time package time
import "core:sys/posix" import "core:sys/posix"
+59 -6
View File
@@ -894,15 +894,49 @@ gb_internal void error_var_decl_identifier(Ast *name) {
} }
} }
gb_internal void check_inline_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) { gb_internal void check_unroll_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) {
ast_node(irs, UnrollRangeStmt, node); ast_node(irs, UnrollRangeStmt, node);
check_open_scope(ctx, node); check_open_scope(ctx, node);
defer (check_close_scope(ctx));
Type *val0 = nullptr; Type *val0 = nullptr;
Type *val1 = nullptr; Type *val1 = nullptr;
Entity *entities[2] = {}; Entity *entities[2] = {};
isize entity_count = 0; isize entity_count = 0;
i64 unroll_count = -1;
if (irs->args.count > 0) {
if (irs->args.count > 1) {
error(irs->args[1], "#unroll only supports a single argument for the unroll per loop amount");
}
Ast *arg = irs->args[0];
if (arg->kind == Ast_FieldValue) {
error(arg, "#unroll does not yet support named arguments");
arg = arg->FieldValue.value;
}
Operand x = {};
check_expr(ctx, &x, arg);
if (x.mode != Addressing_Constant || !is_type_integer(x.type)) {
gbString s = expr_to_string(x.expr);
error(x.expr, "Expected a constant integer for #unroll, got '%s'", s);
gb_string_free(s);
} else {
ExactValue value = exact_value_to_integer(x.value);
i64 v = exact_value_to_i64(value);
if (v < 1) {
error(x.expr, "Expected a constant integer >= 1 for #unroll, got %lld", cast(long long)v);
} else {
unroll_count = v;
if (v > 1024) {
error(x.expr, "Too large of a value for #unroll, got %lld, expected <= 1024", cast(long long)v);
}
}
}
}
Ast *expr = unparen_expr(irs->expr); Ast *expr = unparen_expr(irs->expr);
ExactValue inline_for_depth = exact_value_i64(0); ExactValue inline_for_depth = exact_value_i64(0);
@@ -946,18 +980,39 @@ gb_internal void check_inline_range_stmt(CheckerContext *ctx, Ast *node, u32 mod
val0 = t_rune; val0 = t_rune;
val1 = t_int; val1 = t_int;
inline_for_depth = exact_value_i64(operand.value.value_string.len); inline_for_depth = exact_value_i64(operand.value.value_string.len);
if (unroll_count > 0) {
error(node, "#unroll(%lld) does not support strings", cast(long long)unroll_count);
}
} }
break; break;
case Type_Array: case Type_Array:
val0 = t->Array.elem; val0 = t->Array.elem;
val1 = t_int; val1 = t_int;
inline_for_depth = exact_value_i64(t->Array.count); inline_for_depth = unroll_count > 0 ? exact_value_i64(unroll_count) : exact_value_i64(t->Array.count);
break; break;
case Type_EnumeratedArray: case Type_EnumeratedArray:
val0 = t->EnumeratedArray.elem; val0 = t->EnumeratedArray.elem;
val1 = t->EnumeratedArray.index; val1 = t->EnumeratedArray.index;
if (unroll_count > 0) {
error(node, "#unroll(%lld) does not support enumerated arrays", cast(long long)unroll_count);
}
inline_for_depth = exact_value_i64(t->EnumeratedArray.count); inline_for_depth = exact_value_i64(t->EnumeratedArray.count);
break; break;
case Type_Slice:
if (unroll_count > 0) {
val0 = t->Slice.elem;
val1 = t_int;
inline_for_depth = exact_value_i64(unroll_count);
}
break;
case Type_DynamicArray:
if (unroll_count > 0) {
val0 = t->DynamicArray.elem;
val1 = t_int;
inline_for_depth = exact_value_i64(unroll_count);
}
break;
} }
} }
@@ -967,7 +1022,7 @@ gb_internal void check_inline_range_stmt(CheckerContext *ctx, Ast *node, u32 mod
error(operand.expr, "Cannot iterate over '%s' of type '%s' in an '#unroll for' statement", s, t); error(operand.expr, "Cannot iterate over '%s' of type '%s' in an '#unroll for' statement", s, t);
gb_string_free(t); gb_string_free(t);
gb_string_free(s); gb_string_free(s);
} else if (operand.mode != Addressing_Constant) { } else if (operand.mode != Addressing_Constant && unroll_count <= 0) {
error(operand.expr, "An '#unroll for' expression must be known at compile time"); error(operand.expr, "An '#unroll for' expression must be known at compile time");
} }
} }
@@ -1050,8 +1105,6 @@ gb_internal void check_inline_range_stmt(CheckerContext *ctx, Ast *node, u32 mod
check_stmt(ctx, irs->body, mod_flags); check_stmt(ctx, irs->body, mod_flags);
check_close_scope(ctx);
} }
gb_internal void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) { gb_internal void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) {
@@ -2679,7 +2732,7 @@ gb_internal void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags)
case_end; case_end;
case_ast_node(irs, UnrollRangeStmt, node); case_ast_node(irs, UnrollRangeStmt, node);
check_inline_range_stmt(ctx, node, mod_flags); check_unroll_range_stmt(ctx, node, mod_flags);
case_end; case_end;
case_ast_node(ss, SwitchStmt, node); case_ast_node(ss, SwitchStmt, node);
+8 -5
View File
@@ -408,13 +408,18 @@ gb_internal LLVMMetadataRef lb_debug_union(lbModule *m, Type *type, String name,
lb_set_llvm_metadata(m, type, temp_forward_decl); lb_set_llvm_metadata(m, type, temp_forward_decl);
isize index_offset = 1; isize index_offset = 1;
isize variant_offset = 1;
if (is_type_union_maybe_pointer(bt)) { if (is_type_union_maybe_pointer(bt)) {
index_offset = 0; index_offset = 0;
variant_offset = 0;
} else if (bt->Union.kind == UnionType_no_nil) {
variant_offset = 0;
} }
LLVMMetadataRef member_scope = lb_get_llvm_metadata(m, bt->Union.scope); LLVMMetadataRef member_scope = lb_get_llvm_metadata(m, bt->Union.scope);
unsigned element_count = cast(unsigned)bt->Union.variants.count; unsigned element_count = cast(unsigned)bt->Union.variants.count;
if (index_offset > 0) { if (index_offset > 0) {
GB_ASSERT(index_offset == 1);
element_count += 1; element_count += 1;
} }
@@ -437,13 +442,11 @@ gb_internal LLVMMetadataRef lb_debug_union(lbModule *m, Type *type, String name,
for_array(j, bt->Union.variants) { for_array(j, bt->Union.variants) {
Type *variant = bt->Union.variants[j]; Type *variant = bt->Union.variants[j];
unsigned field_index = cast(unsigned)(index_offset+j); char name[32] = {};
gb_snprintf(name, gb_size_of(name), "v%td", variant_offset+j);
char name[16] = {};
gb_snprintf(name, gb_size_of(name), "v%u", field_index);
isize name_len = gb_strlen(name); isize name_len = gb_strlen(name);
elements[field_index] = LLVMDIBuilderCreateMemberType( elements[index_offset+j] = LLVMDIBuilderCreateMemberType(
m->debug_builder, member_scope, m->debug_builder, member_scope,
name, name_len, name, name_len,
file, line, file, line,
+184 -55
View File
@@ -256,7 +256,7 @@ gb_internal void lb_build_when_stmt(lbProcedure *p, AstWhenStmt *ws) {
gb_internal void lb_build_range_indexed(lbProcedure *p, lbValue expr, Type *val_type, lbValue count_ptr, gb_internal void lb_build_range_indexed(lbProcedure *p, lbValue expr, Type *val_type, lbValue count_ptr,
lbValue *val_, lbValue *idx_, lbBlock **loop_, lbBlock **done_, lbValue *val_, lbValue *idx_, lbBlock **loop_, lbBlock **done_,
bool is_reverse) { bool is_reverse, i64 unroll_count=0) {
lbModule *m = p->module; lbModule *m = p->module;
lbValue count = {}; lbValue count = {};
@@ -1230,7 +1230,6 @@ gb_internal void lb_build_unroll_range_stmt(lbProcedure *p, AstUnrollRangeStmt *
TypeAndValue tav = type_and_value_of_expr(expr); TypeAndValue tav = type_and_value_of_expr(expr);
if (is_ast_range(expr)) { if (is_ast_range(expr)) {
lbAddr val0_addr = {}; lbAddr val0_addr = {};
lbAddr val1_addr = {}; lbAddr val1_addr = {};
if (val0_type) val0_addr = lb_build_addr(p, val0); if (val0_type) val0_addr = lb_build_addr(p, val0);
@@ -1268,7 +1267,6 @@ gb_internal void lb_build_unroll_range_stmt(lbProcedure *p, AstUnrollRangeStmt *
} }
} }
} else if (tav.mode == Addressing_Type) { } else if (tav.mode == Addressing_Type) {
GB_ASSERT(is_type_enum(type_deref(tav.type))); GB_ASSERT(is_type_enum(type_deref(tav.type)));
Type *et = type_deref(tav.type); Type *et = type_deref(tav.type);
@@ -1293,72 +1291,203 @@ gb_internal void lb_build_unroll_range_stmt(lbProcedure *p, AstUnrollRangeStmt *
if (val0_type) val0_addr = lb_build_addr(p, val0); if (val0_type) val0_addr = lb_build_addr(p, val0);
if (val1_type) val1_addr = lb_build_addr(p, val1); if (val1_type) val1_addr = lb_build_addr(p, val1);
GB_ASSERT(expr->tav.mode == Addressing_Constant); ExactValue unroll_count_ev = {};
if (rs->args.count != 0) {
Type *t = base_type(expr->tav.type); unroll_count_ev = rs->args[0]->tav.value;
}
switch (t->kind) { if (unroll_count_ev.kind == ExactValue_Invalid) {
case Type_Basic: GB_ASSERT(expr->tav.mode == Addressing_Constant);
GB_ASSERT(is_type_string(t));
{
ExactValue value = expr->tav.value;
GB_ASSERT(value.kind == ExactValue_String);
String str = value.value_string;
Rune codepoint = 0;
isize offset = 0;
do {
isize width = utf8_decode(str.text+offset, str.len-offset, &codepoint);
if (val0_type) lb_addr_store(p, val0_addr, lb_const_value(m, val0_type, exact_value_i64(codepoint)));
if (val1_type) lb_addr_store(p, val1_addr, lb_const_value(m, val1_type, exact_value_i64(offset)));
lb_build_stmt(p, rs->body);
offset += width; Type *t = base_type(expr->tav.type);
} while (offset < str.len);
}
break;
case Type_Array:
if (t->Array.count > 0) {
lbValue val = lb_build_expr(p, expr);
lbValue val_addr = lb_address_from_load_or_generate_local(p, val);
for (i64 i = 0; i < t->Array.count; i++) { switch (t->kind) {
if (val0_type) { case Type_Basic:
// NOTE(bill): Due to weird legacy issues in LLVM, this needs to be an i32 GB_ASSERT(is_type_string(t));
lbValue elem = lb_emit_array_epi(p, val_addr, cast(i32)i); {
lb_addr_store(p, val0_addr, lb_emit_load(p, elem)); ExactValue value = expr->tav.value;
GB_ASSERT(value.kind == ExactValue_String);
String str = value.value_string;
Rune codepoint = 0;
isize offset = 0;
do {
isize width = utf8_decode(str.text+offset, str.len-offset, &codepoint);
if (val0_type) lb_addr_store(p, val0_addr, lb_const_value(m, val0_type, exact_value_i64(codepoint)));
if (val1_type) lb_addr_store(p, val1_addr, lb_const_value(m, val1_type, exact_value_i64(offset)));
lb_build_stmt(p, rs->body);
offset += width;
} while (offset < str.len);
}
break;
case Type_Array:
if (t->Array.count > 0) {
lbValue val = lb_build_expr(p, expr);
lbValue val_addr = lb_address_from_load_or_generate_local(p, val);
for (i64 i = 0; i < t->Array.count; i++) {
if (val0_type) {
// NOTE(bill): Due to weird legacy issues in LLVM, this needs to be an i32
lbValue elem = lb_emit_array_epi(p, val_addr, cast(i32)i);
lb_addr_store(p, val0_addr, lb_emit_load(p, elem));
}
if (val1_type) lb_addr_store(p, val1_addr, lb_const_value(m, val1_type, exact_value_i64(i)));
lb_build_stmt(p, rs->body);
} }
if (val1_type) lb_addr_store(p, val1_addr, lb_const_value(m, val1_type, exact_value_i64(i)));
lb_build_stmt(p, rs->body); }
break;
case Type_EnumeratedArray:
if (t->EnumeratedArray.count > 0) {
lbValue val = lb_build_expr(p, expr);
lbValue val_addr = lb_address_from_load_or_generate_local(p, val);
for (i64 i = 0; i < t->EnumeratedArray.count; i++) {
if (val0_type) {
// NOTE(bill): Due to weird legacy issues in LLVM, this needs to be an i32
lbValue elem = lb_emit_array_epi(p, val_addr, cast(i32)i);
lb_addr_store(p, val0_addr, lb_emit_load(p, elem));
}
if (val1_type) {
ExactValue idx = exact_value_add(exact_value_i64(i), *t->EnumeratedArray.min_value);
lb_addr_store(p, val1_addr, lb_const_value(m, val1_type, idx));
}
lb_build_stmt(p, rs->body);
}
}
break;
default:
GB_PANIC("Invalid '#unroll for' type");
break;
}
} else {
////////////////////////////////
// //
// #unroll(N) logic //
// //
////////////////////////////////
i64 unroll_count = exact_value_to_i64(unroll_count_ev);
gb_unused(unroll_count);
Type *t = base_type(expr->tav.type);
lbValue data_ptr = {};
lbValue count_ptr = {};
switch (t->kind) {
case Type_Slice:
case Type_DynamicArray: {
lbValue slice = lb_build_expr(p, expr);
if (is_type_pointer(slice.type)) {
count_ptr = lb_emit_struct_ep(p, slice, 1);
slice = lb_emit_load(p, slice);
} else {
count_ptr = lb_add_local_generated(p, t_int, false).addr;
lb_emit_store(p, count_ptr, lb_slice_len(p, slice));
}
data_ptr = lb_emit_struct_ev(p, slice, 0);
break;
}
case Type_Array: {
lbValue array = lb_build_expr(p, expr);
count_ptr = lb_add_local_generated(p, t_int, false).addr;
lb_emit_store(p, count_ptr, lb_const_int(p->module, t_int, t->Array.count));
if (!is_type_pointer(array.type)) {
array = lb_address_from_load_or_generate_local(p, array);
} }
GB_ASSERT(is_type_pointer(array.type));
data_ptr = lb_emit_conv(p, array, alloc_type_pointer(t->Array.elem));
break;
} }
break;
case Type_EnumeratedArray:
if (t->EnumeratedArray.count > 0) {
lbValue val = lb_build_expr(p, expr);
lbValue val_addr = lb_address_from_load_or_generate_local(p, val);
for (i64 i = 0; i < t->EnumeratedArray.count; i++) { default:
if (val0_type) { GB_PANIC("Invalid '#unroll for' type");
// NOTE(bill): Due to weird legacy issues in LLVM, this needs to be an i32 break;
lbValue elem = lb_emit_array_epi(p, val_addr, cast(i32)i); }
lb_addr_store(p, val0_addr, lb_emit_load(p, elem));
} data_ptr.type = alloc_type_multi_pointer_to_pointer(data_ptr.type);
if (val1_type) {
ExactValue idx = exact_value_add(exact_value_i64(i), *t->EnumeratedArray.min_value); lbBlock *loop_top = lb_create_block(p, "for.unroll.loop.top");
lb_addr_store(p, val1_addr, lb_const_value(m, val1_type, idx));
} lbBlock *body_top = lb_create_block(p, "for.unroll.body.top");
lbBlock *body_bot = lb_create_block(p, "for.unroll.body.bot");
lbBlock *done = lb_create_block(p, "for.unroll.done");
lbBlock *loop_bot = unroll_count > 1 ? lb_create_block(p, "for.unroll.loop.bot") : done;
/*
i := 0
for ; i+N <= len(array); i += N {
body
}
for ; i < len(array); i += 1 {
body
}
*/
Entity *val_entity = val0 ? entity_of_node(val0) : nullptr;
Entity *idx_entity = val1 ? entity_of_node(val1) : nullptr;
lbAddr val_addr = lb_add_local(p, type_deref(data_ptr.type, true), val_entity);
lbAddr idx_addr = lb_add_local(p, t_int, idx_entity);
lb_addr_store(p, idx_addr, lb_const_nil(p->module, t_int));
lb_emit_jump(p, loop_top);
lb_start_block(p, loop_top);
lbValue idx_add_n = lb_addr_load(p, idx_addr);
idx_add_n = lb_emit_arith(p, Token_Add, idx_add_n, lb_const_int(p->module, t_int, unroll_count), t_int);
lbValue cond_top = lb_emit_comp(p, Token_LtEq, idx_add_n, lb_emit_load(p, count_ptr));
lb_emit_if(p, cond_top, body_top, loop_bot);
lb_start_block(p, body_top);
for (i64 top = 0; top < unroll_count; top++) {
lbValue idx = lb_addr_load(p, idx_addr);
lbValue val = lb_emit_load(p, lb_emit_ptr_offset(p, data_ptr, idx));
lb_addr_store(p, val_addr, val);
lb_build_stmt(p, rs->body);
lb_emit_increment(p, lb_addr_get_ptr(p, idx_addr));
}
lb_emit_jump(p, loop_top);
if (unroll_count > 1) {
lb_start_block(p, loop_bot);
lbValue cond_bot = lb_emit_comp(p, Token_Lt, lb_addr_load(p, idx_addr), lb_emit_load(p, count_ptr));
lb_emit_if(p, cond_bot, body_bot, done);
lb_start_block(p, body_bot);
{
lbValue idx = lb_addr_load(p, idx_addr);
lbValue val = lb_emit_load(p, lb_emit_ptr_offset(p, data_ptr, idx));
lb_addr_store(p, val_addr, val);
lb_build_stmt(p, rs->body); lb_build_stmt(p, rs->body);
}
lb_emit_increment(p, lb_addr_get_ptr(p, idx_addr));
}
lb_emit_jump(p, loop_bot);
} }
break;
default: lb_close_scope(p, lbDeferExit_Default, nullptr, rs->body);
GB_PANIC("Invalid '#unroll for' type"); lb_emit_jump(p, done);
break; lb_start_block(p, done);
return;
} }
} }
+47 -11
View File
@@ -348,10 +348,11 @@ gb_internal Ast *clone_ast(Ast *node, AstFile *f) {
n->RangeStmt.body = clone_ast(n->RangeStmt.body, f); n->RangeStmt.body = clone_ast(n->RangeStmt.body, f);
break; break;
case Ast_UnrollRangeStmt: case Ast_UnrollRangeStmt:
n->UnrollRangeStmt.val0 = clone_ast(n->UnrollRangeStmt.val0, f); n->UnrollRangeStmt.args = clone_ast_array(n->UnrollRangeStmt.args, f);
n->UnrollRangeStmt.val1 = clone_ast(n->UnrollRangeStmt.val1, f); n->UnrollRangeStmt.val0 = clone_ast(n->UnrollRangeStmt.val0, f);
n->UnrollRangeStmt.expr = clone_ast(n->UnrollRangeStmt.expr, f); n->UnrollRangeStmt.val1 = clone_ast(n->UnrollRangeStmt.val1, f);
n->UnrollRangeStmt.body = clone_ast(n->UnrollRangeStmt.body, f); n->UnrollRangeStmt.expr = clone_ast(n->UnrollRangeStmt.expr, f);
n->UnrollRangeStmt.body = clone_ast(n->UnrollRangeStmt.body, f);
break; break;
case Ast_CaseClause: case Ast_CaseClause:
n->CaseClause.list = clone_ast_array(n->CaseClause.list, f); n->CaseClause.list = clone_ast_array(n->CaseClause.list, f);
@@ -1037,15 +1038,16 @@ gb_internal Ast *ast_range_stmt(AstFile *f, Token token, Slice<Ast *> vals, Toke
return result; return result;
} }
gb_internal Ast *ast_unroll_range_stmt(AstFile *f, Token unroll_token, Token for_token, Ast *val0, Ast *val1, Token in_token, Ast *expr, Ast *body) { gb_internal Ast *ast_unroll_range_stmt(AstFile *f, Token unroll_token, Slice<Ast *> args, Token for_token, Ast *val0, Ast *val1, Token in_token, Ast *expr, Ast *body) {
Ast *result = alloc_ast_node(f, Ast_UnrollRangeStmt); Ast *result = alloc_ast_node(f, Ast_UnrollRangeStmt);
result->UnrollRangeStmt.unroll_token = unroll_token; result->UnrollRangeStmt.unroll_token = unroll_token;
result->UnrollRangeStmt.args = args;
result->UnrollRangeStmt.for_token = for_token; result->UnrollRangeStmt.for_token = for_token;
result->UnrollRangeStmt.val0 = val0; result->UnrollRangeStmt.val0 = val0;
result->UnrollRangeStmt.val1 = val1; result->UnrollRangeStmt.val1 = val1;
result->UnrollRangeStmt.in_token = in_token; result->UnrollRangeStmt.in_token = in_token;
result->UnrollRangeStmt.expr = expr; result->UnrollRangeStmt.expr = expr;
result->UnrollRangeStmt.body = body; result->UnrollRangeStmt.body = body;
return result; return result;
} }
@@ -5137,6 +5139,40 @@ gb_internal Ast *parse_attribute(AstFile *f, Token token, TokenKind open_kind, T
gb_internal Ast *parse_unrolled_for_loop(AstFile *f, Token unroll_token) { gb_internal Ast *parse_unrolled_for_loop(AstFile *f, Token unroll_token) {
Array<Ast *> args = {};
if (allow_token(f, Token_OpenParen)) {
f->expr_level++;
if (f->curr_token.kind == Token_CloseParen) {
syntax_error(f->curr_token, "#unroll expected at least 1 argument, got 0");
} else {
args = array_make<Ast *>(ast_allocator(f));
while (f->curr_token.kind != Token_CloseParen &&
f->curr_token.kind != Token_EOF) {
Ast *arg = nullptr;
arg = parse_value(f);
if (f->curr_token.kind == Token_Eq) {
Token eq = expect_token(f, Token_Eq);
if (arg != nullptr && arg->kind != Ast_Ident) {
syntax_error(arg, "Expected an identifier for 'key=value'");
}
Ast *value = parse_value(f);
arg = ast_field_value(f, arg, value, eq);
}
array_add(&args, arg);
if (!allow_field_separator(f)) {
break;
}
}
}
f->expr_level--;
Token close = expect_closing(f, Token_CloseParen, str_lit("#unroll"));
gb_unused(close);
}
Token for_token = expect_token(f, Token_for); Token for_token = expect_token(f, Token_for);
Ast *val0 = nullptr; Ast *val0 = nullptr;
Ast *val1 = nullptr; Ast *val1 = nullptr;
@@ -5180,7 +5216,7 @@ gb_internal Ast *parse_unrolled_for_loop(AstFile *f, Token unroll_token) {
if (bad_stmt) { if (bad_stmt) {
return ast_bad_stmt(f, unroll_token, f->curr_token); return ast_bad_stmt(f, unroll_token, f->curr_token);
} }
return ast_unroll_range_stmt(f, unroll_token, for_token, val0, val1, in_token, expr, body); return ast_unroll_range_stmt(f, unroll_token, slice_from_array(args), for_token, val0, val1, in_token, expr, body);
} }
gb_internal Ast *parse_stmt(AstFile *f) { gb_internal Ast *parse_stmt(AstFile *f) {
+1
View File
@@ -563,6 +563,7 @@ AST_KIND(_ComplexStmtBegin, "", bool) \
AST_KIND(UnrollRangeStmt, "#unroll range statement", struct { \ AST_KIND(UnrollRangeStmt, "#unroll range statement", struct { \
Scope *scope; \ Scope *scope; \
Token unroll_token; \ Token unroll_token; \
Slice<Ast *> args; \
Token for_token; \ Token for_token; \
Ast *val0; \ Ast *val0; \
Ast *val1; \ Ast *val1; \
@@ -11,6 +11,7 @@ import "core:log"
test_rbtree_integer :: proc(t: ^testing.T, $Key: typeid, $Value: typeid) { test_rbtree_integer :: proc(t: ^testing.T, $Key: typeid, $Value: typeid) {
track: mem.Tracking_Allocator track: mem.Tracking_Allocator
mem.tracking_allocator_init(&track, context.allocator) mem.tracking_allocator_init(&track, context.allocator)
track.bad_free_callback = mem.tracking_allocator_bad_free_callback_add_to_array
defer mem.tracking_allocator_destroy(&track) defer mem.tracking_allocator_destroy(&track)
context.allocator = mem.tracking_allocator(&track) context.allocator = mem.tracking_allocator(&track)
+32 -14
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, freebsd, openbsd, netbsd #+build linux, darwin, freebsd, openbsd, netbsd, haiku
package tests_core_posix package tests_core_posix
import "core:log" import "core:log"
@@ -65,8 +65,17 @@ test_dirent :: proc(t: ^testing.T) {
for entry in entries { for entry in entries {
defer posix.free(entry) defer posix.free(entry)
if entry.d_type != .REG { when ODIN_OS == .Haiku {
continue stat: posix.stat_t
posix.stat(cstring(raw_data(entry.d_name[:])), &stat)
if !posix.S_ISREG(stat.st_mode) {
continue
}
} else {
if entry.d_type != .REG {
continue
}
} }
name := string(cstring(raw_data(entry.d_name[:]))) name := string(cstring(raw_data(entry.d_name[:])))
@@ -86,8 +95,17 @@ test_dirent :: proc(t: ^testing.T) {
break break
} }
if entry.d_type != .REG { when ODIN_OS == .Haiku {
continue stat: posix.stat_t
posix.stat(cstring(raw_data(entry.d_name[:])), &stat)
if !posix.S_ISREG(stat.st_mode) {
continue
}
} else {
if entry.d_type != .REG {
continue
}
} }
name := string(cstring(raw_data(entry.d_name[:]))) name := string(cstring(raw_data(entry.d_name[:])))
@@ -140,15 +158,15 @@ test_langinfo :: proc(t: ^testing.T) {
@(test) @(test)
test_libgen :: proc(t: ^testing.T) { test_libgen :: proc(t: ^testing.T) {
tests := [][3]cstring{ tests := [][3]cstring{
{ "usr", ".", "usr" }, { "usr", ".", "usr" },
{ "usr/", ".", "usr" }, { "usr/", ".", "usr" },
{ "", ".", "." }, { "", ".", "." },
{ "/", "/", "/" }, { "/", "/", "/" },
{ "///", "/", "/" }, { "///", "/", "/" },
{ "/usr/", "/", "usr" }, { "/usr/", "/", "usr" },
{ "/usr/lib", "/usr", "lib" }, { "/usr/lib", "/usr", "lib" },
{ "//usr//lib//", "//usr", "lib" }, { "//usr//lib//", "//usr" + ("/" when ODIN_OS == .Haiku else ""), "lib" },
{ "/home//dwc//test", "/home//dwc", "test" }, { "/home//dwc//test", "/home//dwc" + ("/" when ODIN_OS == .Haiku else ""), "test" },
} }
for test in tests { for test in tests {
+1 -1
View File
@@ -1,4 +1,4 @@
#+build linux, darwin, freebsd, openbsd, netbsd #+build linux, darwin, freebsd, openbsd, netbsd, haiku
package tests_core_posix package tests_core_posix
import "core:log" import "core:log"
+13
View File
@@ -10,7 +10,11 @@
#include <netdb.h> #include <netdb.h>
#include <poll.h> #include <poll.h>
#include <pwd.h> #include <pwd.h>
#ifndef __HAIKU__
#include <sys/shm.h> #include <sys/shm.h>
#endif
#include <sys/ipc.h> #include <sys/ipc.h>
#include <sys/msg.h> #include <sys/msg.h>
#include <sys/un.h> #include <sys/un.h>
@@ -25,7 +29,11 @@
#include <sys/statvfs.h> #include <sys/statvfs.h>
#include <sys/time.h> #include <sys/time.h>
#include <utime.h> #include <utime.h>
#ifndef __HAIKU__
#include <wordexp.h> #include <wordexp.h>
#endif
#include <sys/socket.h> #include <sys/socket.h>
int main(int argc, char *argv[]) int main(int argc, char *argv[])
@@ -67,7 +75,10 @@ int main(int argc, char *argv[])
printf("passwd %zu %zu\n", sizeof(struct passwd), _Alignof(struct passwd)); printf("passwd %zu %zu\n", sizeof(struct passwd), _Alignof(struct passwd));
#ifndef __HAIKU__
printf("shmid_ds %zu %zu\n", sizeof(struct shmid_ds), _Alignof(struct shmid_ds)); printf("shmid_ds %zu %zu\n", sizeof(struct shmid_ds), _Alignof(struct shmid_ds));
#endif
printf("ipc_perm %zu %zu\n", sizeof(struct ipc_perm), _Alignof(struct ipc_perm)); printf("ipc_perm %zu %zu\n", sizeof(struct ipc_perm), _Alignof(struct ipc_perm));
printf("msqid_ds %zu %zu\n", sizeof(struct msqid_ds), _Alignof(struct msqid_ds)); printf("msqid_ds %zu %zu\n", sizeof(struct msqid_ds), _Alignof(struct msqid_ds));
@@ -95,7 +106,9 @@ int main(int argc, char *argv[])
printf("utimbuf %zu %zu\n", sizeof(struct utimbuf), _Alignof(struct utimbuf)); printf("utimbuf %zu %zu\n", sizeof(struct utimbuf), _Alignof(struct utimbuf));
#ifndef __HAIKU__
printf("wordexp_t %zu %zu\n", sizeof(wordexp_t), _Alignof(wordexp_t)); printf("wordexp_t %zu %zu\n", sizeof(wordexp_t), _Alignof(wordexp_t));
#endif
printf("time_t %zu %zu\n", sizeof(time_t), _Alignof(time_t)); printf("time_t %zu %zu\n", sizeof(time_t), _Alignof(time_t));
printf("timespec %zu %zu\n", sizeof(struct timespec), _Alignof(struct timespec)); printf("timespec %zu %zu\n", sizeof(struct timespec), _Alignof(struct timespec));
+8 -3
View File
@@ -42,7 +42,10 @@ main :: proc() {
fmt.println("pollfd", size_of(posix.pollfd), align_of(posix.pollfd)) fmt.println("pollfd", size_of(posix.pollfd), align_of(posix.pollfd))
fmt.println("passwd", size_of(posix.passwd), align_of(posix.passwd)) fmt.println("passwd", size_of(posix.passwd), align_of(posix.passwd))
fmt.println("shmid_ds", size_of(posix.shmid_ds), align_of(posix.shmid_ds)) when ODIN_OS != .Haiku {
fmt.println("shmid_ds", size_of(posix.shmid_ds), align_of(posix.shmid_ds))
}
fmt.println("ipc_perm", size_of(posix.ipc_perm), align_of(posix.ipc_perm)) fmt.println("ipc_perm", size_of(posix.ipc_perm), align_of(posix.ipc_perm))
fmt.println("msqid_ds", size_of(posix.msqid_ds), align_of(posix.msqid_ds)) fmt.println("msqid_ds", size_of(posix.msqid_ds), align_of(posix.msqid_ds))
@@ -70,8 +73,10 @@ main :: proc() {
fmt.println("utimbuf", size_of(posix.utimbuf), align_of(posix.utimbuf)) fmt.println("utimbuf", size_of(posix.utimbuf), align_of(posix.utimbuf))
fmt.println("wordexp_t", size_of(posix.wordexp_t), align_of(posix.wordexp_t)) when ODIN_OS != .Haiku {
fmt.println("wordexp_t", size_of(posix.wordexp_t), align_of(posix.wordexp_t))
}
fmt.println("time_t", size_of(posix.time_t), align_of(posix.time_t)) fmt.println("time_t", size_of(posix.time_t), align_of(posix.time_t))
fmt.println("timespec", size_of(posix.timespec), align_of(posix.timespec)) fmt.println("timespec", size_of(posix.timespec), align_of(posix.timespec))
fmt.println("clock_t", size_of(posix.clock_t), align_of(posix.clock_t)) fmt.println("clock_t", size_of(posix.clock_t), align_of(posix.clock_t))
+11 -1
View File
@@ -1571,7 +1571,7 @@ VIEW_INSTANCING_DESC :: struct {
Flags: VIEW_INSTANCING_FLAGS, Flags: VIEW_INSTANCING_FLAGS,
} }
SHADER_COMPONENT_MAPPING :: enum i32 { SHADER_COMPONENT_MAPPING :: enum u32 {
FROM_MEMORY_COMPONENT_0 = 0, FROM_MEMORY_COMPONENT_0 = 0,
FROM_MEMORY_COMPONENT_1 = 1, FROM_MEMORY_COMPONENT_1 = 1,
FROM_MEMORY_COMPONENT_2 = 2, FROM_MEMORY_COMPONENT_2 = 2,
@@ -1579,6 +1579,16 @@ SHADER_COMPONENT_MAPPING :: enum i32 {
FORCE_VALUE_0 = 4, FORCE_VALUE_0 = 4,
FORCE_VALUE_1 = 5, FORCE_VALUE_1 = 5,
} }
ENCODE_SHADER_4_COMPONENT_MAPPING :: #force_inline proc "contextless" (Src0, Src1, Src2, Src3: u32) -> u32 {
return (Src0 & SHADER_COMPONENT_MAPPING_MASK) |
((Src1 & SHADER_COMPONENT_MAPPING_MASK) << SHADER_COMPONENT_MAPPING_SHIFT) |
((Src2 & SHADER_COMPONENT_MAPPING_MASK) << (SHADER_COMPONENT_MAPPING_SHIFT * 2)) |
((Src3 & SHADER_COMPONENT_MAPPING_MASK) << (SHADER_COMPONENT_MAPPING_SHIFT * 3)) |
SHADER_COMPONENT_MAPPING_ALWAYS_SET_BIT_AVOIDING_ZEROMEM_MISTAKES
}
DECODE_SHADER_4_COMPONENT_MAPPING :: #force_inline proc "contextless" (ComponentToExtract, Mapping: u32) -> u32 {
return Mapping >> (SHADER_COMPONENT_MAPPING_SHIFT * ComponentToExtract) & SHADER_COMPONENT_MAPPING_MASK
}
BUFFER_SRV_FLAGS :: distinct bit_set[BUFFER_SRV_FLAG; u32] BUFFER_SRV_FLAGS :: distinct bit_set[BUFFER_SRV_FLAG; u32]
BUFFER_SRV_FLAG :: enum u32 { BUFFER_SRV_FLAG :: enum u32 {
+6
View File
@@ -498,6 +498,12 @@ WHQL_DRAW_VERTEX_COUNT_2_TO_EXP :: 25
SHADER_COMPONENT_MAPPING_MASK :: 0x7 SHADER_COMPONENT_MAPPING_MASK :: 0x7
SHADER_COMPONENT_MAPPING_SHIFT :: 3 SHADER_COMPONENT_MAPPING_SHIFT :: 3
SHADER_COMPONENT_MAPPING_ALWAYS_SET_BIT_AVOIDING_ZEROMEM_MISTAKES :: 1 << (SHADER_COMPONENT_MAPPING_SHIFT * 4)
DEFAULT_SHADER_4_COMPONENT_MAPPING :: (0 & SHADER_COMPONENT_MAPPING_MASK) |
((1 & SHADER_COMPONENT_MAPPING_MASK) << SHADER_COMPONENT_MAPPING_SHIFT) |
((2 & SHADER_COMPONENT_MAPPING_MASK) << (SHADER_COMPONENT_MAPPING_SHIFT * 2)) |
((3 & SHADER_COMPONENT_MAPPING_MASK) << (SHADER_COMPONENT_MAPPING_SHIFT * 3)) |
SHADER_COMPONENT_MAPPING_ALWAYS_SET_BIT_AVOIDING_ZEROMEM_MISTAKES
FILTER_REDUCTION_TYPE_MASK :: 0x3 FILTER_REDUCTION_TYPE_MASK :: 0x3
FILTER_REDUCTION_TYPE_SHIFT :: 7 FILTER_REDUCTION_TYPE_SHIFT :: 7
+2 -6
View File
@@ -18,12 +18,8 @@ when LIB != "" {
} }
} }
when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 { foreign import stbi {
foreign import stbi "../lib/stb_image_wasm.o" LIB when LIB != "" else "system:stb_image",
} else when LIB != "" {
foreign import stbi { LIB }
} else {
foreign import stbi "system:stb_image"
} }
NO_STDIO :: ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 NO_STDIO :: ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32
+2 -6
View File
@@ -18,12 +18,8 @@ when RESIZE_LIB != "" {
} }
} }
when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 { foreign import lib {
foreign import lib "../lib/stb_image_resize_wasm.o" RESIZE_LIB when RESIZE_LIB != "" else "system:stb_image_resize",
} else when RESIZE_LIB != "" {
foreign import lib { RESIZE_LIB }
} else {
foreign import lib "system:stb_image_resize"
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
+2 -6
View File
@@ -18,12 +18,8 @@ when WRITE_LIB != "" {
} }
} }
when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 { foreign import stbiw {
foreign import stbiw "../lib/stb_image_write_wasm.o" WRITE_LIB when WRITE_LIB != "" else "system:stb_image_write",
} else when WRITE_LIB != "" {
foreign import stbiw { WRITE_LIB }
} else {
foreign import stbiw "system:stb_image_write"
} }
write_func :: proc "c" (ctx: rawptr, data: rawptr, size: c.int) write_func :: proc "c" (ctx: rawptr, data: rawptr, size: c.int)
+12 -12
View File
@@ -1181,7 +1181,7 @@ class WebGPUInterface {
*/ */
wgpuBufferSetLabel: (bufferIdx, labelPtr) => { wgpuBufferSetLabel: (bufferIdx, labelPtr) => {
const buffer = this.buffers.get(bufferIdx); const buffer = this.buffers.get(bufferIdx);
buffer.buffer.label = this.mem.loadCstring(labelPtr); buffer.buffer.label = this.mem.loadCstringDirect(labelPtr);
}, },
/** /**
@@ -1370,7 +1370,7 @@ class WebGPUInterface {
*/ */
wgpuCommandEncoderInsertDebugMarker: (commandEncoderIdx, markerLabelPtr) => { wgpuCommandEncoderInsertDebugMarker: (commandEncoderIdx, markerLabelPtr) => {
const commandEncoder = this.commandEncoders.get(commandEncoderIdx); const commandEncoder = this.commandEncoders.get(commandEncoderIdx);
commandEncoder.insertDebugMarker(this.mem.loadCstring(markerLabelPtr)); commandEncoder.insertDebugMarker(this.mem.loadCstringDirect(markerLabelPtr));
}, },
/** /**
@@ -1387,7 +1387,7 @@ class WebGPUInterface {
*/ */
wgpuCommandEncoderPushDebugGroup: (commandEncoderIdx, groupLabelPtr) => { wgpuCommandEncoderPushDebugGroup: (commandEncoderIdx, groupLabelPtr) => {
const commandEncoder = this.commandEncoders.get(commandEncoderIdx); const commandEncoder = this.commandEncoders.get(commandEncoderIdx);
commandEncoder.pushDebugGroup(this.mem.loadCstring(groupLabelPtr)); commandEncoder.pushDebugGroup(this.mem.loadCstringDirect(groupLabelPtr));
}, },
/** /**
@@ -1459,7 +1459,7 @@ class WebGPUInterface {
*/ */
wgpuComputePassEncoderInsertDebugMarker: (computePassEncoderIdx, markerLabelPtr) => { wgpuComputePassEncoderInsertDebugMarker: (computePassEncoderIdx, markerLabelPtr) => {
const computePassEncoder = this.computePassEncoders.get(computePassEncoderIdx); const computePassEncoder = this.computePassEncoders.get(computePassEncoderIdx);
computePassEncoder.insertDebugMarker(this.mem.loadCstring(markerLabelPtr)); computePassEncoder.insertDebugMarker(this.mem.loadCstringDirect(markerLabelPtr));
}, },
/** /**
@@ -1476,7 +1476,7 @@ class WebGPUInterface {
*/ */
wgpuComputePassEncoderPushDebugGroup: (computePassEncoderIdx, groupLabelPtr) => { wgpuComputePassEncoderPushDebugGroup: (computePassEncoderIdx, groupLabelPtr) => {
const computePassEncoder = this.computePassEncoders.get(computePassEncoderIdx); const computePassEncoder = this.computePassEncoders.get(computePassEncoderIdx);
computePassEncoder.pushDebugGroup(this.mem.loadCstring(groupLabelPtr)); computePassEncoder.pushDebugGroup(this.mem.loadCstringDirect(groupLabelPtr));
}, },
/** /**
@@ -2216,7 +2216,7 @@ class WebGPUInterface {
wgpuRenderBundleEncoderInsertDebugMarker: (renderBundleEncoderIdx, markerLabelPtr) => { wgpuRenderBundleEncoderInsertDebugMarker: (renderBundleEncoderIdx, markerLabelPtr) => {
const renderBundleEncoder = this.renderBundleEncoders.get(renderBundleEncoderIdx); const renderBundleEncoder = this.renderBundleEncoders.get(renderBundleEncoderIdx);
this.assert(markerLabelPtr != 0); this.assert(markerLabelPtr != 0);
const markerLabel = this.mem.loadCstring(markerLabelPtr); const markerLabel = this.mem.loadCstringDirect(markerLabelPtr);
renderBundleEncoder.insertDebugMarker(markerLabel); renderBundleEncoder.insertDebugMarker(markerLabel);
}, },
@@ -2235,7 +2235,7 @@ class WebGPUInterface {
wgpuRenderBundleEncoderPushDebugGroup: (renderBundleEncoderIdx, groupLabelPtr) => { wgpuRenderBundleEncoderPushDebugGroup: (renderBundleEncoderIdx, groupLabelPtr) => {
const renderBundleEncoder = this.renderBundleEncoders.get(renderBundleEncoderIdx); const renderBundleEncoder = this.renderBundleEncoders.get(renderBundleEncoderIdx);
this.assert(groupLabelPtr!= 0); this.assert(groupLabelPtr!= 0);
const groupLabel = this.mem.loadCstring(groupLabelPtr); const groupLabel = this.mem.loadCstringDirect(groupLabelPtr);
renderBundleEncoder.pushDebugGroup(groupLabel); renderBundleEncoder.pushDebugGroup(groupLabel);
}, },
@@ -2407,7 +2407,7 @@ class WebGPUInterface {
*/ */
wgpuRenderPassEncoderInsertDebugMarker: (renderPassEncoderIdx, markerLabelPtr) => { wgpuRenderPassEncoderInsertDebugMarker: (renderPassEncoderIdx, markerLabelPtr) => {
const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx); const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx);
const markerLabel = this.mem.loadCstring(markerLabelPtr); const markerLabel = this.mem.loadCstringDirect(markerLabelPtr);
renderPassEncoder.insertDebugMarker(markerLabel); renderPassEncoder.insertDebugMarker(markerLabel);
}, },
@@ -2425,7 +2425,7 @@ class WebGPUInterface {
*/ */
wgpuRenderPassEncoderPushDebugGroup: (renderPassEncoderIdx, groupLabelPtr) => { wgpuRenderPassEncoderPushDebugGroup: (renderPassEncoderIdx, groupLabelPtr) => {
const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx); const renderPassEncoder = this.renderPassEncoders.get(renderPassEncoderIdx);
const groupLabel = this.mem.loadCstring(groupLabelPtr); const groupLabel = this.mem.loadCstringDirect(groupLabelPtr);
renderPassEncoder.pushDebugGroup(groupLabel); renderPassEncoder.pushDebugGroup(groupLabel);
}, },
@@ -2881,11 +2881,11 @@ class WebGPUObjectManager {
} }
/** /**
* @param {number} idx * @param {?number} idx
* @returns {T} * @returns {T}
*/ */
get(idx) { get(idx) {
return this.objects[idx-1].object; return this.objects[idx-1]?.object;
} }
/** @param {number} idx */ /** @param {number} idx */
@@ -2908,7 +2908,7 @@ class WebGPUObjectManager {
if (withLabelSetter) { if (withLabelSetter) {
inter[`wgpu${this.name}SetLabel`] = (idx, labelPtr) => { inter[`wgpu${this.name}SetLabel`] = (idx, labelPtr) => {
const obj = this.get(idx); const obj = this.get(idx);
obj.label = this.mem.loadCstring(labelPtr); obj.label = this.mem.loadCstringDirect(labelPtr);
}; };
} }
return inter; return inter;