Merge branch 'master' of github.com:odin-lang/Odin into posix-linux

This commit is contained in:
Isaac Andrade
2024-08-27 18:51:58 -06:00
67 changed files with 3045 additions and 2704 deletions
+2
View File
@@ -219,6 +219,8 @@ type_map_cell_info :: proc($T: typeid) -> ^runtime.Map_Cell_Info ---
type_convert_variants_to_pointers :: proc($T: typeid) -> typeid where type_is_union(T) ---
type_merge :: proc($U, $V: typeid) -> typeid where type_is_union(U), type_is_union(V) ---
type_has_shared_fields :: proc($U, $V: typeid) -> bool typeid where type_is_struct(U), type_is_struct(V) ---
constant_utf16_cstring :: proc($literal: string) -> [^]u16 ---
constant_log2 :: proc($v: $T) -> T where type_is_integer(T) ---
+2 -2
View File
@@ -1,8 +1,8 @@
package runtime
nil_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
size, alignment: int,
old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, Allocator_Error) {
size, alignment: int,
old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, Allocator_Error) {
switch mode {
case .Alloc, .Alloc_Non_Zeroed:
return nil, .Out_Of_Memory
+34
View File
@@ -0,0 +1,34 @@
package runtime
Thread_Local_Cleaner :: #type proc "odin" ()
@(private="file")
thread_local_cleaners: [8]Thread_Local_Cleaner
// Add a procedure that will be run at the end of a thread for the purpose of
// deallocating state marked as `thread_local`.
//
// Intended to be called in an `init` procedure of a package with
// dynamically-allocated memory that is stored in `thread_local` variables.
add_thread_local_cleaner :: proc "contextless" (p: Thread_Local_Cleaner) {
for &v in thread_local_cleaners {
if v == nil {
v = p
return
}
}
panic_contextless("There are no more thread-local cleaner slots available.")
}
// Run all of the thread-local cleaner procedures.
//
// Intended to be called by the internals of a threading API at the end of a
// thread's lifetime.
run_thread_local_cleaners :: proc "odin" () {
for p in thread_local_cleaners {
if p == nil {
break
}
p()
}
}
+20 -15
View File
@@ -11,7 +11,7 @@ Write a UUID in the 8-4-4-4-12 format.
This procedure performs error checking with every byte written.
If you can guarantee beforehand that your stream has enough space to hold the
UUID (32 bytes), then it is better to use `unsafe_write` instead as that will
UUID (36 bytes), then it is better to use `unsafe_write` instead as that will
be faster.
Inputs:
@@ -22,7 +22,7 @@ Returns:
- error: An `io` error, if one occurred, otherwise `nil`.
*/
write :: proc(w: io.Writer, id: Identifier) -> (error: io.Error) #no_bounds_check {
write_octet :: proc (w: io.Writer, octet: u8) -> io.Error #no_bounds_check {
write_octet :: proc(w: io.Writer, octet: u8) -> io.Error #no_bounds_check {
high_nibble := octet >> 4
low_nibble := octet & 0xF
@@ -31,15 +31,15 @@ write :: proc(w: io.Writer, id: Identifier) -> (error: io.Error) #no_bounds_chec
return nil
}
for index in 0 ..< 4 { write_octet(w, id[index]) or_return }
for index in 0 ..< 4 {write_octet(w, id[index]) or_return}
io.write_byte(w, '-') or_return
for index in 4 ..< 6 { write_octet(w, id[index]) or_return }
for index in 4 ..< 6 {write_octet(w, id[index]) or_return}
io.write_byte(w, '-') or_return
for index in 6 ..< 8 { write_octet(w, id[index]) or_return }
for index in 6 ..< 8 {write_octet(w, id[index]) or_return}
io.write_byte(w, '-') or_return
for index in 8 ..< 10 { write_octet(w, id[index]) or_return }
for index in 8 ..< 10 {write_octet(w, id[index]) or_return}
io.write_byte(w, '-') or_return
for index in 10 ..< 16 { write_octet(w, id[index]) or_return }
for index in 10 ..< 16 {write_octet(w, id[index]) or_return}
return nil
}
@@ -54,7 +54,7 @@ Inputs:
- id: The identifier to convert.
*/
unsafe_write :: proc(w: io.Writer, id: Identifier) #no_bounds_check {
write_octet :: proc (w: io.Writer, octet: u8) #no_bounds_check {
write_octet :: proc(w: io.Writer, octet: u8) #no_bounds_check {
high_nibble := octet >> 4
low_nibble := octet & 0xF
@@ -62,15 +62,15 @@ unsafe_write :: proc(w: io.Writer, id: Identifier) #no_bounds_check {
io.write_byte(w, strconv.digits[low_nibble])
}
for index in 0 ..< 4 { write_octet(w, id[index]) }
for index in 0 ..< 4 {write_octet(w, id[index])}
io.write_byte(w, '-')
for index in 4 ..< 6 { write_octet(w, id[index]) }
for index in 4 ..< 6 {write_octet(w, id[index])}
io.write_byte(w, '-')
for index in 6 ..< 8 { write_octet(w, id[index]) }
for index in 6 ..< 8 {write_octet(w, id[index])}
io.write_byte(w, '-')
for index in 8 ..< 10 { write_octet(w, id[index]) }
for index in 8 ..< 10 {write_octet(w, id[index])}
io.write_byte(w, '-')
for index in 10 ..< 16 { write_octet(w, id[index]) }
for index in 10 ..< 16 {write_octet(w, id[index])}
}
/*
@@ -106,7 +106,7 @@ Convert a UUID to a string in the 8-4-4-4-12 format.
Inputs:
- id: The identifier to convert.
- buffer: A byte buffer to store the result. Must be at least 32 bytes large.
- buffer: A byte buffer to store the result. Must be at least 36 bytes large.
- loc: The caller location for debugging purposes (default: #caller_location)
Returns:
@@ -119,7 +119,11 @@ to_string_buffer :: proc(
) -> (
str: string,
) {
assert(len(buffer) >= EXPECTED_LENGTH, "The buffer provided is not at least 32 bytes large.", loc)
assert(
len(buffer) >= EXPECTED_LENGTH,
"The buffer provided is not at least 36 bytes large.",
loc,
)
builder := strings.builder_from_bytes(buffer)
unsafe_write(strings.to_writer(&builder), id)
return strings.to_string(builder)
@@ -129,3 +133,4 @@ to_string :: proc {
to_string_allocated,
to_string_buffer,
}
+9 -9
View File
@@ -19,15 +19,15 @@ xxh_u64 :: u64
XXH64_DEFAULT_SEED :: XXH64_hash(0)
XXH64_state :: struct {
total_len: XXH64_hash, /*!< Total length hashed. This is always 64-bit. */
v1: XXH64_hash, /*!< First accumulator lane */
v2: XXH64_hash, /*!< Second accumulator lane */
v3: XXH64_hash, /*!< Third accumulator lane */
v4: XXH64_hash, /*!< Fourth accumulator lane */
mem64: [4]XXH64_hash, /*!< Internal buffer for partial reads. Treated as unsigned char[32]. */
memsize: XXH32_hash, /*!< Amount of data in @ref mem64 */
reserved32: XXH32_hash, /*!< Reserved field, needed for padding anyways*/
reserved64: XXH64_hash, /*!< Reserved field. Do not read or write to it, it may be removed. */
total_len: XXH64_hash, /*!< Total length hashed. This is always 64-bit. */
v1: XXH64_hash, /*!< First accumulator lane */
v2: XXH64_hash, /*!< Second accumulator lane */
v3: XXH64_hash, /*!< Third accumulator lane */
v4: XXH64_hash, /*!< Fourth accumulator lane */
mem64: [4]XXH64_hash, /*!< Internal buffer for partial reads. Treated as unsigned char[32]. */
memsize: XXH32_hash, /*!< Amount of data in @ref mem64 */
reserved32: XXH32_hash, /*!< Reserved field, needed for padding anyways*/
reserved64: XXH64_hash, /*!< Reserved field. Do not read or write to it, it may be removed. */
}
XXH64_canonical :: struct {
+2
View File
@@ -1393,6 +1393,7 @@ expand_grayscale :: proc(img: ^Image, allocator := context.allocator) -> (ok: bo
for p in inp {
out[0].rgb = p.r // Gray component.
out[0].a = p.g // Alpha component.
out = out[1:]
}
case:
@@ -1417,6 +1418,7 @@ expand_grayscale :: proc(img: ^Image, allocator := context.allocator) -> (ok: bo
for p in inp {
out[0].rgb = p.r // Gray component.
out[0].a = p.g // Alpha component.
out = out[1:]
}
case:
+1 -1
View File
@@ -195,7 +195,7 @@ Error_String :: #sparse[Error]string{
}
Primality_Flag :: enum u8 {
Blum_Blum_Shub = 0, // Make prime congruent to 3 mod 4
Blum_Blum_Shub = 0, // Make prime congruent to 3 mod 4
Safe = 1, // Make sure (p-1)/2 is prime as well (implies .Blum_Blum_Shub)
Second_MSB_On = 3, // Make the 2nd highest bit one
}
+2 -2
View File
@@ -178,11 +178,11 @@ make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocato
}
@(require_results)
make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) {
return runtime.make_dynamic_array(T, len, allocator, loc)
return runtime.make_dynamic_array_len_cap(T, len, len, allocator, loc)
}
@(require_results)
make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, #any_int len: int, #any_int cap: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) {
return runtime.make_dynamic_array(T, len, cap, allocator, loc)
return runtime.make_dynamic_array_len_cap(T, len, cap, allocator, loc)
}
@(require_results)
make_map :: proc($T: typeid/map[$K]$E, #any_int cap: int = 1<<runtime.MAP_MIN_LOG2_CAPACITY, allocator := context.allocator, loc := #caller_location) -> (m: T, err: Allocator_Error) {
+18 -14
View File
@@ -128,33 +128,37 @@ _get_dns_records_os :: proc(hostname: string, type: DNS_Record_Type, allocator :
append(&recs, record)
case .SRV:
target := strings.clone(string(r.Data.SRV.pNameTarget)) // The target hostname/address that the service can be found on
priority := int(r.Data.SRV.wPriority)
weight := int(r.Data.SRV.wWeight)
port := int(r.Data.SRV.wPort)
// NOTE(tetra): Srv record name should be of the form '_servicename._protocol.hostname'
// The record name is the name of the record.
// Not to be confused with the _target_ of the record, which is--in combination with the port--what we're looking up
// by making this request in the first place.
// NOTE(Jeroen): Service Name and Protocol Name can probably just be string slices into the record name.
// It's already cloned, after all. I wouldn't put them on the temp allocator like this.
service_name, protocol_name: string
parts := strings.split_n(base_record.record_name, ".", 3, context.temp_allocator)
if len(parts) != 3 {
s := base_record.record_name
i := strings.index_byte(s, '.')
if i > -1 {
service_name = s[:i]
s = s[len(service_name) + 1:]
} else {
continue
}
i = strings.index_byte(s, '.')
if i > -1 {
protocol_name = s[:i]
} else {
continue
}
service_name, protocol_name := parts[0], parts[1]
append(&recs, DNS_Record_SRV {
base = base_record,
target = target,
port = port,
target = strings.clone(string(r.Data.SRV.pNameTarget)), // The target hostname/address that the service can be found on
port = int(r.Data.SRV.wPort),
service_name = service_name,
protocol_name = protocol_name,
priority = priority,
weight = weight,
priority = int(r.Data.SRV.wPriority),
weight = int(r.Data.SRV.wWeight),
})
}
+5
View File
@@ -61,3 +61,8 @@ TEMP_ALLOCATOR_GUARD :: #force_inline proc(loc := #caller_location) -> (runtime.
global_default_temp_allocator_index = (global_default_temp_allocator_index+1)%MAX_TEMP_ARENA_COUNT
return tmp, loc
}
@(init, private)
init_thread_local_cleaner :: proc() {
runtime.add_thread_local_cleaner(temp_allocator_fini)
}
-3
View File
@@ -125,9 +125,6 @@ read_entire_file_from_file :: proc(f: ^File, allocator: runtime.Allocator) -> (d
has_size = true
size = int(size64)
}
} else if serr != .No_Size {
err = serr
return
}
if has_size && size > 0 {
+14 -13
View File
@@ -166,15 +166,15 @@ Process_Info :: struct {
This procedure obtains an information, specified by `selection` parameter of
a process given by `pid`.
Use `free_process_info` to free the memory allocated by this procedure. In
case the function returns an error it may only have been an error for one part
of the information and you would still need to call it to free the other parts.
Use `free_process_info` to free the memory allocated by this procedure. The
`free_process_info` procedure needs to be called, even if this procedure
returned an error, as some of the fields may have been allocated.
**Note**: The resulting information may or may contain the fields specified
by the `selection` parameter. Always check whether the returned
`Process_Info` struct has the required fields before checking the error code
returned by this function.
returned by this procedure.
*/
@(require_results)
process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator: runtime.Allocator) -> (Process_Info, Error) {
@@ -188,14 +188,14 @@ process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator:
about a process that has been opened by the application, specified in
the `process` parameter.
Use `free_process_info` to free the memory allocated by this procedure. In
case the function returns an error it may only have been an error for one part
of the information and you would still need to call it to free the other parts.
Use `free_process_info` to free the memory allocated by this procedure. The
`free_process_info` procedure needs to be called, even if this procedure
returned an error, as some of the fields may have been allocated.
**Note**: The resulting information may or may contain the fields specified
by the `selection` parameter. Always check whether the returned
`Process_Info` struct has the required fields before checking the error code
returned by this function.
returned by this procedure.
*/
@(require_results)
process_info_by_handle :: proc(process: Process, selection: Process_Info_Fields, allocator: runtime.Allocator) -> (Process_Info, Error) {
@@ -208,14 +208,14 @@ process_info_by_handle :: proc(process: Process, selection: Process_Info_Fields,
This procedure obtains the information, specified by `selection` parameter
about the currently running process.
Use `free_process_info` to free the memory allocated by this procedure. In
case the function returns an error it may only have been an error for one part
of the information and you would still need to call it to free the other parts.
Use `free_process_info` to free the memory allocated by this procedure. The
`free_process_info` procedure needs to be called, even if this procedure
returned an error, as some of the fields may have been allocated.
**Note**: The resulting information may or may contain the fields specified
by the `selection` parameter. Always check whether the returned
`Process_Info` struct has the required fields before checking the error code
returned by this function.
returned by this procedure.
*/
@(require_results)
current_process_info :: proc(selection: Process_Info_Fields, allocator: runtime.Allocator) -> (Process_Info, Error) {
@@ -305,6 +305,7 @@ Process_Desc :: struct {
// A slice of strings, each having the format `KEY=VALUE` representing the
// full environment that the child process will receive.
// In case this slice is `nil`, the current process' environment is used.
// NOTE(laytan): maybe should be `Maybe([]string)` so you can do `nil` == current env, empty == empty/no env.
env: []string,
// The `stderr` handle to give to the child process. It can be either a file
// or a writeable end of a pipe. Passing `nil` will shut down the process'
+5 -11
View File
@@ -490,7 +490,6 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
if errno = linux.pipe2(&child_pipe_fds, {.CLOEXEC}); errno != .NONE {
return process, _get_platform_error(errno)
}
defer linux.close(child_pipe_fds[WRITE])
defer linux.close(child_pipe_fds[READ])
@@ -508,6 +507,7 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
//
pid: linux.Pid
if pid, errno = linux.fork(); errno != .NONE {
linux.close(child_pipe_fds[WRITE])
return process, _get_platform_error(errno)
}
@@ -573,25 +573,19 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
write_errno_to_parent_and_abort(child_pipe_fds[WRITE], errno)
}
success_byte: [1]u8
linux.write(child_pipe_fds[WRITE], success_byte[:])
errno = linux.execveat(exe_fd, "", &cargs[0], env, {.AT_EMPTY_PATH})
// NOTE: we can't tell the parent about this failure because we already wrote the success byte.
// So if this happens the user will just see the process failed when they call process_wait.
assert(errno != nil)
intrinsics.trap()
write_errno_to_parent_and_abort(child_pipe_fds[WRITE], errno)
}
linux.close(child_pipe_fds[WRITE])
process.pid = int(pid)
n: int
child_byte: [1]u8
errno = .EINTR
for errno == .EINTR {
n, errno = linux.read(child_pipe_fds[READ], child_byte[:])
_, errno = linux.read(child_pipe_fds[READ], child_byte[:])
}
// If the read failed, something weird happened. Do not return the read
+8 -11
View File
@@ -139,20 +139,22 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
err = _get_platform_error()
return
}
defer posix.close(pipe[WRITE])
defer posix.close(pipe[READ])
if posix.fcntl(pipe[READ], .SETFD, i32(posix.FD_CLOEXEC)) == -1 {
posix.close(pipe[WRITE])
err = _get_platform_error()
return
}
if posix.fcntl(pipe[WRITE], .SETFD, i32(posix.FD_CLOEXEC)) == -1 {
posix.close(pipe[WRITE])
err = _get_platform_error()
return
}
switch pid := posix.fork(); pid {
case -1:
posix.close(pipe[WRITE])
err = _get_platform_error()
return
@@ -179,25 +181,20 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
if posix.chdir(cwd) != .OK { abort(pipe[WRITE]) }
}
ok := u8(0)
posix.write(pipe[WRITE], &ok, 1)
res := posix.execve(strings.to_cstring(&exe_builder), raw_data(cmd), env)
// NOTE: we can't tell the parent about this failure because we already wrote the success byte.
// So if this happens the user will just see the process failed when they call process_wait.
assert(res == -1)
runtime.trap()
abort(pipe[WRITE])
case:
posix.close(pipe[WRITE])
errno: posix.Errno
for {
errno_byte: u8
switch posix.read(pipe[READ], &errno_byte, 1) {
case 1:
case 1:
errno = posix.Errno(errno_byte)
case:
case -1:
errno = posix.errno()
if errno == .EINTR {
continue
+185 -141
View File
@@ -93,34 +93,11 @@ read_memory_as_slice :: proc(h: win32.HANDLE, addr: rawptr, dest: []$T) -> (byte
@(private="package")
_process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator: runtime.Allocator) -> (info: Process_Info, err: Error) {
info.pid = pid
defer if err != nil {
free_process_info(info, allocator)
}
// Data obtained from process snapshots
if selection >= {.PPid, .Priority} {
entry, entry_err := _process_entry_by_pid(info.pid)
if entry_err != nil {
err = General_Error.Not_Exist
return
}
if .PPid in selection {
info.fields += {.PPid}
info.ppid = int(entry.th32ParentProcessID)
}
if .Priority in selection {
info.fields += {.Priority}
info.priority = int(entry.pcPriClassBase)
}
}
if .Executable_Path in selection { // snap module
info.executable_path = _process_exe_by_pid(pid, allocator) or_return
info.fields += {.Executable_Path}
}
// Note(flysand): Open the process handle right away to prevent some race
// conditions. Once the handle is open, the process will be kept alive by
// the OS.
ph := win32.INVALID_HANDLE_VALUE
if selection >= {.Command_Line, .Environment, .Working_Dir, .Username} { // need process handle
if selection >= {.Command_Line, .Environment, .Working_Dir, .Username} {
ph = win32.OpenProcess(
win32.PROCESS_QUERY_LIMITED_INFORMATION | win32.PROCESS_VM_READ,
false,
@@ -134,84 +111,15 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator
defer if ph != win32.INVALID_HANDLE_VALUE {
win32.CloseHandle(ph)
}
if selection >= {.Command_Line, .Environment, .Working_Dir} { // need peb
process_info_size: u32
process_info: win32.PROCESS_BASIC_INFORMATION
status := win32.NtQueryInformationProcess(ph, .ProcessBasicInformation, &process_info, size_of(process_info), &process_info_size)
if status != 0 {
// TODO(flysand): There's probably a mismatch between NTSTATUS and
// windows userland error codes, I haven't checked.
err = Platform_Error(status)
return
}
if process_info.PebBaseAddress == nil {
// Not sure what the error is
err = General_Error.Unsupported
return
}
process_peb: win32.PEB
_ = read_memory_as_struct(ph, process_info.PebBaseAddress, &process_peb) or_return
process_params: win32.RTL_USER_PROCESS_PARAMETERS
_ = read_memory_as_struct(ph, process_peb.ProcessParameters, &process_params) or_return
if selection >= {.Command_Line, .Command_Args} {
TEMP_ALLOCATOR_GUARD()
cmdline_w := make([]u16, process_params.CommandLine.Length, temp_allocator()) or_return
_ = read_memory_as_slice(ph, process_params.CommandLine.Buffer, cmdline_w) or_return
if .Command_Line in selection {
info.command_line = win32_utf16_to_utf8(cmdline_w, allocator) or_return
info.fields += {.Command_Line}
}
if .Command_Args in selection {
info.command_args = _parse_command_line(raw_data(cmdline_w), allocator) or_return
info.fields += {.Command_Args}
}
}
if .Environment in selection {
TEMP_ALLOCATOR_GUARD()
env_len := process_params.EnvironmentSize / 2
envs_w := make([]u16, env_len, temp_allocator()) or_return
_ = read_memory_as_slice(ph, process_params.Environment, envs_w) or_return
info.environment = _parse_environment_block(raw_data(envs_w), allocator) or_return
info.fields += {.Environment}
}
if .Working_Dir in selection {
TEMP_ALLOCATOR_GUARD()
cwd_w := make([]u16, process_params.CurrentDirectoryPath.Length, temp_allocator()) or_return
_ = read_memory_as_slice(ph, process_params.CurrentDirectoryPath.Buffer, cwd_w) or_return
info.working_dir = win32_utf16_to_utf8(cwd_w, allocator) or_return
info.fields += {.Working_Dir}
}
}
if .Username in selection {
info.username = _get_process_user(ph, allocator) or_return
info.fields += {.Username}
}
err = nil
return
}
@(private="package")
_process_info_by_handle :: proc(process: Process, selection: Process_Info_Fields, allocator: runtime.Allocator) -> (info: Process_Info, err: Error) {
pid := process.pid
info.pid = pid
defer if err != nil {
free_process_info(info, allocator)
}
// Data obtained from process snapshots
if selection >= {.PPid, .Priority} { // snap process
snapshot_process: if selection >= {.PPid, .Priority} {
entry, entry_err := _process_entry_by_pid(info.pid)
if entry_err != nil {
err = General_Error.Not_Exist
return
err = entry_err
if entry_err == General_Error.Not_Exist {
return
} else {
break snapshot_process
}
}
if .PPid in selection {
info.fields += {.PPid}
@@ -222,12 +130,18 @@ _process_info_by_handle :: proc(process: Process, selection: Process_Info_Fields
info.priority = int(entry.pcPriClassBase)
}
}
if .Executable_Path in selection { // snap module
info.executable_path = _process_exe_by_pid(pid, allocator) or_return
snapshot_modules: if .Executable_Path in selection {
exe_path: string
exe_path, err = _process_exe_by_pid(pid, allocator)
if _, ok := err.(runtime.Allocator_Error); ok {
return
} else if err != nil {
break snapshot_modules
}
info.executable_path = exe_path
info.fields += {.Executable_Path}
}
ph := win32.HANDLE(process.handle)
if selection >= {.Command_Line, .Environment, .Working_Dir} { // need peb
read_peb: if selection >= {.Command_Line, .Environment, .Working_Dir} {
process_info_size: u32
process_info: win32.PROCESS_BASIC_INFORMATION
status := win32.NtQueryInformationProcess(ph, .ProcessBasicInformation, &process_info, size_of(process_info), &process_info_size)
@@ -235,25 +149,26 @@ _process_info_by_handle :: proc(process: Process, selection: Process_Info_Fields
// TODO(flysand): There's probably a mismatch between NTSTATUS and
// windows userland error codes, I haven't checked.
err = Platform_Error(status)
return
break read_peb
}
if process_info.PebBaseAddress == nil {
// Not sure what the error is
err = General_Error.Unsupported
return
}
assert(process_info.PebBaseAddress != nil)
process_peb: win32.PEB
_ = read_memory_as_struct(ph, process_info.PebBaseAddress, &process_peb) or_return
_, err = read_memory_as_struct(ph, process_info.PebBaseAddress, &process_peb)
if err != nil {
break read_peb
}
process_params: win32.RTL_USER_PROCESS_PARAMETERS
_ = read_memory_as_struct(ph, process_peb.ProcessParameters, &process_params) or_return
_, err = read_memory_as_struct(ph, process_peb.ProcessParameters, &process_params)
if err != nil {
break read_peb
}
if selection >= {.Command_Line, .Command_Args} {
TEMP_ALLOCATOR_GUARD()
cmdline_w := make([]u16, process_params.CommandLine.Length, temp_allocator()) or_return
_ = read_memory_as_slice(ph, process_params.CommandLine.Buffer, cmdline_w) or_return
_, err = read_memory_as_slice(ph, process_params.CommandLine.Buffer, cmdline_w)
if err != nil {
break read_peb
}
if .Command_Line in selection {
info.command_line = win32_utf16_to_utf8(cmdline_w, allocator) or_return
info.fields += {.Command_Line}
@@ -263,28 +178,147 @@ _process_info_by_handle :: proc(process: Process, selection: Process_Info_Fields
info.fields += {.Command_Args}
}
}
if .Environment in selection {
TEMP_ALLOCATOR_GUARD()
env_len := process_params.EnvironmentSize / 2
envs_w := make([]u16, env_len, temp_allocator()) or_return
_ = read_memory_as_slice(ph, process_params.Environment, envs_w) or_return
info.environment = _parse_environment_block(raw_data(envs_w), allocator) or_return
_, err = read_memory_as_slice(ph, process_params.Environment, envs_w)
if err != nil {
break read_peb
}
info.environment = _parse_environment_block(raw_data(envs_w), allocator) or_return
info.fields += {.Environment}
}
if .Working_Dir in selection {
TEMP_ALLOCATOR_GUARD()
cwd_w := make([]u16, process_params.CurrentDirectoryPath.Length, temp_allocator()) or_return
_ = read_memory_as_slice(ph, process_params.CurrentDirectoryPath.Buffer, cwd_w) or_return
_, err = read_memory_as_slice(ph, process_params.CurrentDirectoryPath.Buffer, cwd_w)
if err != nil {
break read_peb
}
info.working_dir = win32_utf16_to_utf8(cwd_w, allocator) or_return
info.fields += {.Working_Dir}
}
}
if .Username in selection {
info.username = _get_process_user(ph, allocator) or_return
read_username: if .Username in selection {
username: string
username, err = _get_process_user(ph, allocator)
if _, ok := err.(runtime.Allocator_Error); ok {
return
} else if err != nil {
break read_username
}
info.username = username
info.fields += {.Username}
}
err = nil
return
}
@(private="package")
_process_info_by_handle :: proc(process: Process, selection: Process_Info_Fields, allocator: runtime.Allocator) -> (info: Process_Info, err: Error) {
pid := process.pid
info.pid = pid
// Data obtained from process snapshots
snapshot_process: if selection >= {.PPid, .Priority} {
entry, entry_err := _process_entry_by_pid(info.pid)
if entry_err != nil {
err = entry_err
if entry_err == General_Error.Not_Exist {
return
} else {
break snapshot_process
}
}
if .PPid in selection {
info.fields += {.PPid}
info.ppid = int(entry.th32ParentProcessID)
}
if .Priority in selection {
info.fields += {.Priority}
info.priority = int(entry.pcPriClassBase)
}
}
snapshot_module: if .Executable_Path in selection {
exe_path: string
exe_path, err = _process_exe_by_pid(pid, allocator)
if _, ok := err.(runtime.Allocator_Error); ok {
return
} else if err != nil {
break snapshot_module
}
info.executable_path = exe_path
info.fields += {.Executable_Path}
}
ph := win32.HANDLE(process.handle)
read_peb: if selection >= {.Command_Line, .Environment, .Working_Dir} {
process_info_size: u32
process_info: win32.PROCESS_BASIC_INFORMATION
status := win32.NtQueryInformationProcess(ph, .ProcessBasicInformation, &process_info, size_of(process_info), &process_info_size)
if status != 0 {
// TODO(flysand): There's probably a mismatch between NTSTATUS and
// windows userland error codes, I haven't checked.
err = Platform_Error(status)
return
}
assert(process_info.PebBaseAddress != nil)
process_peb: win32.PEB
_, err = read_memory_as_struct(ph, process_info.PebBaseAddress, &process_peb)
if err != nil {
break read_peb
}
process_params: win32.RTL_USER_PROCESS_PARAMETERS
_, err = read_memory_as_struct(ph, process_peb.ProcessParameters, &process_params)
if err != nil {
break read_peb
}
if selection >= {.Command_Line, .Command_Args} {
TEMP_ALLOCATOR_GUARD()
cmdline_w := make([]u16, process_params.CommandLine.Length, temp_allocator()) or_return
_, err = read_memory_as_slice(ph, process_params.CommandLine.Buffer, cmdline_w)
if err != nil {
break read_peb
}
if .Command_Line in selection {
info.command_line = win32_utf16_to_utf8(cmdline_w, allocator) or_return
info.fields += {.Command_Line}
}
if .Command_Args in selection {
info.command_args = _parse_command_line(raw_data(cmdline_w), allocator) or_return
info.fields += {.Command_Args}
}
}
if .Environment in selection {
TEMP_ALLOCATOR_GUARD()
env_len := process_params.EnvironmentSize / 2
envs_w := make([]u16, env_len, temp_allocator()) or_return
_, err = read_memory_as_slice(ph, process_params.Environment, envs_w)
if err != nil {
break read_peb
}
info.environment = _parse_environment_block(raw_data(envs_w), allocator) or_return
info.fields += {.Environment}
}
if .Working_Dir in selection {
TEMP_ALLOCATOR_GUARD()
cwd_w := make([]u16, process_params.CurrentDirectoryPath.Length, temp_allocator()) or_return
_, err = read_memory_as_slice(ph, process_params.CurrentDirectoryPath.Buffer, cwd_w)
if err != nil {
break read_peb
}
info.working_dir = win32_utf16_to_utf8(cwd_w, allocator) or_return
info.fields += {.Working_Dir}
}
}
read_username: if .Username in selection {
username: string
username, err = _get_process_user(ph, allocator)
if _, ok := err.(runtime.Allocator_Error); ok {
return
} else if err != nil {
break read_username
}
info.username = username
info.fields += {.Username}
}
err = nil
@@ -294,15 +328,15 @@ _process_info_by_handle :: proc(process: Process, selection: Process_Info_Fields
@(private="package")
_current_process_info :: proc(selection: Process_Info_Fields, allocator: runtime.Allocator) -> (info: Process_Info, err: Error) {
info.pid = get_pid()
defer if err != nil {
free_process_info(info, allocator)
}
if selection >= {.PPid, .Priority} { // snap process
snapshot_process: if selection >= {.PPid, .Priority} {
entry, entry_err := _process_entry_by_pid(info.pid)
if entry_err != nil {
err = General_Error.Not_Exist
return
err = entry_err
if entry_err == General_Error.Not_Exist {
return
} else {
break snapshot_process
}
}
if .PPid in selection {
info.fields += {.PPid}
@@ -313,14 +347,16 @@ _current_process_info :: proc(selection: Process_Info_Fields, allocator: runtime
info.priority = int(entry.pcPriClassBase)
}
}
if .Executable_Path in selection {
module_filename: if .Executable_Path in selection {
exe_filename_w: [256]u16
path_len := win32.GetModuleFileNameW(nil, raw_data(exe_filename_w[:]), len(exe_filename_w))
assert(path_len > 0)
info.executable_path = win32_utf16_to_utf8(exe_filename_w[:path_len], allocator) or_return
info.fields += {.Executable_Path}
}
if selection >= {.Command_Line, .Command_Args} {
command_line: if selection >= {.Command_Line, .Command_Args} {
command_line_w := win32.GetCommandLineW()
assert(command_line_w != nil)
if .Command_Line in selection {
info.command_line = win32_wstring_to_utf8(command_line_w, allocator) or_return
info.fields += {.Command_Line}
@@ -330,14 +366,22 @@ _current_process_info :: proc(selection: Process_Info_Fields, allocator: runtime
info.fields += {.Command_Args}
}
}
if .Environment in selection {
read_environment: if .Environment in selection {
env_block := win32.GetEnvironmentStringsW()
assert(env_block != nil)
info.environment = _parse_environment_block(env_block, allocator) or_return
info.fields += {.Environment}
}
if .Username in selection {
read_username: if .Username in selection {
process_handle := win32.GetCurrentProcess()
info.username = _get_process_user(process_handle, allocator) or_return
username: string
username, err = _get_process_user(process_handle, allocator)
if _, ok := err.(runtime.Allocator_Error); ok {
return
} else if err != nil {
break read_username
}
info.username = username
info.fields += {.Username}
}
if .Working_Dir in selection {
+3 -3
View File
@@ -398,9 +398,9 @@ SIOCGIFFLAG :: enum c.int {
PORTSEL = 13, /* Can set media type. */
AUTOMEDIA = 14, /* Auto media select active. */
DYNAMIC = 15, /* Dialup device with changing addresses. */
LOWER_UP = 16,
DORMANT = 17,
ECHO = 18,
LOWER_UP = 16,
DORMANT = 17,
ECHO = 18,
}
SIOCGIFFLAGS :: bit_set[SIOCGIFFLAG; c.int]
+6 -1
View File
@@ -19,6 +19,7 @@ iterate_array :: proc(val: any, it: ^int) -> (elem: any, index: int, ok: bool) {
elem.data = rawptr(uintptr(val.data) + uintptr(it^ * info.elem_size))
elem.id = info.elem.id
ok = true
index = it^
it^ += 1
}
case Type_Info_Slice:
@@ -27,6 +28,7 @@ iterate_array :: proc(val: any, it: ^int) -> (elem: any, index: int, ok: bool) {
elem.data = rawptr(uintptr(array.data) + uintptr(it^ * info.elem_size))
elem.id = info.elem.id
ok = true
index = it^
it^ += 1
}
case Type_Info_Dynamic_Array:
@@ -35,6 +37,7 @@ iterate_array :: proc(val: any, it: ^int) -> (elem: any, index: int, ok: bool) {
elem.data = rawptr(uintptr(array.data) + uintptr(it^ * info.elem_size))
elem.id = info.elem.id
ok = true
index = it^
it^ += 1
}
}
@@ -69,10 +72,12 @@ iterate_map :: proc(val: any, it: ^int) -> (key, value: any, ok: bool) {
key.id = info.key.id
value.id = info.value.id
ok = true
it^ += 1
break
}
}
}
return
}
}
+145 -152
View File
@@ -9,157 +9,157 @@ String :: distinct TypeRef // same as CFStringRef
StringEncoding :: distinct u32
StringBuiltInEncodings :: enum StringEncoding {
MacRoman = 0,
MacRoman = 0,
WindowsLatin1 = 0x0500,
ISOLatin1 = 0x0201,
ISOLatin1 = 0x0201,
NextStepLatin = 0x0B01,
ASCII = 0x0600,
Unicode = 0x0100,
UTF8 = 0x08000100,
ASCII = 0x0600,
Unicode = 0x0100,
UTF8 = 0x08000100,
NonLossyASCII = 0x0BFF,
UTF16 = 0x0100,
UTF16 = 0x0100,
UTF16BE = 0x10000100,
UTF16LE = 0x14000100,
UTF32 = 0x0c000100,
UTF32BE = 0x18000100,
UTF32LE = 0x1c000100,
UTF32 = 0x0c000100,
UTF32BE = 0x18000100,
UTF32LE = 0x1c000100,
}
StringEncodings :: enum Index {
MacJapanese = 1,
MacChineseTrad = 2,
MacKorean = 3,
MacArabic = 4,
MacHebrew = 5,
MacGreek = 6,
MacCyrillic = 7,
MacDevanagari = 9,
MacGurmukhi = 10,
MacGujarati = 11,
MacOriya = 12,
MacBengali = 13,
MacTamil = 14,
MacTelugu = 15,
MacKannada = 16,
MacMalayalam = 17,
MacSinhalese = 18,
MacBurmese = 19,
MacKhmer = 20,
MacThai = 21,
MacLaotian = 22,
MacGeorgian = 23,
MacArmenian = 24,
MacChineseSimp = 25,
MacTibetan = 26,
MacMongolian = 27,
MacEthiopic = 28,
MacCentralEurRoman = 29,
MacVietnamese = 30,
MacExtArabic = 31,
MacSymbol = 33,
MacDingbats = 34,
MacTurkish = 35,
MacCroatian = 36,
MacIcelandic = 37,
MacRomanian = 38,
MacCeltic = 39,
MacGaelic = 40,
MacFarsi = 0x8C,
MacUkrainian = 0x98,
MacInuit = 0xEC,
MacVT100 = 0xFC,
MacHFS = 0xFF,
ISOLatin2 = 0x0202,
ISOLatin3 = 0x0203,
ISOLatin4 = 0x0204,
ISOLatinCyrillic = 0x0205,
ISOLatinArabic = 0x0206,
ISOLatinGreek = 0x0207,
ISOLatinHebrew = 0x0208,
ISOLatin5 = 0x0209,
ISOLatin6 = 0x020A,
ISOLatinThai = 0x020B,
ISOLatin7 = 0x020D,
ISOLatin8 = 0x020E,
ISOLatin9 = 0x020F,
ISOLatin10 = 0x0210,
DOSLatinUS = 0x0400,
DOSGreek = 0x0405,
DOSBalticRim = 0x0406,
DOSLatin1 = 0x0410,
DOSGreek1 = 0x0411,
DOSLatin2 = 0x0412,
DOSCyrillic = 0x0413,
DOSTurkish = 0x0414,
DOSPortuguese = 0x0415,
DOSIcelandic = 0x0416,
DOSHebrew = 0x0417,
DOSCanadianFrench = 0x0418,
DOSArabic = 0x0419,
DOSNordic = 0x041A,
DOSRussian = 0x041B,
DOSGreek2 = 0x041C,
DOSThai = 0x041D,
DOSJapanese = 0x0420,
DOSChineseSimplif = 0x0421,
DOSKorean = 0x0422,
DOSChineseTrad = 0x0423,
WindowsLatin2 = 0x0501,
WindowsCyrillic = 0x0502,
WindowsGreek = 0x0503,
WindowsLatin5 = 0x0504,
WindowsHebrew = 0x0505,
WindowsArabic = 0x0506,
WindowsBalticRim = 0x0507,
WindowsVietnamese = 0x0508,
WindowsKoreanJohab = 0x0510,
ANSEL = 0x0601,
JIS_X0201_76 = 0x0620,
JIS_X0208_83 = 0x0621,
JIS_X0208_90 = 0x0622,
JIS_X0212_90 = 0x0623,
JIS_C6226_78 = 0x0624,
ShiftJIS_X0213 = 0x0628,
ShiftJIS_X0213_MenKuTen = 0x0629,
GB_2312_80 = 0x0630,
GBK_95 = 0x0631,
GB_18030_2000 = 0x0632,
KSC_5601_87 = 0x0640,
KSC_5601_92_Johab = 0x0641,
CNS_11643_92_P1 = 0x0651,
CNS_11643_92_P2 = 0x0652,
CNS_11643_92_P3 = 0x0653,
ISO_2022_JP = 0x0820,
ISO_2022_JP_2 = 0x0821,
ISO_2022_JP_1 = 0x0822,
ISO_2022_JP_3 = 0x0823,
ISO_2022_CN = 0x0830,
ISO_2022_CN_EXT = 0x0831,
ISO_2022_KR = 0x0840,
EUC_JP = 0x0920,
EUC_CN = 0x0930,
EUC_TW = 0x0931,
EUC_KR = 0x0940,
ShiftJIS = 0x0A01,
KOI8_R = 0x0A02,
Big5 = 0x0A03,
MacRomanLatin1 = 0x0A04,
HZ_GB_2312 = 0x0A05,
Big5_HKSCS_1999 = 0x0A06,
VISCII = 0x0A07,
KOI8_U = 0x0A08,
Big5_E = 0x0A09,
NextStepJapanese = 0x0B02,
EBCDIC_US = 0x0C01,
EBCDIC_CP037 = 0x0C02,
UTF7 = 0x04000100,
UTF7_IMAP = 0x0A10,
ShiftJIS_X0213_00 = 0x0628, // Deprecated. Use `ShiftJIS_X0213` instead.
MacJapanese = 1,
MacChineseTrad = 2,
MacKorean = 3,
MacArabic = 4,
MacHebrew = 5,
MacGreek = 6,
MacCyrillic = 7,
MacDevanagari = 9,
MacGurmukhi = 10,
MacGujarati = 11,
MacOriya = 12,
MacBengali = 13,
MacTamil = 14,
MacTelugu = 15,
MacKannada = 16,
MacMalayalam = 17,
MacSinhalese = 18,
MacBurmese = 19,
MacKhmer = 20,
MacThai = 21,
MacLaotian = 22,
MacGeorgian = 23,
MacArmenian = 24,
MacChineseSimp = 25,
MacTibetan = 26,
MacMongolian = 27,
MacEthiopic = 28,
MacCentralEurRoman = 29,
MacVietnamese = 30,
MacExtArabic = 31,
MacSymbol = 33,
MacDingbats = 34,
MacTurkish = 35,
MacCroatian = 36,
MacIcelandic = 37,
MacRomanian = 38,
MacCeltic = 39,
MacGaelic = 40,
MacFarsi = 0x8C,
MacUkrainian = 0x98,
MacInuit = 0xEC,
MacVT100 = 0xFC,
MacHFS = 0xFF,
ISOLatin2 = 0x0202,
ISOLatin3 = 0x0203,
ISOLatin4 = 0x0204,
ISOLatinCyrillic = 0x0205,
ISOLatinArabic = 0x0206,
ISOLatinGreek = 0x0207,
ISOLatinHebrew = 0x0208,
ISOLatin5 = 0x0209,
ISOLatin6 = 0x020A,
ISOLatinThai = 0x020B,
ISOLatin7 = 0x020D,
ISOLatin8 = 0x020E,
ISOLatin9 = 0x020F,
ISOLatin10 = 0x0210,
DOSLatinUS = 0x0400,
DOSGreek = 0x0405,
DOSBalticRim = 0x0406,
DOSLatin1 = 0x0410,
DOSGreek1 = 0x0411,
DOSLatin2 = 0x0412,
DOSCyrillic = 0x0413,
DOSTurkish = 0x0414,
DOSPortuguese = 0x0415,
DOSIcelandic = 0x0416,
DOSHebrew = 0x0417,
DOSCanadianFrench = 0x0418,
DOSArabic = 0x0419,
DOSNordic = 0x041A,
DOSRussian = 0x041B,
DOSGreek2 = 0x041C,
DOSThai = 0x041D,
DOSJapanese = 0x0420,
DOSChineseSimplif = 0x0421,
DOSKorean = 0x0422,
DOSChineseTrad = 0x0423,
WindowsLatin2 = 0x0501,
WindowsCyrillic = 0x0502,
WindowsGreek = 0x0503,
WindowsLatin5 = 0x0504,
WindowsHebrew = 0x0505,
WindowsArabic = 0x0506,
WindowsBalticRim = 0x0507,
WindowsVietnamese = 0x0508,
WindowsKoreanJohab = 0x0510,
ANSEL = 0x0601,
JIS_X0201_76 = 0x0620,
JIS_X0208_83 = 0x0621,
JIS_X0208_90 = 0x0622,
JIS_X0212_90 = 0x0623,
JIS_C6226_78 = 0x0624,
ShiftJIS_X0213 = 0x0628,
ShiftJIS_X0213_MenKuTen = 0x0629,
GB_2312_80 = 0x0630,
GBK_95 = 0x0631,
GB_18030_2000 = 0x0632,
KSC_5601_87 = 0x0640,
KSC_5601_92_Johab = 0x0641,
CNS_11643_92_P1 = 0x0651,
CNS_11643_92_P2 = 0x0652,
CNS_11643_92_P3 = 0x0653,
ISO_2022_JP = 0x0820,
ISO_2022_JP_2 = 0x0821,
ISO_2022_JP_1 = 0x0822,
ISO_2022_JP_3 = 0x0823,
ISO_2022_CN = 0x0830,
ISO_2022_CN_EXT = 0x0831,
ISO_2022_KR = 0x0840,
EUC_JP = 0x0920,
EUC_CN = 0x0930,
EUC_TW = 0x0931,
EUC_KR = 0x0940,
ShiftJIS = 0x0A01,
KOI8_R = 0x0A02,
Big5 = 0x0A03,
MacRomanLatin1 = 0x0A04,
HZ_GB_2312 = 0x0A05,
Big5_HKSCS_1999 = 0x0A06,
VISCII = 0x0A07,
KOI8_U = 0x0A08,
Big5_E = 0x0A09,
NextStepJapanese = 0x0B02,
EBCDIC_US = 0x0C01,
EBCDIC_CP037 = 0x0C02,
UTF7 = 0x04000100,
UTF7_IMAP = 0x0A10,
ShiftJIS_X0213_00 = 0x0628, // Deprecated. Use `ShiftJIS_X0213` instead.
}
@(link_prefix = "CF", default_calling_convention = "c")
@(link_prefix="CF", default_calling_convention="c")
foreign CoreFoundation {
// Copies the character contents of a string to a local C string buffer after converting the characters to a given encoding.
StringGetCString :: proc(theString: String, buffer: [^]byte, bufferSize: Index, encoding: StringEncoding) -> b8 ---
@@ -181,23 +181,16 @@ foreign CoreFoundation {
STR :: StringMakeConstantString
StringCopyToOdinString :: proc(
theString: String,
allocator := context.allocator,
) -> (
str: string,
ok: bool,
) #optional_ok {
StringCopyToOdinString :: proc(theString: String, allocator := context.allocator) -> (str: string, ok: bool) #optional_ok {
length := StringGetLength(theString)
max := StringGetMaximumSizeForEncoding(length, StringEncoding(StringBuiltInEncodings.UTF8))
buf, err := make([]byte, max, allocator)
if err != nil { return }
raw_str := runtime.Raw_String {
data = raw_data(buf),
if err != nil {
return
}
StringGetBytes(theString, {0, length}, StringEncoding(StringBuiltInEncodings.UTF8), 0, false, raw_data(buf), max, (^Index)(&raw_str.len))
return transmute(string)raw_str, true
n: Index
StringGetBytes(theString, {0, length}, StringEncoding(StringBuiltInEncodings.UTF8), 0, false, raw_data(buf), Index(len(buf)), &n)
return string(buf[:n]), true
}
+3 -3
View File
@@ -15,9 +15,9 @@ sys_write_string :: proc (fd: c.int, message: string) -> bool {
Offset_From :: enum c.int {
SEEK_SET = 0, // the offset is set to offset bytes.
SEEK_CUR = 1, // the offset is set to its current location plus offset bytes.
SEEK_END = 2, // the offset is set to the size of the file plus offset bytes.
SEEK_HOLE = 3, // the offset is set to the start of the next hole greater than or equal to the supplied offset.
SEEK_DATA = 4, // the offset is set to the start of the next non-hole file region greater than or equal to the supplied offset.
SEEK_END = 2, // the offset is set to the size of the file plus offset bytes.
SEEK_HOLE = 3, // the offset is set to the start of the next hole greater than or equal to the supplied offset.
SEEK_DATA = 4, // the offset is set to the start of the next non-hole file region greater than or equal to the supplied offset.
}
Open_Flags_Enum :: enum u8 {
+29 -29
View File
@@ -192,43 +192,43 @@ _STRUCT_TIMEVAL :: struct {
/* pwd.h */
_Password_Entry :: struct {
pw_name: cstring, /* username */
pw_passwd: cstring, /* user password */
pw_uid: i32, /* user ID */
pw_gid: i32, /* group ID */
pw_name: cstring, /* username */
pw_passwd: cstring, /* user password */
pw_uid: i32, /* user ID */
pw_gid: i32, /* group ID */
pw_change: u64, /* password change time */
pw_class: cstring, /* user access class */
pw_gecos: cstring, /* full user name */
pw_dir: cstring, /* home directory */
pw_shell: cstring, /* shell program */
pw_gecos: cstring, /* full user name */
pw_dir: cstring, /* home directory */
pw_shell: cstring, /* shell program */
pw_expire: u64, /* account expiration */
pw_fields: i32, /* filled fields */
}
/* processinfo.h */
_Proc_Bsdinfo :: struct {
pbi_flags: u32, /* if is 64bit; emulated etc */
pbi_status: u32,
pbi_xstatus: u32,
pbi_pid: u32,
pbi_ppid: u32,
pbi_uid: u32,
pbi_gid: u32,
pbi_ruid: u32,
pbi_rgid: u32,
pbi_svuid: u32,
pbi_svgid: u32,
res: u32,
pbi_comm: [DARWIN_MAXCOMLEN]u8,
pbi_name: [2 * DARWIN_MAXCOMLEN]u8, /* empty if no name is registered */
pbi_nfiles: u32,
pbi_pgid: u32,
pbi_pjobc: u32,
e_tdev: u32, /* controlling tty dev */
e_tpgid: u32, /* tty process group id */
pbi_nice: i32,
pbi_start_tvsec: u64,
pbi_start_tvusec: u64,
pbi_flags: u32, /* if is 64bit; emulated etc */
pbi_status: u32,
pbi_xstatus: u32,
pbi_pid: u32,
pbi_ppid: u32,
pbi_uid: u32,
pbi_gid: u32,
pbi_ruid: u32,
pbi_rgid: u32,
pbi_svuid: u32,
pbi_svgid: u32,
res: u32,
pbi_comm: [DARWIN_MAXCOMLEN]u8,
pbi_name: [2 * DARWIN_MAXCOMLEN]u8, /* empty if no name is registered */
pbi_nfiles: u32,
pbi_pgid: u32,
pbi_pjobc: u32,
e_tdev: u32, /* controlling tty dev */
e_tpgid: u32, /* tty process group id */
pbi_nice: i32,
pbi_start_tvsec: u64,
pbi_start_tvusec: u64,
}
/*--==========================================================================--*/
+6 -6
View File
@@ -695,12 +695,12 @@ Record_Lock_Flag :: enum c.int {
// struct flock
File_Lock :: struct {
start: off_t, /* starting offset */
len: off_t, /* len = 0 means until end of file */
pid: pid_t, /* lock owner */
type: Record_Lock_Flag, /* lock type: read/write, etc. */
whence: c.short, /* type of l_start */
sysid: c.int, /* remote system id or zero for local */
start: off_t, /* starting offset */
len: off_t, /* len = 0 means until end of file */
pid: pid_t, /* lock owner */
type: Record_Lock_Flag, /* lock type: read/write, etc. */
whence: c.short, /* type of l_start */
sysid: c.int, /* remote system id or zero for local */
}
/*
+2 -2
View File
@@ -4,7 +4,7 @@ package sys_windows
foreign import dwmapi "system:Dwmapi.lib"
DWMWINDOWATTRIBUTE :: enum {
DWMWA_NCRENDERING_ENABLED,
DWMWA_NCRENDERING_ENABLED = 1,
DWMWA_NCRENDERING_POLICY,
DWMWA_TRANSITIONS_FORCEDISABLED,
DWMWA_ALLOW_NCPAINT,
@@ -28,7 +28,7 @@ DWMWINDOWATTRIBUTE :: enum {
DWMWA_TEXT_COLOR,
DWMWA_VISIBLE_FRAME_BORDER_THICKNESS,
DWMWA_SYSTEMBACKDROP_TYPE,
DWMWA_LAST,
DWMWA_LAST,
}
DWMNCRENDERINGPOLICY :: enum {
+8 -8
View File
@@ -1175,17 +1175,17 @@ SYSTEM_POWER_STATUS :: struct {
}
AC_Line_Status :: enum BYTE {
Offline = 0,
Online = 1,
Unknown = 255,
Offline = 0,
Online = 1,
Unknown = 255,
}
Battery_Flag :: enum BYTE {
High = 0,
Low = 1,
Critical = 2,
Charging = 3,
No_Battery = 7,
High = 0,
Low = 1,
Critical = 2,
Charging = 3,
No_Battery = 7,
}
Battery_Flags :: bit_set[Battery_Flag; BYTE]
+26 -26
View File
@@ -3546,11 +3546,11 @@ SIGDN :: enum c_int {
}
SIATTRIBFLAGS :: enum c_int {
AND = 0x1,
OR = 0x2,
APPCOMPAT = 0x3,
MASK = 0x3,
ALLITEMS = 0x4000,
AND = 0x1,
OR = 0x2,
APPCOMPAT = 0x3,
MASK = 0x3,
ALLITEMS = 0x4000,
}
FDAP :: enum c_int {
@@ -4503,35 +4503,35 @@ DNS_INFO_NO_RECORDS :: 9501
DNS_QUERY_NO_RECURSION :: 0x00000004
DNS_RECORD :: struct { // aka DNS_RECORDA
pNext: ^DNS_RECORD,
pName: cstring,
wType: WORD,
wDataLength: USHORT,
Flags: DWORD,
dwTtl: DWORD,
_: DWORD,
Data: struct #raw_union {
CNAME: DNS_PTR_DATAA,
A: u32be, // Ipv4 Address
AAAA: u128be, // Ipv6 Address
TXT: DNS_TXT_DATAA,
NS: DNS_PTR_DATAA,
MX: DNS_MX_DATAA,
SRV: DNS_SRV_DATAA,
},
pNext: ^DNS_RECORD,
pName: cstring,
wType: WORD,
wDataLength: USHORT,
Flags: DWORD,
dwTtl: DWORD,
_: DWORD,
Data: struct #raw_union {
CNAME: DNS_PTR_DATAA,
A: u32be, // Ipv4 Address
AAAA: u128be, // Ipv6 Address
TXT: DNS_TXT_DATAA,
NS: DNS_PTR_DATAA,
MX: DNS_MX_DATAA,
SRV: DNS_SRV_DATAA,
},
}
DNS_TXT_DATAA :: struct {
dwStringCount: DWORD,
pStringArray: cstring,
dwStringCount: DWORD,
pStringArray: cstring,
}
DNS_PTR_DATAA :: cstring
DNS_MX_DATAA :: struct {
pNameExchange: cstring, // the hostname
wPreference: WORD, // lower values preferred
_: WORD, // padding.
pNameExchange: cstring, // the hostname
wPreference: WORD, // lower values preferred
_: WORD, // padding.
}
DNS_SRV_DATAA :: struct {
pNameTarget: cstring,
+1 -1
View File
@@ -56,7 +56,7 @@ Decorations :: struct {
// Connecting decorations:
nw, n, ne,
w, x, e,
w, x, e,
sw, s, se: string,
// Straight lines:
+6 -2
View File
@@ -175,10 +175,12 @@ pool_stop_task :: proc(pool: ^Pool, user_index: int, exit_code: int = 1) -> bool
intrinsics.atomic_sub(&pool.num_outstanding, 1)
intrinsics.atomic_sub(&pool.num_in_processing, 1)
old_thread_user_index := t.user_index
destroy(t)
replacement := create(pool_thread_runner)
replacement.user_index = t.user_index
replacement.user_index = old_thread_user_index
replacement.data = data
data.task = {}
pool.threads[i] = replacement
@@ -207,10 +209,12 @@ pool_stop_all_tasks :: proc(pool: ^Pool, exit_code: int = 1) {
intrinsics.atomic_sub(&pool.num_outstanding, 1)
intrinsics.atomic_sub(&pool.num_in_processing, 1)
old_thread_user_index := t.user_index
destroy(t)
replacement := create(pool_thread_runner)
replacement.user_index = t.user_index
replacement.user_index = old_thread_user_index
replacement.data = data
data.task = {}
pool.threads[i] = replacement
+5 -1
View File
@@ -2,6 +2,7 @@
// +private
package thread
import "base:runtime"
import "core:sync"
import "core:sys/unix"
import "core:time"
@@ -55,7 +56,10 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread {
// Here on Unix, we start the OS thread in a running state, and so we manually have it wait on a condition
// variable above. We must perform that waiting BEFORE we select the context!
context = _select_context_for_thread(init_context)
defer _maybe_destroy_default_temp_allocator(init_context)
defer {
_maybe_destroy_default_temp_allocator(init_context)
runtime.run_thread_local_cleaners()
}
t.procedure(t)
}
+5 -1
View File
@@ -3,6 +3,7 @@
package thread
import "base:intrinsics"
import "base:runtime"
import "core:sync"
import win32 "core:sys/windows"
@@ -39,7 +40,10 @@ _create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread {
// Here on Windows, the thread is created in a suspended state, and so we can select the context anywhere before the call
// to t.procedure().
context = _select_context_for_thread(init_context)
defer _maybe_destroy_default_temp_allocator(init_context)
defer {
_maybe_destroy_default_temp_allocator(init_context)
runtime.run_thread_local_cleaners()
}
t.procedure(t)
}
+61
View File
@@ -2048,6 +2048,14 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
return ok;
}
if (BuiltinProc__atomic_begin < id && id < BuiltinProc__atomic_end) {
if (build_context.metrics.arch == TargetArch_riscv64) {
if (!check_target_feature_is_enabled(str_lit("a"), nullptr)) {
error(call, "missing required target feature \"a\" for atomics, enable it by setting a different -microarch or explicitly adding it through -target-features");
}
}
}
switch (id) {
default:
GB_PANIC("Implement built-in procedure: %.*s", LIT(builtin_name));
@@ -5665,6 +5673,59 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
break;
}
break;
case BuiltinProc_type_has_shared_fields:
{
Type *u = check_type(c, ce->args[0]);
Type *ut = base_type(u);
if (ut == nullptr || ut == t_invalid) {
error(ce->args[0], "Expected a type for '%.*s'", LIT(builtin_name));
return false;
}
if (ut->kind != Type_Struct || ut->Struct.soa_kind != StructSoa_None) {
gbString t = type_to_string(ut);
error(ce->args[0], "Expected a struct type for '%.*s', got %s", LIT(builtin_name), t);
gb_string_free(t);
return false;
}
Type *v = check_type(c, ce->args[1]);
Type *vt = base_type(v);
if (vt == nullptr || vt == t_invalid) {
error(ce->args[1], "Expected a type for '%.*s'", LIT(builtin_name));
return false;
}
if (vt->kind != Type_Struct || vt->Struct.soa_kind != StructSoa_None) {
gbString t = type_to_string(vt);
error(ce->args[1], "Expected a struct type for '%.*s', got %s", LIT(builtin_name), t);
gb_string_free(t);
return false;
}
bool is_shared = true;
for (Entity *v_field : vt->Struct.fields) {
bool found = false;
for (Entity *u_field : ut->Struct.fields) {
if (v_field->token.string == u_field->token.string &&
are_types_identical(v_field->type, u_field->type)) {
found = true;
break;
}
}
if (!found) {
is_shared = false;
break;
}
}
operand->mode = Addressing_Constant;
operand->value = exact_value_bool(is_shared);
operand->type = t_untyped_bool;
break;
}
case BuiltinProc_type_field_type:
{
Operand op = {};
+32 -9
View File
@@ -1180,11 +1180,15 @@ gb_internal void check_assignment(CheckerContext *c, Operand *operand, Type *typ
LIT(article),
LIT(context_name));
} else {
ERROR_BLOCK();
error(operand->expr,
"Cannot assign '%s', a type, to %.*s%.*s",
op_type_str,
LIT(article),
LIT(context_name));
if (type && are_types_identical(type, t_any)) {
error_line("\tSuggestion: 'typeid_of(%s)'", expr_str);
}
}
break;
default:
@@ -3782,10 +3786,10 @@ gb_internal void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Typ
// NOTE(bill): Allow comparisons between types
if (is_ise_expr(be->left)) {
// Evalute the right before the left for an '.X' expression
check_expr_or_type(c, y, be->right, type_hint);
check_expr_or_type(c, y, be->right, nullptr /* ignore type hint */);
check_expr_or_type(c, x, be->left, y->type);
} else {
check_expr_or_type(c, x, be->left, type_hint);
check_expr_or_type(c, x, be->left, nullptr /* ignore type hint */);
check_expr_or_type(c, y, be->right, x->type);
}
bool xt = x->mode == Addressing_Type;
@@ -4658,7 +4662,8 @@ gb_internal bool check_index_value(CheckerContext *c, Type *main_type, bool open
check_expr_with_type_hint(c, &operand, index_value, type_hint);
if (operand.mode == Addressing_Invalid) {
if (value) *value = 0;
return false;
// NOTE(bill): return true here to propagate the errors better
return true;
}
Type *index_type = t_int;
@@ -4879,7 +4884,7 @@ gb_internal ExactValue get_constant_field_single(CheckerContext *c, ExactValue v
TypeAndValue tav = fv->value->tav;
if (success_) *success_ = true;
if (finish_) *finish_ = false;
return tav.value;;
return tav.value;
}
}
@@ -4954,7 +4959,6 @@ gb_internal ExactValue get_constant_field(CheckerContext *c, Operand const *oper
return value;
}
}
if (success_) *success_ = true;
return value;
} else if (value.kind == ExactValue_Quaternion) {
@@ -7625,7 +7629,7 @@ gb_internal CallArgumentError check_polymorphic_record_type(CheckerContext *c, O
gbString s = gb_string_make_reserve(heap_allocator(), e->token.string.len+3);
s = gb_string_append_fmt(s, "%.*s(", LIT(e->token.string));
TypeTuple *tuple = get_record_polymorphic_params(e->type);
TypeTuple *tuple = get_record_polymorphic_params(bt);
if (tuple != nullptr) for_array(i, tuple->variables) {
Entity *v = tuple->variables[i];
String name = v->token.string;
@@ -7640,8 +7644,10 @@ gb_internal CallArgumentError check_polymorphic_record_type(CheckerContext *c, O
s = write_type_to_string(s, v->type, false);
}
} else if (v->kind == Entity_Constant) {
s = gb_string_append_fmt(s, "=");
s = write_exact_value_to_string(s, v->Constant.value);
if (v->Constant.value.kind != ExactValue_Invalid) {
s = gb_string_append_fmt(s, "=");
s = write_exact_value_to_string(s, v->Constant.value);
}
}
}
s = gb_string_append_fmt(s, ")");
@@ -10055,6 +10061,22 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *
is_constant = o->mode == Addressing_Constant;
}
if (elem->kind == Ast_BinaryExpr) {
switch (elem->BinaryExpr.op.kind) {
case Token_Or:
{
gbString x = expr_to_string(elem->BinaryExpr.left);
gbString y = expr_to_string(elem->BinaryExpr.right);
gbString e = expr_to_string(elem);
error(elem, "Was the following intended? '%s, %s'; if not, surround the expression with parentheses '(%s)'", x, y, e);
gb_string_free(e);
gb_string_free(y);
gb_string_free(x);
}
break;
}
}
check_assignment(c, o, t->BitSet.elem, str_lit("bit_set literal"));
if (o->mode == Addressing_Constant) {
i64 lower = t->BitSet.lower;
@@ -10544,7 +10566,8 @@ gb_internal ExprKind check_index_expr(CheckerContext *c, Operand *o, Ast *node,
o->expr = node;
return kind;
} else if (ok && !is_type_matrix(t)) {
ExactValue value = type_and_value_of_expr(ie->expr).value;
TypeAndValue tav = type_and_value_of_expr(ie->expr);
ExactValue value = tav.value;
o->mode = Addressing_Constant;
bool success = false;
bool finish = false;
+10 -1
View File
@@ -199,6 +199,9 @@ gb_internal bool check_has_break(Ast *stmt, String const &label, bool implicit)
}
break;
case Ast_DeferStmt:
return check_has_break(stmt->DeferStmt.stmt, label, implicit);
case Ast_BlockStmt:
return check_has_break_list(stmt->BlockStmt.stmts, label, implicit);
@@ -1695,7 +1698,7 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
}
}
}
bool is_ptr = type_deref(operand.type);
bool is_ptr = is_type_pointer(type_deref(operand.type));
Type *t = base_type(type_deref(operand.type));
switch (t->kind) {
@@ -1735,6 +1738,7 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
break;
case Type_EnumeratedArray:
is_possibly_addressable = operand.mode == Addressing_Variable || is_ptr;
array_add(&vals, t->EnumeratedArray.elem);
array_add(&vals, t->EnumeratedArray.index);
break;
@@ -2706,6 +2710,7 @@ gb_internal void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags)
error(bs->label, "A branch statement's label name must be an identifier");
return;
}
Ast *ident = bs->label;
String name = ident->Ident.token.string;
Operand o = {};
@@ -2737,6 +2742,10 @@ gb_internal void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags)
break;
}
if (ctx->in_defer) {
error(bs->label, "A labelled '%.*s' cannot be used within a 'defer'", LIT(token.string));
}
}
case_end;
+29 -9
View File
@@ -3174,8 +3174,8 @@ gb_internal DECL_ATTRIBUTE_PROC(foreign_block_decl_attribute) {
return true;
} else if (name == "link_prefix") {
if (ev.kind == ExactValue_String) {
String link_prefix = ev.value_string;
if (!is_foreign_name_valid(link_prefix)) {
String link_prefix = string_trim_whitespace(ev.value_string);
if (link_prefix.len != 0 && !is_foreign_name_valid(link_prefix)) {
error(elem, "Invalid link prefix: '%.*s'", LIT(link_prefix));
} else {
c->foreign_context.link_prefix = link_prefix;
@@ -3186,8 +3186,8 @@ gb_internal DECL_ATTRIBUTE_PROC(foreign_block_decl_attribute) {
return true;
} else if (name == "link_suffix") {
if (ev.kind == ExactValue_String) {
String link_suffix = ev.value_string;
if (!is_foreign_name_valid(link_suffix)) {
String link_suffix = string_trim_whitespace(ev.value_string);
if (link_suffix.len != 0 && !is_foreign_name_valid(link_suffix)) {
error(elem, "Invalid link suffix: '%.*s'", LIT(link_suffix));
} else {
c->foreign_context.link_suffix = link_suffix;
@@ -3489,7 +3489,7 @@ gb_internal DECL_ATTRIBUTE_PROC(proc_decl_attribute) {
if (ev.kind == ExactValue_String) {
ac->link_prefix = ev.value_string;
if (!is_foreign_name_valid(ac->link_prefix)) {
if (ac->link_prefix.len != 0 && !is_foreign_name_valid(ac->link_prefix)) {
error(elem, "Invalid link prefix: %.*s", LIT(ac->link_prefix));
}
} else {
@@ -3501,7 +3501,7 @@ gb_internal DECL_ATTRIBUTE_PROC(proc_decl_attribute) {
if (ev.kind == ExactValue_String) {
ac->link_suffix = ev.value_string;
if (!is_foreign_name_valid(ac->link_suffix)) {
if (ac->link_suffix.len != 0 && !is_foreign_name_valid(ac->link_suffix)) {
error(elem, "Invalid link suffix: %.*s", LIT(ac->link_suffix));
}
} else {
@@ -3774,7 +3774,7 @@ gb_internal DECL_ATTRIBUTE_PROC(var_decl_attribute) {
ExactValue ev = check_decl_attribute_value(c, value);
if (ev.kind == ExactValue_String) {
ac->link_prefix = ev.value_string;
if (!is_foreign_name_valid(ac->link_prefix)) {
if (ac->link_prefix.len != 0 && !is_foreign_name_valid(ac->link_prefix)) {
error(elem, "Invalid link prefix: %.*s", LIT(ac->link_prefix));
}
} else {
@@ -3785,7 +3785,7 @@ gb_internal DECL_ATTRIBUTE_PROC(var_decl_attribute) {
ExactValue ev = check_decl_attribute_value(c, value);
if (ev.kind == ExactValue_String) {
ac->link_suffix = ev.value_string;
if (!is_foreign_name_valid(ac->link_suffix)) {
if (ac->link_suffix.len != 0 && !is_foreign_name_valid(ac->link_suffix)) {
error(elem, "Invalid link suffix: %.*s", LIT(ac->link_suffix));
}
} else {
@@ -4532,7 +4532,9 @@ gb_internal void check_collect_entities(CheckerContext *c, Slice<Ast *> const &n
case_end;
case_ast_node(fb, ForeignBlockDecl, decl);
check_add_foreign_block_decl(c, decl);
if (curr_file != nullptr) {
array_add(&curr_file->delayed_decls_queues[AstDelayQueue_ForeignBlock], decl);
}
case_end;
default:
@@ -4548,6 +4550,14 @@ gb_internal void check_collect_entities(CheckerContext *c, Slice<Ast *> const &n
// NOTE(bill): 'when' stmts need to be handled after the other as the condition may refer to something
// declared after this stmt in source
if (curr_file == nullptr) {
// For 'foreign' block statements that are not in file scope.
for_array(decl_index, nodes) {
Ast *decl = nodes[decl_index];
if (decl->kind == Ast_ForeignBlockDecl) {
check_add_foreign_block_decl(c, decl);
}
}
for_array(decl_index, nodes) {
Ast *decl = nodes[decl_index];
if (decl->kind == Ast_WhenStmt) {
@@ -5508,6 +5518,16 @@ gb_internal void check_import_entities(Checker *c) {
correct_type_aliases_in_scope(&ctx, pkg->scope);
}
for_array(i, pkg->files) {
AstFile *f = pkg->files[i];
reset_checker_context(&ctx, f, &untyped);
for (Ast *decl : f->delayed_decls_queues[AstDelayQueue_ForeignBlock]) {
check_add_foreign_block_decl(&ctx, decl);
}
array_clear(&f->delayed_decls_queues[AstDelayQueue_ForeignBlock]);
}
for_array(i, pkg->files) {
AstFile *f = pkg->files[i];
reset_checker_context(&ctx, f, &untyped);
+7
View File
@@ -99,6 +99,7 @@ enum BuiltinProcId {
BuiltinProc_prefetch_write_instruction,
BuiltinProc_prefetch_write_data,
BuiltinProc__atomic_begin,
BuiltinProc_atomic_type_is_lock_free,
BuiltinProc_atomic_thread_fence,
BuiltinProc_atomic_signal_fence,
@@ -124,6 +125,7 @@ enum BuiltinProcId {
BuiltinProc_atomic_compare_exchange_strong_explicit,
BuiltinProc_atomic_compare_exchange_weak,
BuiltinProc_atomic_compare_exchange_weak_explicit,
BuiltinProc__atomic_end,
BuiltinProc_fixed_point_mul,
BuiltinProc_fixed_point_div,
@@ -313,6 +315,8 @@ BuiltinProc__type_simple_boolean_end,
BuiltinProc_type_map_info,
BuiltinProc_type_map_cell_info,
BuiltinProc_type_has_shared_fields,
BuiltinProc__type_end,
BuiltinProc_procedure_of,
@@ -436,6 +440,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
{STR_LIT("prefetch_write_instruction"), 2, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
{STR_LIT("prefetch_write_data"), 2, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
{STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
{STR_LIT("atomic_type_is_lock_free"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("atomic_thread_fence"), 1, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
{STR_LIT("atomic_signal_fence"), 1, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
@@ -461,6 +466,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
{STR_LIT("atomic_compare_exchange_strong_explicit"), 5, false, Expr_Expr, BuiltinProcPkg_intrinsics, false, true},
{STR_LIT("atomic_compare_exchange_weak"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics, false, true},
{STR_LIT("atomic_compare_exchange_weak_explicit"), 5, false, Expr_Expr, BuiltinProcPkg_intrinsics, false, true},
{STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
{STR_LIT("fixed_point_mul"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("fixed_point_div"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics},
@@ -647,6 +653,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
{STR_LIT("type_map_info"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("type_map_cell_info"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("type_has_shared_fields"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
+13 -3
View File
@@ -55,6 +55,16 @@ gb_internal void lb_debug_file_line(lbModule *m, Ast *node, LLVMMetadataRef *fil
}
}
gb_internal LLVMMetadataRef lb_debug_procedure_parameters(lbModule *m, Type *type) {
if (is_type_proc(type)) {
return lb_debug_type(m, t_rawptr);
}
if (type->kind == Type_Tuple && type->Tuple.variables.count == 1) {
return lb_debug_procedure_parameters(m, type->Tuple.variables[0]->type);
}
return lb_debug_type(m, type);
}
gb_internal LLVMMetadataRef lb_debug_type_internal_proc(lbModule *m, Type *type) {
i64 size = type_size_of(type); // Check size
gb_unused(size);
@@ -78,7 +88,7 @@ gb_internal LLVMMetadataRef lb_debug_type_internal_proc(lbModule *m, Type *type)
if (type->Proc.result_count == 0) {
parameters[param_index++] = nullptr;
} else {
parameters[param_index++] = lb_debug_type(m, type->Proc.results);
parameters[param_index++] = lb_debug_procedure_parameters(m, type->Proc.results);
}
LLVMMetadataRef file = nullptr;
@@ -88,7 +98,7 @@ gb_internal LLVMMetadataRef lb_debug_type_internal_proc(lbModule *m, Type *type)
if (e->kind != Entity_Variable) {
continue;
}
parameters[param_index] = lb_debug_type(m, e->type);
parameters[param_index] = lb_debug_procedure_parameters(m, e->type);
param_index += 1;
}
@@ -969,7 +979,7 @@ gb_internal LLVMMetadataRef lb_debug_type(lbModule *m, Type *type) {
return lb_debug_struct(m, type, bt, name, scope, file, line);
}
case Type_Struct: return lb_debug_struct(m, type, base_type(type), name, scope, file, line);
case Type_Struct: return lb_debug_struct(m, type, bt, name, scope, file, line);
case Type_Slice: return lb_debug_slice(m, type, name, scope, file, line);
case Type_DynamicArray: return lb_debug_dynamic_array(m, type, name, scope, file, line);
case Type_Union: return lb_debug_union(m, type, name, scope, file, line);
+1 -1
View File
@@ -263,7 +263,7 @@ gb_internal lbValue lb_emit_transmute(lbProcedure *p, lbValue value, Type *t) {
if (is_type_simd_vector(src) && is_type_simd_vector(dst)) {
res.value = LLVMBuildBitCast(p->builder, value.value, lb_type(p->module, t), "");
return res;
} else if (is_type_array_like(src) && is_type_simd_vector(dst)) {
} else if (is_type_array_like(src) && (is_type_simd_vector(dst) || is_type_integer_128bit(dst))) {
unsigned align = cast(unsigned)gb_max(type_align_of(src), type_align_of(dst));
lbValue ptr = lb_address_from_load_or_generate_local(p, value);
if (lb_try_update_alignment(ptr, align)) {
+39 -9
View File
@@ -1921,6 +1921,9 @@ gb_internal Array<Ast *> parse_enum_field_list(AstFile *f) {
f->curr_token.kind != Token_EOF) {
CommentGroup *docs = f->lead_comment;
CommentGroup *comment = nullptr;
parse_enforce_tabs(f);
Ast *name = parse_value(f);
Ast *value = nullptr;
if (f->curr_token.kind == Token_Eq) {
@@ -2259,6 +2262,7 @@ gb_internal Array<Ast *> parse_union_variant_list(AstFile *f) {
auto variants = array_make<Ast *>(ast_allocator(f));
while (f->curr_token.kind != Token_CloseBrace &&
f->curr_token.kind != Token_EOF) {
parse_enforce_tabs(f);
Ast *type = parse_type(f);
if (type->kind != Ast_BadExpr) {
array_add(&variants, type);
@@ -4274,6 +4278,7 @@ gb_internal Ast *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_fl
while (f->curr_token.kind != follow &&
f->curr_token.kind != Token_Colon &&
f->curr_token.kind != Token_EOF) {
if (!is_signature) parse_enforce_tabs(f);
u32 flags = parse_field_prefixes(f);
Ast *param = parse_var_type(f, allow_ellipsis, allow_typeid_token);
if (param->kind == Ast_Ellipsis) {
@@ -4363,6 +4368,8 @@ gb_internal Ast *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_fl
f->curr_token.kind != Token_EOF &&
f->curr_token.kind != Token_Semicolon) {
CommentGroup *docs = f->lead_comment;
if (!is_signature) parse_enforce_tabs(f);
u32 set_flags = parse_field_prefixes(f);
Token tag = {};
Array<Ast *> names = parse_ident_list(f, allow_poly_names);
@@ -4532,6 +4539,10 @@ gb_internal Ast *parse_if_stmt(AstFile *f) {
return ast_bad_stmt(f, f->curr_token, f->curr_token);
}
Ast *top_if_stmt = nullptr;
Ast *prev_if_stmt = nullptr;
if_else_chain:;
Token token = expect_token(f, Token_if);
Ast *init = nullptr;
Ast *cond = nullptr;
@@ -4573,12 +4584,24 @@ gb_internal Ast *parse_if_stmt(AstFile *f) {
ignore_strict_style = true;
}
skip_possible_newline_for_literal(f, ignore_strict_style);
Ast *curr_if_stmt = ast_if_stmt(f, token, init, cond, body, nullptr);
if (top_if_stmt == nullptr) {
top_if_stmt = curr_if_stmt;
}
if (prev_if_stmt != nullptr) {
prev_if_stmt->IfStmt.else_stmt = curr_if_stmt;
}
if (f->curr_token.kind == Token_else) {
Token else_token = expect_token(f, Token_else);
switch (f->curr_token.kind) {
case Token_if:
else_stmt = parse_if_stmt(f);
break;
// NOTE(bill): Instead of relying on recursive descent for an if-else chain
// we can just inline the tail-recursion manually with a simple loop like
// construct using a `goto`
prev_if_stmt = curr_if_stmt;
goto if_else_chain;
case Token_OpenBrace:
else_stmt = parse_block_stmt(f, false);
break;
@@ -4593,7 +4616,9 @@ gb_internal Ast *parse_if_stmt(AstFile *f) {
}
}
return ast_if_stmt(f, token, init, cond, body, else_stmt);
curr_if_stmt->IfStmt.else_stmt = else_stmt;
return top_if_stmt;
}
gb_internal Ast *parse_when_stmt(AstFile *f) {
@@ -5357,6 +5382,11 @@ gb_internal u64 check_vet_flags(AstFile *file) {
gb_internal void parse_enforce_tabs(AstFile *f) {
// Checks to see if tabs have been used for indentation
if ((check_vet_flags(f) & VetFlag_Tabs) == 0) {
return;
}
Token prev = f->prev_token;
Token curr = f->curr_token;
if (prev.pos.line < curr.pos.line) {
@@ -5373,6 +5403,10 @@ gb_internal void parse_enforce_tabs(AstFile *f) {
isize len = end-it;
for (isize i = 0; i < len; i++) {
if (it[i] == '/') {
// ignore comments
break;
}
if (it[i] == ' ') {
syntax_error(curr, "With '-vet-tabs', tabs must be used for indentation");
break;
@@ -5387,11 +5421,7 @@ gb_internal Array<Ast *> parse_stmt_list(AstFile *f) {
while (f->curr_token.kind != Token_case &&
f->curr_token.kind != Token_CloseBrace &&
f->curr_token.kind != Token_EOF) {
// Checks to see if tabs have been used for indentation
if (check_vet_flags(f) & VetFlag_Tabs) {
parse_enforce_tabs(f);
}
parse_enforce_tabs(f);
Ast *stmt = parse_stmt(f);
if (stmt && stmt->kind != Ast_EmptyStmt) {
@@ -6416,7 +6446,7 @@ gb_internal bool parse_file(Parser *p, AstFile *f) {
}
f->total_file_decl_count += calc_decl_count(stmt);
if (stmt->kind == Ast_WhenStmt || stmt->kind == Ast_ExprStmt || stmt->kind == Ast_ImportDecl) {
if (stmt->kind == Ast_WhenStmt || stmt->kind == Ast_ExprStmt || stmt->kind == Ast_ImportDecl || stmt->kind == Ast_ForeignBlockDecl) {
f->delayed_decl_count += 1;
}
}
+5 -1
View File
@@ -82,6 +82,7 @@ enum AstFileFlag : u32 {
enum AstDelayQueueKind {
AstDelayQueue_Import,
AstDelayQueue_Expr,
AstDelayQueue_ForeignBlock,
AstDelayQueue_COUNT,
};
@@ -885,4 +886,7 @@ gb_internal gb_inline gbAllocator ast_allocator(AstFile *f) {
gb_internal Ast *alloc_ast_node(AstFile *f, AstKind kind);
gb_internal gbString expr_to_string(Ast *expression);
gb_internal bool allow_field_separator(AstFile *f);
gb_internal bool allow_field_separator(AstFile *f);
gb_internal void parse_enforce_tabs(AstFile *f);
@@ -69,18 +69,18 @@ test_libc_pow_binding :: proc(t: ^testing.T, $LIBC_COMPLEX:typeid, $F:typeid, po
complex_power := LIBC_COMPLEX(complex(F(n), F(0.)))
result := pow(complex_base, complex_power)
switch n%%4 {
case 0:
expected_real = value
expected_imag = 0.
case 1:
expected_real = 0.
expected_imag = value
case 2:
expected_real = -value
expected_imag = 0.
case 3:
expected_real = 0.
expected_imag = -value
case 0:
expected_real = value
expected_imag = 0.
case 1:
expected_real = 0.
expected_imag = value
case 2:
expected_real = -value
expected_imag = 0.
case 3:
expected_real = 0.
expected_imag = -value
}
testing.expectf(t, isclose(t, expected_real, F(real(result)), rtol, atol), "ftype:%T, n:%v reldiff(%v, re(%v)) is greater than specified rtol:%e", F{}, n, expected_real, result, rtol)
testing.expectf(t, isclose(t, expected_imag, F(imag(result)), rtol, atol), "ftype:%T, n:%v reldiff(%v, im(%v)) is greater than specified rtol:%e", F{}, n, expected_imag, result, rtol)
+1 -1
View File
@@ -187,7 +187,7 @@ validate_rbtree :: proc(t: ^testing.T, tree: ^$T/rb.Tree($Key, $Value)) {
}
verify_rbtree_propery_1 :: proc(t: ^testing.T, n: ^$N/rb.Node($Key, $Value)) {
testing.expect(t, rb.node_color(n) == .Black || rb.node_color(n) == .Red, "Property #1: Each node is either red or black.")
testing.expect(t, rb.node_color(n) == .Black || rb.node_color(n) == .Red, "Property #1: Each node is either red or black.")
if n == nil {
return
}
+1 -1
View File
@@ -429,7 +429,7 @@ map_with_integer_keys :: proc(t: ^testing.T) {
defer delete_map(my_map2)
unmarshal_err := json.unmarshal(marshaled_data, &my_map2)
defer for key, item in my_map2 {
defer for _, item in my_map2 {
runtime.delete_string(item)
}
testing.expectf(t, unmarshal_err == nil, "Expected `json.unmarshal` to return nil, got %v", unmarshal_err)
+5 -5
View File
@@ -241,7 +241,7 @@ doc_to_string :: proc(doc: ^xml.Document) -> (result: string) {
written += fmt.wprintf(writer, "[DOCTYPE] %v\n", doc.doctype.ident)
if len(doc.doctype.rest) > 0 {
fmt.wprintf(writer, "\t%v\n", doc.doctype.rest)
fmt.wprintf(writer, "\t%v\n", doc.doctype.rest)
}
}
@@ -250,10 +250,10 @@ doc_to_string :: proc(doc: ^xml.Document) -> (result: string) {
}
if doc.element_count > 0 {
fmt.wprintln(writer, " --- ")
print_element(writer, doc, 0)
fmt.wprintln(writer, " --- ")
}
fmt.wprintln(writer, " --- ")
print_element(writer, doc, 0)
fmt.wprintln(writer, " --- ")
}
return written, .None
}
@@ -11,6 +11,7 @@ import "core:testing"
test_temp_allocator_alignment_boundary :: proc(t: ^testing.T) {
arena: runtime.Arena
context.allocator = runtime.arena_allocator(&arena)
defer runtime.arena_destroy(&arena)
_, _ = mem.alloc(int(runtime.DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE)-120)
_, err := mem.alloc(112, 32)
@@ -22,6 +23,7 @@ test_temp_allocator_alignment_boundary :: proc(t: ^testing.T) {
test_temp_allocator_big_alloc_and_alignment :: proc(t: ^testing.T) {
arena: runtime.Arena
context.allocator = runtime.arena_allocator(&arena)
defer runtime.arena_destroy(&arena)
mappy: map[[8]int]int
err := reserve(&mappy, 50000)
@@ -32,6 +34,7 @@ test_temp_allocator_big_alloc_and_alignment :: proc(t: ^testing.T) {
test_temp_allocator_returns_correct_size :: proc(t: ^testing.T) {
arena: runtime.Arena
context.allocator = runtime.arena_allocator(&arena)
defer runtime.arena_destroy(&arena)
bytes, err := mem.alloc_bytes(10, 16)
testing.expect(t, err == nil)
+1 -2
View File
@@ -16,8 +16,7 @@ run_test_cases :: proc(t: ^testing.T, test_cases: []Test_Case, loc := #caller_lo
result, _, _ := utf8.grapheme_count(c.str)
if !testing.expectf(t, result == c.expected_clusters,
"(#% 4i) graphemes: %i != %i, %q %s", i, result, c.expected_clusters, c.str, c.str,
loc = loc)
{
loc = loc) {
failed += 1
}
}
+1 -1
View File
@@ -338,7 +338,7 @@ foreign lib {
node_set_list_tight :: proc(node: ^Node, tight: b32) -> (success: b32) ---
// Returns the info string from a fenced code block.
get_fence_info :: proc(node: ^Node) -> (fence_info: cstring) ---
node_get_fence_info :: proc(node: ^Node) -> (fence_info: cstring) ---
// Sets the info string in a fenced code block, returning `true` on success and `false` on failure.
node_set_fence_info :: proc(node: ^Node, fence_info: cstring) -> (success: b32) ---
+4 -4
View File
@@ -3459,10 +3459,10 @@ DRED_DEVICE_STATE :: enum i32 {
}
DRED_PAGE_FAULT_OUTPUT2 :: struct {
PageFaultVA: GPU_VIRTUAL_ADDRESS,
pHeadExistingAllocationNode: ^DRED_ALLOCATION_NODE1,
pHeadRecentFreedAllocationNode: ^DRED_ALLOCATION_NODE1,
PageFaultFlags: DRED_PAGE_FAULT_FLAGS,
PageFaultVA: GPU_VIRTUAL_ADDRESS,
pHeadExistingAllocationNode: ^DRED_ALLOCATION_NODE1,
pHeadRecentFreedAllocationNode: ^DRED_ALLOCATION_NODE1,
PageFaultFlags: DRED_PAGE_FAULT_FLAGS,
}
DEVICE_REMOVED_EXTENDED_DATA1 :: struct {
+2 -2
View File
@@ -476,8 +476,8 @@ IVersionInfo3_VTable :: struct {
}
ArgPair :: struct {
pName: wstring,
pValue: wstring,
pName: wstring,
pValue: wstring,
}
IPdbUtils_UUID_STRING :: "E6C9647E-9D6A-4C3B-B94C-524B5A6C343D"
+1 -1
View File
@@ -575,7 +575,7 @@ PRELOAD_TABLE :: "_PRELOAD"
L_Reg :: struct {
name: cstring,
func: CFunction,
func: CFunction,
}
L_NUMSIZES :: size_of(Integer)*16 + size_of(Number)
+3 -3
View File
@@ -69,9 +69,9 @@ decoder :: struct {
outputSampleRate: u32,
converter: data_converter, /* <-- Data conversion is achieved by running frames through this. */
pInputCache: rawptr, /* In input format. Can be null if it's not needed. */
inputCacheCap: u64, /* The capacity of the input cache. */
inputCacheConsumed: u64, /* The number of frames that have been consumed in the cache. Used for determining the next valid frame. */
inputCacheRemaining: u64, /* The number of valid frames remaining in the cahce. */
inputCacheCap: u64, /* The capacity of the input cache. */
inputCacheConsumed: u64, /* The number of frames that have been consumed in the cache. Used for determining the next valid frame. */
inputCacheRemaining: u64, /* The number of valid frames remaining in the cahce. */
allocationCallbacks: allocation_callbacks,
data: struct #raw_union {
vfs: struct {
+3 -3
View File
@@ -381,7 +381,7 @@ device_config :: struct {
noPreSilencedOutputBuffer: b8, /* When set to true, the contents of the output buffer passed into the data callback will be left undefined rather than initialized to zero. */
noClip: b8, /* When set to true, the contents of the output buffer passed into the data callback will not be clipped after returning. Only applies when the playback sample format is f32. */
noDisableDenormals: b8, /* Do not disable denormals when firing the data callback. */
noFixedSizedCallback: b8, /* Disables strict fixed-sized data callbacks. Setting this to true will result in the period size being treated only as a hint to the backend. This is an optimization for those who don't need fixed sized callbacks. */
noFixedSizedCallback: b8, /* Disables strict fixed-sized data callbacks. Setting this to true will result in the period size being treated only as a hint to the backend. This is an optimization for those who don't need fixed sized callbacks. */
dataCallback: device_data_proc,
notificationCallback: device_notification_proc,
stopCallback: stop_proc,
@@ -813,7 +813,7 @@ context_type :: struct {
/*pa_mainloop**/ pMainLoop: rawptr,
/*pa_context**/ pPulseContext: rawptr,
pApplicationName: cstring, /* Set when the context is initialized. Used by devices for their local pa_context objects. */
pServerName: cstring, /* Set when the context is initialized. Used by devices for their local pa_context objects. */
pServerName: cstring, /* Set when the context is initialized. Used by devices for their local pa_context objects. */
} when SUPPORT_PULSEAUDIO else struct {}),
jack: (struct {
@@ -1140,7 +1140,7 @@ device :: struct {
pulse: (struct {
/*pa_mainloop**/ pMainLoop: rawptr,
/*pa_context**/ pPulseContext: rawptr,
/*pa_context**/ pPulseContext: rawptr,
/*pa_stream**/ pStreamPlayback: rawptr,
/*pa_stream**/ pStreamCapture: rawptr,
} when SUPPORT_PULSEAUDIO else struct {}),
+23 -8
View File
@@ -84,7 +84,6 @@ package raylib
import "core:c"
import "core:fmt"
import "core:mem"
import "core:strings"
import "core:math/linalg"
_ :: linalg
@@ -447,9 +446,9 @@ VrStereoConfig :: struct #align(4) {
// File path list
FilePathList :: struct {
capacity: c.uint, // Filepaths max entries
count: c.uint, // Filepaths entries count
paths: [^]cstring, // Filepaths entries
capacity: c.uint, // Filepaths max entries
count: c.uint, // Filepaths entries count
paths: [^]cstring, // Filepaths entries
}
// Automation event
@@ -1029,7 +1028,6 @@ foreign lib {
SetTraceLogLevel :: proc(logLevel: TraceLogLevel) --- // Set the current threshold (minimum) log level
MemAlloc :: proc(size: c.uint) -> rawptr --- // Internal memory allocator
MemRealloc :: proc(ptr: rawptr, size: c.uint) -> rawptr --- // Internal memory reallocator
MemFree :: proc(ptr: rawptr) --- // Internal memory free
// Set custom callbacks
// WARNING: Callbacks setup is intended for advance users
@@ -1256,7 +1254,7 @@ foreign lib {
LoadImage :: proc(fileName: cstring) -> Image --- // Load image from file into CPU memory (RAM)
LoadImageRaw :: proc(fileName: cstring, width, height: c.int, format: PixelFormat, headerSize: c.int) -> Image --- // Load image from RAW file data
LoadImageSvg :: proc(fileNameOrString: cstring, width, height: c.int) -> Image --- // Load image from SVG file data or string with specified size
LoadImageAnim :: proc(fileName: cstring, frames: [^]c.int) -> Image --- // Load image sequence from file (frames appended to image.data)
LoadImageAnim :: proc(fileName: cstring, frames: ^c.int) -> Image --- // Load image sequence from file (frames appended to image.data)
LoadImageFromMemory :: proc(fileType: cstring, fileData: rawptr, dataSize: c.int) -> Image --- // Load image from memory buffer, fileType refers to extension: i.e. '.png'
LoadImageFromTexture :: proc(texture: Texture2D) -> Image --- // Load image from GPU texture data
LoadImageFromScreen :: proc() -> Image --- // Load image from screen buffer and (screenshot)
@@ -1684,8 +1682,25 @@ TextFormat :: proc(text: cstring, args: ..any) -> cstring {
// Text formatting with variables (sprintf style) and allocates (must be freed with 'MemFree')
TextFormatAlloc :: proc(text: cstring, args: ..any) -> cstring {
str := fmt.tprintf(string(text), ..args)
return strings.clone_to_cstring(str, MemAllocator())
return fmt.caprintf(string(text), ..args, allocator=MemAllocator())
}
// Internal memory free
MemFree :: proc{
MemFreePtr,
MemFreeCstring,
}
@(default_calling_convention="c")
foreign lib {
@(link_name="MemFree")
MemFreePtr :: proc(ptr: rawptr) ---
}
MemFreeCstring :: proc "c" (s: cstring) {
MemFreePtr(rawptr(s))
}
+6
View File
@@ -41,6 +41,12 @@ MAJOR_VERSION :: 2
MINOR_VERSION :: 0
PATCHLEVEL :: 16
VERSION :: proc "contextless" (ver: ^version) {
ver.major = MAJOR_VERSION
ver.minor = MINOR_VERSION
ver.patch = PATCHLEVEL
}
@(default_calling_convention="c", link_prefix="SDL_")
foreign lib {
GetVersion :: proc(ver: ^version) ---
+4 -4
View File
@@ -171,9 +171,9 @@ KeyboardEvent :: struct {
TEXTEDITINGEVENT_TEXT_SIZE :: 32
TextEditingEvent :: struct {
type: EventType, /**< ::SDL_TEXTEDITING */
timestamp: u32, /**< In milliseconds, populated using SDL_GetTicks() */
windowID: u32, /**< The window with keyboard focus, if any */
text: [TEXTEDITINGEVENT_TEXT_SIZE]u8, /**< The editing text */
timestamp: u32, /**< In milliseconds, populated using SDL_GetTicks() */
windowID: u32, /**< The window with keyboard focus, if any */
text: [TEXTEDITINGEVENT_TEXT_SIZE]u8, /**< The editing text */
start: i32, /**< The start cursor of selected editing text */
length: i32, /**< The length of selected editing text */
}
@@ -184,7 +184,7 @@ TextInputEvent :: struct {
type: EventType, /**< ::SDL_TEXTINPUT */
timestamp: u32, /**< In milliseconds, populated using SDL_GetTicks() */
windowID: u32, /**< The window with keyboard focus, if any */
text: [TEXTINPUTEVENT_TEXT_SIZE]u8, /**< The input text */
text: [TEXTINPUTEVENT_TEXT_SIZE]u8, /**< The input text */
}
MouseMotionEvent :: struct {
+23 -23
View File
@@ -54,29 +54,29 @@ GameControllerAxis :: enum c.int {
}
GameControllerButton :: enum c.int {
INVALID = -1,
A,
B,
X,
Y,
BACK,
GUIDE,
START,
LEFTSTICK,
RIGHTSTICK,
LEFTSHOULDER,
RIGHTSHOULDER,
DPAD_UP,
DPAD_DOWN,
DPAD_LEFT,
DPAD_RIGHT,
MISC1, /* Xbox Series X share button, PS5 microphone button, Nintendo Switch Pro capture button, Amazon Luna microphone button */
PADDLE1, /* Xbox Elite paddle P1 */
PADDLE2, /* Xbox Elite paddle P3 */
PADDLE3, /* Xbox Elite paddle P2 */
PADDLE4, /* Xbox Elite paddle P4 */
TOUCHPAD, /* PS4/PS5 touchpad button */
MAX,
INVALID = -1,
A,
B,
X,
Y,
BACK,
GUIDE,
START,
LEFTSTICK,
RIGHTSTICK,
LEFTSHOULDER,
RIGHTSHOULDER,
DPAD_UP,
DPAD_DOWN,
DPAD_LEFT,
DPAD_RIGHT,
MISC1, /* Xbox Series X share button, PS5 microphone button, Nintendo Switch Pro capture button, Amazon Luna microphone button */
PADDLE1, /* Xbox Elite paddle P1 */
PADDLE2, /* Xbox Elite paddle P3 */
PADDLE3, /* Xbox Elite paddle P2 */
PADDLE4, /* Xbox Elite paddle P4 */
TOUCHPAD, /* PS4/PS5 touchpad button */
MAX,
}
+4 -4
View File
@@ -19,10 +19,10 @@ TouchDeviceType :: enum c.int {
}
Finger :: struct {
id: FingerID,
x: f32,
y: f32,
pressure: f32,
id: FingerID,
x: f32,
y: f32,
pressure: f32,
}
TOUCH_MOUSEID :: ~u32(0)
+1 -1
View File
@@ -166,7 +166,7 @@ datatype :: enum c.int {
UINT32,
FLOAT,
MAX_TYPES,
MAX_TYPES,
}
@(default_calling_convention="c", link_prefix="stbir_")
+2 -2
View File
@@ -11,8 +11,8 @@ Have a look at the `example/` directory for the rendering of a basic triangle.
## Getting the wgpu-native libraries
For native support (not the browser), some libraries are required. Fortunately this is
extremely easy, just download them from the [releases on GitHub](https://github.com/gfx-rs/wgpu-native/releases/tag/v0.19.4.1),
the bindings are for v0.19.4.1 at the moment.
extremely easy, just download them from the [releases on GitHub](https://github.com/gfx-rs/wgpu-native/releases/tag/v22.1.0.1),
the bindings are for v22.1.0.1 at the moment.
These are expected in the `lib` folder under the same name as they are released (just unzipped).
By default it will look for a static release version (`wgpu-OS-ARCH-release.a|lib`),
+3 -1
View File
@@ -158,15 +158,17 @@ frame :: proc "c" (dt: f32) {
view = frame,
loadOp = .Clear,
storeOp = .Store,
depthSlice = wgpu.DEPTH_SLICE_UNDEFINED,
clearValue = { 0, 1, 0, 1 },
},
},
)
defer wgpu.RenderPassEncoderRelease(render_pass_encoder)
wgpu.RenderPassEncoderSetPipeline(render_pass_encoder, state.pipeline)
wgpu.RenderPassEncoderDraw(render_pass_encoder, vertexCount=3, instanceCount=1, firstVertex=0, firstInstance=0)
wgpu.RenderPassEncoderEnd(render_pass_encoder)
wgpu.RenderPassEncoderRelease(render_pass_encoder)
command_buffer := wgpu.CommandEncoderFinish(command_encoder, nil)
defer wgpu.CommandBufferRelease(command_buffer)
+3 -1
View File
@@ -158,15 +158,17 @@ frame :: proc "c" (dt: f32) {
view = frame,
loadOp = .Clear,
storeOp = .Store,
depthSlice = wgpu.DEPTH_SLICE_UNDEFINED,
clearValue = { 0, 1, 0, 1 },
},
},
)
defer wgpu.RenderPassEncoderRelease(render_pass_encoder)
wgpu.RenderPassEncoderSetPipeline(render_pass_encoder, state.pipeline)
wgpu.RenderPassEncoderDraw(render_pass_encoder, vertexCount=3, instanceCount=1, firstVertex=0, firstInstance=0)
wgpu.RenderPassEncoderEnd(render_pass_encoder)
wgpu.RenderPassEncoderRelease(render_pass_encoder)
command_buffer := wgpu.CommandEncoderFinish(command_encoder, nil)
defer wgpu.CommandBufferRelease(command_buffer)
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2
View File
@@ -5,7 +5,9 @@ import "vendor:wgpu"
GetSurface :: proc(instance: wgpu.Instance, window: ^sdl2.Window) -> wgpu.Surface {
window_info: sdl2.SysWMinfo
sdl2.VERSION(&window_info.version)
sdl2.GetWindowWMInfo(window, &window_info)
if window_info.subsystem == .WAYLAND {
display := window_info.info.wl.display
surface := window_info.info.wl.surface
+91 -96
View File
@@ -44,6 +44,7 @@ class WebGPUInterface {
BlendFactor: ["zero", "one", "src", "one-minus-src", "src-alpha", "one-minus-src-alpha", "dst", "one-minus-dst", "dst-alpha", "one-minus-dst-alpha", "src-alpha-saturated", "constant", "one-minus-constant", ],
PresentMode: ["fifo", "fifo-relaxed", "immediate", "mailbox", ],
TextureAspect: ["all", "stencil-only", "depth-only"],
DeviceLostReason: [undefined, "unknown", "destroyed"],
};
/** @type {WebGPUObjectManager<{}>} */
@@ -382,13 +383,19 @@ class WebGPUInterface {
*/
RenderPassColorAttachment(start) {
const viewIdx = this.mem.loadPtr(start + 4);
const resolveTargetIdx = this.mem.loadPtr(start + 8);
const resolveTargetIdx = this.mem.loadPtr(start + 12);
let depthSlice = this.mem.loadU32(start + 8);
if (depthSlice == 0xFFFFFFFF) { // DEPTH_SLICE_UNDEFINED.
depthSlice = undefined;
}
return {
view: viewIdx > 0 ? this.textureViews.get(viewIdx) : undefined,
resolveTarget: resolveTargetIdx > 0 ? this.textureViews.get(resolveTargetIdx) : undefined,
loadOp: this.enumeration("LoadOp", start + 12),
storeOp: this.enumeration("StoreOp", start + 16),
depthSlice: depthSlice,
loadOp: this.enumeration("LoadOp", start + 16),
storeOp: this.enumeration("StoreOp", start + 20),
clearValue: this.Color(start + 24),
};
}
@@ -950,14 +957,25 @@ class WebGPUInterface {
/**
* @param {number} adapterIdx
* @param {number} propertiesPtr
* @param {number} infoPtr
*/
wgpuAdapterGetProperties: (adapterIdx, propertiesPtr) => {
this.assert(propertiesPtr != 0);
// Unknown adapter.
this.mem.storeI32(propertiesPtr + 28, 3);
wgpuAdapterGetInfo: (adapterIdx, infoPtr) => {
this.assert(infoPtr != 0);
// WebGPU backend.
this.mem.storeI32(propertiesPtr + 32, 2);
this.mem.storeI32(infoPtr + 20, 2);
// Unknown adapter.
this.mem.storeI32(infoPtr + 24, 3);
// NOTE: I don't think getting the other fields in this struct is possible.
// `adapter.requestAdapterInfo` is deprecated.
},
/**
* @param {number} infoPtr
*/
wgpuAdapterInfoFreeMembers: (infoPtr) => {
// NOTE: nothing to free.
},
/**
@@ -970,50 +988,6 @@ class WebGPUInterface {
return adapter.features.has(this.enums.FeatureName[featureInt]);
},
/**
* @param {number} adapterIdx
* @param {number} callbackPtr
* @param {0|number} userdata
*/
wgpuAdapterRequestAdapterInfo: async (adapterIdx, callbackPtr, userdata) => {
const adapter = this.adapters.get(adapterIdx);
const callback = this.mem.exports.__indirect_function_table.get(callbackPtr);
const info = await adapter.requestAdapterInfo();
const addr = this.mem.exports.wgpu_alloc(16);
const vendorLength = new TextEncoder().encode(info.vendor).length;
const vendorAddr = this.mem.exports.wgpu_alloc(vendorLength);
this.mem.storeString(vendorAddr, info.vendor);
this.mem.storeI32(addr + 0, vendorAddr);
const architectureLength = new TextEncoder().encode(info.architecture).length;
const architectureAddr = this.mem.exports.wgpu_alloc(architectureLength);
this.mem.storeString(architectureAddr, info.architecture);
this.mem.storeI32(addr + 4, architectureAddr);
const deviceLength = new TextEncoder().encode(info.device).length;
const deviceAddr = this.mem.exports.wgpu_alloc(deviceLength);
this.mem.storeString(deviceAddr, info.device);
this.mem.storeI32(addr + 8, deviceAddr);
const descriptionLength = new TextEncoder().encode(info.description).length;
const descriptionAddr = this.mem.exports.wgpu_alloc(descriptionLength);
this.mem.storeString(descriptionAddr, info.description);
this.mem.storeI32(addr + 12, descriptionAddr);
callback(addr, userdata);
this.mem.exports.wgpu_free(descriptionAddr);
this.mem.exports.wgpu_free(deviceAddr);
this.mem.exports.wgpu_free(architectureAddr);
this.mem.exports.wgpu_free(vendorAddr);
this.mem.exports.wgpu_free(addr);
},
/**
* @param {number} adapterIdx
* @param {0|number} descriptorPtr
@@ -1040,14 +1014,69 @@ class WebGPUInterface {
};
}
let device;
let deviceIdx;
try {
const device = await adapter.requestDevice(descriptor);
device = await adapter.requestDevice(descriptor);
deviceIdx = this.devices.create(device);
// NOTE: don't callback here, any errors that happen later will then be caught by the catch here.
} catch (e) {
console.warn(e);
callback(1, null, null, userdata);
const messageLength = new TextEncoder().encode(e.message).length;
const messageAddr = this.mem.exports.wgpu_alloc(messageLength + 1);
this.mem.storeString(messageAddr, e.message);
callback(1, null, messageAddr, userdata);
this.mem.exports.wgpu_free(messageAddr);
}
let callbacksPtr = descriptorPtr + 24 + this.mem.intSize;
const deviceLostCallbackPtr = this.mem.loadPtr(callbacksPtr);
if (deviceLostCallbackPtr != 0) {
const deviceLostUserData = this.mem.loadPtr(callbacksPtr) + 4;
const deviceLostCallback = this.mem.exports.__indirect_function_table.get(deviceLostCallbackPtr);
device.lost.then((info) => {
const reason = this.enums.DeviceLostReason.indexOf(info.reason);
const messageLength = new TextEncoder().encode(info.message).length;
const messageAddr = this.mem.exports.wgpu_alloc(messageLength + 1);
this.mem.storeString(messageAddr, info.message);
deviceLostCallback(reason, messageAddr, deviceLostUserData);
this.mem.exports.wgpu_free(messageAddr);
});
}
callbacksPtr += 8;
// Skip over `nextInChain`.
callbacksPtr += 4;
const uncapturedErrorCallbackPtr = this.mem.loadPtr(callbacksPtr);
if (uncapturedErrorCallbackPtr != 0) {
const uncapturedErrorUserData = this.mem.loadPtr(callbacksPtr + 4);
const uncapturedErrorCallback = this.mem.exports.__indirect_function_table.get(uncapturedErrorCallbackPtr);
device.onuncapturederror = (ev) => {
let status = 4; // Unknown
if (ev.error instanceof GPUValidationError) {
status = 1; // Validation
} else if (ev.error instanceof GPUOutOfMemoryError) {
status = 2; // OutOfMemory
} else if (ev.error instanceof GPUInternalError) {
status = 3; // Internal
}
const messageLength = new TextEncoder().encode(ev.error.message).length;
const messageAddr = this.mem.exports.wgpu_alloc(messageLength + 1);
this.mem.storeString(messageAddr, ev.error.message);
uncapturedErrorCallback(status, messageAddr, uncapturedErrorUserData);
this.mem.exports.wgpu_free(messageAddr);
};
}
callback(0, deviceIdx, null, userdata);
@@ -1918,29 +1947,6 @@ class WebGPUInterface {
device.pushErrorScope(this.enums.ErrorFilter[filterInt]);
},
/**
* @param {number} deviceIdx
* @param {number} callbackPtr
* @param {number} userdata
*/
wgpuDeviceSetUncapturedErrorCallback: (deviceIdx, callbackPtr, userdata) => {
const device = this.devices.get(deviceIdx);
const callback = this.mem.exports.__indirect_function_table.get(callbackPtr);
device.onuncapturederror = (ev) => {
console.warn(ev.error);
let status = 4;
if (error instanceof GPUValidationError) {
status = 1;
} else if (error instanceof GPUOutOfMemoryError) {
status = 2;
} else if (error instanceof GPUInternalError) {
status = 3;
}
callback(status, null, userdata);
};
},
...this.devices.interface(true),
/* ---------------------- Instance ---------------------- */
@@ -2646,23 +2652,23 @@ class WebGPUInterface {
const formatStr = navigator.gpu.getPreferredCanvasFormat();
const format = this.enums.TextureFormat.indexOf(formatStr);
this.mem.storeUint(capabilitiesPtr + this.mem.intSize, 1);
this.mem.storeUint(capabilitiesPtr + 8, 1);
const formatAddr = this.mem.exports.wgpu_alloc(4);
this.mem.storeI32(formatAddr, format);
this.mem.storeI32(capabilitiesPtr + this.mem.intSize*2, formatAddr);
this.mem.storeI32(capabilitiesPtr + 8 + this.mem.intSize, formatAddr);
// NOTE: present modes don't seem to actually do anything in JS, we can just give back a default FIFO though.
this.mem.storeUint(capabilitiesPtr + this.mem.intSize*3, 1);
this.mem.storeUint(capabilitiesPtr + 8 + this.mem.intSize*2, 1);
const presentModesAddr = this.mem.exports.wgpu_alloc(4);
this.mem.storeI32(presentModesAddr, 0);
this.mem.storeI32(capabilitiesPtr + this.mem.intSize*4, presentModesAddr);
this.mem.storeI32(capabilitiesPtr + 8 + this.mem.intSize*3, presentModesAddr);
// Browser seems to support opaque (1) and premultiplied (2).
this.mem.storeUint(capabilitiesPtr + this.mem.intSize*5, 2);
this.mem.storeUint(capabilitiesPtr + 8 + this.mem.intSize*4, 2);
const alphaModesAddr = this.mem.exports.wgpu_alloc(8);
this.mem.storeI32(alphaModesAddr + 0, 1); // Opaque.
this.mem.storeI32(alphaModesAddr + 4, 2); // premultiplied.
this.mem.storeI32(capabilitiesPtr + this.mem.intSize*6, alphaModesAddr);
this.mem.storeI32(capabilitiesPtr + 8 + this.mem.intSize*5, alphaModesAddr);
},
/**
@@ -2680,17 +2686,6 @@ class WebGPUInterface {
// TODO: determine suboptimal and/or status.
},
/**
* @param {number} surfaceIdx
* @param {number} texturePtr
* @returns {number}
*/
wgpuSurfaceGetPreferredFormat: (surfaceIdx, adapterIdx) => {
const formatStr = navigator.gpu.getPreferredCanvasFormat();
const format = this.enums.TextureFormat.indexOf(formatStr);
return format;
},
/**
* @param {number} surfaceIdx
*/
+111 -53
View File
@@ -13,7 +13,7 @@ when ODIN_OS == .Windows {
@(private) LIB :: "lib/wgpu-windows-" + ARCH + "-" + TYPE + "/wgpu_native" + EXT
when !#exists(LIB) {
#panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v0.19.4.1, make sure to read the README at '" + #directory + "vendor/wgpu/README.md'")
#panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v22.1.0.1, make sure to read the README at '" + #directory + "vendor/wgpu/README.md'")
}
foreign import libwgpu {
@@ -34,7 +34,7 @@ when ODIN_OS == .Windows {
@(private) LIB :: "lib/wgpu-macos-" + ARCH + "-" + TYPE + "/libwgpu_native" + EXT
when !#exists(LIB) {
#panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v0.19.4.1, make sure to read the README at '" + #directory + "vendor/wgpu/README.md'")
#panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v22.1.0.1, make sure to read the README at '" + #directory + "vendor/wgpu/README.md'")
}
foreign import libwgpu {
@@ -49,7 +49,7 @@ when ODIN_OS == .Windows {
@(private) LIB :: "lib/wgpu-linux-" + ARCH + "-" + TYPE + "/libwgpu_native" + EXT
when !#exists(LIB) {
#panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v0.19.4.1, make sure to read the README at '" + #directory + "vendor/wgpu/README.md'")
#panic("Could not find the compiled WGPU Native library at '" + #directory + LIB + "', these can be downloaded from https://github.com/gfx-rs/wgpu-native/releases/tag/v22.1.0.1, make sure to read the README at '" + #directory + "vendor/wgpu/README.md'")
}
foreign import libwgpu {
@@ -220,7 +220,8 @@ CullMode :: enum i32 {
DeviceLostReason :: enum i32 {
Undefined = 0x00000000,
Destroyed = 0x00000001,
Unknown = 0x00000001,
Destroyed = 0x00000002,
}
ErrorFilter :: enum i32 {
@@ -264,6 +265,30 @@ FeatureName :: enum i32 {
PipelineStatisticsQuery,
StorageResourceBindingArray,
PartiallyBoundBindingArray,
TextureFormat16bitNorm,
TextureCompressionAstcHdr,
// TODO: requires wgpu.h api change
// TimestampQueryInsidePasses,
MappablePrimaryBuffers = 0x0003000E,
BufferBindingArray,
UniformBufferAndStorageTextureArrayNonUniformIndexing,
// TODO: requires wgpu.h api change
// AddressModeClampToZero,
// AddressModeClampToBorder,
// PolygonModeLine,
// PolygonModePoint,
// ConservativeRasterization,
// ClearTexture,
// SprivShaderPassThrough,
// MultiView,
VertexAttribute64bit = 0x00030019,
TextureFormatNv12,
RayTracingAccelarationStructure,
RayQuery,
ShaderF64,
ShaderI16,
ShaderPrimitiveIndex,
ShaderEarlyDepthTest,
}
FilterMode :: enum i32 {
@@ -520,6 +545,18 @@ TextureFormat :: enum i32 {
ASTC12x10UnormSrgb = 0x0000005D,
ASTC12x12Unorm = 0x0000005E,
ASTC12x12UnormSrgb = 0x0000005F,
// Native.
// From FeatureName.TextureFormat16bitNorm
R16Unorm = 0x00030001,
R16Snorm,
Rg16Unorm,
Rg16Snorm,
Rgba16Unorm,
Rgba16Snorm,
// From FeatureName.TextureFormatNv12
NV12,
}
TextureSampleType :: enum i32 {
@@ -581,13 +618,13 @@ VertexStepMode :: enum i32 {
VertexBufferNotUsed = 0x00000002,
}
// WGSLFeatureName :: enum i32 {
// Undefined = 0x00000000,
// ReadonlyAndReadwriteStorageTextures = 0x00000001,
// Packed4x8IntegerDotProduct = 0x00000002,
// UnrestrictedPointerParameters = 0x00000003,
// PointerCompositeAccess = 0x00000004,
// }
WGSLFeatureName :: enum i32 {
Undefined = 0x00000000,
ReadonlyAndReadwriteStorageTextures = 0x00000001,
Packed4x8IntegerDotProduct = 0x00000002,
UnrestrictedPointerParameters = 0x00000003,
PointerCompositeAccess = 0x00000004,
}
BufferUsage :: enum i32 {
MapRead = 0x00000000,
@@ -634,22 +671,18 @@ TextureUsage :: enum i32 {
}
TextureUsageFlags :: bit_set[TextureUsage; Flags]
BufferMapAsyncCallback :: #type proc "c" (status: BufferMapAsyncStatus, /* NULLABLE */ userdata: rawptr)
ShaderModuleGetCompilationInfoCallback :: #type proc "c" (status: CompilationInfoRequestStatus, compilationInfo: ^CompilationInfo, /* NULLABLE */ userdata: rawptr)
DeviceCreateComputePipelineAsyncCallback :: #type proc "c" (status: CreatePipelineAsyncStatus, pipeline: ComputePipeline, message: cstring, /* NULLABLE */ userdata: rawptr)
DeviceCreateRenderPipelineAsyncCallback :: #type proc "c" (status: CreatePipelineAsyncStatus, pipeline: RenderPipeline, message: cstring, /* NULLABLE */ userdata: rawptr)
Proc :: distinct rawptr
DeviceLostCallback :: #type proc "c" (reason: DeviceLostReason, message: cstring, userdata: rawptr)
ErrorCallback :: #type proc "c" (type: ErrorType, message: cstring, userdata: rawptr)
Proc :: distinct rawptr
QueueOnSubmittedWorkDoneCallback :: #type proc "c" (status: QueueWorkDoneStatus, /* NULLABLE */ userdata: rawptr)
InstanceRequestAdapterCallback :: #type proc "c" (status: RequestAdapterStatus, adapter: Adapter, message: cstring, /* NULLABLE */ userdata: rawptr)
AdapterRequestDeviceCallback :: #type proc "c" (status: RequestDeviceStatus, device: Device, message: cstring, /* NULLABLE */ userdata: rawptr)
// AdapterRequestAdapterInfoCallback :: #type proc "c" (adapterInfo: AdapterInfo, /* NULLABLE */ userdata: rawptr)
BufferMapAsyncCallback :: #type proc "c" (status: BufferMapAsyncStatus, /* NULLABLE */ userdata: rawptr)
DeviceCreateComputePipelineAsyncCallback :: #type proc "c" (status: CreatePipelineAsyncStatus, pipeline: ComputePipeline, message: cstring, /* NULLABLE */ userdata: rawptr)
DeviceCreateRenderPipelineAsyncCallback :: #type proc "c" (status: CreatePipelineAsyncStatus, pipeline: RenderPipeline, message: cstring, /* NULLABLE */ userdata: rawptr)
InstanceRequestAdapterCallback :: #type proc "c" (status: RequestAdapterStatus, adapter: Adapter, message: cstring, /* NULLABLE */ userdata: rawptr)
QueueOnSubmittedWorkDoneCallback :: #type proc "c" (status: QueueWorkDoneStatus, /* NULLABLE */ userdata: rawptr)
ShaderModuleGetCompilationInfoCallback :: #type proc "c" (status: CompilationInfoRequestStatus, compilationInfo: ^CompilationInfo, /* NULLABLE */ userdata: rawptr)
ChainedStruct :: struct {
next: ^ChainedStruct,
@@ -661,28 +694,23 @@ ChainedStructOut :: struct {
sType: SType,
}
// AdapterInfo :: struct {
// next: ^ChainedStructOut,
// vendor: cstring,
// architecture: cstring,
// device: cstring,
// description: cstring,
// backendType: BackendType,
// adapterType: AdapterType,
// vendorID: u32,
// deviceID: u32,
// }
AdapterProperties :: struct {
AdapterInfo :: struct {
nextInChain: ^ChainedStructOut,
vendorID: u32,
vendorName: cstring,
vendor: cstring,
architecture: cstring,
deviceID: u32,
name: cstring,
driverDescription: cstring,
adapterType: AdapterType,
device: cstring,
description: cstring,
backendType: BackendType,
adapterType: AdapterType,
vendorID: u32,
deviceID: u32,
}
when ODIN_OS == .JS {
#assert(int(BackendType.WebGPU) == 2)
#assert(offset_of(AdapterInfo, backendType) == 20)
#assert(int(AdapterType.Unknown) == 3)
#assert(offset_of(AdapterInfo, adapterType) == 24)
}
BindGroupEntry :: struct {
@@ -943,6 +971,7 @@ StorageTextureBindingLayout :: struct {
SurfaceCapabilities :: struct {
nextInChain: ^ChainedStructOut,
usages: TextureUsageFlags,
formatCount: uint,
formats: /* const */ [^]TextureFormat `fmt:"v,formatCount"`,
presentModeCount: uint,
@@ -950,6 +979,16 @@ SurfaceCapabilities :: struct {
alphaModeCount: uint,
alphaModes: /* const */ [^]CompositeAlphaMode `fmt:"v,alphaModeCount"`,
}
when ODIN_OS == .JS {
#assert(offset_of(SurfaceCapabilities, formatCount) == 8)
#assert(offset_of(SurfaceCapabilities, formats) == 8 + 1*size_of(int))
#assert(offset_of(SurfaceCapabilities, presentModeCount) == 8 + 2*size_of(int))
#assert(offset_of(SurfaceCapabilities, presentModes) == 8 + 3*size_of(int))
#assert(offset_of(SurfaceCapabilities, alphaModeCount) == 8 + 4*size_of(int))
#assert(offset_of(SurfaceCapabilities, alphaModes) == 8 + 5*size_of(int))
}
SurfaceConfiguration :: struct {
nextInChain: ^ChainedStruct,
@@ -1040,6 +1079,12 @@ TextureViewDescriptor :: struct {
aspect: TextureAspect,
}
UncapturedErrorCallbackInfo :: struct {
nextInChain: ^ChainedStruct,
callback: ErrorCallback,
userdata: rawptr,
}
VertexAttribute :: struct {
format: VertexFormat,
offset: u64,
@@ -1120,12 +1165,21 @@ ProgrammableStageDescriptor :: struct {
RenderPassColorAttachment :: struct {
nextInChain: ^ChainedStruct,
/* NULLABLE */ view: TextureView,
// depthSlice: u32,
depthSlice: u32,
/* NULLABLE */ resolveTarget: TextureView,
loadOp: LoadOp,
storeOp: StoreOp,
clearValue: Color,
}
when ODIN_OS == .JS {
#assert(size_of(RenderPassColorAttachment) == 56)
#assert(offset_of(RenderPassColorAttachment, view) == 4)
#assert(offset_of(RenderPassColorAttachment, depthSlice) == 8)
#assert(offset_of(RenderPassColorAttachment, resolveTarget) == 12)
#assert(offset_of(RenderPassColorAttachment, loadOp) == 16)
#assert(offset_of(RenderPassColorAttachment, storeOp) == 20)
#assert(offset_of(RenderPassColorAttachment, clearValue) == 24)
}
RequiredLimits :: struct {
nextInChain: ^ChainedStruct,
@@ -1194,6 +1248,10 @@ DeviceDescriptor :: struct {
defaultQueue: QueueDescriptor,
deviceLostCallback: DeviceLostCallback,
deviceLostUserdata: rawptr,
uncapturedErrorCallbackInfo: UncapturedErrorCallbackInfo,
}
when ODIN_OS == .JS {
#assert(offset_of(DeviceDescriptor, deviceLostCallback) == 24 + size_of(int))
}
RenderPassDescriptor :: struct {
@@ -1245,16 +1303,18 @@ foreign libwgpu {
// Methods of Adapter
@(link_name="wgpuAdapterEnumerateFeatures")
RawAdapterEnumerateFeatures :: proc(adapter: Adapter, features: [^]FeatureName) -> uint ---
@(link_name="wgpuAdapterGetInfo")
RawAdapterGetInfo :: proc(adapter: Adapter, info: ^AdapterInfo) ---
@(link_name="wgpuAdapterGetLimits")
RawAdapterGetLimits :: proc(adapter: Adapter, limits: ^SupportedLimits) -> b32 ---
@(link_name="wgpuAdapterGetProperties")
RawAdapterGetProperties :: proc(adapter: Adapter, properties: ^AdapterProperties) ---
AdapterHasFeature :: proc(adapter: Adapter, feature: FeatureName) -> b32 ---
// AdapterRequestAdapterInfo :: proc(adapter: Adapter, callback: AdapterRequestAdapterInfoCallback, /* NULLABLE */ userdata: rawptr) ---
AdapterRequestDevice :: proc(adapter: Adapter, /* NULLABLE */ descriptor: /* const */ ^DeviceDescriptor, callback: AdapterRequestDeviceCallback, /* NULLABLE */ userdata: rawptr = nil) ---
AdapterReference :: proc(adapter: Adapter) ---
AdapterRelease :: proc(adapter: Adapter) ---
// Procs of AdapterInfo
AdapterInfoFreeMembers :: proc(adapterInfo: AdapterInfo) ---
// Methods of BindGroup
BindGroupSetLabel :: proc(bindGroup: BindGroup, label: cstring) ---
BindGroupReference :: proc(bindGroup: BindGroup) ---
@@ -1348,13 +1408,12 @@ foreign libwgpu {
DevicePopErrorScope :: proc(device: Device, callback: ErrorCallback, userdata: rawptr) ---
DevicePushErrorScope :: proc(device: Device, filter: ErrorFilter) ---
DeviceSetLabel :: proc(device: Device, label: cstring) ---
DeviceSetUncapturedErrorCallback :: proc(device: Device, callback: ErrorCallback, userdata: rawptr) ---
DeviceReference :: proc(device: Device) ---
DeviceRelease :: proc(device: Device) ---
// Methods of Instance
InstanceCreateSurface :: proc(instance: Instance, descriptor: /* const */ ^SurfaceDescriptor) -> Surface ---
// InstanceHasWGSLLanguageFeature :: proc(instance: Instance, feature: WGSLFeatureName) -> b32 ---
InstanceHasWGSLLanguageFeature :: proc(instance: Instance, feature: WGSLFeatureName) -> b32 ---
InstanceProcessEvents :: proc(instance: Instance) ---
InstanceRequestAdapter :: proc(instance: Instance, /* NULLABLE */ options: /* const */ ^RequestAdapterOptions, callback: InstanceRequestAdapterCallback, /* NULLABLE */ userdata: rawptr = nil) ---
InstanceReference :: proc(instance: Instance) ---
@@ -1455,9 +1514,8 @@ foreign libwgpu {
RawSurfaceGetCapabilities :: proc(surface: Surface, adapter: Adapter, capabilities: ^SurfaceCapabilities) ---
@(link_name="wgpuSurfaceGetCurrentTexture")
RawSurfaceGetCurrentTexture :: proc(surface: Surface, surfaceTexture: ^SurfaceTexture) ---
SurfaceGetPreferredFormat :: proc(surface: Surface, adapter: Adapter) -> TextureFormat ---
SurfacePresent :: proc(surface: Surface) ---
// SurfaceSetLabel :: proc(surface: Surface, label: cstring) ---
SurfaceSetLabel :: proc(surface: Surface, label: cstring) ---
SurfaceUnconfigure :: proc(surface: Surface) ---
SurfaceReference :: proc(surface: Surface) ---
SurfaceRelease :: proc(surface: Surface) ---
@@ -1500,8 +1558,8 @@ AdapterGetLimits :: proc(adapter: Adapter) -> (limits: SupportedLimits, ok: bool
return
}
AdapterGetProperties :: proc(adapter: Adapter) -> (properties: AdapterProperties) {
RawAdapterGetProperties(adapter, &properties)
AdapterGetInfo :: proc(adapter: Adapter) -> (info: AdapterInfo) {
RawAdapterGetInfo(adapter, &info)
return
}
@@ -1634,8 +1692,8 @@ SurfaceGetCurrentTexture :: proc(surface: Surface) -> (surface_texture: SurfaceT
// WGPU Native bindings
BINDINGS_VERSION :: [4]u8{0, 19, 4, 1}
BINDINGS_VERSION_STRING :: "0.19.4.1"
BINDINGS_VERSION :: [4]u8{22, 1, 0, 1}
BINDINGS_VERSION_STRING :: "22.1.0.1"
when ODIN_OS != .JS {
@(private="file", init)
+1675 -1675
View File
File diff suppressed because it is too large Load Diff
+311 -311
View File
@@ -47,9 +47,9 @@ XExtCodes :: struct {
}
XPixmapFormatValues :: struct {
depth: i32,
bits_per_pixel: i32,
scanline_pad: i32,
depth: i32,
bits_per_pixel: i32,
scanline_pad: i32,
}
XGCValues :: struct {
@@ -130,47 +130,47 @@ ScreenFormat :: struct {
}
XSetWindowAttributes :: struct {
background_pixmap: Pixmap,
background_pixel: uint,
border_pixmap: Pixmap,
border_pixel: uint,
bit_gravity: Gravity,
win_gravity: Gravity,
backing_store: BackingStore,
backing_planes: uint,
backing_pixel: uint,
save_under: b32,
event_mask: EventMask,
do_not_propagate_mask: EventMask,
override_redirect: b32,
colormap: Colormap,
cursor: Cursor,
background_pixmap: Pixmap,
background_pixel: uint,
border_pixmap: Pixmap,
border_pixel: uint,
bit_gravity: Gravity,
win_gravity: Gravity,
backing_store: BackingStore,
backing_planes: uint,
backing_pixel: uint,
save_under: b32,
event_mask: EventMask,
do_not_propagate_mask: EventMask,
override_redirect: b32,
colormap: Colormap,
cursor: Cursor,
}
XWindowAttributes :: struct {
x: i32,
y: i32,
width: i32,
height: i32,
border_width: i32,
depth: i32,
visual: ^Visual,
root: Window,
class: WindowClass,
bit_gravity: Gravity,
win_gravity: Gravity,
backing_store: BackingStore,
backing_planes: uint,
backing_pixel: uint,
save_under: b32,
colormap: Colormap,
map_installed: b32,
map_state: WindowMapState,
all_event_masks: EventMask,
your_event_mask: EventMask,
do_not_propagate_mask: EventMask,
override_redirect: b32,
screen: ^Screen,
x: i32,
y: i32,
width: i32,
height: i32,
border_width: i32,
depth: i32,
visual: ^Visual,
root: Window,
class: WindowClass,
bit_gravity: Gravity,
win_gravity: Gravity,
backing_store: BackingStore,
backing_planes: uint,
backing_pixel: uint,
save_under: b32,
colormap: Colormap,
map_installed: b32,
map_state: WindowMapState,
all_event_masks: EventMask,
your_event_mask: EventMask,
do_not_propagate_mask: EventMask,
override_redirect: b32,
screen: ^Screen,
}
XHostAddress :: struct {
@@ -187,50 +187,50 @@ XServerInterpretedAddress :: struct {
}
XImage :: struct {
width: i32,
height: i32,
xoffset: i32,
format: ImageFormat,
data: rawptr,
byte_order: i32,
bitmap_unit: i32,
bitmap_bit_order: ByteOrder,
bitmap_pad: i32,
depth: i32,
bytes_per_line: i32,
bits_per_pixel: i32,
red_mask: uint,
green_mask: uint,
blue_mask: uint,
obdata: rawptr,
f: struct {
create_image: proc "c" (
display: ^Display,
visual: ^Visual,
depth: u32,
format: i32,
offset: i32,
data: rawptr,
width: u32,
height: u32,
pad: i32,
stride: i32) -> ^XImage,
destroy_image: proc "c" (image: ^XImage) -> i32,
get_pixel: proc "c" (image: ^XImage) -> uint,
put_pixel: proc "c" (image: ^XImage, x: i32, y: i32, pixel: uint) -> i32,
sub_image: proc "c" (image: ^XImage, x: i32, y: i32, w: u32, h: u32) -> ^XImage,
add_pixel: proc "c" (image: ^XImage, val: int) -> i32,
width: i32,
height: i32,
xoffset: i32,
format: ImageFormat,
data: rawptr,
byte_order: i32,
bitmap_unit: i32,
bitmap_bit_order: ByteOrder,
bitmap_pad: i32,
depth: i32,
bytes_per_line: i32,
bits_per_pixel: i32,
red_mask: uint,
green_mask: uint,
blue_mask: uint,
obdata: rawptr,
f: struct {
create_image: proc "c" (
display: ^Display,
visual: ^Visual,
depth: u32,
format: i32,
offset: i32,
data: rawptr,
width: u32,
height: u32,
pad: i32,
stride: i32) -> ^XImage,
destroy_image: proc "c" (image: ^XImage) -> i32,
get_pixel: proc "c" (image: ^XImage) -> uint,
put_pixel: proc "c" (image: ^XImage, x: i32, y: i32, pixel: uint) -> i32,
sub_image: proc "c" (image: ^XImage, x: i32, y: i32, w: u32, h: u32) -> ^XImage,
add_pixel: proc "c" (image: ^XImage, val: int) -> i32,
},
}
XWindowChanges :: struct {
x: i32,
y: i32,
width: i32,
height: i32,
border_width: i32,
sibling: Window,
stack_mode: WindowStacking,
x: i32,
y: i32,
width: i32,
height: i32,
border_width: i32,
sibling: Window,
stack_mode: WindowStacking,
}
XColor :: struct {
@@ -243,42 +243,42 @@ XColor :: struct {
}
XSegment :: struct {
x1: i16,
y1: i16,
x2: i16,
y2: i16,
x1: i16,
y1: i16,
x2: i16,
y2: i16,
}
XPoint :: struct {
x: i16,
y: i16,
x: i16,
y: i16,
}
XRectangle :: struct {
x: i16,
y: i16,
width: u16,
height: u16,
x: i16,
y: i16,
width: u16,
height: u16,
}
XArc :: struct {
x: i16,
y: i16,
width: u16,
height: u16,
angle1: i16,
angle2: i16,
x: i16,
y: i16,
width: u16,
height: u16,
angle1: i16,
angle2: i16,
}
XKeyboardControl :: struct {
key_click_percent: i32,
bell_percent: i32,
bell_pitch: i32,
bell_duration: i32,
led: i32,
led_mode: KeyboardLedMode,
key: i32,
auto_repeat_mode: KeyboardAutoRepeatMode,
key_click_percent: i32,
bell_percent: i32,
bell_pitch: i32,
bell_duration: i32,
led: i32,
led_mode: KeyboardLedMode,
key: i32,
auto_repeat_mode: KeyboardAutoRepeatMode,
}
XKeyboardState :: struct {
@@ -700,23 +700,23 @@ XAnyEvent :: struct {
}
XGenericEvent :: struct {
type: EventType,
serial: uint,
send_event: b32,
display: ^Display,
extension: i32,
evtype: i32,
type: EventType,
serial: uint,
send_event: b32,
display: ^Display,
extension: i32,
evtype: i32,
}
XGenericEventCookie :: struct {
type: EventType,
serial: uint,
send_event: b32,
display: ^Display,
extension: i32,
evtype: i32,
cookie: u32,
data: rawptr,
type: EventType,
serial: uint,
send_event: b32,
display: ^Display,
extension: i32,
evtype: i32,
cookie: u32,
data: rawptr,
}
XEvent :: struct #raw_union {
@@ -758,55 +758,55 @@ XEvent :: struct #raw_union {
}
XCharStruct :: struct {
lbearing: i16,
rbearing: i16,
width: i16,
ascent: i16,
descent: i16,
attributes: u16,
lbearing: i16,
rbearing: i16,
width: i16,
ascent: i16,
descent: i16,
attributes: u16,
}
XFontProp :: struct {
name: Atom,
card32: uint,
name: Atom,
card32: uint,
}
XFontStruct :: struct {
ext_data: ^XExtData,
fid: Font,
direction: u32,
min_char_or_byte2: u32,
max_char_or_byte2: u32,
min_byte1: u32,
max_byte1: u32,
all_chars_exist: i32,
default_char: u32,
n_properties: i32,
properties: ^XFontProp,
min_bounds: XCharStruct,
max_bounds: XCharStruct,
per_char: ^XCharStruct,
ascent: i32,
descent: i32,
ext_data: ^XExtData,
fid: Font,
direction: u32,
min_char_or_byte2: u32,
max_char_or_byte2: u32,
min_byte1: u32,
max_byte1: u32,
all_chars_exist: i32,
default_char: u32,
n_properties: i32,
properties: ^XFontProp,
min_bounds: XCharStruct,
max_bounds: XCharStruct,
per_char: ^XCharStruct,
ascent: i32,
descent: i32,
}
XTextItem :: struct {
chars: [^]u8,
nchars: i32,
delta: i32,
font: Font,
chars: [^]u8,
nchars: i32,
delta: i32,
font: Font,
}
XChar2b :: struct {
byte1: u8,
byte2: u8,
byte1: u8,
byte2: u8,
}
XTextItem16 :: struct {
chars: ^XChar2b,
nchars: i32,
delta: i32,
font: Font,
chars: ^XChar2b,
nchars: i32,
delta: i32,
font: Font,
}
XEDataObject :: struct #raw_union {
@@ -819,8 +819,8 @@ XEDataObject :: struct #raw_union {
}
XFontSetExtents :: struct {
max_ink_extent: XRectangle,
max_logical_extent: XRectangle,
max_ink_extent: XRectangle,
max_logical_extent: XRectangle,
}
XOM :: distinct rawptr
@@ -828,41 +828,41 @@ XOC :: distinct rawptr
XFontSet :: XOC
XmbTextItem :: struct {
chars: [^]u8,
nchars: i32,
delta: i32,
font_set: XFontSet,
chars: [^]u8,
nchars: i32,
delta: i32,
font_set: XFontSet,
}
XwcTextItem :: struct {
chars: [^]rune,
nchars: i32,
delta: i32,
font_set: XFontSet,
chars: [^]rune,
nchars: i32,
delta: i32,
font_set: XFontSet,
}
XOMCharSetList :: struct {
charset_count: i32,
charset_list: [^]cstring,
charset_count: i32,
charset_list: [^]cstring,
}
XOrientation :: enum i32 {
XOMOrientation_LTR_TTB = 0,
XOMOrientation_RTL_TTB = 1,
XOMOrientation_TTB_LTR = 2,
XOMOrientation_TTB_RTL = 3,
XOMOrientation_Context = 4,
XOMOrientation_LTR_TTB = 0,
XOMOrientation_RTL_TTB = 1,
XOMOrientation_TTB_LTR = 2,
XOMOrientation_TTB_RTL = 3,
XOMOrientation_Context = 4,
}
XOMOrientation :: struct {
num_orientation: i32,
orientation: [^]XOrientation,
num_orientation: i32,
orientation: [^]XOrientation,
}
XOMFontInfo :: struct {
num_font: i32,
font_struct_list: [^]^XFontStruct,
font_name_list: [^]cstring,
num_font: i32,
font_struct_list: [^]^XFontStruct,
font_name_list: [^]cstring,
}
XIM :: distinct rawptr
@@ -875,38 +875,38 @@ XIDProc :: #type proc "c" (xim: XIM, client_data: rawptr, call_data: rawptr)
XIMStyle :: uint
XIMStyles :: struct {
count_styles: u16,
supported_styles: [^]XIMStyle,
count_styles: u16,
supported_styles: [^]XIMStyle,
}
XVaNestedList :: distinct rawptr
XIMCallback :: struct {
client_data: rawptr,
callback: XIMProc,
client_data: rawptr,
callback: XIMProc,
}
XICCallback :: struct {
client_data: rawptr,
callback: XICProc,
client_data: rawptr,
callback: XICProc,
}
XIMFeedback :: uint
XIMText :: struct {
length: u16,
feedback: ^XIMFeedback,
encoding_is_wchar: b32,
string: struct #raw_union {
length: u16,
feedback: ^XIMFeedback,
encoding_is_wchar: b32,
string: struct #raw_union {
multi_byte: [^]u8,
wide_char: [^]rune,
},
},
}
XIMPreeditState :: uint
XIMPreeditStateNotifyCallbackStruct :: struct {
state: XIMPreeditState,
state: XIMPreeditState,
}
XIMResetState :: uint
@@ -914,13 +914,13 @@ XIMResetState :: uint
XIMStringConversionFeedback :: uint
XIMStringConversionText :: struct {
length: u16,
feedback: ^XIMStringConversionFeedback,
encoding_is_wchar: b32,
string: struct #raw_union {
length: u16,
feedback: ^XIMStringConversionFeedback,
encoding_is_wchar: b32,
string: struct #raw_union {
mbs: [^]u8,
wcs: [^]rune,
},
},
}
XIMStringConversionPosition :: u16
@@ -928,76 +928,76 @@ XIMStringConversionType :: u16
XIMStringConversionOperation :: u16
XIMCaretDirection :: enum i32 {
XIMForwardChar = 0,
XIMBackwardChar = 1,
XIMForwardWord = 2,
XIMBackwardWord = 3,
XIMCaretUp = 4,
XIMCaretDown = 5,
XIMNextLine = 6,
XIMPreviousLine = 7,
XIMLineStart = 8,
XIMLineEnd = 9,
XIMAbsolutePosition = 10,
XIMDontChang = 11,
XIMForwardChar = 0,
XIMBackwardChar = 1,
XIMForwardWord = 2,
XIMBackwardWord = 3,
XIMCaretUp = 4,
XIMCaretDown = 5,
XIMNextLine = 6,
XIMPreviousLine = 7,
XIMLineStart = 8,
XIMLineEnd = 9,
XIMAbsolutePosition = 10,
XIMDontChang = 11,
}
XIMStringConversionCallbackStruct :: struct {
position: XIMStringConversionPosition,
direction: XIMCaretDirection,
operation: XIMStringConversionOperation,
factor: u16,
text: ^XIMStringConversionText,
position: XIMStringConversionPosition,
direction: XIMCaretDirection,
operation: XIMStringConversionOperation,
factor: u16,
text: ^XIMStringConversionText,
}
XIMPreeditDrawCallbackStruct :: struct {
caret: i32,
chg_first: i32,
chg_length: i32,
text: ^XIMText,
caret: i32,
chg_first: i32,
chg_length: i32,
text: ^XIMText,
}
XIMCaretStyle :: enum i32 {
XIMIsInvisible,
XIMIsPrimary,
XIMIsSecondary,
XIMIsInvisible,
XIMIsPrimary,
XIMIsSecondary,
}
XIMPreeditCaretCallbackStruct :: struct {
position: i32,
direction: XIMCaretDirection,
style: XIMCaretStyle,
position: i32,
direction: XIMCaretDirection,
style: XIMCaretStyle,
}
XIMStatusDataType :: enum {
XIMTextType,
XIMBitmapType,
XIMTextType,
XIMBitmapType,
}
XIMStatusDrawCallbackStruct :: struct {
type: XIMStatusDataType,
data: struct #raw_union {
type: XIMStatusDataType,
data: struct #raw_union {
text: ^XIMText,
bitmap: Pixmap,
},
},
}
XIMHotKeyTrigger :: struct {
keysym: KeySym,
modifier: i32,
modifier_mask: i32,
keysym: KeySym,
modifier: i32,
modifier_mask: i32,
}
XIMHotKeyTriggers :: struct {
num_hot_key: i32,
key: [^]XIMHotKeyTrigger,
num_hot_key: i32,
key: [^]XIMHotKeyTrigger,
}
XIMHotKeyState :: uint
XIMValuesList :: struct {
count_values: u16,
supported_values: [^]cstring,
count_values: u16,
supported_values: [^]cstring,
}
XConnectionWatchProc :: #type proc "c" (
@@ -1775,62 +1775,62 @@ XcmsColorFormat :: uint
XcmsFloat :: f64
XcmsRGB :: struct {
red: u16,
green: u16,
blue: u16,
red: u16,
green: u16,
blue: u16,
}
XcmsRGBi :: struct {
red: XcmsFloat,
green: XcmsFloat,
blue: XcmsFloat,
red: XcmsFloat,
green: XcmsFloat,
blue: XcmsFloat,
}
XcmsCIEXYZ :: struct {
X: XcmsFloat,
Y: XcmsFloat,
Z: XcmsFloat,
X: XcmsFloat,
Y: XcmsFloat,
Z: XcmsFloat,
}
XcmsCIEuvY :: struct {
u_prime: XcmsFloat,
v_prime: XcmsFloat,
Y: XcmsFloat,
u_prime: XcmsFloat,
v_prime: XcmsFloat,
Y: XcmsFloat,
}
XcmsCIExyY :: struct {
x: XcmsFloat,
y: XcmsFloat,
Y: XcmsFloat,
x: XcmsFloat,
y: XcmsFloat,
Y: XcmsFloat,
}
XcmsCIELab :: struct {
L_star: XcmsFloat,
a_star: XcmsFloat,
b_star: XcmsFloat,
L_star: XcmsFloat,
a_star: XcmsFloat,
b_star: XcmsFloat,
}
XcmsCIELuv :: struct {
L_star: XcmsFloat,
u_star: XcmsFloat,
v_star: XcmsFloat,
L_star: XcmsFloat,
u_star: XcmsFloat,
v_star: XcmsFloat,
}
XcmsTekHVC :: struct {
H: XcmsFloat,
V: XcmsFloat,
C: XcmsFloat,
H: XcmsFloat,
V: XcmsFloat,
C: XcmsFloat,
}
XcmsPad :: struct {
_: XcmsFloat,
_: XcmsFloat,
_: XcmsFloat,
_: XcmsFloat,
_: XcmsFloat,
_: XcmsFloat,
_: XcmsFloat,
_: XcmsFloat,
}
XcmsColor :: struct {
spec: struct #raw_union {
spec: struct #raw_union {
RGB: XcmsRGB,
RGBi: XcmsRGBi,
CIEXYZ: XcmsCIEXYZ,
@@ -1840,17 +1840,17 @@ XcmsColor :: struct {
CIELuv: XcmsCIELuv,
TekHVC: XcmsTekHVC,
_: XcmsPad,
},
pixel: uint,
format: XcmsColorFormat,
},
pixel: uint,
format: XcmsColorFormat,
}
XcmsPerScrnInfo :: struct {
screenWhitePt: XcmsColor,
functionSet: rawptr,
screenData: rawptr,
state: u8,
_: [3]u8,
screenWhitePt: XcmsColor,
functionSet: rawptr,
screenData: rawptr,
state: u8,
_: [3]u8,
}
XcmsCCC :: distinct rawptr
@@ -1872,15 +1872,15 @@ XcmsWhiteAdjustProc :: #type proc "c" (
compression: [^]b32) -> Status
XcmsCCCRec :: struct {
dpy: ^Display,
screenNumber: i32,
visual: ^Visual,
clientWhitePt: XcmsColor,
gamutCompProc: XcmsCompressionProc,
gamutCompClientData: rawptr,
whitePtAdjProc: XcmsWhiteAdjustProc,
whitePtAdjClientData: rawptr,
pPerScrnInfo: ^XcmsPerScrnInfo,
dpy: ^Display,
screenNumber: i32,
visual: ^Visual,
clientWhitePt: XcmsColor,
gamutCompProc: XcmsCompressionProc,
gamutCompClientData: rawptr,
whitePtAdjProc: XcmsWhiteAdjustProc,
whitePtAdjClientData: rawptr,
pPerScrnInfo: ^XcmsPerScrnInfo,
}
XcmsScreenInitProc :: #type proc "c" (
@@ -1909,18 +1909,18 @@ XcmsFuncListPtr :: [^]XcmsConversionProc
XcmsParseStringProc :: #type proc "c" (color_string: cstring, color: ^XcmsColor) -> i32
XcmsColorSpace :: struct {
prefix: cstring,
id: XcmsColorFormat,
parseString: XcmsParseStringProc,
to_CIEXYZ: XcmsFuncListPtr,
from_CIEXYZ: XcmsFuncListPtr,
inverse_flag: i32,
prefix: cstring,
id: XcmsColorFormat,
parseString: XcmsParseStringProc,
to_CIEXYZ: XcmsFuncListPtr,
from_CIEXYZ: XcmsFuncListPtr,
inverse_flag: i32,
}
XcmsFunctionSet :: struct {
DDColorSpaces: [^]^XcmsColorSpace,
screenInitProc: XcmsScreenInitProc,
screenFreeProc: XcmsScreenFreeProc,
DDColorSpaces: [^]^XcmsColorSpace,
screenInitProc: XcmsScreenInitProc,
screenFreeProc: XcmsScreenFreeProc,
}
@@ -1958,18 +1958,18 @@ XWMHints :: struct {
}
XTextProperty :: struct {
value: [^]u8,
encoding: Atom,
format: int,
nitems: uint,
value: [^]u8,
encoding: Atom,
format: int,
nitems: uint,
}
XICCEncodingStyle :: enum i32 {
XStringStyle,
XCompoundTextStyle,
XTextStyle,
XStdICCTextStyle,
XUTF8StringStyle,
XStringStyle,
XCompoundTextStyle,
XTextStyle,
XStdICCTextStyle,
XUTF8StringStyle,
}
XIconSize :: struct {
@@ -1987,8 +1987,8 @@ XClassHint :: struct {
}
XComposeStatus :: struct {
compose_ptr: rawptr,
chars_matched: i32,
compose_ptr: rawptr,
chars_matched: i32,
}
Region :: distinct rawptr
@@ -2041,8 +2041,8 @@ XrmClassList :: XrmQuarkList
XrmRepresentation :: XrmQuark
XrmValue :: struct {
size: u32,
addr: rawptr,
size: u32,
addr: rawptr,
}
XrmValuePtr :: [^]XrmValue
@@ -2052,21 +2052,21 @@ XrmSearchList :: [^]XrmHashTable
XrmDatabase :: distinct rawptr
XrmOptionKind :: enum {
XrmoptionNoArg,
XrmoptionIsArg,
XrmoptionStickyArg,
XrmoptionSepArg,
XrmoptionResArg,
XrmoptionSkipArg,
XrmoptionSkipLine,
XrmoptionSkipNArgs,
XrmoptionNoArg,
XrmoptionIsArg,
XrmoptionStickyArg,
XrmoptionSepArg,
XrmoptionResArg,
XrmoptionSkipArg,
XrmoptionSkipLine,
XrmoptionSkipNArgs,
}
XrmOptionDescRec :: struct {
option: cstring,
specifier: cstring,
argKind: XrmOptionKind,
value: rawptr,
option: cstring,
specifier: cstring,
argKind: XrmOptionKind,
value: rawptr,
}
XrmOptionDescList :: [^]XrmOptionDescRec