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