mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-21 21:24:59 -07:00
Merge branch 'odin-lang:master' into raylib5
This commit is contained in:
@@ -110,6 +110,7 @@ if %errorlevel% neq 0 goto end_of_build
|
||||
call build_vendor.bat
|
||||
if %errorlevel% neq 0 goto end_of_build
|
||||
|
||||
rem If the demo doesn't run for you and your CPU is more than a decade old, try -microarch:native
|
||||
if %release_mode% EQU 0 odin run examples/demo
|
||||
|
||||
del *.obj > NUL 2> NUL
|
||||
|
||||
@@ -27,11 +27,13 @@ error() {
|
||||
if [ -z "$LLVM_CONFIG" ]; then
|
||||
# darwin, linux, openbsd
|
||||
if [ -n "$(command -v llvm-config-17)" ]; then LLVM_CONFIG="llvm-config-17"
|
||||
elif [ -n "$(command -v llvm-config-14)" ]; then LLVM_CONFIG="llvm-config-14"
|
||||
elif [ -n "$(command -v llvm-config-13)" ]; then LLVM_CONFIG="llvm-config-13"
|
||||
elif [ -n "$(command -v llvm-config-12)" ]; then LLVM_CONFIG="llvm-config-12"
|
||||
elif [ -n "$(command -v llvm-config-11)" ]; then LLVM_CONFIG="llvm-config-11"
|
||||
# freebsd
|
||||
elif [ -n "$(command -v llvm-config17)" ]; then LLVM_CONFIG="llvm-config-17"
|
||||
elif [ -n "$(command -v llvm-config14)" ]; then LLVM_CONFIG="llvm-config-14"
|
||||
elif [ -n "$(command -v llvm-config13)" ]; then LLVM_CONFIG="llvm-config-13"
|
||||
elif [ -n "$(command -v llvm-config12)" ]; then LLVM_CONFIG="llvm-config-12"
|
||||
elif [ -n "$(command -v llvm-config11)" ]; then LLVM_CONFIG="llvm-config-11"
|
||||
|
||||
@@ -2,6 +2,8 @@ package libc
|
||||
|
||||
import "core:c"
|
||||
|
||||
#assert(!ODIN_NO_CRT, `"core:c/libc" cannot be imported when '-no-crt' is used`)
|
||||
|
||||
char :: c.char // assuming -funsigned-char
|
||||
|
||||
schar :: c.schar
|
||||
|
||||
@@ -162,7 +162,14 @@ type_is_matrix :: proc($T: typeid) -> bool ---
|
||||
type_has_nil :: proc($T: typeid) -> bool ---
|
||||
|
||||
type_is_specialization_of :: proc($T, $S: typeid) -> bool ---
|
||||
|
||||
type_is_variant_of :: proc($U, $V: typeid) -> bool where type_is_union(U) ---
|
||||
type_union_tag_type :: proc($T: typeid) -> typeid where type_is_union(T) ---
|
||||
type_union_tag_offset :: proc($T: typeid) -> uintptr where type_is_union(T) ---
|
||||
type_union_base_tag_value :: proc($T: typeid) -> int where type_is_union(U) ---
|
||||
type_union_variant_count :: proc($T: typeid) -> int where type_is_union(T) ---
|
||||
type_variant_type_of :: proc($T: typeid, $index: int) -> typeid where type_is_union(T) ---
|
||||
type_variant_index_of :: proc($U, $V: typeid) -> int where type_is_union(U) ---
|
||||
|
||||
type_has_field :: proc($T: typeid, $name: string) -> bool ---
|
||||
type_field_type :: proc($T: typeid, $name: string) -> typeid ---
|
||||
|
||||
+2
-2
@@ -60,9 +60,9 @@ Logger_Proc :: runtime.Logger_Proc
|
||||
/*
|
||||
Logger :: struct {
|
||||
procedure: Logger_Proc,
|
||||
data: rawptr,
|
||||
data: rawptr,
|
||||
lowest_level: Level,
|
||||
options: Logger_Options,
|
||||
options: Logger_Options,
|
||||
}
|
||||
*/
|
||||
Logger :: runtime.Logger
|
||||
|
||||
+11
-11
@@ -2312,17 +2312,17 @@ F32_NORMALIZE :: 0
|
||||
F32_RADIX :: 2
|
||||
F32_ROUNDS :: 1
|
||||
|
||||
F64_DIG :: 15 // # of decimal digits of precision
|
||||
F64_EPSILON :: 2.2204460492503131e-016 // smallest such that 1.0+F64_EPSILON != 1.0
|
||||
F64_MANT_DIG :: 53 // # of bits in mantissa
|
||||
F64_MAX :: 1.7976931348623158e+308 // max value
|
||||
F64_MAX_10_EXP :: 308 // max decimal exponent
|
||||
F64_MAX_EXP :: 1024 // max binary exponent
|
||||
F64_MIN :: 2.2250738585072014e-308 // min positive value
|
||||
F64_MIN_10_EXP :: -307 // min decimal exponent
|
||||
F64_MIN_EXP :: -1021 // min binary exponent
|
||||
F64_RADIX :: 2 // exponent radix
|
||||
F64_ROUNDS :: 1 // addition rounding: near
|
||||
F64_DIG :: 15 // Number of representable decimal digits.
|
||||
F64_EPSILON :: 2.2204460492503131e-016 // Smallest number such that `1.0 + F64_EPSILON != 1.0`.
|
||||
F64_MANT_DIG :: 53 // Number of bits in the mantissa.
|
||||
F64_MAX :: 1.7976931348623158e+308 // Maximum representable value.
|
||||
F64_MAX_10_EXP :: 308 // Maximum base-10 exponent yielding normalized value.
|
||||
F64_MAX_EXP :: 1024 // One greater than the maximum possible base-2 exponent yielding normalized value.
|
||||
F64_MIN :: 2.2250738585072014e-308 // Minimum positive normalized value.
|
||||
F64_MIN_10_EXP :: -307 // Minimum base-10 exponent yielding normalized value.
|
||||
F64_MIN_EXP :: -1021 // One greater than the minimum possible base-2 exponent yielding normalized value.
|
||||
F64_RADIX :: 2 // Exponent radix.
|
||||
F64_ROUNDS :: 1 // Addition rounding: near.
|
||||
|
||||
|
||||
F16_MASK :: 0x1f
|
||||
|
||||
+38
-3
@@ -148,7 +148,29 @@ recv_udp :: proc(socket: UDP_Socket, buf: []byte) -> (bytes_read: int, remote_en
|
||||
return _recv_udp(socket, buf)
|
||||
}
|
||||
|
||||
recv :: proc{recv_tcp, recv_udp}
|
||||
/*
|
||||
Receive data from into a buffer from any socket.
|
||||
|
||||
Note: `remote_endpoint` parameter is non-nil only if the socket type is UDP. On TCP sockets it
|
||||
will always return `nil`.
|
||||
*/
|
||||
recv_any :: proc(socket: Any_Socket, buf: []byte) -> (
|
||||
bytes_read: int,
|
||||
remote_endpoint: Maybe(Endpoint),
|
||||
err: Network_Error,
|
||||
) {
|
||||
switch socktype in socket {
|
||||
case TCP_Socket:
|
||||
bytes_read, err := recv_tcp(socktype, buf)
|
||||
return bytes_read, nil, err
|
||||
case UDP_Socket:
|
||||
bytes_read, endpoint, err := recv_udp(socktype, buf)
|
||||
return bytes_read, endpoint, err
|
||||
case: panic("Not supported")
|
||||
}
|
||||
}
|
||||
|
||||
recv :: proc{recv_tcp, recv_udp, recv_any}
|
||||
|
||||
/*
|
||||
Repeatedly sends data until the entire buffer is sent.
|
||||
@@ -168,7 +190,20 @@ send_udp :: proc(socket: UDP_Socket, buf: []byte, to: Endpoint) -> (bytes_writte
|
||||
return _send_udp(socket, buf, to)
|
||||
}
|
||||
|
||||
send :: proc{send_tcp, send_udp}
|
||||
send_any :: proc(socket: Any_Socket, buf: []byte, to: Maybe(Endpoint) = nil) -> (
|
||||
bytes_written: int,
|
||||
err: Network_Error,
|
||||
) {
|
||||
switch socktype in socket {
|
||||
case TCP_Socket:
|
||||
return send_tcp(socktype, buf)
|
||||
case UDP_Socket:
|
||||
return send_udp(socktype, buf, to.(Endpoint))
|
||||
case: panic("Not supported")
|
||||
}
|
||||
}
|
||||
|
||||
send :: proc{send_tcp, send_udp, send_any}
|
||||
|
||||
shutdown :: proc(socket: Any_Socket, manner: Shutdown_Manner) -> (err: Network_Error) {
|
||||
return _shutdown(socket, manner)
|
||||
@@ -180,4 +215,4 @@ set_option :: proc(socket: Any_Socket, option: Socket_Option, value: any, loc :=
|
||||
|
||||
set_blocking :: proc(socket: Any_Socket, should_block: bool) -> (err: Network_Error) {
|
||||
return _set_blocking(socket, should_block)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ _create_socket :: proc(family: Address_Family, protocol: Socket_Protocol) -> (An
|
||||
}
|
||||
|
||||
@(private)
|
||||
_dial_tcp_from_endpoint :: proc(endpoint: Endpoint, options := default_tcp_options) -> (tcp_sock: TCP_Socket, err: Network_Error) {
|
||||
_dial_tcp_from_endpoint :: proc(endpoint: Endpoint, options := default_tcp_options) -> (TCP_Socket, Network_Error) {
|
||||
errno: linux.Errno
|
||||
if endpoint.port == 0 {
|
||||
return 0, .Port_Required
|
||||
|
||||
@@ -7,7 +7,7 @@ import "core:reflect"
|
||||
import "core:odin/tokenizer"
|
||||
_ :: intrinsics
|
||||
|
||||
new :: proc($T: typeid, pos, end: tokenizer.Pos) -> ^T {
|
||||
new_from_positions :: proc($T: typeid, pos, end: tokenizer.Pos) -> ^T {
|
||||
n, _ := mem.new(T)
|
||||
n.pos = pos
|
||||
n.end = end
|
||||
@@ -23,6 +23,15 @@ new :: proc($T: typeid, pos, end: tokenizer.Pos) -> ^T {
|
||||
return n
|
||||
}
|
||||
|
||||
new_from_pos_and_end_node :: proc($T: typeid, pos: tokenizer.Pos, end: ^Node) -> ^T {
|
||||
return new(T, pos, end != nil ? end.end : pos)
|
||||
}
|
||||
|
||||
new :: proc {
|
||||
new_from_positions,
|
||||
new_from_pos_and_end_node,
|
||||
}
|
||||
|
||||
clone :: proc{
|
||||
clone_node,
|
||||
clone_expr,
|
||||
|
||||
@@ -786,8 +786,11 @@ parse_if_stmt :: proc(p: ^Parser) -> ^ast.If_Stmt {
|
||||
else_stmt = ast.new(ast.Bad_Stmt, p.curr_tok.pos, end_pos(p.curr_tok))
|
||||
}
|
||||
}
|
||||
|
||||
end := body.end
|
||||
|
||||
end: tokenizer.Pos
|
||||
if body != nil {
|
||||
end = body.end
|
||||
}
|
||||
if else_stmt != nil {
|
||||
end = else_stmt.end
|
||||
}
|
||||
@@ -850,7 +853,7 @@ parse_for_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
|
||||
body = parse_body(p)
|
||||
}
|
||||
|
||||
range_stmt := ast.new(ast.Range_Stmt, tok.pos, body.end)
|
||||
range_stmt := ast.new(ast.Range_Stmt, tok.pos, body)
|
||||
range_stmt.for_pos = tok.pos
|
||||
range_stmt.in_pos = in_tok.pos
|
||||
range_stmt.expr = rhs
|
||||
@@ -910,7 +913,7 @@ parse_for_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
|
||||
rhs = assign_stmt.rhs[0]
|
||||
}
|
||||
|
||||
range_stmt := ast.new(ast.Range_Stmt, tok.pos, body.end)
|
||||
range_stmt := ast.new(ast.Range_Stmt, tok.pos, body)
|
||||
range_stmt.for_pos = tok.pos
|
||||
range_stmt.vals = vals
|
||||
range_stmt.in_pos = assign_stmt.op.pos
|
||||
@@ -920,7 +923,7 @@ parse_for_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
|
||||
}
|
||||
|
||||
cond_expr := convert_stmt_to_expr(p, cond, "boolean expression")
|
||||
for_stmt := ast.new(ast.For_Stmt, tok.pos, body.end)
|
||||
for_stmt := ast.new(ast.For_Stmt, tok.pos, body)
|
||||
for_stmt.for_pos = tok.pos
|
||||
for_stmt.init = init
|
||||
for_stmt.cond = cond_expr
|
||||
@@ -976,7 +979,7 @@ parse_switch_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
|
||||
lhs[0] = new_blank_ident(p, tok.pos)
|
||||
rhs[0] = parse_expr(p, true)
|
||||
|
||||
as := ast.new(ast.Assign_Stmt, tok.pos, rhs[0].end)
|
||||
as := ast.new(ast.Assign_Stmt, tok.pos, rhs[0])
|
||||
as.lhs = lhs
|
||||
as.op = in_tok
|
||||
as.rhs = rhs
|
||||
@@ -1010,14 +1013,14 @@ parse_switch_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
|
||||
body.stmts = clauses[:]
|
||||
|
||||
if is_type_switch {
|
||||
ts := ast.new(ast.Type_Switch_Stmt, tok.pos, body.end)
|
||||
ts := ast.new(ast.Type_Switch_Stmt, tok.pos, body)
|
||||
ts.tag = tag
|
||||
ts.body = body
|
||||
ts.switch_pos = tok.pos
|
||||
return ts
|
||||
} else {
|
||||
cond := convert_stmt_to_expr(p, tag, "switch expression")
|
||||
ts := ast.new(ast.Switch_Stmt, tok.pos, body.end)
|
||||
ts := ast.new(ast.Switch_Stmt, tok.pos, body)
|
||||
ts.init = init
|
||||
ts.cond = cond
|
||||
ts.body = body
|
||||
@@ -1044,7 +1047,7 @@ parse_attribute :: proc(p: ^Parser, tok: tokenizer.Token, open_kind, close_kind:
|
||||
if p.curr_tok.kind == .Eq {
|
||||
eq := expect_token(p, .Eq)
|
||||
value := parse_value(p)
|
||||
fv := ast.new(ast.Field_Value, elem.pos, value.end)
|
||||
fv := ast.new(ast.Field_Value, elem.pos, value)
|
||||
fv.field = elem
|
||||
fv.sep = eq.pos
|
||||
fv.value = value
|
||||
@@ -1137,7 +1140,7 @@ parse_foreign_block :: proc(p: ^Parser, tok: tokenizer.Token) -> ^ast.Foreign_Bl
|
||||
body.stmts = decls[:]
|
||||
body.close = close.pos
|
||||
|
||||
decl := ast.new(ast.Foreign_Block_Decl, tok.pos, body.end)
|
||||
decl := ast.new(ast.Foreign_Block_Decl, tok.pos, body)
|
||||
decl.docs = docs
|
||||
decl.tok = tok
|
||||
decl.foreign_library = foreign_library
|
||||
@@ -1248,7 +1251,7 @@ parse_unrolled_for_loop :: proc(p: ^Parser, inline_tok: tokenizer.Token) -> ^ast
|
||||
return ast.new(ast.Bad_Stmt, inline_tok.pos, end_pos(p.prev_tok))
|
||||
}
|
||||
|
||||
range_stmt := ast.new(ast.Inline_Range_Stmt, inline_tok.pos, body.end)
|
||||
range_stmt := ast.new(ast.Inline_Range_Stmt, inline_tok.pos, body)
|
||||
range_stmt.inline_pos = inline_tok.pos
|
||||
range_stmt.for_pos = for_tok.pos
|
||||
range_stmt.val0 = val0
|
||||
@@ -1304,7 +1307,7 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
|
||||
case ^ast.Return_Stmt:
|
||||
error(p, s.pos, "you cannot defer a return statement")
|
||||
}
|
||||
ds := ast.new(ast.Defer_Stmt, tok.pos, stmt.end)
|
||||
ds := ast.new(ast.Defer_Stmt, tok.pos, stmt)
|
||||
ds.stmt = stmt
|
||||
return ds
|
||||
|
||||
@@ -1341,8 +1344,7 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
|
||||
if tok.kind != .Fallthrough && p.curr_tok.kind == .Ident {
|
||||
label = parse_ident(p)
|
||||
}
|
||||
end := label.end if label != nil else end_pos(tok)
|
||||
s := ast.new(ast.Branch_Stmt, tok.pos, end)
|
||||
s := ast.new(ast.Branch_Stmt, tok.pos, label)
|
||||
s.tok = tok
|
||||
s.label = label
|
||||
expect_semicolon(p, s)
|
||||
@@ -1366,7 +1368,7 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
|
||||
if p.curr_tok.kind != .Colon {
|
||||
end := list[len(list)-1]
|
||||
expect_semicolon(p, end)
|
||||
us := ast.new(ast.Using_Stmt, tok.pos, end.end)
|
||||
us := ast.new(ast.Using_Stmt, tok.pos, end)
|
||||
us.list = list
|
||||
return us
|
||||
}
|
||||
@@ -1416,13 +1418,13 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
|
||||
bd.tok = tok
|
||||
bd.name = name
|
||||
ce := parse_call_expr(p, bd)
|
||||
es := ast.new(ast.Expr_Stmt, ce.pos, ce.end)
|
||||
es := ast.new(ast.Expr_Stmt, ce.pos, ce)
|
||||
es.expr = ce
|
||||
return es
|
||||
|
||||
case "force_inline", "force_no_inline":
|
||||
expr := parse_inlining_operand(p, true, tag)
|
||||
es := ast.new(ast.Expr_Stmt, expr.pos, expr.end)
|
||||
es := ast.new(ast.Expr_Stmt, expr.pos, expr)
|
||||
es.expr = expr
|
||||
return es
|
||||
case "unroll":
|
||||
@@ -1444,7 +1446,8 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt {
|
||||
return ast.new(ast.Bad_Stmt, tok.pos, end_pos(tag))
|
||||
case:
|
||||
stmt := parse_stmt(p)
|
||||
te := ast.new(ast.Tag_Stmt, tok.pos, stmt.pos)
|
||||
end := stmt.pos if stmt != nil else end_pos(tok)
|
||||
te := ast.new(ast.Tag_Stmt, tok.pos, end)
|
||||
te.op = tok
|
||||
te.name = name
|
||||
te.stmt = stmt
|
||||
@@ -1572,7 +1575,7 @@ convert_stmt_to_body :: proc(p: ^Parser, stmt: ^ast.Stmt) -> ^ast.Stmt {
|
||||
error(p, stmt.pos, "expected a non-empty statement")
|
||||
}
|
||||
|
||||
bs := ast.new(ast.Block_Stmt, stmt.pos, stmt.end)
|
||||
bs := ast.new(ast.Block_Stmt, stmt.pos, stmt)
|
||||
bs.open = stmt.pos
|
||||
bs.stmts = make([]^ast.Stmt, 1)
|
||||
bs.stmts[0] = stmt
|
||||
@@ -1741,7 +1744,7 @@ parse_var_type :: proc(p: ^Parser, flags: ast.Field_Flags) -> ^ast.Expr {
|
||||
error(p, tok.pos, "variadic field missing type after '..'")
|
||||
type = ast.new(ast.Bad_Expr, tok.pos, end_pos(tok))
|
||||
}
|
||||
e := ast.new(ast.Ellipsis, type.pos, type.end)
|
||||
e := ast.new(ast.Ellipsis, type.pos, type)
|
||||
e.expr = type
|
||||
return e
|
||||
}
|
||||
@@ -1808,7 +1811,7 @@ parse_ident_list :: proc(p: ^Parser, allow_poly_names: bool) -> []^ast.Expr {
|
||||
if is_blank_ident(ident) {
|
||||
error(p, ident.pos, "invalid polymorphic type definition with a blank identifier")
|
||||
}
|
||||
poly_name := ast.new(ast.Poly_Type, tok.pos, ident.end)
|
||||
poly_name := ast.new(ast.Poly_Type, tok.pos, ident)
|
||||
poly_name.type = ident
|
||||
append(&list, poly_name)
|
||||
} else {
|
||||
@@ -2154,7 +2157,7 @@ parse_inlining_operand :: proc(p: ^Parser, lhs: bool, tok: tokenizer.Token) -> ^
|
||||
e.inlining = pi
|
||||
case:
|
||||
error(p, tok.pos, "'%s' must be followed by a procedure literal or call", tok.text)
|
||||
return ast.new(ast.Bad_Expr, tok.pos, expr.end)
|
||||
return ast.new(ast.Bad_Expr, tok.pos, expr)
|
||||
}
|
||||
return expr
|
||||
}
|
||||
@@ -2204,7 +2207,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
case .Distinct:
|
||||
tok := advance_token(p)
|
||||
type := parse_type(p)
|
||||
dt := ast.new(ast.Distinct_Type, tok.pos, type.end)
|
||||
dt := ast.new(ast.Distinct_Type, tok.pos, type)
|
||||
dt.tok = tok.kind
|
||||
dt.type = type
|
||||
return dt
|
||||
@@ -2215,7 +2218,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
switch name.text {
|
||||
case "type":
|
||||
type := parse_type(p)
|
||||
hp := ast.new(ast.Helper_Type, tok.pos, type.end)
|
||||
hp := ast.new(ast.Helper_Type, tok.pos, type)
|
||||
hp.tok = tok.kind
|
||||
hp.type = type
|
||||
return hp
|
||||
@@ -2319,7 +2322,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
tag_call := parse_call_expr(p, tag)
|
||||
type := parse_type(p)
|
||||
|
||||
rt := ast.new(ast.Relative_Type, tok.pos, type.end)
|
||||
rt := ast.new(ast.Relative_Type, tok.pos, type)
|
||||
rt.tag = tag_call
|
||||
rt.type = type
|
||||
return rt
|
||||
@@ -2328,7 +2331,8 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
return parse_inlining_operand(p, lhs, name)
|
||||
case:
|
||||
expr := parse_expr(p, lhs)
|
||||
te := ast.new(ast.Tag_Expr, tok.pos, expr.pos)
|
||||
end := expr.pos if expr != nil else end_pos(tok)
|
||||
te := ast.new(ast.Tag_Expr, tok.pos, end)
|
||||
te.op = tok
|
||||
te.name = name.text
|
||||
te.expr = expr
|
||||
@@ -2456,7 +2460,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
case .Pointer:
|
||||
tok := expect_token(p, .Pointer)
|
||||
elem := parse_type(p)
|
||||
ptr := ast.new(ast.Pointer_Type, tok.pos, elem.end)
|
||||
ptr := ast.new(ast.Pointer_Type, tok.pos, elem)
|
||||
ptr.pointer = tok.pos
|
||||
ptr.elem = elem
|
||||
return ptr
|
||||
@@ -2470,7 +2474,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
tok := expect_token(p, .Pointer)
|
||||
close := expect_token(p, .Close_Bracket)
|
||||
elem := parse_type(p)
|
||||
t := ast.new(ast.Multi_Pointer_Type, open.pos, elem.end)
|
||||
t := ast.new(ast.Multi_Pointer_Type, open.pos, elem)
|
||||
t.open = open.pos
|
||||
t.pointer = tok.pos
|
||||
t.close = close.pos
|
||||
@@ -2480,7 +2484,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
tok := expect_token(p, .Dynamic)
|
||||
close := expect_token(p, .Close_Bracket)
|
||||
elem := parse_type(p)
|
||||
da := ast.new(ast.Dynamic_Array_Type, open.pos, elem.end)
|
||||
da := ast.new(ast.Dynamic_Array_Type, open.pos, elem)
|
||||
da.open = open.pos
|
||||
da.dynamic_pos = tok.pos
|
||||
da.close = close.pos
|
||||
@@ -2500,7 +2504,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
}
|
||||
close := expect_token(p, .Close_Bracket)
|
||||
elem := parse_type(p)
|
||||
at := ast.new(ast.Array_Type, open.pos, elem.end)
|
||||
at := ast.new(ast.Array_Type, open.pos, elem)
|
||||
at.open = open.pos
|
||||
at.len = count
|
||||
at.close = close.pos
|
||||
@@ -2514,7 +2518,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
expect_token(p, .Close_Bracket)
|
||||
value := parse_type(p)
|
||||
|
||||
mt := ast.new(ast.Map_Type, tok.pos, value.end)
|
||||
mt := ast.new(ast.Map_Type, tok.pos, value)
|
||||
mt.tok_pos = tok.pos
|
||||
mt.key = key
|
||||
mt.value = value
|
||||
@@ -2755,7 +2759,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
expect_token(p, .Close_Bracket)
|
||||
elem := parse_type(p)
|
||||
|
||||
mt := ast.new(ast.Matrix_Type, tok.pos, elem.end)
|
||||
mt := ast.new(ast.Matrix_Type, tok.pos, elem)
|
||||
mt.tok_pos = tok.pos
|
||||
mt.row_count = row_count
|
||||
mt.column_count = column_count
|
||||
@@ -2893,7 +2897,7 @@ parse_elem_list :: proc(p: ^Parser) -> []^ast.Expr {
|
||||
eq := expect_token(p, .Eq)
|
||||
value := parse_value(p)
|
||||
|
||||
fv := ast.new(ast.Field_Value, elem.pos, value.end)
|
||||
fv := ast.new(ast.Field_Value, elem.pos, value)
|
||||
fv.field = elem
|
||||
fv.sep = eq.pos
|
||||
fv.value = value
|
||||
@@ -2962,7 +2966,7 @@ parse_call_expr :: proc(p: ^Parser, operand: ^ast.Expr) -> ^ast.Expr {
|
||||
}
|
||||
|
||||
value := parse_value(p)
|
||||
fv := ast.new(ast.Field_Value, arg.pos, value.end)
|
||||
fv := ast.new(ast.Field_Value, arg.pos, value)
|
||||
fv.field = arg
|
||||
fv.sep = eq.pos
|
||||
fv.value = value
|
||||
@@ -2993,7 +2997,7 @@ parse_call_expr :: proc(p: ^Parser, operand: ^ast.Expr) -> ^ast.Expr {
|
||||
|
||||
o := ast.unparen_expr(operand)
|
||||
if se, ok := o.derived.(^ast.Selector_Expr); ok && se.op.kind == .Arrow_Right {
|
||||
sce := ast.new(ast.Selector_Call_Expr, ce.pos, ce.end)
|
||||
sce := ast.new(ast.Selector_Call_Expr, ce.pos, ce)
|
||||
sce.expr = o
|
||||
sce.call = ce
|
||||
return sce
|
||||
@@ -3101,7 +3105,7 @@ parse_atom_expr :: proc(p: ^Parser, value: ^ast.Expr, lhs: bool) -> (operand: ^a
|
||||
case .Ident:
|
||||
field := parse_ident(p)
|
||||
|
||||
sel := ast.new(ast.Selector_Expr, operand.pos, field.end)
|
||||
sel := ast.new(ast.Selector_Expr, operand.pos, field)
|
||||
sel.expr = operand
|
||||
sel.op = tok
|
||||
sel.field = field
|
||||
@@ -3127,7 +3131,7 @@ parse_atom_expr :: proc(p: ^Parser, value: ^ast.Expr, lhs: bool) -> (operand: ^a
|
||||
type.op = question
|
||||
type.expr = nil
|
||||
|
||||
ta := ast.new(ast.Type_Assertion, operand.pos, type.end)
|
||||
ta := ast.new(ast.Type_Assertion, operand.pos, type)
|
||||
ta.expr = operand
|
||||
ta.type = type
|
||||
|
||||
@@ -3145,7 +3149,7 @@ parse_atom_expr :: proc(p: ^Parser, value: ^ast.Expr, lhs: bool) -> (operand: ^a
|
||||
case .Ident:
|
||||
field := parse_ident(p)
|
||||
|
||||
sel := ast.new(ast.Selector_Expr, operand.pos, field.end)
|
||||
sel := ast.new(ast.Selector_Expr, operand.pos, field)
|
||||
sel.expr = operand
|
||||
sel.op = tok
|
||||
sel.field = field
|
||||
@@ -3225,7 +3229,7 @@ parse_unary_expr :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
close := expect_token(p, .Close_Paren)
|
||||
expr := parse_unary_expr(p, lhs)
|
||||
|
||||
tc := ast.new(ast.Type_Cast, tok.pos, expr.end)
|
||||
tc := ast.new(ast.Type_Cast, tok.pos, expr)
|
||||
tc.tok = tok
|
||||
tc.open = open.pos
|
||||
tc.type = type
|
||||
@@ -3237,7 +3241,7 @@ parse_unary_expr :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
op := advance_token(p)
|
||||
expr := parse_unary_expr(p, lhs)
|
||||
|
||||
ac := ast.new(ast.Auto_Cast, op.pos, expr.end)
|
||||
ac := ast.new(ast.Auto_Cast, op.pos, expr)
|
||||
ac.op = op
|
||||
ac.expr = expr
|
||||
return ac
|
||||
@@ -3247,8 +3251,8 @@ parse_unary_expr :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
.And:
|
||||
op := advance_token(p)
|
||||
expr := parse_unary_expr(p, lhs)
|
||||
|
||||
ue := ast.new(ast.Unary_Expr, op.pos, expr.end)
|
||||
|
||||
ue := ast.new(ast.Unary_Expr, op.pos, expr)
|
||||
ue.op = op
|
||||
ue.expr = expr
|
||||
return ue
|
||||
@@ -3258,7 +3262,7 @@ parse_unary_expr :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
error(p, op.pos, "unary '%s' operator is not supported", op.text)
|
||||
expr := parse_unary_expr(p, lhs)
|
||||
|
||||
ue := ast.new(ast.Unary_Expr, op.pos, expr.end)
|
||||
ue := ast.new(ast.Unary_Expr, op.pos, expr)
|
||||
ue.op = op
|
||||
ue.expr = expr
|
||||
return ue
|
||||
@@ -3266,7 +3270,7 @@ parse_unary_expr :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
case .Period:
|
||||
op := advance_token(p)
|
||||
field := parse_ident(p)
|
||||
ise := ast.new(ast.Implicit_Selector_Expr, op.pos, field.end)
|
||||
ise := ast.new(ast.Implicit_Selector_Expr, op.pos, field)
|
||||
ise.field = field
|
||||
return ise
|
||||
|
||||
@@ -3407,7 +3411,7 @@ parse_simple_stmt :: proc(p: ^Parser, flags: Stmt_Allow_Flags) -> ^ast.Stmt {
|
||||
error(p, p.curr_tok.pos, "no right-hand side in assignment statement")
|
||||
return ast.new(ast.Bad_Stmt, start_tok.pos, end_pos(p.curr_tok))
|
||||
}
|
||||
stmt := ast.new(ast.Assign_Stmt, lhs[0].pos, rhs[len(rhs)-1].end)
|
||||
stmt := ast.new(ast.Assign_Stmt, lhs[0].pos, rhs[len(rhs)-1])
|
||||
stmt.lhs = lhs
|
||||
stmt.op = op
|
||||
stmt.rhs = rhs
|
||||
@@ -3424,7 +3428,7 @@ parse_simple_stmt :: proc(p: ^Parser, flags: Stmt_Allow_Flags) -> ^ast.Stmt {
|
||||
rhs := make([]^ast.Expr, 1)
|
||||
rhs[0] = expr
|
||||
|
||||
stmt := ast.new(ast.Assign_Stmt, lhs[0].pos, rhs[len(rhs)-1].end)
|
||||
stmt := ast.new(ast.Assign_Stmt, lhs[0].pos, rhs[len(rhs)-1])
|
||||
stmt.lhs = lhs
|
||||
stmt.op = op
|
||||
stmt.rhs = rhs
|
||||
@@ -3466,7 +3470,7 @@ parse_simple_stmt :: proc(p: ^Parser, flags: Stmt_Allow_Flags) -> ^ast.Stmt {
|
||||
error(p, op.pos, "postfix '%s' statement is not supported", op.text)
|
||||
}
|
||||
|
||||
es := ast.new(ast.Expr_Stmt, lhs[0].pos, lhs[0].end)
|
||||
es := ast.new(ast.Expr_Stmt, lhs[0].pos, lhs[0])
|
||||
es.expr = lhs[0]
|
||||
return es
|
||||
}
|
||||
|
||||
@@ -287,7 +287,7 @@ append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, arg: E, loc := #caller_locat
|
||||
footer := raw_soa_footer(array)
|
||||
|
||||
if size_of(E) > 0 && cap(array)-len(array) > 0 {
|
||||
ti := type_info_of(typeid_of(T))
|
||||
ti := type_info_of(T)
|
||||
ti = type_info_base(ti)
|
||||
si := &ti.variant.(Type_Info_Struct)
|
||||
field_count: uintptr
|
||||
|
||||
@@ -44,7 +44,7 @@ _ :: intrinsics
|
||||
MAP_LOAD_FACTOR :: 75
|
||||
|
||||
// Minimum log2 capacity.
|
||||
MAP_MIN_LOG2_CAPACITY :: 6 // 64 elements
|
||||
MAP_MIN_LOG2_CAPACITY :: 3 // 8 elements
|
||||
|
||||
// Has to be less than 100% though.
|
||||
#assert(MAP_LOAD_FACTOR < 100)
|
||||
|
||||
+85
-36
@@ -49,7 +49,7 @@ to_bytes :: proc "contextless" (s: []$T) -> []byte {
|
||||
```
|
||||
```
|
||||
small_items := []byte{1, 0, 0, 0, 0, 0, 0, 0,
|
||||
2, 0, 0, 0}
|
||||
2, 0, 0, 0}
|
||||
large_items := slice.reinterpret([]i64, small_items)
|
||||
assert(len(large_items) == 1) // only enough bytes to make 1 x i64; two would need at least 8 bytes.
|
||||
```
|
||||
@@ -78,7 +78,7 @@ swap_between :: proc(a, b: $T/[]$E) {
|
||||
n := builtin.min(len(a), len(b))
|
||||
if n >= 0 {
|
||||
ptr_swap_overlapping(&a[0], &b[0], size_of(E)*n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -117,46 +117,95 @@ linear_search_proc :: proc(array: $A/[]$T, f: proc(T) -> bool) -> (index: int, f
|
||||
return -1, false
|
||||
}
|
||||
|
||||
/*
|
||||
Binary search searches the given slice for the given element.
|
||||
If the slice is not sorted, the returned index is unspecified and meaningless.
|
||||
|
||||
If the value is found then the returned int is the index of the matching element.
|
||||
If there are multiple matches, then any one of the matches could be returned.
|
||||
|
||||
If the value is not found then the returned int is the index where a matching
|
||||
element could be inserted while maintaining sorted order.
|
||||
|
||||
# Examples
|
||||
|
||||
Looks up a series of four elements. The first is found, with a
|
||||
uniquely determined position; the second and third are not
|
||||
found; the fourth could match any position in `[1, 4]`.
|
||||
|
||||
```
|
||||
index: int
|
||||
found: bool
|
||||
|
||||
s := []i32{0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55}
|
||||
|
||||
index, found = slice.binary_search(s, 13)
|
||||
assert(index == 9 && found == true)
|
||||
|
||||
index, found = slice.binary_search(s, 4)
|
||||
assert(index == 7 && found == false)
|
||||
|
||||
index, found = slice.binary_search(s, 100)
|
||||
assert(index == 13 && found == false)
|
||||
|
||||
index, found = slice.binary_search(s, 1)
|
||||
assert(index >= 1 && index <= 4 && found == true)
|
||||
```
|
||||
|
||||
For slices of more complex types see: binary_search_by
|
||||
*/
|
||||
@(require_results)
|
||||
binary_search :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool)
|
||||
where intrinsics.type_is_ordered(T) #no_bounds_check {
|
||||
|
||||
n := len(array)
|
||||
switch n {
|
||||
case 0:
|
||||
return -1, false
|
||||
case 1:
|
||||
if array[0] == key {
|
||||
return 0, true
|
||||
}
|
||||
return -1, false
|
||||
}
|
||||
|
||||
lo, hi := 0, n-1
|
||||
|
||||
for array[hi] != array[lo] && key >= array[lo] && key <= array[hi] {
|
||||
when intrinsics.type_is_ordered_numeric(T) {
|
||||
// NOTE(bill): This is technically interpolation search
|
||||
m := lo + int((key - array[lo]) * T(hi - lo) / (array[hi] - array[lo]))
|
||||
} else {
|
||||
m := lo + (hi - lo)/2
|
||||
}
|
||||
where intrinsics.type_is_ordered(T) #no_bounds_check
|
||||
{
|
||||
// I would like to use binary_search_by(array, key, cmp) here, but it doesn't like it:
|
||||
// Cannot assign value 'cmp' of type 'proc($E, $E) -> Ordering' to 'proc(i32, i32) -> Ordering' in argument
|
||||
return binary_search_by(array, key, proc(key: T, element: T) -> Ordering {
|
||||
switch {
|
||||
case array[m] < key:
|
||||
lo = m + 1
|
||||
case key < array[m]:
|
||||
hi = m - 1
|
||||
case:
|
||||
return m, true
|
||||
case element < key: return .Less
|
||||
case element > key: return .Greater
|
||||
case: return .Equal
|
||||
}
|
||||
}
|
||||
|
||||
if key == array[lo] {
|
||||
return lo, true
|
||||
}
|
||||
return -1, false
|
||||
})
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
binary_search_by :: proc(array: $A/[]$T, key: T, f: proc(T, T) -> Ordering) -> (index: int, found: bool)
|
||||
where intrinsics.type_is_ordered(T) #no_bounds_check
|
||||
{
|
||||
// INVARIANTS:
|
||||
// - 0 <= left <= (left + size = right) <= len(array)
|
||||
// - f returns .Less for everything in array[:left]
|
||||
// - f returns .Greater for everything in array[right:]
|
||||
size := len(array)
|
||||
left := 0
|
||||
right := size
|
||||
|
||||
for left < right {
|
||||
mid := left + size / 2
|
||||
|
||||
// Steps to verify this is in-bounds:
|
||||
// 1. We note that `size` is strictly positive due to the loop condition
|
||||
// 2. Therefore `size/2 < size`
|
||||
// 3. Adding `left` to both sides yields `(left + size/2) < (left + size)`
|
||||
// 4. We know from the invariant that `left + size <= len(array)`
|
||||
// 5. Therefore `left + size/2 < self.len()`
|
||||
cmp := f(key, array[mid])
|
||||
|
||||
left = mid + 1 if cmp == .Less else left
|
||||
right = mid if cmp == .Greater else right
|
||||
|
||||
switch cmp {
|
||||
case .Equal: return mid, true
|
||||
case .Less: left = mid + 1
|
||||
case .Greater: right = mid
|
||||
}
|
||||
|
||||
size = right - left
|
||||
}
|
||||
|
||||
return left, false
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
equal :: proc(a, b: $T/[]$E) -> bool where intrinsics.type_is_comparable(E) {
|
||||
|
||||
@@ -718,7 +718,7 @@ Perf_Event_Sample_Type_Bits :: enum {
|
||||
}
|
||||
|
||||
/// Describes field sets to include in mmaped page
|
||||
Perf_Read_Format :: enum {
|
||||
Perf_Read_Format_Bits :: enum {
|
||||
TOTAL_TIME_ENABLED = 0,
|
||||
TOTAL_TIME_RUNNING = 1,
|
||||
ID = 2,
|
||||
|
||||
@@ -283,6 +283,8 @@ Perf_Flags :: bit_set[Perf_Flags_Bits; uint]
|
||||
|
||||
Perf_Event_Flags :: distinct bit_set[Perf_Event_Flags_Bits; u64]
|
||||
|
||||
Perf_Read_Format :: distinct bit_set[Perf_Read_Format_Bits; u64]
|
||||
|
||||
Perf_Cap_Flags :: distinct bit_set[Perf_Cap_Flags_Bits; u64]
|
||||
|
||||
Perf_Event_Sample_Type :: bit_set[Perf_Event_Sample_Type_Bits; u64]
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
// +build windows
|
||||
package sys_windows
|
||||
|
||||
foreign import "system:Dbghelp.lib"
|
||||
|
||||
RVA :: DWORD
|
||||
|
||||
MINIDUMP_LOCATION_DESCRIPTOR :: struct {
|
||||
DataSize: ULONG32,
|
||||
Rva: RVA,
|
||||
}
|
||||
|
||||
MINIDUMP_DIRECTORY :: struct {
|
||||
StreamType: ULONG32,
|
||||
Location: MINIDUMP_LOCATION_DESCRIPTOR,
|
||||
}
|
||||
|
||||
MINIDUMP_EXCEPTION_INFORMATION :: struct {
|
||||
ThreadId: DWORD,
|
||||
ExceptionPointers: ^EXCEPTION_POINTERS,
|
||||
ClientPointers: BOOL,
|
||||
}
|
||||
|
||||
MINIDUMP_MEMORY_INFO :: struct {
|
||||
BaseAddress: ULONG64,
|
||||
AllocationBase: ULONG64,
|
||||
AllocationProtect: ULONG32,
|
||||
__alignment1: ULONG32,
|
||||
RegionSize: ULONG64,
|
||||
State: ULONG32,
|
||||
Protect: ULONG32,
|
||||
Type: ULONG32,
|
||||
__alignment2: ULONG32,
|
||||
}
|
||||
|
||||
MINIDUMP_USER_STREAM :: struct {
|
||||
Type: ULONG32,
|
||||
BufferSize: ULONG,
|
||||
Buffer: PVOID,
|
||||
}
|
||||
|
||||
MINIDUMP_USER_STREAM_INFORMATION :: struct {
|
||||
UserStreamCount: ULONG,
|
||||
UserStreamArray: ^MINIDUMP_USER_STREAM,
|
||||
}
|
||||
|
||||
MINIDUMP_CALLBACK_ROUTINE :: #type proc "stdcall" (
|
||||
CallbackParam: PVOID,
|
||||
CallbackInput: ^MINIDUMP_CALLBACK_INPUT,
|
||||
CallbackOutpu: ^MINIDUMP_CALLBACK_OUTPUT,
|
||||
) -> BOOL
|
||||
|
||||
MINIDUMP_CALLBACK_INFORMATION :: struct {
|
||||
CallbackRoutine: MINIDUMP_CALLBACK_ROUTINE,
|
||||
CallbackParam: PVOID,
|
||||
}
|
||||
|
||||
MINIDUMP_CALLBACK_INPUT :: struct {
|
||||
ProcessId: ULONG,
|
||||
ProcessHandle: HANDLE,
|
||||
CallbackType: ULONG,
|
||||
using _: struct #raw_union {
|
||||
Status: HRESULT,
|
||||
Thread: MINIDUMP_THREAD_CALLBACK,
|
||||
ThreadEx: MINIDUMP_THREAD_EX_CALLBACK,
|
||||
Module: MINIDUMP_MODULE_CALLBACK,
|
||||
IncludeThread: MINIDUMP_INCLUDE_THREAD_CALLBACK,
|
||||
IncludeModule: MINIDUMP_INCLUDE_MODULE_CALLBACK,
|
||||
Io: MINIDUMP_IO_CALLBACK,
|
||||
ReadMemoryFailure: MINIDUMP_READ_MEMORY_FAILURE_CALLBACK,
|
||||
SecondaryFlags: ULONG,
|
||||
VmQuery: MINIDUMP_VM_QUERY_CALLBACK,
|
||||
VmPreRead: MINIDUMP_VM_PRE_READ_CALLBACK,
|
||||
VmPostRead: MINIDUMP_VM_POST_READ_CALLBACK,
|
||||
},
|
||||
}
|
||||
|
||||
_MINIDUMP_ARM64_PAD :: ULONG when ODIN_ARCH == .arm64 else struct {}
|
||||
|
||||
MINIDUMP_THREAD_CALLBACK :: struct {
|
||||
ThreadId: ULONG,
|
||||
ThreadHandle: HANDLE,
|
||||
Pad: _MINIDUMP_ARM64_PAD,
|
||||
Context: CONTEXT,
|
||||
SizeOfContext: ULONG,
|
||||
StackBase: ULONG64,
|
||||
StackEnd: ULONG64,
|
||||
}
|
||||
|
||||
MINIDUMP_THREAD_EX_CALLBACK :: struct {
|
||||
ThreadId: ULONG,
|
||||
ThreadHandle: HANDLE,
|
||||
Pad: _MINIDUMP_ARM64_PAD,
|
||||
Context: CONTEXT,
|
||||
SizeOfContext: ULONG,
|
||||
StackBase: ULONG64,
|
||||
StackEnd: ULONG64,
|
||||
BackingStoreBase: ULONG64,
|
||||
BackingStoreEnd: ULONG64,
|
||||
}
|
||||
|
||||
MINIDUMP_INCLUDE_THREAD_CALLBACK :: struct {
|
||||
ThreadId: ULONG,
|
||||
}
|
||||
|
||||
// NOTE(jakubtomsu): From verrsrc.h
|
||||
VS_FIXEDFILEINFO :: struct {
|
||||
dwSignature: DWORD, /* e.g. 0xfeef04bd */
|
||||
dwStrucVersion: DWORD, /* e.g. 0x00000042 = "0.42" */
|
||||
dwFileVersionMS: DWORD, /* e.g. 0x00030075 = "3.75" */
|
||||
dwFileVersionLS: DWORD, /* e.g. 0x00000031 = "0.31" */
|
||||
dwProductVersionMS: DWORD, /* e.g. 0x00030010 = "3.10" */
|
||||
dwProductVersionLS: DWORD, /* e.g. 0x00000031 = "0.31" */
|
||||
dwFileFlagsMask: DWORD, /* = 0x3F for version "0.42" */
|
||||
dwFileFlags: DWORD, /* e.g. VFF_DEBUG | VFF_PRERELEASE */
|
||||
dwFileOS: DWORD, /* e.g. VOS_DOS_WINDOWS16 */
|
||||
dwFileType: DWORD, /* e.g. VFT_DRIVER */
|
||||
dwFileSubtype: DWORD, /* e.g. VFT2_DRV_KEYBOARD */
|
||||
dwFileDateMS: DWORD, /* e.g. 0 */
|
||||
dwFileDateLS: DWORD, /* e.g. 0 */
|
||||
}
|
||||
|
||||
MINIDUMP_MODULE_CALLBACK :: struct {
|
||||
FullPath: ^WCHAR,
|
||||
BaseOfImage: ULONG64,
|
||||
SizeOfImage: ULONG,
|
||||
CheckSum: ULONG,
|
||||
TimeDateStamp: ULONG,
|
||||
VersionInfo: VS_FIXEDFILEINFO,
|
||||
CvRecord: PVOID,
|
||||
SizeOfCvRecord: ULONG,
|
||||
MiscRecord: PVOID,
|
||||
SizeOfMiscRecord: ULONG,
|
||||
}
|
||||
|
||||
MINIDUMP_INCLUDE_MODULE_CALLBACK :: struct {
|
||||
BaseOfImage: u64,
|
||||
}
|
||||
|
||||
MINIDUMP_IO_CALLBACK :: struct {
|
||||
Handle: HANDLE,
|
||||
Offset: ULONG64,
|
||||
Buffer: PVOID,
|
||||
BufferBytes: ULONG,
|
||||
}
|
||||
|
||||
MINIDUMP_READ_MEMORY_FAILURE_CALLBACK :: struct {
|
||||
Offset: ULONG64,
|
||||
Bytes: ULONG,
|
||||
FailureStatus: HRESULT,
|
||||
}
|
||||
|
||||
MINIDUMP_VM_QUERY_CALLBACK :: struct {
|
||||
Offset: ULONG64,
|
||||
}
|
||||
|
||||
MINIDUMP_VM_PRE_READ_CALLBACK :: struct {
|
||||
Offset: ULONG64,
|
||||
Buffer: PVOID,
|
||||
Size: ULONG,
|
||||
}
|
||||
|
||||
MINIDUMP_VM_POST_READ_CALLBACK :: struct {
|
||||
Offset: ULONG64,
|
||||
Buffer: PVOID,
|
||||
Size: ULONG,
|
||||
Completed: ULONG,
|
||||
Status: HRESULT,
|
||||
}
|
||||
|
||||
MINIDUMP_CALLBACK_OUTPUT :: struct {
|
||||
using _: struct #raw_union {
|
||||
ModuleWriteFlags: ULONG,
|
||||
ThreadWriteFlags: ULONG,
|
||||
SecondaryFlags: ULONG,
|
||||
using _: struct {
|
||||
MemoryBase: ULONG64,
|
||||
MemorySize: ULONG,
|
||||
},
|
||||
using _: struct {
|
||||
CheckCancel: BOOL,
|
||||
Cancel: BOOL,
|
||||
},
|
||||
Handle: HANDLE,
|
||||
using _: struct {
|
||||
VmRegion: MINIDUMP_MEMORY_INFO,
|
||||
Continue: BOOL,
|
||||
},
|
||||
using _: struct {
|
||||
VmQueryStatus: HRESULT,
|
||||
VmQueryResult: MINIDUMP_MEMORY_INFO,
|
||||
},
|
||||
using _: struct {
|
||||
VmReadStatus: HRESULT,
|
||||
VmReadBytesCompleted: ULONG,
|
||||
},
|
||||
Status: HRESULT,
|
||||
},
|
||||
}
|
||||
|
||||
MINIDUMP_TYPE :: enum u32 {
|
||||
Normal = 0x00000000,
|
||||
WithDataSegs = 0x00000001,
|
||||
WithFullMemory = 0x00000002,
|
||||
WithHandleData = 0x00000004,
|
||||
FilterMemory = 0x00000008,
|
||||
ScanMemory = 0x00000010,
|
||||
WithUnloadedModules = 0x00000020,
|
||||
WithIndirectlyReferencedMemory = 0x00000040,
|
||||
FilterModulePaths = 0x00000080,
|
||||
WithProcessThreadData = 0x00000100,
|
||||
WithPrivateReadWriteMemory = 0x00000200,
|
||||
WithoutOptionalData = 0x00000400,
|
||||
WithFullMemoryInfo = 0x00000800,
|
||||
WithThreadInfo = 0x00001000,
|
||||
WithCodeSegs = 0x00002000,
|
||||
WithoutAuxiliaryState = 0x00004000,
|
||||
WithFullAuxiliaryState = 0x00008000,
|
||||
WithPrivateWriteCopyMemory = 0x00010000,
|
||||
IgnoreInaccessibleMemory = 0x00020000,
|
||||
WithTokenInformation = 0x00040000,
|
||||
WithModuleHeaders = 0x00080000,
|
||||
FilterTriage = 0x00100000,
|
||||
WithAvxXStateContext = 0x00200000,
|
||||
WithIptTrace = 0x00400000,
|
||||
ScanInaccessiblePartialPages = 0x00800000,
|
||||
FilterWriteCombinedMemory = 0x01000000,
|
||||
ValidTypeFlags = 0x01ffffff,
|
||||
}
|
||||
|
||||
@(default_calling_convention = "stdcall")
|
||||
foreign Dbghelp {
|
||||
MiniDumpWriteDump :: proc(
|
||||
hProcess: HANDLE,
|
||||
ProcessId: DWORD,
|
||||
hFile: HANDLE,
|
||||
DumpType: MINIDUMP_TYPE,
|
||||
ExceptionParam: ^MINIDUMP_EXCEPTION_INFORMATION,
|
||||
UserStreamParam: ^MINIDUMP_USER_STREAM_INFORMATION,
|
||||
CallbackPara: ^MINIDUMP_CALLBACK_INFORMATION,
|
||||
) -> BOOL ---
|
||||
|
||||
MiniDumpReadDumpStream :: proc(
|
||||
BaseOfDump: PVOID,
|
||||
StreamNumber: ULONG,
|
||||
Dir: ^^MINIDUMP_DIRECTORY,
|
||||
StreamPointer: ^PVOID,
|
||||
StreamSize: ^ULONG,
|
||||
) -> BOOL ---
|
||||
}
|
||||
@@ -43,5 +43,6 @@ foreign dwmapi {
|
||||
DwmFlush :: proc() -> HRESULT ---
|
||||
DwmIsCompositionEnabled :: proc(pfEnabled: ^BOOL) -> HRESULT ---
|
||||
DwmExtendFrameIntoClientArea :: proc(hWnd: HWND, pMarInset: PMARGINS) -> HRESULT ---
|
||||
DwmGetWindowAttribute :: proc(hWnd: HWND, dwAttribute: DWORD, pvAttribute: PVOID, cbAttribute: DWORD) -> HRESULT ---
|
||||
DwmSetWindowAttribute :: proc(hWnd: HWND, dwAttribute: DWORD, pvAttribute: LPCVOID, cbAttribute: DWORD) -> HRESULT ---
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ foreign gdi32 {
|
||||
DeleteObject :: proc(ho: HGDIOBJ) -> BOOL ---
|
||||
SetBkColor :: proc(hdc: HDC, color: COLORREF) -> COLORREF ---
|
||||
|
||||
CreateCompatibleDC :: proc(hdc: HDC) -> HDC ---
|
||||
|
||||
CreateDIBPatternBrush :: proc(h: HGLOBAL, iUsage: UINT) -> HBRUSH ---
|
||||
|
||||
CreateDIBitmap :: proc(
|
||||
@@ -81,6 +83,11 @@ foreign gdi32 {
|
||||
GetTextMetricsW :: proc(hdc: HDC, lptm: LPTEXTMETRICW) -> BOOL ---
|
||||
|
||||
CreateSolidBrush :: proc(color: COLORREF) -> HBRUSH ---
|
||||
|
||||
GetObjectW :: proc(h: HANDLE, c: c_int, pv: LPVOID) -> int ---
|
||||
CreateCompatibleBitmap :: proc(hdc: HDC, cx, cy: c_int) -> HBITMAP ---
|
||||
BitBlt :: proc(hdc: HDC, x, y, cx, cy: c_int, hdcSrc: HDC, x1, y1: c_int, rop: DWORD) -> BOOL ---
|
||||
GetDIBits :: proc(hdc: HDC, hbm: HBITMAP, start, cLines: UINT, lpvBits: LPVOID, lpbmi: ^BITMAPINFO, usage: UINT) -> int ---
|
||||
}
|
||||
|
||||
RGB :: #force_inline proc "contextless" (r, g, b: u8) -> COLORREF {
|
||||
|
||||
@@ -172,6 +172,7 @@ foreign kernel32 {
|
||||
TolerableDelay: ULONG,
|
||||
) -> BOOL ---
|
||||
WaitForSingleObject :: proc(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD ---
|
||||
WaitForSingleObjectEx :: proc(hHandle: HANDLE, dwMilliseconds: DWORD, bAlterable: BOOL) -> DWORD ---
|
||||
Sleep :: proc(dwMilliseconds: DWORD) ---
|
||||
GetProcessId :: proc(handle: HANDLE) -> DWORD ---
|
||||
CopyFileW :: proc(
|
||||
@@ -290,6 +291,14 @@ foreign kernel32 {
|
||||
hTemplateFile: HANDLE,
|
||||
) -> HANDLE ---
|
||||
|
||||
GetFileTime :: proc(
|
||||
hFile: HANDLE,
|
||||
lpCreationTime: LPFILETIME,
|
||||
lpLastAccessTime: LPFILETIME,
|
||||
lpLastWriteTime: LPFILETIME,
|
||||
) -> BOOL ---
|
||||
CompareFileTime :: proc(lpFileTime1: LPFILETIME, lpFileTime2: LPFILETIME) -> LONG ---
|
||||
|
||||
FindFirstFileW :: proc(fileName: LPCWSTR, findFileData: LPWIN32_FIND_DATAW) -> HANDLE ---
|
||||
FindNextFileW :: proc(findFile: HANDLE, findFileData: LPWIN32_FIND_DATAW) -> BOOL ---
|
||||
FindClose :: proc(findFile: HANDLE) -> BOOL ---
|
||||
@@ -320,6 +329,13 @@ foreign kernel32 {
|
||||
bWaitAll: BOOL,
|
||||
dwMilliseconds: DWORD,
|
||||
) -> DWORD ---
|
||||
WaitForMultipleObjectsEx :: proc(
|
||||
nCount: DWORD,
|
||||
lpHandles: ^HANDLE,
|
||||
bWaitAll: BOOL,
|
||||
dwMilliseconds: DWORD,
|
||||
bAlterable: BOOL,
|
||||
) -> DWORD ---
|
||||
CreateNamedPipeW :: proc(
|
||||
lpName: LPCWSTR,
|
||||
dwOpenMode: DWORD,
|
||||
@@ -346,6 +362,9 @@ foreign kernel32 {
|
||||
LocalReAlloc :: proc(mem: LPVOID, bytes: SIZE_T, flags: UINT) -> LPVOID ---
|
||||
LocalFree :: proc(mem: LPVOID) -> LPVOID ---
|
||||
|
||||
GlobalAlloc :: proc(flags: UINT, bytes: SIZE_T) -> LPVOID ---
|
||||
GlobalReAlloc :: proc(mem: LPVOID, bytes: SIZE_T, flags: UINT) -> LPVOID ---
|
||||
GlobalFree :: proc(mem: LPVOID) -> LPVOID ---
|
||||
|
||||
ReadDirectoryChangesW :: proc(
|
||||
hDirectory: HANDLE,
|
||||
@@ -414,7 +433,7 @@ foreign kernel32 {
|
||||
GetConsoleWindow :: proc() -> HWND ---
|
||||
GetConsoleScreenBufferInfo :: proc(hConsoleOutput: HANDLE, lpConsoleScreenBufferInfo: PCONSOLE_SCREEN_BUFFER_INFO) -> BOOL ---
|
||||
SetConsoleScreenBufferSize :: proc(hConsoleOutput: HANDLE, dwSize: COORD) -> BOOL ---
|
||||
SetConsoleWindowInfo :: proc(hConsoleOutput: HANDLE, bAbsolute : BOOL, lpConsoleWindow: ^SMALL_RECT) -> BOOL ---
|
||||
SetConsoleWindowInfo :: proc(hConsoleOutput: HANDLE, bAbsolute: BOOL, lpConsoleWindow: ^SMALL_RECT) -> BOOL ---
|
||||
GetConsoleCursorInfo :: proc(hConsoleOutput: HANDLE, lpConsoleCursorInfo: PCONSOLE_CURSOR_INFO) -> BOOL ---
|
||||
SetConsoleCursorInfo :: proc(hConsoleOutput: HANDLE, lpConsoleCursorInfo: PCONSOLE_CURSOR_INFO) -> BOOL ---
|
||||
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
// +build windows
|
||||
package sys_windows
|
||||
|
||||
FOLDERID_NetworkFolder :: GUID {0xD20BEEC4, 0x5CA8, 0x4905, {0xAE, 0x3B, 0xBF, 0x25, 0x1E, 0xA0, 0x9B, 0x53}}
|
||||
FOLDERID_ComputerFolder :: GUID {0x0AC0837C, 0xBBF8, 0x452A, {0x85, 0x0D, 0x79, 0xD0, 0x8E, 0x66, 0x7C, 0xA7}}
|
||||
FOLDERID_InternetFolder :: GUID {0x4D9F7874, 0x4E0C, 0x4904, {0x96, 0x7B, 0x40, 0xB0, 0xD2, 0x0C, 0x3E, 0x4B}}
|
||||
FOLDERID_ControlPanelFolder :: GUID {0x82A74AEB, 0xAEB4, 0x465C, {0xA0, 0x14, 0xD0, 0x97, 0xEE, 0x34, 0x6D, 0x63}}
|
||||
FOLDERID_PrintersFolder :: GUID {0x76FC4E2D, 0xD6AD, 0x4519, {0xA6, 0x63, 0x37, 0xBD, 0x56, 0x06, 0x81, 0x85}}
|
||||
FOLDERID_SyncManagerFolder :: GUID {0x43668BF8, 0xC14E, 0x49B2, {0x97, 0xC9, 0x74, 0x77, 0x84, 0xD7, 0x84, 0xB7}}
|
||||
FOLDERID_SyncSetupFolder :: GUID {0xf214138 , 0xb1d3, 0x4a90, {0xbb, 0xa9, 0x27, 0xcb, 0xc0, 0xc5, 0x38, 0x9a}}
|
||||
FOLDERID_ConflictFolder :: GUID {0x4bfefb45, 0x347d, 0x4006, {0xa5, 0xbe, 0xac, 0x0c, 0xb0, 0x56, 0x71, 0x92}}
|
||||
FOLDERID_SyncResultsFolder :: GUID {0x289a9a43, 0xbe44, 0x4057, {0xa4, 0x1b, 0x58, 0x7a, 0x76, 0xd7, 0xe7, 0xf9}}
|
||||
FOLDERID_RecycleBinFolder :: GUID {0xB7534046, 0x3ECB, 0x4C18, {0xBE, 0x4E, 0x64, 0xCD, 0x4C, 0xB7, 0xD6, 0xAC}}
|
||||
FOLDERID_ConnectionsFolder :: GUID {0x6F0CD92B, 0x2E97, 0x45D1, {0x88, 0xFF, 0xB0, 0xD1, 0x86, 0xB8, 0xDE, 0xDD}}
|
||||
FOLDERID_Fonts :: GUID {0xFD228CB7, 0xAE11, 0x4AE3, {0x86, 0x4C, 0x16, 0xF3, 0x91, 0x0A, 0xB8, 0xFE}}
|
||||
FOLDERID_Desktop :: GUID {0xB4BFCC3A, 0xDB2C, 0x424C, {0xB0, 0x29, 0x7F, 0xE9, 0x9A, 0x87, 0xC6, 0x41}}
|
||||
FOLDERID_Startup :: GUID {0xB97D20BB, 0xF46A, 0x4C97, {0xBA, 0x10, 0x5E, 0x36, 0x08, 0x43, 0x08, 0x54}}
|
||||
FOLDERID_Programs :: GUID {0xA77F5D77, 0x2E2B, 0x44C3, {0xA6, 0xA2, 0xAB, 0xA6, 0x01, 0x05, 0x4A, 0x51}}
|
||||
FOLDERID_StartMenu :: GUID {0x625B53C3, 0xAB48, 0x4EC1, {0xBA, 0x1F, 0xA1, 0xEF, 0x41, 0x46, 0xFC, 0x19}}
|
||||
FOLDERID_Recent :: GUID {0xAE50C081, 0xEBD2, 0x438A, {0x86, 0x55, 0x8A, 0x09, 0x2E, 0x34, 0x98, 0x7A}}
|
||||
FOLDERID_SendTo :: GUID {0x8983036C, 0x27C0, 0x404B, {0x8F, 0x08, 0x10, 0x2D, 0x10, 0xDC, 0xFD, 0x74}}
|
||||
FOLDERID_Documents :: GUID {0xFDD39AD0, 0x238F, 0x46AF, {0xAD, 0xB4, 0x6C, 0x85, 0x48, 0x03, 0x69, 0xC7}}
|
||||
FOLDERID_Favorites :: GUID {0x1777F761, 0x68AD, 0x4D8A, {0x87, 0xBD, 0x30, 0xB7, 0x59, 0xFA, 0x33, 0xDD}}
|
||||
FOLDERID_NetHood :: GUID {0xC5ABBF53, 0xE17F, 0x4121, {0x89, 0x00, 0x86, 0x62, 0x6F, 0xC2, 0xC9, 0x73}}
|
||||
FOLDERID_PrintHood :: GUID {0x9274BD8D, 0xCFD1, 0x41C3, {0xB3, 0x5E, 0xB1, 0x3F, 0x55, 0xA7, 0x58, 0xF4}}
|
||||
FOLDERID_Templates :: GUID {0xA63293E8, 0x664E, 0x48DB, {0xA0, 0x79, 0xDF, 0x75, 0x9E, 0x05, 0x09, 0xF7}}
|
||||
FOLDERID_CommonStartup :: GUID {0x82A5EA35, 0xD9CD, 0x47C5, {0x96, 0x29, 0xE1, 0x5D, 0x2F, 0x71, 0x4E, 0x6E}}
|
||||
FOLDERID_CommonPrograms :: GUID {0x0139D44E, 0x6AFE, 0x49F2, {0x86, 0x90, 0x3D, 0xAF, 0xCA, 0xE6, 0xFF, 0xB8}}
|
||||
FOLDERID_CommonStartMenu :: GUID {0xA4115719, 0xD62E, 0x491D, {0xAA, 0x7C, 0xE7, 0x4B, 0x8B, 0xE3, 0xB0, 0x67}}
|
||||
FOLDERID_PublicDesktop :: GUID {0xC4AA340D, 0xF20F, 0x4863, {0xAF, 0xEF, 0xF8, 0x7E, 0xF2, 0xE6, 0xBA, 0x25}}
|
||||
FOLDERID_ProgramData :: GUID {0x62AB5D82, 0xFDC1, 0x4DC3, {0xA9, 0xDD, 0x07, 0x0D, 0x1D, 0x49, 0x5D, 0x97}}
|
||||
FOLDERID_CommonTemplates :: GUID {0xB94237E7, 0x57AC, 0x4347, {0x91, 0x51, 0xB0, 0x8C, 0x6C, 0x32, 0xD1, 0xF7}}
|
||||
FOLDERID_PublicDocuments :: GUID {0xED4824AF, 0xDCE4, 0x45A8, {0x81, 0xE2, 0xFC, 0x79, 0x65, 0x08, 0x36, 0x34}}
|
||||
FOLDERID_RoamingAppData :: GUID {0x3EB685DB, 0x65F9, 0x4CF6, {0xA0, 0x3A, 0xE3, 0xEF, 0x65, 0x72, 0x9F, 0x3D}}
|
||||
FOLDERID_LocalAppData :: GUID {0xF1B32785, 0x6FBA, 0x4FCF, {0x9D, 0x55, 0x7B, 0x8E, 0x7F, 0x15, 0x70, 0x91}}
|
||||
FOLDERID_LocalAppDataLow :: GUID {0xA520A1A4, 0x1780, 0x4FF6, {0xBD, 0x18, 0x16, 0x73, 0x43, 0xC5, 0xAF, 0x16}}
|
||||
FOLDERID_InternetCache :: GUID {0x352481E8, 0x33BE, 0x4251, {0xBA, 0x85, 0x60, 0x07, 0xCA, 0xED, 0xCF, 0x9D}}
|
||||
FOLDERID_Cookies :: GUID {0x2B0F765D, 0xC0E9, 0x4171, {0x90, 0x8E, 0x08, 0xA6, 0x11, 0xB8, 0x4F, 0xF6}}
|
||||
FOLDERID_History :: GUID {0xD9DC8A3B, 0xB784, 0x432E, {0xA7, 0x81, 0x5A, 0x11, 0x30, 0xA7, 0x59, 0x63}}
|
||||
FOLDERID_System :: GUID {0x1AC14E77, 0x02E7, 0x4E5D, {0xB7, 0x44, 0x2E, 0xB1, 0xAE, 0x51, 0x98, 0xB7}}
|
||||
FOLDERID_SystemX86 :: GUID {0xD65231B0, 0xB2F1, 0x4857, {0xA4, 0xCE, 0xA8, 0xE7, 0xC6, 0xEA, 0x7D, 0x27}}
|
||||
FOLDERID_Windows :: GUID {0xF38BF404, 0x1D43, 0x42F2, {0x93, 0x05, 0x67, 0xDE, 0x0B, 0x28, 0xFC, 0x23}}
|
||||
FOLDERID_Profile :: GUID {0x5E6C858F, 0x0E22, 0x4760, {0x9A, 0xFE, 0xEA, 0x33, 0x17, 0xB6, 0x71, 0x73}}
|
||||
FOLDERID_Pictures :: GUID {0x33E28130, 0x4E1E, 0x4676, {0x83, 0x5A, 0x98, 0x39, 0x5C, 0x3B, 0xC3, 0xBB}}
|
||||
FOLDERID_ProgramFilesX86 :: GUID {0x7C5A40EF, 0xA0FB, 0x4BFC, {0x87, 0x4A, 0xC0, 0xF2, 0xE0, 0xB9, 0xFA, 0x8E}}
|
||||
FOLDERID_ProgramFilesCommonX86 :: GUID {0xDE974D24, 0xD9C6, 0x4D3E, {0xBF, 0x91, 0xF4, 0x45, 0x51, 0x20, 0xB9, 0x17}}
|
||||
FOLDERID_ProgramFilesX64 :: GUID {0x6d809377, 0x6af0, 0x444b, {0x89, 0x57, 0xa3, 0x77, 0x3f, 0x02, 0x20, 0x0e}}
|
||||
FOLDERID_ProgramFilesCommonX64 :: GUID {0x6365d5a7, 0xf0d , 0x45e5, {0x87, 0xf6, 0xd, 0xa5, 0x6b, 0x6a, 0x4f, 0x7d }}
|
||||
FOLDERID_ProgramFiles :: GUID {0x905e63b6, 0xc1bf, 0x494e, {0xb2, 0x9c, 0x65, 0xb7, 0x32, 0xd3, 0xd2, 0x1a}}
|
||||
FOLDERID_ProgramFilesCommon :: GUID {0xF7F1ED05, 0x9F6D, 0x47A2, {0xAA, 0xAE, 0x29, 0xD3, 0x17, 0xC6, 0xF0, 0x66}}
|
||||
FOLDERID_UserProgramFiles :: GUID {0x5cd7aee2, 0x2219, 0x4a67, {0xb8, 0x5d, 0x6c, 0x9c, 0xe1, 0x56, 0x60, 0xcb}}
|
||||
FOLDERID_UserProgramFilesCommon :: GUID {0xbcbd3057, 0xca5c, 0x4622, {0xb4, 0x2d, 0xbc, 0x56, 0xdb, 0x0a, 0xe5, 0x16}}
|
||||
FOLDERID_AdminTools :: GUID {0x724EF170, 0xA42D, 0x4FEF, {0x9F, 0x26, 0xB6, 0x0E, 0x84, 0x6F, 0xBA, 0x4F}}
|
||||
FOLDERID_CommonAdminTools :: GUID {0xD0384E7D, 0xBAC3, 0x4797, {0x8F, 0x14, 0xCB, 0xA2, 0x29, 0xB3, 0x92, 0xB5}}
|
||||
FOLDERID_Music :: GUID {0x4BD8D571, 0x6D19, 0x48D3, {0xBE, 0x97, 0x42, 0x22, 0x20, 0x08, 0x0E, 0x43}}
|
||||
FOLDERID_Videos :: GUID {0x18989B1D, 0x99B5, 0x455B, {0x84, 0x1C, 0xAB, 0x7C, 0x74, 0xE4, 0xDD, 0xFC}}
|
||||
FOLDERID_Ringtones :: GUID {0xC870044B, 0xF49E, 0x4126, {0xA9, 0xC3, 0xB5, 0x2A, 0x1F, 0xF4, 0x11, 0xE8}}
|
||||
FOLDERID_PublicPictures :: GUID {0xB6EBFB86, 0x6907, 0x413C, {0x9A, 0xF7, 0x4F, 0xC2, 0xAB, 0xF0, 0x7C, 0xC5}}
|
||||
FOLDERID_PublicMusic :: GUID {0x3214FAB5, 0x9757, 0x4298, {0xBB, 0x61, 0x92, 0xA9, 0xDE, 0xAA, 0x44, 0xFF}}
|
||||
FOLDERID_PublicVideos :: GUID {0x2400183A, 0x6185, 0x49FB, {0xA2, 0xD8, 0x4A, 0x39, 0x2A, 0x60, 0x2B, 0xA3}}
|
||||
FOLDERID_PublicRingtones :: GUID {0xE555AB60, 0x153B, 0x4D17, {0x9F, 0x04, 0xA5, 0xFE, 0x99, 0xFC, 0x15, 0xEC}}
|
||||
FOLDERID_ResourceDir :: GUID {0x8AD10C31, 0x2ADB, 0x4296, {0xA8, 0xF7, 0xE4, 0x70, 0x12, 0x32, 0xC9, 0x72}}
|
||||
FOLDERID_LocalizedResourcesDir :: GUID {0x2A00375E, 0x224C, 0x49DE, {0xB8, 0xD1, 0x44, 0x0D, 0xF7, 0xEF, 0x3D, 0xDC}}
|
||||
FOLDERID_CommonOEMLinks :: GUID {0xC1BAE2D0, 0x10DF, 0x4334, {0xBE, 0xDD, 0x7A, 0xA2, 0x0B, 0x22, 0x7A, 0x9D}}
|
||||
FOLDERID_CDBurning :: GUID {0x9E52AB10, 0xF80D, 0x49DF, {0xAC, 0xB8, 0x43, 0x30, 0xF5, 0x68, 0x78, 0x55}}
|
||||
FOLDERID_UserProfiles :: GUID {0x0762D272, 0xC50A, 0x4BB0, {0xA3, 0x82, 0x69, 0x7D, 0xCD, 0x72, 0x9B, 0x80}}
|
||||
FOLDERID_Playlists :: GUID {0xDE92C1C7, 0x837F, 0x4F69, {0xA3, 0xBB, 0x86, 0xE6, 0x31, 0x20, 0x4A, 0x23}}
|
||||
FOLDERID_SamplePlaylists :: GUID {0x15CA69B3, 0x30EE, 0x49C1, {0xAC, 0xE1, 0x6B, 0x5E, 0xC3, 0x72, 0xAF, 0xB5}}
|
||||
FOLDERID_SampleMusic :: GUID {0xB250C668, 0xF57D, 0x4EE1, {0xA6, 0x3C, 0x29, 0x0E, 0xE7, 0xD1, 0xAA, 0x1F}}
|
||||
FOLDERID_SamplePictures :: GUID {0xC4900540, 0x2379, 0x4C75, {0x84, 0x4B, 0x64, 0xE6, 0xFA, 0xF8, 0x71, 0x6B}}
|
||||
FOLDERID_SampleVideos :: GUID {0x859EAD94, 0x2E85, 0x48AD, {0xA7, 0x1A, 0x09, 0x69, 0xCB, 0x56, 0xA6, 0xCD}}
|
||||
FOLDERID_PhotoAlbums :: GUID {0x69D2CF90, 0xFC33, 0x4FB7, {0x9A, 0x0C, 0xEB, 0xB0, 0xF0, 0xFC, 0xB4, 0x3C}}
|
||||
FOLDERID_Public :: GUID {0xDFDF76A2, 0xC82A, 0x4D63, {0x90, 0x6A, 0x56, 0x44, 0xAC, 0x45, 0x73, 0x85}}
|
||||
FOLDERID_ChangeRemovePrograms :: GUID {0xdf7266ac, 0x9274, 0x4867, {0x8d, 0x55, 0x3b, 0xd6, 0x61, 0xde, 0x87, 0x2d}}
|
||||
FOLDERID_AppUpdates :: GUID {0xa305ce99, 0xf527, 0x492b, {0x8b, 0x1a, 0x7e, 0x76, 0xfa, 0x98, 0xd6, 0xe4}}
|
||||
FOLDERID_AddNewPrograms :: GUID {0xde61d971, 0x5ebc, 0x4f02, {0xa3, 0xa9, 0x6c, 0x82, 0x89, 0x5e, 0x5c, 0x04}}
|
||||
FOLDERID_Downloads :: GUID {0x374de290, 0x123f, 0x4565, {0x91, 0x64, 0x39, 0xc4, 0x92, 0x5e, 0x46, 0x7b}}
|
||||
FOLDERID_PublicDownloads :: GUID {0x3d644c9b, 0x1fb8, 0x4f30, {0x9b, 0x45, 0xf6, 0x70, 0x23, 0x5f, 0x79, 0xc0}}
|
||||
FOLDERID_SavedSearches :: GUID {0x7d1d3a04, 0xdebb, 0x4115, {0x95, 0xcf, 0x2f, 0x29, 0xda, 0x29, 0x20, 0xda}}
|
||||
FOLDERID_QuickLaunch :: GUID {0x52a4f021, 0x7b75, 0x48a9, {0x9f, 0x6b, 0x4b, 0x87, 0xa2, 0x10, 0xbc, 0x8f}}
|
||||
FOLDERID_Contacts :: GUID {0x56784854, 0xc6cb, 0x462b, {0x81, 0x69, 0x88, 0xe3, 0x50, 0xac, 0xb8, 0x82}}
|
||||
FOLDERID_SidebarParts :: GUID {0xa75d362e, 0x50fc, 0x4fb7, {0xac, 0x2c, 0xa8, 0xbe, 0xaa, 0x31, 0x44, 0x93}}
|
||||
FOLDERID_SidebarDefaultParts :: GUID {0x7b396e54, 0x9ec5, 0x4300, {0xbe, 0xa , 0x24, 0x82, 0xeb, 0xae, 0x1a, 0x26}}
|
||||
FOLDERID_PublicGameTasks :: GUID {0xdebf2536, 0xe1a8, 0x4c59, {0xb6, 0xa2, 0x41, 0x45, 0x86, 0x47, 0x6a, 0xea}}
|
||||
FOLDERID_GameTasks :: GUID {0x54fae61 , 0x4dd8, 0x4787, {0x80, 0xb6, 0x9 , 0x2 , 0x20, 0xc4, 0xb7, 0x0 }}
|
||||
FOLDERID_SavedGames :: GUID {0x4c5c32ff, 0xbb9d, 0x43b0, {0xb5, 0xb4, 0x2d, 0x72, 0xe5, 0x4e, 0xaa, 0xa4}}
|
||||
FOLDERID_Games :: GUID {0xcac52c1a, 0xb53d, 0x4edc, {0x92, 0xd7, 0x6b, 0x2e, 0x8a, 0xc1, 0x94, 0x34}}
|
||||
FOLDERID_SEARCH_MAPI :: GUID {0x98ec0e18, 0x2098, 0x4d44, {0x86, 0x44, 0x66, 0x97, 0x93, 0x15, 0xa2, 0x81}}
|
||||
FOLDERID_SEARCH_CSC :: GUID {0xee32e446, 0x31ca, 0x4aba, {0x81, 0x4f, 0xa5, 0xeb, 0xd2, 0xfd, 0x6d, 0x5e}}
|
||||
FOLDERID_Links :: GUID {0xbfb9d5e0, 0xc6a9, 0x404c, {0xb2, 0xb2, 0xae, 0x6d, 0xb6, 0xaf, 0x49, 0x68}}
|
||||
FOLDERID_UsersFiles :: GUID {0xf3ce0f7c, 0x4901, 0x4acc, {0x86, 0x48, 0xd5, 0xd4, 0x4b, 0x04, 0xef, 0x8f}}
|
||||
FOLDERID_UsersLibraries :: GUID {0xa302545d, 0xdeff, 0x464b, {0xab, 0xe8, 0x61, 0xc8, 0x64, 0x8d, 0x93, 0x9b}}
|
||||
FOLDERID_SearchHome :: GUID {0x190337d1, 0xb8ca, 0x4121, {0xa6, 0x39, 0x6d, 0x47, 0x2d, 0x16, 0x97, 0x2a}}
|
||||
FOLDERID_OriginalImages :: GUID {0x2C36C0AA, 0x5812, 0x4b87, {0xbf, 0xd0, 0x4c, 0xd0, 0xdf, 0xb1, 0x9b, 0x39}}
|
||||
FOLDERID_DocumentsLibrary :: GUID {0x7b0db17d, 0x9cd2, 0x4a93, {0x97, 0x33, 0x46, 0xcc, 0x89, 0x02, 0x2e, 0x7c}}
|
||||
FOLDERID_MusicLibrary :: GUID {0x2112ab0a, 0xc86a, 0x4ffe, {0xa3, 0x68, 0xd , 0xe9, 0x6e, 0x47, 0x1 , 0x2e}}
|
||||
FOLDERID_PicturesLibrary :: GUID {0xa990ae9f, 0xa03b, 0x4e80, {0x94, 0xbc, 0x99, 0x12, 0xd7, 0x50, 0x41, 0x4 }}
|
||||
FOLDERID_VideosLibrary :: GUID {0x491e922f, 0x5643, 0x4af4, {0xa7, 0xeb, 0x4e, 0x7a, 0x13, 0x8d, 0x81, 0x74}}
|
||||
FOLDERID_RecordedTVLibrary :: GUID {0x1a6fdba2, 0xf42d, 0x4358, {0xa7, 0x98, 0xb7, 0x4d, 0x74, 0x59, 0x26, 0xc5}}
|
||||
FOLDERID_HomeGroup :: GUID {0x52528a6b, 0xb9e3, 0x4add, {0xb6, 0xd , 0x58, 0x8c, 0x2d, 0xba, 0x84, 0x2d}}
|
||||
FOLDERID_HomeGroupCurrentUser :: GUID {0x9b74b6a3, 0xdfd , 0x4f11, {0x9e, 0x78, 0x5f, 0x78, 0x0 , 0xf2, 0xe7, 0x72}}
|
||||
FOLDERID_DeviceMetadataStore :: GUID {0x5ce4a5e9, 0xe4eb, 0x479d, {0xb8, 0x9f, 0x13, 0x0c, 0x02, 0x88, 0x61, 0x55}}
|
||||
FOLDERID_Libraries :: GUID {0x1b3ea5dc, 0xb587, 0x4786, {0xb4, 0xef, 0xbd, 0x1d, 0xc3, 0x32, 0xae, 0xae}}
|
||||
FOLDERID_PublicLibraries :: GUID {0x48daf80b, 0xe6cf, 0x4f4e, {0xb8, 0x00, 0x0e, 0x69, 0xd8, 0x4e, 0xe3, 0x84}}
|
||||
FOLDERID_UserPinned :: GUID {0x9e3995ab, 0x1f9c, 0x4f13, {0xb8, 0x27, 0x48, 0xb2, 0x4b, 0x6c, 0x71, 0x74}}
|
||||
FOLDERID_ImplicitAppShortcuts :: GUID {0xbcb5256f, 0x79f6, 0x4cee, {0xb7, 0x25, 0xdc, 0x34, 0xe4, 0x2 , 0xfd, 0x46}}
|
||||
FOLDERID_AccountPictures :: GUID {0x008ca0b1, 0x55b4, 0x4c56, {0xb8, 0xa8, 0x4d, 0xe4, 0xb2, 0x99, 0xd3, 0xbe}}
|
||||
FOLDERID_PublicUserTiles :: GUID {0x0482af6c, 0x08f1, 0x4c34, {0x8c, 0x90, 0xe1, 0x7e, 0xc9, 0x8b, 0x1e, 0x17}}
|
||||
FOLDERID_AppsFolder :: GUID {0x1e87508d, 0x89c2, 0x42f0, {0x8a, 0x7e, 0x64, 0x5a, 0x0f, 0x50, 0xca, 0x58}}
|
||||
FOLDERID_StartMenuAllPrograms :: GUID {0xf26305ef, 0x6948, 0x40b9, {0xb2, 0x55, 0x81, 0x45, 0x3d, 0x9 , 0xc7, 0x85}}
|
||||
FOLDERID_CommonStartMenuPlaces :: GUID {0xa440879f, 0x87a0, 0x4f7d, {0xb7, 0x0 , 0x2 , 0x7 , 0xb9, 0x66, 0x19, 0x4a}}
|
||||
FOLDERID_ApplicationShortcuts :: GUID {0xa3918781, 0xe5f2, 0x4890, {0xb3, 0xd9, 0xa7, 0xe5, 0x43, 0x32, 0x32, 0x8c}}
|
||||
FOLDERID_RoamingTiles :: GUID {0xbcfc5a , 0xed94, 0x4e48, {0x96, 0xa1, 0x3f, 0x62, 0x17, 0xf2, 0x19, 0x90}}
|
||||
FOLDERID_RoamedTileImages :: GUID {0xaaa8d5a5, 0xf1d6, 0x4259, {0xba, 0xa8, 0x78, 0xe7, 0xef, 0x60, 0x83, 0x5e}}
|
||||
FOLDERID_Screenshots :: GUID {0xb7bede81, 0xdf94, 0x4682, {0xa7, 0xd8, 0x57, 0xa5, 0x26, 0x20, 0xb8, 0x6f}}
|
||||
FOLDERID_CameraRoll :: GUID {0xab5fb87b, 0x7ce2, 0x4f83, {0x91, 0x5d, 0x55, 0x8 , 0x46, 0xc9, 0x53, 0x7b}}
|
||||
FOLDERID_SkyDrive :: GUID {0xa52bba46, 0xe9e1, 0x435f, {0xb3, 0xd9, 0x28, 0xda, 0xa6, 0x48, 0xc0, 0xf6}}
|
||||
FOLDERID_OneDrive :: GUID {0xa52bba46, 0xe9e1, 0x435f, {0xb3, 0xd9, 0x28, 0xda, 0xa6, 0x48, 0xc0, 0xf6}}
|
||||
FOLDERID_SkyDriveDocuments :: GUID {0x24d89e24, 0x2f19, 0x4534, {0x9d, 0xde, 0x6a, 0x66, 0x71, 0xfb, 0xb8, 0xfe}}
|
||||
FOLDERID_SkyDrivePictures :: GUID {0x339719b5, 0x8c47, 0x4894, {0x94, 0xc2, 0xd8, 0xf7, 0x7a, 0xdd, 0x44, 0xa6}}
|
||||
FOLDERID_SkyDriveMusic :: GUID {0xc3f2459e, 0x80d6, 0x45dc, {0xbf, 0xef, 0x1f, 0x76, 0x9f, 0x2b, 0xe7, 0x30}}
|
||||
FOLDERID_SkyDriveCameraRoll :: GUID {0x767e6811, 0x49cb, 0x4273, {0x87, 0xc2, 0x20, 0xf3, 0x55, 0xe1, 0x08, 0x5b}}
|
||||
FOLDERID_SearchHistory :: GUID {0x0d4c3db6, 0x03a3, 0x462f, {0xa0, 0xe6, 0x08, 0x92, 0x4c, 0x41, 0xb5, 0xd4}}
|
||||
FOLDERID_SearchTemplates :: GUID {0x7e636bfe, 0xdfa9, 0x4d5e, {0xb4, 0x56, 0xd7, 0xb3, 0x98, 0x51, 0xd8, 0xa9}}
|
||||
FOLDERID_CameraRollLibrary :: GUID {0x2b20df75, 0x1eda, 0x4039, {0x80, 0x97, 0x38, 0x79, 0x82, 0x27, 0xd5, 0xb7}}
|
||||
FOLDERID_SavedPictures :: GUID {0x3b193882, 0xd3ad, 0x4eab, {0x96, 0x5a, 0x69, 0x82, 0x9d, 0x1f, 0xb5, 0x9f}}
|
||||
FOLDERID_SavedPicturesLibrary :: GUID {0xe25b5812, 0xbe88, 0x4bd9, {0x94, 0xb0, 0x29, 0x23, 0x34, 0x77, 0xb6, 0xc3}}
|
||||
FOLDERID_RetailDemo :: GUID {0x12d4c69e, 0x24ad, 0x4923, {0xbe, 0x19, 0x31, 0x32, 0x1c, 0x43, 0xa7, 0x67}}
|
||||
FOLDERID_Device :: GUID {0x1C2AC1DC, 0x4358, 0x4B6C, {0x97, 0x33, 0xAF, 0x21, 0x15, 0x65, 0x76, 0xF0}}
|
||||
FOLDERID_DevelopmentFiles :: GUID {0xdbe8e08e, 0x3053, 0x4bbc, {0xb1, 0x83, 0x2a, 0x7b, 0x2b, 0x19, 0x1e, 0x59}}
|
||||
FOLDERID_Objects3D :: GUID {0x31c0dd25, 0x9439, 0x4f12, {0xbf, 0x41, 0x7f, 0xf4, 0xed, 0xa3, 0x87, 0x22}}
|
||||
FOLDERID_AppCaptures :: GUID {0xedc0fe71, 0x98d8, 0x4f4a, {0xb9, 0x20, 0xc8, 0xdc, 0x13, 0x3c, 0xb1, 0x65}}
|
||||
FOLDERID_LocalDocuments :: GUID {0xf42ee2d3, 0x909f, 0x4907, {0x88, 0x71, 0x4c, 0x22, 0xfc, 0x0b, 0xf7, 0x56}}
|
||||
FOLDERID_LocalPictures :: GUID {0x0ddd015d, 0xb06c, 0x45d5, {0x8c, 0x4c, 0xf5, 0x97, 0x13, 0x85, 0x46, 0x39}}
|
||||
FOLDERID_LocalVideos :: GUID {0x35286a68, 0x3c57, 0x41a1, {0xbb, 0xb1, 0x0e, 0xae, 0x73, 0xd7, 0x6c, 0x95}}
|
||||
FOLDERID_LocalMusic :: GUID {0xa0c69a99, 0x21c8, 0x4671, {0x87, 0x03, 0x79, 0x34, 0x16, 0x2f, 0xcf, 0x1d}}
|
||||
FOLDERID_LocalDownloads :: GUID {0x7d83ee9b, 0x2244, 0x4e70, {0xb1, 0xf5, 0x53, 0x93, 0x04, 0x2a, 0xf1, 0xe4}}
|
||||
FOLDERID_RecordedCalls :: GUID {0x2f8b40c2, 0x83ed, 0x48ee, {0xb3, 0x83, 0xa1, 0xf1, 0x57, 0xec, 0x6f, 0x9a}}
|
||||
FOLDERID_AllAppMods :: GUID {0x7ad67899, 0x66af, 0x43ba, {0x91, 0x56, 0x6a, 0xad, 0x42, 0xe6, 0xc5, 0x96}}
|
||||
FOLDERID_CurrentAppMods :: GUID {0x3db40b20, 0x2a30, 0x4dbe, {0x91, 0x7e, 0x77, 0x1d, 0xd2, 0x1d, 0xd0, 0x99}}
|
||||
FOLDERID_AppDataDesktop :: GUID {0xb2c5e279, 0x7add, 0x439f, {0xb2, 0x8c, 0xc4, 0x1f, 0xe1, 0xbb, 0xf6, 0x72}}
|
||||
FOLDERID_AppDataDocuments :: GUID {0x7be16610, 0x1f7f, 0x44ac, {0xbf, 0xf0, 0x83, 0xe1, 0x5f, 0x2f, 0xfc, 0xa1}}
|
||||
FOLDERID_AppDataFavorites :: GUID {0x7cfbefbc, 0xde1f, 0x45aa, {0xb8, 0x43, 0xa5, 0x42, 0xac, 0x53, 0x6c, 0xc9}}
|
||||
FOLDERID_AppDataProgramData :: GUID {0x559d40a3, 0xa036, 0x40fa, {0xaf, 0x61, 0x84, 0xcb, 0x43, 0xa , 0x4d, 0x34}}
|
||||
FOLDERID_LocalStorage :: GUID {0xB3EB08D3, 0xA1F3, 0x496B, {0x86, 0x5A, 0x42, 0xB5, 0x36, 0xCD, 0xA0, 0xEC}}
|
||||
@@ -22,9 +22,13 @@ foreign shell32 {
|
||||
) -> c_int ---
|
||||
SHFileOperationW :: proc(lpFileOp: LPSHFILEOPSTRUCTW) -> c_int ---
|
||||
SHGetFolderPathW :: proc(hwnd: HWND, csidl: c_int, hToken: HANDLE, dwFlags: DWORD, pszPath: LPWSTR) -> HRESULT ---
|
||||
SHAppBarMessage :: proc(dwMessage: DWORD, pData: PAPPBARDATA) -> UINT_PTR ---
|
||||
SHAppBarMessage :: proc(dwMessage: DWORD, pData: PAPPBARDATA) -> UINT_PTR ---
|
||||
|
||||
Shell_NotifyIconW :: proc(dwMessage: DWORD, lpData: ^NOTIFYICONDATAW) -> BOOL ---
|
||||
|
||||
SHGetKnownFolderIDList :: proc(rfid: REFKNOWNFOLDERID, dwFlags: /* KNOWN_FOLDER_FLAG */ DWORD, hToken: HANDLE, ppidl: rawptr) -> HRESULT ---
|
||||
SHSetKnownFolderPath :: proc(rfid: REFKNOWNFOLDERID, dwFlags: /* KNOWN_FOLDER_FLAG */ DWORD, hToken: HANDLE, pszPath: PCWSTR ) -> HRESULT ---
|
||||
SHGetKnownFolderPath :: proc(rfid: REFKNOWNFOLDERID, dwFlags: /* KNOWN_FOLDER_FLAG */ DWORD, hToken: HANDLE, ppszPath: ^LPWSTR) -> HRESULT ---
|
||||
}
|
||||
|
||||
APPBARDATA :: struct {
|
||||
@@ -36,16 +40,16 @@ APPBARDATA :: struct {
|
||||
lParam: LPARAM,
|
||||
}
|
||||
PAPPBARDATA :: ^APPBARDATA
|
||||
|
||||
|
||||
ABM_NEW :: 0x00000000
|
||||
ABM_REMOVE :: 0x00000001
|
||||
ABM_QUERYPOS :: 0x00000002
|
||||
ABM_SETPOS :: 0x00000003
|
||||
ABM_GETSTATE :: 0x00000004
|
||||
ABM_GETTASKBARPOS :: 0x00000005
|
||||
ABM_ACTIVATE :: 0x00000006
|
||||
ABM_ACTIVATE :: 0x00000006
|
||||
ABM_GETAUTOHIDEBAR :: 0x00000007
|
||||
ABM_SETAUTOHIDEBAR :: 0x00000008
|
||||
ABM_SETAUTOHIDEBAR :: 0x00000008
|
||||
ABM_WINDOWPOSCHANGED :: 0x0000009
|
||||
ABM_SETSTATE :: 0x0000000a
|
||||
ABN_STATECHANGE :: 0x0000000
|
||||
@@ -58,3 +62,32 @@ ABE_LEFT :: 0
|
||||
ABE_TOP :: 1
|
||||
ABE_RIGHT :: 2
|
||||
ABE_BOTTOM :: 3
|
||||
|
||||
KNOWNFOLDERID :: GUID
|
||||
REFKNOWNFOLDERID :: ^KNOWNFOLDERID
|
||||
|
||||
KNOWN_FOLDER_FLAG :: enum u32 {
|
||||
DEFAULT = 0x00000000,
|
||||
|
||||
// if NTDDI_VERSION >= NTDDI_WIN10_RS3
|
||||
FORCE_APP_DATA_REDIRECTION = 0x00080000,
|
||||
|
||||
// if NTDDI_VERSION >= NTDDI_WIN10_RS2
|
||||
RETURN_FILTER_REDIRECTION_TARGET = 0x00040000,
|
||||
FORCE_PACKAGE_REDIRECTION = 0x00020000,
|
||||
NO_PACKAGE_REDIRECTION = 0x00010000,
|
||||
FORCE_APPCONTAINER_REDIRECTION = 0x00020000,
|
||||
|
||||
// if NTDDI_VERSION >= NTDDI_WIN7
|
||||
NO_APPCONTAINER_REDIRECTION = 0x00010000,
|
||||
|
||||
CREATE = 0x00008000,
|
||||
DONT_VERIFY = 0x00004000,
|
||||
DONT_UNEXPAND = 0x00002000,
|
||||
NO_ALIAS = 0x00001000,
|
||||
INIT = 0x00000800,
|
||||
DEFAULT_PATH = 0x00000400,
|
||||
NOT_PARENT_RELATIVE = 0x00000200,
|
||||
SIMPLE_IDLIST = 0x00000100,
|
||||
ALIAS_ONLY = 0x80000000,
|
||||
}
|
||||
|
||||
@@ -86,6 +86,8 @@ INT16 :: i16
|
||||
INT32 :: i32
|
||||
INT64 :: i64
|
||||
|
||||
ULONG32 :: u32
|
||||
LONG32 :: i32
|
||||
|
||||
ULONG64 :: u64
|
||||
LONG64 :: i64
|
||||
@@ -1969,6 +1971,16 @@ BITMAPINFO :: struct {
|
||||
bmiColors: [1]RGBQUAD,
|
||||
}
|
||||
|
||||
BITMAP :: struct {
|
||||
bmType: LONG,
|
||||
bmWidth: LONG,
|
||||
bmHeight: LONG,
|
||||
bmWidthBytes: LONG,
|
||||
bmPlanes: WORD,
|
||||
bmBitsPixel: WORD,
|
||||
bmBits: LPVOID,
|
||||
}
|
||||
|
||||
// pixel types
|
||||
PFD_TYPE_RGBA :: 0
|
||||
PFD_TYPE_COLORINDEX :: 1
|
||||
|
||||
@@ -136,6 +136,7 @@ foreign user32 {
|
||||
GetKeyboardState :: proc(lpKeyState: PBYTE) -> BOOL ---
|
||||
|
||||
MapVirtualKeyW :: proc(uCode: UINT, uMapType: UINT) -> UINT ---
|
||||
ToUnicode :: proc(nVirtKey: UINT, wScanCode: UINT, lpKeyState: ^BYTE, pwszBuff: LPWSTR, cchBuff: c_int, wFlags: UINT) -> c_int ---
|
||||
|
||||
SetWindowsHookExW :: proc(idHook: c_int, lpfn: HOOKPROC, hmod: HINSTANCE, dwThreadId: DWORD) -> HHOOK ---
|
||||
UnhookWindowsHookEx :: proc(hhk: HHOOK) -> BOOL ---
|
||||
@@ -160,6 +161,8 @@ foreign user32 {
|
||||
MonitorFromRect :: proc(lprc: LPRECT, dwFlags: Monitor_From_Flags) -> HMONITOR ---
|
||||
MonitorFromWindow :: proc(hwnd: HWND, dwFlags: Monitor_From_Flags) -> HMONITOR ---
|
||||
EnumDisplayMonitors :: proc(hdc: HDC, lprcClip: LPRECT, lpfnEnum: Monitor_Enum_Proc, dwData: LPARAM) -> BOOL ---
|
||||
|
||||
EnumWindows :: proc(lpEnumFunc: Window_Enum_Proc, lParam: LPARAM) -> BOOL ---
|
||||
|
||||
SetThreadDpiAwarenessContext :: proc(dpiContext: DPI_AWARENESS_CONTEXT) -> DPI_AWARENESS_CONTEXT ---
|
||||
GetThreadDpiAwarenessContext :: proc() -> DPI_AWARENESS_CONTEXT ---
|
||||
@@ -310,6 +313,7 @@ Monitor_From_Flags :: enum DWORD {
|
||||
}
|
||||
|
||||
Monitor_Enum_Proc :: #type proc "stdcall" (HMONITOR, HDC, LPRECT, LPARAM) -> BOOL
|
||||
Window_Enum_Proc :: #type proc "stdcall" (HWND, LPARAM) -> BOOL
|
||||
|
||||
USER_DEFAULT_SCREEN_DPI :: 96
|
||||
DPI_AWARENESS_CONTEXT :: distinct HANDLE
|
||||
|
||||
@@ -63,7 +63,9 @@ Translation :: enum u32 {
|
||||
Soft_Line_End,
|
||||
}
|
||||
|
||||
|
||||
// init the state to some timeout and set the respective allocators
|
||||
// - undo_state_allocator dictates the dynamic undo|redo arrays allocators
|
||||
// - undo_text_allocator is the allocator which allocates strings only
|
||||
init :: proc(s: ^State, undo_text_allocator, undo_state_allocator: runtime.Allocator, undo_timeout := DEFAULT_UNDO_TIMEOUT) {
|
||||
s.undo_timeout = undo_timeout
|
||||
|
||||
@@ -74,6 +76,7 @@ init :: proc(s: ^State, undo_text_allocator, undo_state_allocator: runtime.Alloc
|
||||
s.redo.allocator = undo_state_allocator
|
||||
}
|
||||
|
||||
// clear undo|redo strings and delete their stacks
|
||||
destroy :: proc(s: ^State) {
|
||||
undo_clear(s, &s.undo)
|
||||
undo_clear(s, &s.redo)
|
||||
@@ -82,7 +85,6 @@ destroy :: proc(s: ^State) {
|
||||
s.builder = nil
|
||||
}
|
||||
|
||||
|
||||
// Call at the beginning of each frame
|
||||
begin :: proc(s: ^State, id: u64, builder: ^strings.Builder) {
|
||||
assert(builder != nil)
|
||||
@@ -92,11 +94,7 @@ begin :: proc(s: ^State, id: u64, builder: ^strings.Builder) {
|
||||
s.id = id
|
||||
s.selection = {len(builder.buf), 0}
|
||||
s.builder = builder
|
||||
s.current_time = time.tick_now()
|
||||
if s.undo_timeout <= 0 {
|
||||
s.undo_timeout = DEFAULT_UNDO_TIMEOUT
|
||||
}
|
||||
set_text(s, string(s.builder.buf[:]))
|
||||
update_time(s)
|
||||
undo_clear(s, &s.undo)
|
||||
undo_clear(s, &s.redo)
|
||||
}
|
||||
@@ -107,12 +105,37 @@ end :: proc(s: ^State) {
|
||||
s.builder = nil
|
||||
}
|
||||
|
||||
set_text :: proc(s: ^State, text: string) {
|
||||
strings.builder_reset(s.builder)
|
||||
strings.write_string(s.builder, text)
|
||||
// update current time so "insert" can check for timeouts
|
||||
update_time :: proc(s: ^State) {
|
||||
s.current_time = time.tick_now()
|
||||
if s.undo_timeout <= 0 {
|
||||
s.undo_timeout = DEFAULT_UNDO_TIMEOUT
|
||||
}
|
||||
}
|
||||
|
||||
// setup the builder, selection and undo|redo state once allowing to retain selection
|
||||
setup_once :: proc(s: ^State, builder: ^strings.Builder) {
|
||||
s.builder = builder
|
||||
s.selection = { len(builder.buf), 0 }
|
||||
undo_clear(s, &s.undo)
|
||||
undo_clear(s, &s.redo)
|
||||
}
|
||||
|
||||
// returns true when the builder had content to be cleared
|
||||
// clear builder&selection and the undo|redo stacks
|
||||
clear_all :: proc(s: ^State) -> (cleared: bool) {
|
||||
if s.builder != nil && len(s.builder.buf) > 0 {
|
||||
clear(&s.builder.buf)
|
||||
s.selection = {}
|
||||
cleared = true
|
||||
}
|
||||
|
||||
undo_clear(s, &s.undo)
|
||||
undo_clear(s, &s.redo)
|
||||
return
|
||||
}
|
||||
|
||||
// push current text state to the wanted undo|redo stack
|
||||
undo_state_push :: proc(s: ^State, undo: ^[dynamic]^Undo_State) -> mem.Allocator_Error {
|
||||
text := string(s.builder.buf[:])
|
||||
item := (^Undo_State)(mem.alloc(size_of(Undo_State) + len(text), align_of(Undo_State), s.undo_text_allocator) or_return)
|
||||
@@ -125,18 +148,21 @@ undo_state_push :: proc(s: ^State, undo: ^[dynamic]^Undo_State) -> mem.Allocator
|
||||
return nil
|
||||
}
|
||||
|
||||
// pop undo|redo state - push to redo|undo - set selection & text
|
||||
undo :: proc(s: ^State, undo, redo: ^[dynamic]^Undo_State) {
|
||||
if len(undo) > 0 {
|
||||
undo_state_push(s, redo)
|
||||
item := pop(undo)
|
||||
s.selection = item.selection
|
||||
#no_bounds_check {
|
||||
set_text(s, string(item.text[:item.len]))
|
||||
strings.builder_reset(s.builder)
|
||||
strings.write_string(s.builder, string(item.text[:item.len]))
|
||||
}
|
||||
free(item, s.undo_text_allocator)
|
||||
}
|
||||
}
|
||||
|
||||
// iteratively clearn the undo|redo stack and free each allocated text state
|
||||
undo_clear :: proc(s: ^State, undo: ^[dynamic]^Undo_State) {
|
||||
for len(undo) > 0 {
|
||||
item := pop(undo)
|
||||
@@ -144,6 +170,7 @@ undo_clear :: proc(s: ^State, undo: ^[dynamic]^Undo_State) {
|
||||
}
|
||||
}
|
||||
|
||||
// clear redo stack and check if the undo timeout gets hit
|
||||
undo_check :: proc(s: ^State) {
|
||||
undo_clear(s, &s.redo)
|
||||
if time.tick_diff(s.last_edit_time, s.current_time) > s.undo_timeout {
|
||||
@@ -152,8 +179,7 @@ undo_check :: proc(s: ^State) {
|
||||
s.last_edit_time = s.current_time
|
||||
}
|
||||
|
||||
|
||||
|
||||
// insert text into the edit state - deletes the current selection
|
||||
input_text :: proc(s: ^State, text: string) {
|
||||
if len(text) == 0 {
|
||||
return
|
||||
@@ -166,6 +192,7 @@ input_text :: proc(s: ^State, text: string) {
|
||||
s.selection = {offset, offset}
|
||||
}
|
||||
|
||||
// insert slice of runes into the edit state - deletes the current selection
|
||||
input_runes :: proc(s: ^State, text: []rune) {
|
||||
if len(text) == 0 {
|
||||
return
|
||||
@@ -182,43 +209,55 @@ input_runes :: proc(s: ^State, text: []rune) {
|
||||
s.selection = {offset, offset}
|
||||
}
|
||||
|
||||
// insert a single rune into the edit state - deletes the current selection
|
||||
input_rune :: proc(s: ^State, r: rune) {
|
||||
if has_selection(s) {
|
||||
selection_delete(s)
|
||||
}
|
||||
offset := s.selection[0]
|
||||
b, w := utf8.encode_rune(r)
|
||||
insert(s, offset, string(b[:w]))
|
||||
offset += w
|
||||
s.selection = {offset, offset}
|
||||
}
|
||||
|
||||
// insert a single rune into the edit state - deletes the current selection
|
||||
insert :: proc(s: ^State, at: int, text: string) {
|
||||
undo_check(s)
|
||||
inject_at(&s.builder.buf, at, text)
|
||||
}
|
||||
|
||||
// remove the wanted range withing, usually the selection within byte indices
|
||||
remove :: proc(s: ^State, lo, hi: int) {
|
||||
undo_check(s)
|
||||
remove_range(&s.builder.buf, lo, hi)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// true if selection head and tail dont match and form a selection of multiple characters
|
||||
has_selection :: proc(s: ^State) -> bool {
|
||||
return s.selection[0] != s.selection[1]
|
||||
}
|
||||
|
||||
// return the clamped lo/hi of the current selection
|
||||
// since the selection[0] moves around and could be ahead of selection[1]
|
||||
// useful when rendering and needing left->right
|
||||
sorted_selection :: proc(s: ^State) -> (lo, hi: int) {
|
||||
lo = min(s.selection[0], s.selection[1])
|
||||
hi = max(s.selection[0], s.selection[1])
|
||||
lo = clamp(lo, 0, len(s.builder.buf))
|
||||
hi = clamp(hi, 0, len(s.builder.buf))
|
||||
s.selection[0] = lo
|
||||
s.selection[1] = hi
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// delete the current selection range and set the proper selection afterwards
|
||||
selection_delete :: proc(s: ^State) {
|
||||
lo, hi := sorted_selection(s)
|
||||
remove(s, lo, hi)
|
||||
s.selection = {lo, lo}
|
||||
}
|
||||
|
||||
|
||||
|
||||
translate_position :: proc(s: ^State, pos: int, t: Translation) -> int {
|
||||
// translates the caret position
|
||||
translate_position :: proc(s: ^State, t: Translation) -> int {
|
||||
is_continuation_byte :: proc(b: byte) -> bool {
|
||||
return b >= 0x80 && b < 0xc0
|
||||
}
|
||||
@@ -227,9 +266,7 @@ translate_position :: proc(s: ^State, pos: int, t: Translation) -> int {
|
||||
}
|
||||
|
||||
buf := s.builder.buf[:]
|
||||
|
||||
pos := pos
|
||||
pos = clamp(pos, 0, len(buf))
|
||||
pos := clamp(s.selection[0], 0, len(buf))
|
||||
|
||||
switch t {
|
||||
case .Start:
|
||||
@@ -280,6 +317,7 @@ translate_position :: proc(s: ^State, pos: int, t: Translation) -> int {
|
||||
return clamp(pos, 0, len(buf))
|
||||
}
|
||||
|
||||
// Moves the position of the caret (both sides of the selection)
|
||||
move_to :: proc(s: ^State, t: Translation) {
|
||||
if t == .Left && has_selection(s) {
|
||||
lo, _ := sorted_selection(s)
|
||||
@@ -288,32 +326,36 @@ move_to :: proc(s: ^State, t: Translation) {
|
||||
_, hi := sorted_selection(s)
|
||||
s.selection = {hi, hi}
|
||||
} else {
|
||||
pos := translate_position(s, s.selection[0], t)
|
||||
pos := translate_position(s, t)
|
||||
s.selection = {pos, pos}
|
||||
}
|
||||
}
|
||||
|
||||
// Moves only the head of the selection and leaves the tail uneffected
|
||||
select_to :: proc(s: ^State, t: Translation) {
|
||||
s.selection[0] = translate_position(s, s.selection[0], t)
|
||||
s.selection[0] = translate_position(s, t)
|
||||
}
|
||||
|
||||
// Deletes everything between the caret and resultant position
|
||||
delete_to :: proc(s: ^State, t: Translation) {
|
||||
if has_selection(s) {
|
||||
selection_delete(s)
|
||||
} else {
|
||||
lo := s.selection[0]
|
||||
hi := translate_position(s, lo, t)
|
||||
hi := translate_position(s, t)
|
||||
lo, hi = min(lo, hi), max(lo, hi)
|
||||
remove(s, lo, hi)
|
||||
s.selection = {lo, lo}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// return the currently selected text
|
||||
current_selected_text :: proc(s: ^State) -> string {
|
||||
lo, hi := sorted_selection(s)
|
||||
return string(s.builder.buf[lo:hi])
|
||||
}
|
||||
|
||||
|
||||
// copy & delete the current selection when copy() succeeds
|
||||
cut :: proc(s: ^State) -> bool {
|
||||
if copy(s) {
|
||||
selection_delete(s)
|
||||
@@ -322,6 +364,8 @@ cut :: proc(s: ^State) -> bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// try and copy the currently selected text to the clipboard
|
||||
// State.set_clipboard needs to be assigned
|
||||
copy :: proc(s: ^State) -> bool {
|
||||
if s.set_clipboard != nil {
|
||||
return s.set_clipboard(s.clipboard_user_data, current_selected_text(s))
|
||||
@@ -329,6 +373,8 @@ copy :: proc(s: ^State) -> bool {
|
||||
return s.set_clipboard != nil
|
||||
}
|
||||
|
||||
// reinsert whatever the get_clipboard would return
|
||||
// State.get_clipboard needs to be assigned
|
||||
paste :: proc(s: ^State) -> bool {
|
||||
if s.get_clipboard != nil {
|
||||
input_text(s, s.get_clipboard(s.clipboard_user_data) or_return)
|
||||
|
||||
+55
-38
@@ -116,26 +116,21 @@ run_with_data :: proc(data: rawptr, fn: proc(data: rawptr), init_context: Maybe(
|
||||
}
|
||||
|
||||
run_with_poly_data :: proc(data: $T, fn: proc(data: T), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal)
|
||||
where size_of(T) <= size_of(rawptr) {
|
||||
where size_of(T) <= size_of(rawptr) * MAX_USER_ARGUMENTS {
|
||||
create_and_start_with_poly_data(data, fn, init_context, priority, true)
|
||||
}
|
||||
|
||||
run_with_poly_data2 :: proc(arg1: $T1, arg2: $T2, fn: proc(T1, T2), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal)
|
||||
where size_of(T1) <= size_of(rawptr),
|
||||
size_of(T2) <= size_of(rawptr) {
|
||||
where size_of(T1) + size_of(T2) <= size_of(rawptr) * MAX_USER_ARGUMENTS {
|
||||
create_and_start_with_poly_data2(arg1, arg2, fn, init_context, priority, true)
|
||||
}
|
||||
|
||||
run_with_poly_data3 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, fn: proc(arg1: T1, arg2: T2, arg3: T3), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal)
|
||||
where size_of(T1) <= size_of(rawptr),
|
||||
size_of(T2) <= size_of(rawptr),
|
||||
size_of(T3) <= size_of(rawptr) {
|
||||
where size_of(T1) + size_of(T2) + size_of(T3) <= size_of(rawptr) * MAX_USER_ARGUMENTS {
|
||||
create_and_start_with_poly_data3(arg1, arg2, arg3, fn, init_context, priority, true)
|
||||
}
|
||||
run_with_poly_data4 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, arg4: $T4, fn: proc(arg1: T1, arg2: T2, arg3: T3, arg4: T4), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal)
|
||||
where size_of(T1) <= size_of(rawptr),
|
||||
size_of(T2) <= size_of(rawptr),
|
||||
size_of(T3) <= size_of(rawptr) {
|
||||
where size_of(T1) + size_of(T2) + size_of(T3) + size_of(T4) <= size_of(rawptr) * MAX_USER_ARGUMENTS {
|
||||
create_and_start_with_poly_data4(arg1, arg2, arg3, arg4, fn, init_context, priority, true)
|
||||
}
|
||||
|
||||
@@ -178,7 +173,7 @@ create_and_start_with_data :: proc(data: rawptr, fn: proc(data: rawptr), init_co
|
||||
}
|
||||
|
||||
create_and_start_with_poly_data :: proc(data: $T, fn: proc(data: T), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, self_cleanup := false) -> ^Thread
|
||||
where size_of(T) <= size_of(rawptr) {
|
||||
where size_of(T) <= size_of(rawptr) * MAX_USER_ARGUMENTS {
|
||||
thread_proc :: proc(t: ^Thread) {
|
||||
fn := cast(proc(T))t.data
|
||||
assert(t.user_index >= 1)
|
||||
@@ -188,96 +183,118 @@ create_and_start_with_poly_data :: proc(data: $T, fn: proc(data: T), init_contex
|
||||
t := create(thread_proc, priority)
|
||||
t.data = rawptr(fn)
|
||||
t.user_index = 1
|
||||
|
||||
data := data
|
||||
mem.copy(&t.user_args[0], &data, size_of(data))
|
||||
|
||||
mem.copy(&t.user_args[0], &data, size_of(T))
|
||||
|
||||
if self_cleanup {
|
||||
t.flags += {.Self_Cleanup}
|
||||
}
|
||||
|
||||
t.init_context = init_context
|
||||
start(t)
|
||||
return t
|
||||
}
|
||||
|
||||
create_and_start_with_poly_data2 :: proc(arg1: $T1, arg2: $T2, fn: proc(T1, T2), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, self_cleanup := false) -> ^Thread
|
||||
where size_of(T1) <= size_of(rawptr),
|
||||
size_of(T2) <= size_of(rawptr) {
|
||||
where size_of(T1) + size_of(T2) <= size_of(rawptr) * MAX_USER_ARGUMENTS {
|
||||
thread_proc :: proc(t: ^Thread) {
|
||||
fn := cast(proc(T1, T2))t.data
|
||||
assert(t.user_index >= 2)
|
||||
arg1 := (^T1)(&t.user_args[0])^
|
||||
arg2 := (^T2)(&t.user_args[1])^
|
||||
|
||||
user_args := mem.slice_to_bytes(t.user_args[:])
|
||||
arg1 := (^T1)(raw_data(user_args))^
|
||||
arg2 := (^T2)(raw_data(user_args[size_of(T1):]))^
|
||||
|
||||
fn(arg1, arg2)
|
||||
}
|
||||
t := create(thread_proc, priority)
|
||||
t.data = rawptr(fn)
|
||||
t.user_index = 2
|
||||
|
||||
arg1, arg2 := arg1, arg2
|
||||
mem.copy(&t.user_args[0], &arg1, size_of(arg1))
|
||||
mem.copy(&t.user_args[1], &arg2, size_of(arg2))
|
||||
user_args := mem.slice_to_bytes(t.user_args[:])
|
||||
|
||||
n := copy(user_args, mem.ptr_to_bytes(&arg1))
|
||||
_ = copy(user_args[n:], mem.ptr_to_bytes(&arg2))
|
||||
|
||||
if self_cleanup {
|
||||
t.flags += {.Self_Cleanup}
|
||||
}
|
||||
|
||||
t.init_context = init_context
|
||||
start(t)
|
||||
return t
|
||||
}
|
||||
|
||||
create_and_start_with_poly_data3 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, fn: proc(arg1: T1, arg2: T2, arg3: T3), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, self_cleanup := false) -> ^Thread
|
||||
where size_of(T1) <= size_of(rawptr),
|
||||
size_of(T2) <= size_of(rawptr),
|
||||
size_of(T3) <= size_of(rawptr) {
|
||||
where size_of(T1) + size_of(T2) + size_of(T3) <= size_of(rawptr) * MAX_USER_ARGUMENTS {
|
||||
thread_proc :: proc(t: ^Thread) {
|
||||
fn := cast(proc(T1, T2, T3))t.data
|
||||
assert(t.user_index >= 3)
|
||||
arg1 := (^T1)(&t.user_args[0])^
|
||||
arg2 := (^T2)(&t.user_args[1])^
|
||||
arg3 := (^T3)(&t.user_args[2])^
|
||||
|
||||
user_args := mem.slice_to_bytes(t.user_args[:])
|
||||
arg1 := (^T1)(raw_data(user_args))^
|
||||
arg2 := (^T2)(raw_data(user_args[size_of(T1):]))^
|
||||
arg3 := (^T3)(raw_data(user_args[size_of(T1) + size_of(T2):]))^
|
||||
|
||||
fn(arg1, arg2, arg3)
|
||||
}
|
||||
t := create(thread_proc, priority)
|
||||
t.data = rawptr(fn)
|
||||
t.user_index = 3
|
||||
|
||||
arg1, arg2, arg3 := arg1, arg2, arg3
|
||||
mem.copy(&t.user_args[0], &arg1, size_of(arg1))
|
||||
mem.copy(&t.user_args[1], &arg2, size_of(arg2))
|
||||
mem.copy(&t.user_args[2], &arg3, size_of(arg3))
|
||||
user_args := mem.slice_to_bytes(t.user_args[:])
|
||||
|
||||
n := copy(user_args, mem.ptr_to_bytes(&arg1))
|
||||
n += copy(user_args[n:], mem.ptr_to_bytes(&arg2))
|
||||
_ = copy(user_args[n:], mem.ptr_to_bytes(&arg3))
|
||||
|
||||
if self_cleanup {
|
||||
t.flags += {.Self_Cleanup}
|
||||
}
|
||||
|
||||
t.init_context = init_context
|
||||
start(t)
|
||||
return t
|
||||
}
|
||||
create_and_start_with_poly_data4 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, arg4: $T4, fn: proc(arg1: T1, arg2: T2, arg3: T3, arg4: T4), init_context: Maybe(runtime.Context) = nil, priority := Thread_Priority.Normal, self_cleanup := false) -> ^Thread
|
||||
where size_of(T1) <= size_of(rawptr),
|
||||
size_of(T2) <= size_of(rawptr),
|
||||
size_of(T3) <= size_of(rawptr) {
|
||||
where size_of(T1) + size_of(T2) + size_of(T3) + size_of(T4) <= size_of(rawptr) * MAX_USER_ARGUMENTS {
|
||||
thread_proc :: proc(t: ^Thread) {
|
||||
fn := cast(proc(T1, T2, T3, T4))t.data
|
||||
assert(t.user_index >= 4)
|
||||
arg1 := (^T1)(&t.user_args[0])^
|
||||
arg2 := (^T2)(&t.user_args[1])^
|
||||
arg3 := (^T3)(&t.user_args[2])^
|
||||
arg4 := (^T4)(&t.user_args[3])^
|
||||
|
||||
user_args := mem.slice_to_bytes(t.user_args[:])
|
||||
arg1 := (^T1)(raw_data(user_args))^
|
||||
arg2 := (^T2)(raw_data(user_args[size_of(T1):]))^
|
||||
arg3 := (^T3)(raw_data(user_args[size_of(T1) + size_of(T2):]))^
|
||||
arg4 := (^T4)(raw_data(user_args[size_of(T1) + size_of(T2) + size_of(T3):]))^
|
||||
|
||||
fn(arg1, arg2, arg3, arg4)
|
||||
}
|
||||
t := create(thread_proc, priority)
|
||||
t.data = rawptr(fn)
|
||||
t.user_index = 4
|
||||
|
||||
arg1, arg2, arg3, arg4 := arg1, arg2, arg3, arg4
|
||||
mem.copy(&t.user_args[0], &arg1, size_of(arg1))
|
||||
mem.copy(&t.user_args[1], &arg2, size_of(arg2))
|
||||
mem.copy(&t.user_args[2], &arg3, size_of(arg3))
|
||||
mem.copy(&t.user_args[3], &arg4, size_of(arg4))
|
||||
user_args := mem.slice_to_bytes(t.user_args[:])
|
||||
|
||||
n := copy(user_args, mem.ptr_to_bytes(&arg1))
|
||||
n += copy(user_args[n:], mem.ptr_to_bytes(&arg2))
|
||||
n += copy(user_args[n:], mem.ptr_to_bytes(&arg3))
|
||||
_ = copy(user_args[n:], mem.ptr_to_bytes(&arg4))
|
||||
|
||||
if self_cleanup {
|
||||
t.flags += {.Self_Cleanup}
|
||||
}
|
||||
|
||||
t.init_context = init_context
|
||||
start(t)
|
||||
return t
|
||||
}
|
||||
|
||||
|
||||
_select_context_for_thread :: proc(init_context: Maybe(runtime.Context)) -> runtime.Context {
|
||||
ctx, ok := init_context.?
|
||||
if !ok {
|
||||
|
||||
@@ -39,6 +39,8 @@ import nvg "vendor:nanovg"
|
||||
import nvg_gl "vendor:nanovg/gl"
|
||||
import fontstash "vendor:fontstash"
|
||||
|
||||
import xlib "vendor:x11/xlib"
|
||||
|
||||
_ :: botan_bindings
|
||||
_ :: botan_blake2b
|
||||
_ :: keccak
|
||||
@@ -76,4 +78,6 @@ _ :: lua_5_4
|
||||
|
||||
_ :: nvg
|
||||
_ :: nvg_gl
|
||||
_ :: fontstash
|
||||
_ :: fontstash
|
||||
|
||||
_ :: xlib
|
||||
+17
-3
@@ -82,6 +82,23 @@ gb_global String target_arch_names[TargetArch_COUNT] = {
|
||||
str_lit("wasm64p32"),
|
||||
};
|
||||
|
||||
gb_global String target_microarch_list[TargetArch_COUNT] = {
|
||||
// TargetArch_Invalid,
|
||||
str_lit("Invalid!"),
|
||||
// TargetArch_amd64,
|
||||
str_lit("alderlake,amdfam10,athlon-fx,athlon64,athlon64-sse3,atom_sse4_2,atom_sse4_2_movbe,barcelona,bdver1,bdver2,bdver3,bdver4,broadwell,btver1,btver2,cannonlake,cascadelake,cooperlake,core-avx-i,core-avx2,core2,core_2_duo_sse4_1,core_2_duo_ssse3,core_2nd_gen_avx,core_3rd_gen_avx,core_4th_gen_avx,core_4th_gen_avx_tsx,core_5th_gen_avx,core_5th_gen_avx_tsx,core_aes_pclmulqdq,core_i7_sse4_2,corei7,corei7-avx,generic,goldmont,goldmont-plus,goldmont_plus,grandridge,graniterapids,graniterapids-d,graniterapids_d,haswell,icelake-client,icelake-server,icelake_client,icelake_server,ivybridge,k8,k8-sse3,knl,knm,meteorlake,mic_avx512,native,nehalem,nocona,opteron,opteron-sse3,penryn,raptorlake,rocketlake,sandybridge,sapphirerapids,sierraforest,silvermont,skx,skylake,skylake-avx512,skylake_avx512,slm,tigerlake,tremont,westmere,x86-64,x86-64-v2,x86-64-v3,x86-64-v4,znver1,znver2,znver3,znver4"),
|
||||
// TargetArch_i386,
|
||||
str_lit("athlon,athlon-4,athlon-mp,athlon-tbird,athlon-xp,atom,bonnell,c3,c3-2,generic,geode,i386,i486,i586,i686,k6,k6-2,k6-3,lakemont,native,pentium,pentium-m,pentium-mmx,pentium2,pentium3,pentium3m,pentium4,pentium4m,pentium_4,pentium_4_sse3,pentium_ii,pentium_iii,pentium_iii_no_xmm_regs,pentium_m,pentium_mmx,pentium_pro,pentiumpro,prescott,winchip-c6,winchip2,yonah"),
|
||||
// TargetArch_arm32,
|
||||
str_lit("arm1020e,arm1020t,arm1022e,arm10e,arm10tdmi,arm1136j-s,arm1136jf-s,arm1156t2-s,arm1156t2f-s,arm1176jz-s,arm1176jzf-s,arm710t,arm720t,arm7tdmi,arm7tdmi-s,arm8,arm810,arm9,arm920,arm920t,arm922t,arm926ej-s,arm940t,arm946e-s,arm966e-s,arm968e-s,arm9e,arm9tdmi,cortex-a12,cortex-a15,cortex-a17,cortex-a32,cortex-a35,cortex-a5,cortex-a53,cortex-a55,cortex-a57,cortex-a7,cortex-a710,cortex-a72,cortex-a73,cortex-a75,cortex-a76,cortex-a76ae,cortex-a77,cortex-a78,cortex-a78c,cortex-a8,cortex-a9,cortex-m0,cortex-m0plus,cortex-m1,cortex-m23,cortex-m3,cortex-m33,cortex-m35p,cortex-m4,cortex-m55,cortex-m7,cortex-m85,cortex-r4,cortex-r4f,cortex-r5,cortex-r52,cortex-r7,cortex-r8,cortex-x1,cortex-x1c,cyclone,ep9312,exynos-m3,exynos-m4,exynos-m5,generic,iwmmxt,krait,kryo,mpcore,mpcorenovfp,native,neoverse-n1,neoverse-n2,neoverse-v1,sc000,sc300,strongarm,strongarm110,strongarm1100,strongarm1110,swift,xscale"),
|
||||
// TargetArch_arm64,
|
||||
str_lit("a64fx,ampere1,ampere1a,apple-a10,apple-a11,apple-a12,apple-a13,apple-a14,apple-a15,apple-a16,apple-a7,apple-a8,apple-a9,apple-latest,apple-m1,apple-m2,apple-s4,apple-s5,carmel,cortex-a34,cortex-a35,cortex-a510,cortex-a53,cortex-a55,cortex-a57,cortex-a65,cortex-a65ae,cortex-a710,cortex-a715,cortex-a72,cortex-a73,cortex-a75,cortex-a76,cortex-a76ae,cortex-a77,cortex-a78,cortex-a78c,cortex-r82,cortex-x1,cortex-x1c,cortex-x2,cortex-x3,cyclone,exynos-m3,exynos-m4,exynos-m5,falkor,generic,kryo,native,neoverse-512tvb,neoverse-e1,neoverse-n1,neoverse-n2,neoverse-v1,neoverse-v2,saphira,thunderx,thunderx2t99,thunderx3t110,thunderxt81,thunderxt83,thunderxt88,tsv110"),
|
||||
// TargetArch_wasm32,
|
||||
str_lit("generic"),
|
||||
// TargetArch_wasm64p32,
|
||||
str_lit("generic"),
|
||||
};
|
||||
|
||||
gb_global String target_endian_names[TargetEndian_COUNT] = {
|
||||
str_lit("little"),
|
||||
str_lit("big"),
|
||||
@@ -109,8 +126,6 @@ gb_global TargetEndianKind target_endians[TargetArch_COUNT] = {
|
||||
|
||||
gb_global String const ODIN_VERSION = str_lit(ODIN_VERSION_RAW);
|
||||
|
||||
|
||||
|
||||
struct TargetMetrics {
|
||||
TargetOsKind os;
|
||||
TargetArchKind arch;
|
||||
@@ -623,7 +638,6 @@ gb_internal TargetArchKind get_target_arch_from_string(String str) {
|
||||
return TargetArch_Invalid;
|
||||
}
|
||||
|
||||
|
||||
gb_internal bool is_excluded_target_filename(String name) {
|
||||
String original_name = name;
|
||||
name = remove_extension_from_path(name);
|
||||
|
||||
@@ -2088,6 +2088,8 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
|
||||
t = default_type(t);
|
||||
|
||||
add_type_info_type(c, t);
|
||||
GB_ASSERT(t_type_info_ptr != nullptr);
|
||||
add_type_info_type(c, t_type_info_ptr);
|
||||
|
||||
if (is_operand_value(o) && is_type_typeid(t)) {
|
||||
add_package_dependency(c, "runtime", "__type_info_of");
|
||||
@@ -5117,6 +5119,202 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
|
||||
}
|
||||
break;
|
||||
|
||||
case BuiltinProc_type_union_tag_type:
|
||||
{
|
||||
if (operand->mode != Addressing_Type) {
|
||||
error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
|
||||
operand->mode = Addressing_Invalid;
|
||||
operand->type = t_invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
Type *u = operand->type;
|
||||
|
||||
if (!is_type_union(u)) {
|
||||
error(operand->expr, "Expected a union type for '%.*s'", LIT(builtin_name));
|
||||
operand->mode = Addressing_Invalid;
|
||||
operand->type = t_invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
u = base_type(u);
|
||||
GB_ASSERT(u->kind == Type_Union);
|
||||
|
||||
operand->mode = Addressing_Type;
|
||||
operand->type = union_tag_type(u);
|
||||
}
|
||||
break;
|
||||
|
||||
case BuiltinProc_type_union_tag_offset:
|
||||
{
|
||||
if (operand->mode != Addressing_Type) {
|
||||
error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
|
||||
operand->mode = Addressing_Invalid;
|
||||
operand->type = t_invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
Type *u = operand->type;
|
||||
|
||||
if (!is_type_union(u)) {
|
||||
error(operand->expr, "Expected a union type for '%.*s'", LIT(builtin_name));
|
||||
operand->mode = Addressing_Invalid;
|
||||
operand->type = t_invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
u = base_type(u);
|
||||
GB_ASSERT(u->kind == Type_Union);
|
||||
|
||||
// NOTE(jakubtomsu): forces calculation of variant_block_size
|
||||
type_size_of(u);
|
||||
i64 tag_offset = u->Union.variant_block_size;
|
||||
GB_ASSERT(tag_offset > 0);
|
||||
|
||||
operand->mode = Addressing_Constant;
|
||||
operand->type = t_untyped_integer;
|
||||
operand->value = exact_value_i64(tag_offset);
|
||||
}
|
||||
break;
|
||||
|
||||
case BuiltinProc_type_union_base_tag_value:
|
||||
{
|
||||
if (operand->mode != Addressing_Type) {
|
||||
error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
|
||||
operand->mode = Addressing_Invalid;
|
||||
operand->type = t_invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
Type *u = operand->type;
|
||||
|
||||
if (!is_type_union(u)) {
|
||||
error(operand->expr, "Expected a union type for '%.*s'", LIT(builtin_name));
|
||||
operand->mode = Addressing_Invalid;
|
||||
operand->type = t_invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
u = base_type(u);
|
||||
GB_ASSERT(u->kind == Type_Union);
|
||||
|
||||
operand->mode = Addressing_Constant;
|
||||
operand->type = t_untyped_integer;
|
||||
operand->value = exact_value_i64(u->Union.kind == UnionType_no_nil ? 0 : 1);
|
||||
} break;
|
||||
|
||||
case BuiltinProc_type_union_variant_count:
|
||||
{
|
||||
if (operand->mode != Addressing_Type) {
|
||||
error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
|
||||
operand->mode = Addressing_Invalid;
|
||||
operand->type = t_invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
Type *u = operand->type;
|
||||
|
||||
if (!is_type_union(u)) {
|
||||
error(operand->expr, "Expected a union type for '%.*s'", LIT(builtin_name));
|
||||
operand->mode = Addressing_Invalid;
|
||||
operand->type = t_invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
u = base_type(u);
|
||||
GB_ASSERT(u->kind == Type_Union);
|
||||
|
||||
operand->mode = Addressing_Constant;
|
||||
operand->type = t_untyped_integer;
|
||||
operand->value = exact_value_i64(u->Union.variants.count);
|
||||
} break;
|
||||
|
||||
case BuiltinProc_type_variant_type_of:
|
||||
{
|
||||
if (operand->mode != Addressing_Type) {
|
||||
error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
|
||||
operand->mode = Addressing_Invalid;
|
||||
operand->type = t_invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
Type *u = operand->type;
|
||||
|
||||
if (!is_type_union(u)) {
|
||||
error(operand->expr, "Expected a union type for '%.*s'", LIT(builtin_name));
|
||||
operand->mode = Addressing_Invalid;
|
||||
operand->type = t_invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
u = base_type(u);
|
||||
GB_ASSERT(u->kind == Type_Union);
|
||||
Operand x = {};
|
||||
check_expr_or_type(c, &x, ce->args[1]);
|
||||
if (!is_type_integer(x.type) || x.mode != Addressing_Constant) {
|
||||
error(call, "Expected a constant integer for '%.*s", LIT(builtin_name));
|
||||
operand->mode = Addressing_Type;
|
||||
operand->type = t_invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
i64 index = big_int_to_i64(&x.value.value_integer);
|
||||
if (index < 0 || index >= u->Union.variants.count) {
|
||||
error(call, "Variant tag out of bounds index for '%.*s", LIT(builtin_name));
|
||||
operand->mode = Addressing_Type;
|
||||
operand->type = t_invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
operand->mode = Addressing_Type;
|
||||
operand->type = u->Union.variants[index];
|
||||
}
|
||||
break;
|
||||
|
||||
case BuiltinProc_type_variant_index_of:
|
||||
{
|
||||
if (operand->mode != Addressing_Type) {
|
||||
error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name));
|
||||
operand->mode = Addressing_Invalid;
|
||||
operand->type = t_invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
Type *u = operand->type;
|
||||
|
||||
if (!is_type_union(u)) {
|
||||
error(operand->expr, "Expected a union type for '%.*s'", LIT(builtin_name));
|
||||
operand->mode = Addressing_Invalid;
|
||||
operand->type = t_invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
Type *v = check_type(c, ce->args[1]);
|
||||
u = base_type(u);
|
||||
GB_ASSERT(u->kind == Type_Union);
|
||||
|
||||
i64 index = -1;
|
||||
for_array(i, u->Union.variants) {
|
||||
Type *vt = u->Union.variants[i];
|
||||
if (union_variant_index_types_equal(v, vt)) {
|
||||
index = i64(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index < 0) {
|
||||
error(operand->expr, "Expected a variant type for '%.*s'", LIT(builtin_name));
|
||||
operand->mode = Addressing_Invalid;
|
||||
operand->type = t_invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
operand->mode = Addressing_Constant;
|
||||
operand->type = t_untyped_integer;
|
||||
operand->value = exact_value_i64(index);
|
||||
}
|
||||
break;
|
||||
|
||||
case BuiltinProc_type_struct_field_count:
|
||||
operand->value = exact_value_i64(0);
|
||||
if (operand->mode != Addressing_Type) {
|
||||
|
||||
+2
-5
@@ -2339,7 +2339,7 @@ gb_internal void check_unary_expr(CheckerContext *c, Operand *o, Token op, Ast *
|
||||
ast_node(ue, UnaryExpr, node);
|
||||
if (ast_node_expect(ue->expr, Ast_IndexExpr)) {
|
||||
ast_node(ie, IndexExpr, ue->expr);
|
||||
Type *soa_type = type_of_expr(ie->expr);
|
||||
Type *soa_type = type_deref(type_of_expr(ie->expr));
|
||||
GB_ASSERT(is_type_soa_struct(soa_type));
|
||||
o->type = alloc_type_soa_pointer(soa_type);
|
||||
} else {
|
||||
@@ -5606,9 +5606,6 @@ gb_internal CallArgumentError check_call_arguments_internal(CheckerContext *c, A
|
||||
for (isize i = 0; i < pt->param_count; i++) {
|
||||
if (!visited[i]) {
|
||||
Entity *e = pt->params->Tuple.variables[i];
|
||||
if (is_blank_ident(e->token)) {
|
||||
continue;
|
||||
}
|
||||
if (e->kind == Entity_Variable) {
|
||||
if (e->Variable.param_value.kind != ParameterValue_Invalid) {
|
||||
ordered_operands[i].mode = Addressing_Value;
|
||||
@@ -7428,7 +7425,7 @@ gb_internal bool check_set_index_data(Operand *o, Type *t, bool indirection, i64
|
||||
*max_count = t->Struct.soa_count;
|
||||
}
|
||||
o->type = t->Struct.soa_elem;
|
||||
if (o->mode == Addressing_SoaVariable || o->mode == Addressing_Variable) {
|
||||
if (o->mode == Addressing_SoaVariable || o->mode == Addressing_Variable || indirection) {
|
||||
o->mode = Addressing_SoaVariable;
|
||||
} else {
|
||||
o->mode = Addressing_Value;
|
||||
|
||||
+10
-3
@@ -2211,9 +2211,14 @@ gb_internal void add_min_dep_type_info(Checker *c, Type *t) {
|
||||
Entity *e = entry.value;
|
||||
switch (bt->Struct.soa_kind) {
|
||||
case StructSoa_Dynamic:
|
||||
add_min_dep_type_info(c, t_type_info_ptr); // append_soa
|
||||
|
||||
add_min_dep_type_info(c, t_allocator);
|
||||
/*fallthrough*/
|
||||
case StructSoa_Slice:
|
||||
add_min_dep_type_info(c, t_int);
|
||||
add_min_dep_type_info(c, t_uint);
|
||||
/*fallthrough*/
|
||||
case StructSoa_Fixed:
|
||||
add_min_dep_type_info(c, alloc_type_pointer(e->type));
|
||||
break;
|
||||
@@ -6091,9 +6096,6 @@ gb_internal void check_parsed_files(Checker *c) {
|
||||
TIME_SECTION("calculate global init order");
|
||||
calculate_global_init_order(c);
|
||||
|
||||
TIME_SECTION("check test procedures");
|
||||
check_test_procedures(c);
|
||||
|
||||
TIME_SECTION("add type info for type definitions");
|
||||
add_type_info_for_type_definitions(c);
|
||||
check_merge_queues_into_arrays(c);
|
||||
@@ -6104,6 +6106,11 @@ gb_internal void check_parsed_files(Checker *c) {
|
||||
TIME_SECTION("generate minimum dependency set");
|
||||
generate_minimum_dependency_set(c, c->info.entry_point);
|
||||
|
||||
// NOTE(laytan): has to be ran after generate_minimum_dependency_set,
|
||||
// because that collects the test procedures.
|
||||
TIME_SECTION("check test procedures");
|
||||
check_test_procedures(c);
|
||||
|
||||
TIME_SECTION("check bodies have all been checked");
|
||||
check_unchecked_bodies(c);
|
||||
|
||||
|
||||
@@ -260,6 +260,12 @@ BuiltinProc__type_simple_boolean_end,
|
||||
BuiltinProc_type_is_specialization_of,
|
||||
|
||||
BuiltinProc_type_is_variant_of,
|
||||
BuiltinProc_type_union_tag_type,
|
||||
BuiltinProc_type_union_tag_offset,
|
||||
BuiltinProc_type_union_base_tag_value,
|
||||
BuiltinProc_type_union_variant_count,
|
||||
BuiltinProc_type_variant_type_of,
|
||||
BuiltinProc_type_variant_index_of,
|
||||
|
||||
BuiltinProc_type_struct_field_count,
|
||||
|
||||
@@ -557,7 +563,13 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
|
||||
|
||||
{STR_LIT("type_is_specialization_of"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
|
||||
{STR_LIT("type_is_variant_of"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("type_is_variant_of"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("type_union_tag_type"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("type_union_tag_offset"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("type_union_base_tag_value"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("type_union_variant_count"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("type_variant_type_of"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("type_variant_index_of"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
|
||||
{STR_LIT("type_struct_field_count"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
|
||||
|
||||
+27
-15
@@ -21,6 +21,25 @@
|
||||
#include "llvm_backend_stmt.cpp"
|
||||
#include "llvm_backend_proc.cpp"
|
||||
|
||||
char *get_default_microarchitecture() {
|
||||
char * default_march = "generic";
|
||||
if (build_context.metrics.arch == TargetArch_amd64) {
|
||||
// NOTE(bill): x86-64-v2 is more than enough for everyone
|
||||
//
|
||||
// x86-64: CMOV, CMPXCHG8B, FPU, FXSR, MMX, FXSR, SCE, SSE, SSE2
|
||||
// x86-64-v2: (close to Nehalem) CMPXCHG16B, LAHF-SAHF, POPCNT, SSE3, SSE4.1, SSE4.2, SSSE3
|
||||
// x86-64-v3: (close to Haswell) AVX, AVX2, BMI1, BMI2, F16C, FMA, LZCNT, MOVBE, XSAVE
|
||||
// x86-64-v4: AVX512F, AVX512BW, AVX512CD, AVX512DQ, AVX512VL
|
||||
if (ODIN_LLVM_MINIMUM_VERSION_12) {
|
||||
if (build_context.metrics.os == TargetOs_freestanding) {
|
||||
default_march = "x86-64";
|
||||
} else {
|
||||
default_march = "x86-64-v2";
|
||||
}
|
||||
}
|
||||
}
|
||||
return default_march;
|
||||
}
|
||||
|
||||
gb_internal void lb_add_foreign_library_path(lbModule *m, Entity *e) {
|
||||
if (e == nullptr) {
|
||||
@@ -2491,7 +2510,7 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
|
||||
}
|
||||
|
||||
char const *host_cpu_name = LLVMGetHostCPUName();
|
||||
char const *llvm_cpu = "generic";
|
||||
char const *llvm_cpu = get_default_microarchitecture();
|
||||
char const *llvm_features = "";
|
||||
if (build_context.microarch.len != 0) {
|
||||
if (build_context.microarch == "native") {
|
||||
@@ -2502,22 +2521,15 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
|
||||
if (gb_strcmp(llvm_cpu, host_cpu_name) == 0) {
|
||||
llvm_features = LLVMGetHostCPUFeatures();
|
||||
}
|
||||
} else if (build_context.metrics.arch == TargetArch_amd64) {
|
||||
// NOTE(bill): x86-64-v2 is more than enough for everyone
|
||||
//
|
||||
// x86-64: CMOV, CMPXCHG8B, FPU, FXSR, MMX, FXSR, SCE, SSE, SSE2
|
||||
// x86-64-v2: (close to Nehalem) CMPXCHG16B, LAHF-SAHF, POPCNT, SSE3, SSE4.1, SSE4.2, SSSE3
|
||||
// x86-64-v3: (close to Haswell) AVX, AVX2, BMI1, BMI2, F16C, FMA, LZCNT, MOVBE, XSAVE
|
||||
// x86-64-v4: AVX512F, AVX512BW, AVX512CD, AVX512DQ, AVX512VL
|
||||
if (ODIN_LLVM_MINIMUM_VERSION_12) {
|
||||
if (build_context.metrics.os == TargetOs_freestanding) {
|
||||
llvm_cpu = "x86-64";
|
||||
} else {
|
||||
llvm_cpu = "x86-64-v2";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(Jeroen): Uncomment to get the list of supported microarchitectures.
|
||||
/*
|
||||
if (build_context.microarch == "?") {
|
||||
string_set_add(&build_context.target_features_set, str_lit("+cpuhelp"));
|
||||
}
|
||||
*/
|
||||
|
||||
if (build_context.target_features_set.entries.count != 0) {
|
||||
llvm_features = target_features_set_to_cstring(permanent_allocator(), false);
|
||||
}
|
||||
|
||||
@@ -339,6 +339,8 @@ struct lbProcedure {
|
||||
bool in_multi_assignment;
|
||||
Array<LLVMValueRef> raw_input_parameters;
|
||||
|
||||
LLVMValueRef temp_callee_return_struct_memory;
|
||||
|
||||
Ast *curr_stmt;
|
||||
|
||||
Array<Scope *> scope_stack;
|
||||
@@ -550,6 +552,7 @@ gb_internal LLVMValueRef lb_call_intrinsic(lbProcedure *p, const char *name, LLV
|
||||
gb_internal void lb_mem_copy_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue len, bool is_volatile=false);
|
||||
gb_internal void lb_mem_copy_non_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue len, bool is_volatile=false);
|
||||
gb_internal LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, LLVMValueRef len, unsigned alignment, bool is_volatile);
|
||||
gb_internal LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, usize len, unsigned alignment, bool is_volatile);
|
||||
|
||||
gb_internal gb_inline i64 lb_max_zero_init_size(void) {
|
||||
return cast(i64)(4*build_context.int_size);
|
||||
|
||||
@@ -2939,6 +2939,12 @@ gb_internal lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) {
|
||||
} else if (is_type_soa_pointer(tv.type)) {
|
||||
ast_node(ie, IndexExpr, ue_expr);
|
||||
lbValue addr = lb_build_addr_ptr(p, ie->expr);
|
||||
|
||||
if (is_type_pointer(type_deref(addr.type))) {
|
||||
addr = lb_emit_load(p, addr);
|
||||
}
|
||||
GB_ASSERT(is_type_pointer(addr.type));
|
||||
|
||||
lbValue index = lb_build_expr(p, ie->index);
|
||||
|
||||
if (!build_context.no_bounds_check) {
|
||||
|
||||
@@ -1332,6 +1332,8 @@ gb_internal void lb_emit_store_union_variant(lbProcedure *p, lbValue parent, lbV
|
||||
Type *pt = base_type(type_deref(parent.type));
|
||||
GB_ASSERT(pt->kind == Type_Union);
|
||||
if (pt->Union.kind == UnionType_shared_nil) {
|
||||
GB_ASSERT(type_size_of(variant_type));
|
||||
|
||||
lbBlock *if_nil = lb_create_block(p, "shared_nil.if_nil");
|
||||
lbBlock *if_not_nil = lb_create_block(p, "shared_nil.if_not_nil");
|
||||
lbBlock *done = lb_create_block(p, "shared_nil.done");
|
||||
@@ -1353,9 +1355,13 @@ gb_internal void lb_emit_store_union_variant(lbProcedure *p, lbValue parent, lbV
|
||||
|
||||
|
||||
} else {
|
||||
lbValue underlying = lb_emit_conv(p, parent, alloc_type_pointer(variant_type));
|
||||
|
||||
lb_emit_store(p, underlying, variant);
|
||||
if (type_size_of(variant_type) == 0) {
|
||||
unsigned alignment = 1;
|
||||
lb_mem_zero_ptr_internal(p, parent.value, pt->Union.variant_block_size, alignment, false);
|
||||
} else {
|
||||
lbValue underlying = lb_emit_conv(p, parent, alloc_type_pointer(variant_type));
|
||||
lb_emit_store(p, underlying, variant);
|
||||
}
|
||||
lb_emit_store_union_variant_tag(p, parent, variant_type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1846,9 +1846,25 @@ gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res) {
|
||||
LLVMBuildRetVoid(p->builder);
|
||||
} else {
|
||||
LLVMValueRef ret_val = res.value;
|
||||
ret_val = OdinLLVMBuildTransmute(p, ret_val, p->abi_function_type->ret.type);
|
||||
if (p->abi_function_type->ret.cast_type != nullptr) {
|
||||
ret_val = OdinLLVMBuildTransmute(p, ret_val, p->abi_function_type->ret.cast_type);
|
||||
LLVMTypeRef ret_type = p->abi_function_type->ret.type;
|
||||
if (LLVMTypeRef cast_type = p->abi_function_type->ret.cast_type) {
|
||||
ret_type = cast_type;
|
||||
}
|
||||
|
||||
if (LLVMGetTypeKind(ret_type) == LLVMStructTypeKind) {
|
||||
LLVMTypeRef src_type = LLVMTypeOf(ret_val);
|
||||
|
||||
if (p->temp_callee_return_struct_memory == nullptr) {
|
||||
i64 max_align = gb_max(lb_alignof(ret_type), lb_alignof(src_type));
|
||||
p->temp_callee_return_struct_memory = llvm_alloca(p, ret_type, max_align);
|
||||
}
|
||||
// reuse the temp return value memory where possible
|
||||
LLVMValueRef ptr = p->temp_callee_return_struct_memory;
|
||||
LLVMValueRef nptr = LLVMBuildPointerCast(p->builder, ptr, LLVMPointerType(src_type, 0), "");
|
||||
LLVMBuildStore(p->builder, ret_val, nptr);
|
||||
ret_val = LLVMBuildLoad2(p->builder, ret_type, ptr, "");
|
||||
} else {
|
||||
ret_val = OdinLLVMBuildTransmute(p, ret_val, ret_type);
|
||||
}
|
||||
|
||||
lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr);
|
||||
|
||||
@@ -9,7 +9,12 @@ gb_internal isize lb_type_info_index(CheckerInfo *info, Type *type, bool err_on_
|
||||
}
|
||||
}
|
||||
if (err_on_not_found) {
|
||||
GB_PANIC("NOT FOUND lb_type_info_index %s @ index %td", type_to_string(type), index);
|
||||
gb_printf_err("NOT FOUND lb_type_info_index:\n\t%s\n\t@ index %td\n\tmax count: %u\nFound:\n", type_to_string(type), index, set->count);
|
||||
for (auto const &entry : *set) {
|
||||
isize type_info_index = entry.key;
|
||||
gb_printf_err("\t%s\n", type_to_string(info->type_info_types[type_info_index]));
|
||||
}
|
||||
GB_PANIC("NOT FOUND");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -57,6 +57,10 @@ gb_internal lbValue lb_correct_endianness(lbProcedure *p, lbValue value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
gb_internal LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, usize len, unsigned alignment, bool is_volatile) {
|
||||
return lb_mem_zero_ptr_internal(p, ptr, LLVMConstInt(lb_type(p->module, t_uint), len, false), alignment, is_volatile);
|
||||
}
|
||||
|
||||
gb_internal LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, LLVMValueRef len, unsigned alignment, bool is_volatile) {
|
||||
bool is_inlinable = false;
|
||||
|
||||
|
||||
+182
-132
@@ -199,19 +199,19 @@ gb_internal void print_usage_line(i32 indent, char const *fmt, ...) {
|
||||
}
|
||||
|
||||
gb_internal void usage(String argv0) {
|
||||
print_usage_line(0, "%.*s is a tool for managing Odin source code", LIT(argv0));
|
||||
print_usage_line(0, "%.*s is a tool for managing Odin source code.", LIT(argv0));
|
||||
print_usage_line(0, "Usage:");
|
||||
print_usage_line(1, "%.*s command [arguments]", LIT(argv0));
|
||||
print_usage_line(0, "Commands:");
|
||||
print_usage_line(1, "build compile directory of .odin files, as an executable.");
|
||||
print_usage_line(1, " one must contain the program's entry point, all must be in the same package.");
|
||||
print_usage_line(1, "run same as 'build', but also then runs the newly compiled executable.");
|
||||
print_usage_line(1, "check parse, and type check a directory of .odin files");
|
||||
print_usage_line(1, "strip-semicolon parse, type check, and remove unneeded semicolons from the entire program");
|
||||
print_usage_line(1, "test build and runs procedures with the attribute @(test) in the initial package");
|
||||
print_usage_line(1, "doc generate documentation on a directory of .odin files");
|
||||
print_usage_line(1, "version print version");
|
||||
print_usage_line(1, "report print information useful to reporting a bug");
|
||||
print_usage_line(1, "build Compiles directory of .odin files, as an executable.");
|
||||
print_usage_line(1, " One must contain the program's entry point, all must be in the same package.");
|
||||
print_usage_line(1, "run Same as 'build', but also then runs the newly compiled executable.");
|
||||
print_usage_line(1, "check Parses, and type checks a directory of .odin files.");
|
||||
print_usage_line(1, "strip-semicolon Parses, type checks, and removes unneeded semicolons from the entire program.");
|
||||
print_usage_line(1, "test Builds and runs procedures with the attribute @(test) in the initial package.");
|
||||
print_usage_line(1, "doc Generates documentation on a directory of .odin files.");
|
||||
print_usage_line(1, "version Prints version.");
|
||||
print_usage_line(1, "report Prints information useful to reporting a bug.");
|
||||
print_usage_line(0, "");
|
||||
print_usage_line(0, "For further details on a command, invoke command help:");
|
||||
print_usage_line(1, "e.g. `odin build -help` or `odin help build`");
|
||||
@@ -1580,45 +1580,45 @@ gb_internal void remove_temp_files(lbGenerator *gen) {
|
||||
|
||||
|
||||
gb_internal void print_show_help(String const arg0, String const &command) {
|
||||
print_usage_line(0, "%.*s is a tool for managing Odin source code", LIT(arg0));
|
||||
print_usage_line(0, "%.*s is a tool for managing Odin source code.", LIT(arg0));
|
||||
print_usage_line(0, "Usage:");
|
||||
print_usage_line(1, "%.*s %.*s [arguments]", LIT(arg0), LIT(command));
|
||||
print_usage_line(0, "");
|
||||
|
||||
if (command == "build") {
|
||||
print_usage_line(1, "build Compile directory of .odin files as an executable.");
|
||||
print_usage_line(1, "build Compiles directory of .odin files as an executable.");
|
||||
print_usage_line(2, "One must contain the program's entry point, all must be in the same package.");
|
||||
print_usage_line(2, "Use `-file` to build a single file instead.");
|
||||
print_usage_line(2, "Examples:");
|
||||
print_usage_line(3, "odin build . # Build package in current directory");
|
||||
print_usage_line(3, "odin build <dir> # Build package in <dir>");
|
||||
print_usage_line(3, "odin build filename.odin -file # Build single-file package, must contain entry point.");
|
||||
print_usage_line(3, "odin build . Builds package in current directory.");
|
||||
print_usage_line(3, "odin build <dir> Builds package in <dir>.");
|
||||
print_usage_line(3, "odin build filename.odin -file Builds single-file package, must contain entry point.");
|
||||
} else if (command == "run") {
|
||||
print_usage_line(1, "run Same as 'build', but also then runs the newly compiled executable.");
|
||||
print_usage_line(2, "Append an empty flag and then the args, '-- <args>', to specify args for the output.");
|
||||
print_usage_line(2, "Examples:");
|
||||
print_usage_line(3, "odin run . # Build and run package in current directory");
|
||||
print_usage_line(3, "odin run <dir> # Build and run package in <dir>");
|
||||
print_usage_line(3, "odin run filename.odin -file # Build and run single-file package, must contain entry point.");
|
||||
print_usage_line(3, "odin run . Builds and runs package in current directory.");
|
||||
print_usage_line(3, "odin run <dir> Builds and runs package in <dir>.");
|
||||
print_usage_line(3, "odin run filename.odin -file Builds and runs single-file package, must contain entry point.");
|
||||
} else if (command == "check") {
|
||||
print_usage_line(1, "check Parse and type check directory of .odin files");
|
||||
print_usage_line(1, "check Parses and type checks directory of .odin files.");
|
||||
print_usage_line(2, "Examples:");
|
||||
print_usage_line(3, "odin check . # Type check package in current directory");
|
||||
print_usage_line(3, "odin check <dir> # Type check package in <dir>");
|
||||
print_usage_line(3, "odin check filename.odin -file # Type check single-file package, must contain entry point.");
|
||||
print_usage_line(3, "odin check . Type checks package in current directory.");
|
||||
print_usage_line(3, "odin check <dir> Type checks package in <dir>.");
|
||||
print_usage_line(3, "odin check filename.odin -file Type checks single-file package, must contain entry point.");
|
||||
} else if (command == "test") {
|
||||
print_usage_line(1, "test Build and runs procedures with the attribute @(test) in the initial package");
|
||||
print_usage_line(1, "test Builds and runs procedures with the attribute @(test) in the initial package.");
|
||||
} else if (command == "doc") {
|
||||
print_usage_line(1, "doc generate documentation from a directory of .odin files");
|
||||
print_usage_line(1, "doc Generates documentation from a directory of .odin files.");
|
||||
print_usage_line(2, "Examples:");
|
||||
print_usage_line(3, "odin doc . # Generate documentation on package in current directory");
|
||||
print_usage_line(3, "odin doc <dir> # Generate documentation on package in <dir>");
|
||||
print_usage_line(3, "odin doc filename.odin -file # Generate documentation on single-file package.");
|
||||
print_usage_line(3, "odin doc . Generates documentation on package in current directory.");
|
||||
print_usage_line(3, "odin doc <dir> Generates documentation on package in <dir>.");
|
||||
print_usage_line(3, "odin doc filename.odin -file Generates documentation on single-file package.");
|
||||
} else if (command == "version") {
|
||||
print_usage_line(1, "version print version");
|
||||
print_usage_line(1, "version Prints version.");
|
||||
} else if (command == "strip-semicolon") {
|
||||
print_usage_line(1, "strip-semicolon");
|
||||
print_usage_line(2, "Parse and type check .odin file(s) and then remove unneeded semicolons from the entire project");
|
||||
print_usage_line(2, "Parses and type checks .odin file(s) and then removes unneeded semicolons from the entire project.");
|
||||
}
|
||||
|
||||
bool doc = command == "doc";
|
||||
@@ -1642,311 +1642,318 @@ gb_internal void print_show_help(String const arg0, String const &command) {
|
||||
|
||||
if (doc) {
|
||||
print_usage_line(1, "-short");
|
||||
print_usage_line(2, "Show shortened documentation for the packages");
|
||||
print_usage_line(2, "Shows shortened documentation for the packages.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-all-packages");
|
||||
print_usage_line(2, "Generates documentation for all packages used in the current project");
|
||||
print_usage_line(2, "Generates documentation for all packages used in the current project.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-doc-format");
|
||||
print_usage_line(2, "Generates documentation as the .odin-doc format (useful for external tooling)");
|
||||
print_usage_line(2, "Generates documentation as the .odin-doc format (useful for external tooling).");
|
||||
print_usage_line(0, "");
|
||||
}
|
||||
|
||||
if (run_or_build) {
|
||||
print_usage_line(1, "-out:<filepath>");
|
||||
print_usage_line(2, "Set the file name of the outputted executable");
|
||||
print_usage_line(2, "Sets the file name of the outputted executable.");
|
||||
print_usage_line(2, "Example: -out:foo.exe");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-o:<string>");
|
||||
print_usage_line(2, "Set the optimization mode for compilation");
|
||||
print_usage_line(2, "Sets the optimization mode for compilation.");
|
||||
print_usage_line(2, "Available options:");
|
||||
print_usage_line(3, "-o:none");
|
||||
print_usage_line(3, "-o:minimal");
|
||||
print_usage_line(3, "-o:size");
|
||||
print_usage_line(3, "-o:speed");
|
||||
if (LB_USE_NEW_PASS_SYSTEM) {
|
||||
print_usage_line(2, "Accepted values: none, minimal, size, speed, aggressive");
|
||||
} else {
|
||||
print_usage_line(2, "Accepted values: none, minimal, size, speed");
|
||||
print_usage_line(3, "-o:aggressive");
|
||||
}
|
||||
print_usage_line(2, "Example: -o:speed");
|
||||
print_usage_line(2, "The default is -o:minimal");
|
||||
print_usage_line(2, "The default is -o:minimal.");
|
||||
print_usage_line(0, "");
|
||||
}
|
||||
|
||||
if (check) {
|
||||
print_usage_line(1, "-show-timings");
|
||||
print_usage_line(2, "Shows basic overview of the timings of different stages within the compiler in milliseconds");
|
||||
print_usage_line(2, "Shows basic overview of the timings of different stages within the compiler in milliseconds.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-show-more-timings");
|
||||
print_usage_line(2, "Shows an advanced overview of the timings of different stages within the compiler in milliseconds");
|
||||
print_usage_line(2, "Shows an advanced overview of the timings of different stages within the compiler in milliseconds.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-show-system-calls");
|
||||
print_usage_line(2, "Prints the whole command and arguments for calls to external tools like linker and assembler");
|
||||
print_usage_line(2, "Prints the whole command and arguments for calls to external tools like linker and assembler.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-export-timings:<format>");
|
||||
print_usage_line(2, "Export timings to one of a few formats. Requires `-show-timings` or `-show-more-timings`");
|
||||
print_usage_line(2, "Exports timings to one of a few formats. Requires `-show-timings` or `-show-more-timings`.");
|
||||
print_usage_line(2, "Available options:");
|
||||
print_usage_line(3, "-export-timings:json Export compile time stats to JSON");
|
||||
print_usage_line(3, "-export-timings:csv Export compile time stats to CSV");
|
||||
print_usage_line(3, "-export-timings:json Exports compile time stats to JSON.");
|
||||
print_usage_line(3, "-export-timings:csv Exports compile time stats to CSV.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-export-timings-file:<filename>");
|
||||
print_usage_line(2, "Specify the filename for `-export-timings`");
|
||||
print_usage_line(2, "Specifies the filename for `-export-timings`.");
|
||||
print_usage_line(2, "Example: -export-timings-file:timings.json");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-thread-count:<integer>");
|
||||
print_usage_line(2, "Override the number of threads the compiler will use to compile with");
|
||||
print_usage_line(2, "Overrides the number of threads the compiler will use to compile with.");
|
||||
print_usage_line(2, "Example: -thread-count:2");
|
||||
print_usage_line(0, "");
|
||||
}
|
||||
|
||||
if (check_only) {
|
||||
print_usage_line(1, "-show-unused");
|
||||
print_usage_line(2, "Shows unused package declarations within the current project");
|
||||
print_usage_line(2, "Shows unused package declarations within the current project.");
|
||||
print_usage_line(0, "");
|
||||
print_usage_line(1, "-show-unused-with-location");
|
||||
print_usage_line(2, "Shows unused package declarations within the current project with the declarations source location");
|
||||
print_usage_line(2, "Shows unused package declarations within the current project with the declarations source location.");
|
||||
print_usage_line(0, "");
|
||||
}
|
||||
|
||||
if (run_or_build) {
|
||||
print_usage_line(1, "-keep-temp-files");
|
||||
print_usage_line(2, "Keeps the temporary files generated during compilation");
|
||||
print_usage_line(2, "Keeps the temporary files generated during compilation.");
|
||||
print_usage_line(0, "");
|
||||
} else if (strip_semicolon) {
|
||||
print_usage_line(1, "-keep-temp-files");
|
||||
print_usage_line(2, "Keeps the temporary files generated during stripping the unneeded semicolons from files");
|
||||
print_usage_line(2, "Keeps the temporary files generated during stripping the unneeded semicolons from files.");
|
||||
print_usage_line(0, "");
|
||||
}
|
||||
|
||||
if (check) {
|
||||
print_usage_line(1, "-collection:<name>=<filepath>");
|
||||
print_usage_line(2, "Defines a library collection used for imports");
|
||||
print_usage_line(2, "Defines a library collection used for imports.");
|
||||
print_usage_line(2, "Example: -collection:shared=dir/to/shared");
|
||||
print_usage_line(2, "Usage in Code:");
|
||||
print_usage_line(3, "import \"shared:foo\"");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-define:<name>=<value>");
|
||||
print_usage_line(2, "Defines a scalar boolean, integer or string as global constant");
|
||||
print_usage_line(2, "Defines a scalar boolean, integer or string as global constant.");
|
||||
print_usage_line(2, "Example: -define:SPAM=123");
|
||||
print_usage_line(2, "To use: #config(SPAM, default_value)");
|
||||
print_usage_line(2, "Usage in code:");
|
||||
print_usage_line(3, "#config(SPAM, default_value)");
|
||||
print_usage_line(0, "");
|
||||
}
|
||||
|
||||
if (build) {
|
||||
print_usage_line(1, "-build-mode:<mode>");
|
||||
print_usage_line(2, "Sets the build mode");
|
||||
print_usage_line(2, "Sets the build mode.");
|
||||
print_usage_line(2, "Available options:");
|
||||
print_usage_line(3, "-build-mode:exe Build as an executable");
|
||||
print_usage_line(3, "-build-mode:dll Build as a dynamically linked library");
|
||||
print_usage_line(3, "-build-mode:shared Build as a dynamically linked library");
|
||||
print_usage_line(3, "-build-mode:obj Build as an object file");
|
||||
print_usage_line(3, "-build-mode:object Build as an object file");
|
||||
print_usage_line(3, "-build-mode:assembly Build as an assembly file");
|
||||
print_usage_line(3, "-build-mode:assembler Build as an assembly file");
|
||||
print_usage_line(3, "-build-mode:asm Build as an assembly file");
|
||||
print_usage_line(3, "-build-mode:llvm-ir Build as an LLVM IR file");
|
||||
print_usage_line(3, "-build-mode:llvm Build as an LLVM IR file");
|
||||
print_usage_line(3, "-build-mode:exe Builds as an executable.");
|
||||
print_usage_line(3, "-build-mode:dll Builds as a dynamically linked library.");
|
||||
print_usage_line(3, "-build-mode:shared Builds as a dynamically linked library.");
|
||||
print_usage_line(3, "-build-mode:obj Builds as an object file.");
|
||||
print_usage_line(3, "-build-mode:object Builds as an object file.");
|
||||
print_usage_line(3, "-build-mode:assembly Builds as an assembly file.");
|
||||
print_usage_line(3, "-build-mode:assembler Builds as an assembly file.");
|
||||
print_usage_line(3, "-build-mode:asm Builds as an assembly file.");
|
||||
print_usage_line(3, "-build-mode:llvm-ir Builds as an LLVM IR file.");
|
||||
print_usage_line(3, "-build-mode:llvm Builds as an LLVM IR file.");
|
||||
print_usage_line(0, "");
|
||||
}
|
||||
|
||||
if (check) {
|
||||
print_usage_line(1, "-target:<string>");
|
||||
print_usage_line(2, "Sets the target for the executable to be built in");
|
||||
print_usage_line(2, "Sets the target for the executable to be built in.");
|
||||
print_usage_line(0, "");
|
||||
}
|
||||
|
||||
if (run_or_build) {
|
||||
print_usage_line(1, "-debug");
|
||||
print_usage_line(2, "Enabled debug information, and defines the global constant ODIN_DEBUG to be 'true'");
|
||||
print_usage_line(2, "Enables debug information, and defines the global constant ODIN_DEBUG to be 'true'.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-disable-assert");
|
||||
print_usage_line(2, "Disable the code generation of the built-in run-time 'assert' procedure, and defines the global constant ODIN_DISABLE_ASSERT to be 'true'");
|
||||
print_usage_line(2, "Disables the code generation of the built-in run-time 'assert' procedure, and defines the global constant ODIN_DISABLE_ASSERT to be 'true'.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-no-bounds-check");
|
||||
print_usage_line(2, "Disables bounds checking program wide");
|
||||
print_usage_line(2, "Disables bounds checking program wide.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-no-crt");
|
||||
print_usage_line(2, "Disables automatic linking with the C Run Time");
|
||||
print_usage_line(2, "Disables automatic linking with the C Run Time.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-no-thread-local");
|
||||
print_usage_line(2, "Ignore @thread_local attribute, effectively treating the program as if it is single-threaded");
|
||||
print_usage_line(2, "Ignores @thread_local attribute, effectively treating the program as if it is single-threaded.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-lld");
|
||||
print_usage_line(2, "Use the LLD linker rather than the default");
|
||||
print_usage_line(2, "Uses the LLD linker rather than the default.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-use-separate-modules");
|
||||
print_usage_line(1, "[EXPERIMENTAL]");
|
||||
print_usage_line(2, "The backend generates multiple build units which are then linked together");
|
||||
print_usage_line(2, "Normally, a single build unit is generated for a standard project");
|
||||
print_usage_line(2, "The backend generates multiple build units which are then linked together.");
|
||||
print_usage_line(2, "Normally, a single build unit is generated for a standard project.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
}
|
||||
|
||||
if (check) {
|
||||
print_usage_line(1, "-no-threaded-checker");
|
||||
print_usage_line(2, "Disabled multithreading in the semantic checker stage");
|
||||
print_usage_line(2, "Disables multithreading in the semantic checker stage.");
|
||||
print_usage_line(0, "");
|
||||
}
|
||||
|
||||
if (check) {
|
||||
print_usage_line(1, "-vet");
|
||||
print_usage_line(2, "Do extra checks on the code");
|
||||
print_usage_line(2, "Does extra checks on the code.");
|
||||
print_usage_line(2, "Extra checks include:");
|
||||
print_usage_line(2, "-vet-unused");
|
||||
print_usage_line(2, "-vet-shadowing");
|
||||
print_usage_line(2, "-vet-using-stmt");
|
||||
print_usage_line(3, "-vet-unused");
|
||||
print_usage_line(3, "-vet-shadowing");
|
||||
print_usage_line(3, "-vet-using-stmt");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-vet-unused");
|
||||
print_usage_line(2, "Checks for unused declarations");
|
||||
print_usage_line(2, "Checks for unused declarations.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-vet-shadowing");
|
||||
print_usage_line(2, "Checks for variable shadowing within procedures");
|
||||
print_usage_line(2, "Checks for variable shadowing within procedures.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-vet-using-stmt");
|
||||
print_usage_line(2, "Checks for the use of 'using' as a statement");
|
||||
print_usage_line(2, "'using' is considered bad practice outside of immediate refactoring");
|
||||
print_usage_line(2, "Checks for the use of 'using' as a statement.");
|
||||
print_usage_line(2, "'using' is considered bad practice outside of immediate refactoring.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-vet-using-param");
|
||||
print_usage_line(2, "Checks for the use of 'using' on procedure parameters");
|
||||
print_usage_line(2, "'using' is considered bad practice outside of immediate refactoring");
|
||||
print_usage_line(2, "Checks for the use of 'using' on procedure parameters.");
|
||||
print_usage_line(2, "'using' is considered bad practice outside of immediate refactoring.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-vet-style");
|
||||
print_usage_line(2, "Errs on missing trailing commas followed by a newline");
|
||||
print_usage_line(2, "Errs on deprecated syntax");
|
||||
print_usage_line(2, "Does not err on unneeded tokens (unlike -strict-style)");
|
||||
print_usage_line(2, "Errs on missing trailing commas followed by a newline.");
|
||||
print_usage_line(2, "Errs on deprecated syntax.");
|
||||
print_usage_line(2, "Does not err on unneeded tokens (unlike -strict-style).");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-vet-semicolon");
|
||||
print_usage_line(2, "Errs on unneeded semicolons");
|
||||
print_usage_line(2, "Errs on unneeded semicolons.");
|
||||
print_usage_line(0, "");
|
||||
}
|
||||
|
||||
if (check) {
|
||||
print_usage_line(1, "-ignore-unknown-attributes");
|
||||
print_usage_line(2, "Ignores unknown attributes");
|
||||
print_usage_line(2, "This can be used with metaprogramming tools");
|
||||
print_usage_line(2, "Ignores unknown attributes.");
|
||||
print_usage_line(2, "This can be used with metaprogramming tools.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
if (command != "test") {
|
||||
print_usage_line(1, "-no-entry-point");
|
||||
print_usage_line(2, "Removes default requirement of an entry point (e.g. main procedure)");
|
||||
print_usage_line(2, "Removes default requirement of an entry point (e.g. main procedure).");
|
||||
print_usage_line(0, "");
|
||||
}
|
||||
}
|
||||
|
||||
if (test_only) {
|
||||
print_usage_line(1, "-test-name:<string>");
|
||||
print_usage_line(2, "Run specific test only by name");
|
||||
print_usage_line(2, "Runs specific test only by name.");
|
||||
print_usage_line(0, "");
|
||||
}
|
||||
|
||||
if (run_or_build) {
|
||||
print_usage_line(1, "-minimum-os-version:<string>");
|
||||
print_usage_line(2, "Sets the minimum OS version targeted by the application");
|
||||
print_usage_line(2, "e.g. -minimum-os-version:12.0.0");
|
||||
print_usage_line(2, "(Only used when target is Darwin)");
|
||||
print_usage_line(2, "Sets the minimum OS version targeted by the application.");
|
||||
print_usage_line(2, "Example: -minimum-os-version:12.0.0");
|
||||
print_usage_line(2, "(Only used when target is Darwin.)");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-extra-linker-flags:<string>");
|
||||
print_usage_line(2, "Adds extra linker specific flags in a string");
|
||||
print_usage_line(2, "Adds extra linker specific flags in a string.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-extra-assembler-flags:<string>");
|
||||
print_usage_line(2, "Adds extra assembler specific flags in a string");
|
||||
print_usage_line(2, "Adds extra assembler specific flags in a string.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-microarch:<string>");
|
||||
print_usage_line(2, "Specifies the specific micro-architecture for the build in a string");
|
||||
print_usage_line(2, "Specifies the specific micro-architecture for the build in a string.");
|
||||
print_usage_line(2, "Examples:");
|
||||
print_usage_line(3, "-microarch:sandybridge");
|
||||
print_usage_line(3, "-microarch:native");
|
||||
print_usage_line(3, "-microarch:? for a list");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-reloc-mode:<string>");
|
||||
print_usage_line(2, "Specifies the reloc mode");
|
||||
print_usage_line(2, "Options:");
|
||||
print_usage_line(3, "default");
|
||||
print_usage_line(3, "static");
|
||||
print_usage_line(3, "pic");
|
||||
print_usage_line(3, "dynamic-no-pic");
|
||||
print_usage_line(2, "Specifies the reloc mode.");
|
||||
print_usage_line(2, "Available options:");
|
||||
print_usage_line(3, "-reloc-mode:default");
|
||||
print_usage_line(3, "-reloc-mode:static");
|
||||
print_usage_line(3, "-reloc-mode:pic");
|
||||
print_usage_line(3, "-reloc-mode:dynamic-no-pic");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-disable-red-zone");
|
||||
print_usage_line(2, "Disable red zone on a supported freestanding target");
|
||||
print_usage_line(2, "Disables red zone on a supported freestanding target.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-dynamic-map-calls");
|
||||
print_usage_line(2, "Use dynamic map calls to minimize code generation at the cost of runtime execution");
|
||||
print_usage_line(2, "Uses dynamic map calls to minimize code generation at the cost of runtime execution.");
|
||||
print_usage_line(0, "");
|
||||
}
|
||||
|
||||
if (check) {
|
||||
print_usage_line(1, "-disallow-do");
|
||||
print_usage_line(2, "Disallows the 'do' keyword in the project");
|
||||
print_usage_line(2, "Disallows the 'do' keyword in the project.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-default-to-nil-allocator");
|
||||
print_usage_line(2, "Sets the default allocator to be the nil_allocator, an allocator which does nothing");
|
||||
print_usage_line(2, "Sets the default allocator to be the nil_allocator, an allocator which does nothing.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-strict-style");
|
||||
print_usage_line(2, "Errs on unneeded tokens, such as unneeded semicolons");
|
||||
print_usage_line(2, "Errs on missing trailing commas followed by a newline");
|
||||
print_usage_line(2, "Errs on deprecated syntax");
|
||||
print_usage_line(2, "Errs on unneeded tokens, such as unneeded semicolons.");
|
||||
print_usage_line(2, "Errs on missing trailing commas followed by a newline.");
|
||||
print_usage_line(2, "Errs on deprecated syntax.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-ignore-warnings");
|
||||
print_usage_line(2, "Ignores warning messages");
|
||||
print_usage_line(2, "Ignores warning messages.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-warnings-as-errors");
|
||||
print_usage_line(2, "Treats warning messages as error messages");
|
||||
print_usage_line(2, "Treats warning messages as error messages.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-terse-errors");
|
||||
print_usage_line(2, "Prints a terse error message without showing the code on that line and the location in that line");
|
||||
print_usage_line(2, "Prints a terse error message without showing the code on that line and the location in that line.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-error-pos-style:<string>");
|
||||
print_usage_line(2, "Options are 'unix', 'odin' and 'default' (odin)");
|
||||
print_usage_line(2, "'odin' file/path(45:3)");
|
||||
print_usage_line(2, "'unix' file/path:45:3:");
|
||||
print_usage_line(2, "Available options:");
|
||||
print_usage_line(3, "-error-pos-style:unix file/path:45:3:");
|
||||
print_usage_line(3, "-error-pos-style:odin file/path(45:3)");
|
||||
print_usage_line(3, "-error-pos-style:default (Defaults to 'odin'.)");
|
||||
print_usage_line(0, "");
|
||||
|
||||
|
||||
print_usage_line(1, "-max-error-count:<integer>");
|
||||
print_usage_line(2, "Set the maximum number of errors that can be displayed before the compiler terminates");
|
||||
print_usage_line(2, "Must be an integer >0");
|
||||
print_usage_line(2, "If not set, the default max error count is %d", DEFAULT_MAX_ERROR_COLLECTOR_COUNT);
|
||||
print_usage_line(2, "Sets the maximum number of errors that can be displayed before the compiler terminates.");
|
||||
print_usage_line(2, "Must be an integer >0.");
|
||||
print_usage_line(2, "If not set, the default max error count is %d.", DEFAULT_MAX_ERROR_COLLECTOR_COUNT);
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-foreign-error-procedures");
|
||||
print_usage_line(2, "States that the error procedues used in the runtime are defined in a separate translation unit");
|
||||
print_usage_line(2, "States that the error procedures used in the runtime are defined in a separate translation unit.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
}
|
||||
|
||||
if (run_or_build) {
|
||||
print_usage_line(1, "-sanitize:<string>");
|
||||
print_usage_line(1, "Enables sanitization analysis");
|
||||
print_usage_line(1, "Options are 'address', 'memory', and 'thread'");
|
||||
print_usage_line(1, "NOTE: This flag can be used multiple times");
|
||||
print_usage_line(2, "Enables sanitization analysis.");
|
||||
print_usage_line(2, "Available options:");
|
||||
print_usage_line(3, "-sanitize:address");
|
||||
print_usage_line(3, "-sanitize:memory");
|
||||
print_usage_line(3, "-sanitize:thread");
|
||||
print_usage_line(2, "NOTE: This flag can be used multiple times.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
}
|
||||
@@ -1955,27 +1962,27 @@ gb_internal void print_show_help(String const arg0, String const &command) {
|
||||
#if defined(GB_SYSTEM_WINDOWS)
|
||||
print_usage_line(1, "-ignore-vs-search");
|
||||
print_usage_line(2, "[Windows only]");
|
||||
print_usage_line(2, "Ignores the Visual Studio search for library paths");
|
||||
print_usage_line(2, "Ignores the Visual Studio search for library paths.");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-resource:<filepath>");
|
||||
print_usage_line(2, "[Windows only]");
|
||||
print_usage_line(2, "Defines the resource file for the executable");
|
||||
print_usage_line(2, "Defines the resource file for the executable.");
|
||||
print_usage_line(2, "Example: -resource:path/to/file.rc");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-pdb-name:<filepath>");
|
||||
print_usage_line(2, "[Windows only]");
|
||||
print_usage_line(2, "Defines the generated PDB name when -debug is enabled");
|
||||
print_usage_line(2, "Defines the generated PDB name when -debug is enabled.");
|
||||
print_usage_line(2, "Example: -pdb-name:different.pdb");
|
||||
print_usage_line(0, "");
|
||||
|
||||
print_usage_line(1, "-subsystem:<option>");
|
||||
print_usage_line(2, "[Windows only]");
|
||||
print_usage_line(2, "Defines the subsystem for the application");
|
||||
print_usage_line(2, "Defines the subsystem for the application.");
|
||||
print_usage_line(2, "Available options:");
|
||||
print_usage_line(3, "console");
|
||||
print_usage_line(3, "windows");
|
||||
print_usage_line(3, "-subsystem:console");
|
||||
print_usage_line(3, "-subsystem:windows");
|
||||
print_usage_line(0, "");
|
||||
|
||||
#endif
|
||||
@@ -2518,6 +2525,49 @@ int main(int arg_count, char const **arg_ptr) {
|
||||
// return 1;
|
||||
// }
|
||||
|
||||
// Check chosen microarchitecture. If not found or ?, print list.
|
||||
bool print_microarch_list = true;
|
||||
if (build_context.microarch.len == 0) {
|
||||
// Autodetect, no need to print list.
|
||||
print_microarch_list = false;
|
||||
} else {
|
||||
String march_list = target_microarch_list[build_context.metrics.arch];
|
||||
String_Iterator it = {march_list, 0};
|
||||
for (;;) {
|
||||
String str = string_split_iterator(&it, ',');
|
||||
if (str == "") break;
|
||||
if (str == build_context.microarch) {
|
||||
// Found matching microarch
|
||||
print_microarch_list = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (print_microarch_list) {
|
||||
if (build_context.microarch != "?") {
|
||||
gb_printf("Unknown microarchitecture '%.*s'.\n", LIT(build_context.microarch));
|
||||
}
|
||||
gb_printf("Possible -microarch values for target %.*s are:\n", LIT(target_arch_names[build_context.metrics.arch]));
|
||||
gb_printf("\n");
|
||||
|
||||
String march_list = target_microarch_list[build_context.metrics.arch];
|
||||
String_Iterator it = {march_list, 0};
|
||||
|
||||
String default_march = make_string_c(get_default_microarchitecture());
|
||||
|
||||
for (;;) {
|
||||
String str = string_split_iterator(&it, ',');
|
||||
if (str == "") break;
|
||||
if (str == default_march) {
|
||||
gb_printf("\t%.*s (default)\n", LIT(str));
|
||||
} else {
|
||||
gb_printf("\t%.*s\n", LIT(str));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Set and check build paths...
|
||||
if (!init_build_paths(init_filename)) {
|
||||
return 1;
|
||||
|
||||
+25
-1
@@ -10,6 +10,10 @@ struct String {
|
||||
return text[i];
|
||||
}
|
||||
};
|
||||
struct String_Iterator {
|
||||
String const &str;
|
||||
isize pos;
|
||||
};
|
||||
// NOTE(bill): used for printf style arguments
|
||||
#define LIT(x) ((int)(x).len), (x).text
|
||||
#if defined(GB_COMPILER_MSVC) && _MSC_VER < 1700
|
||||
@@ -201,11 +205,31 @@ gb_internal gb_inline String string_trim_starts_with(String const &s, String con
|
||||
}
|
||||
|
||||
|
||||
gb_internal String string_split_iterator(String_Iterator *it, const char sep) {
|
||||
isize start = it->pos;
|
||||
isize end = it->str.len;
|
||||
|
||||
if (start == end) {
|
||||
return str_lit("");
|
||||
}
|
||||
|
||||
isize i = start;
|
||||
for (; i < it->str.len; i++) {
|
||||
if (it->str[i] == sep) {
|
||||
String res = substring(it->str, start, i);
|
||||
it->pos += res.len + 1;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
it->pos = end;
|
||||
return substring(it->str, start, end);
|
||||
}
|
||||
|
||||
gb_internal gb_inline isize string_extension_position(String const &str) {
|
||||
isize dot_pos = -1;
|
||||
isize i = str.len;
|
||||
while (i --> 0) {
|
||||
if (str[i] == GB_PATH_SEPARATOR)
|
||||
if (str[i] == '\\' || str[i] == '/')
|
||||
break;
|
||||
if (str[i] == '.') {
|
||||
dot_pos = i;
|
||||
|
||||
+1
-1
@@ -660,7 +660,7 @@ gb_internal void futex_broadcast(Futex *addr) {
|
||||
gb_internal void futex_wait(Futex *addr, Footex val) {
|
||||
for (;;) {
|
||||
int ret = _umtx_op(addr, UMTX_OP_WAIT_UINT, val, 0, NULL);
|
||||
if (ret == 0) {
|
||||
if (ret == -1) {
|
||||
if (errno == ETIMEDOUT || errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
+26
-3
@@ -1,9 +1,26 @@
|
||||
ODIN=../../odin
|
||||
PYTHON=$(shell which python3)
|
||||
|
||||
all: download_test_assets image_test compress_test strings_test hash_test crypto_test noise_test encoding_test \
|
||||
math_test linalg_glsl_math_test filepath_test reflect_test os_exit_test i18n_test match_test c_libc_test net_test \
|
||||
fmt_test
|
||||
all: c_libc_test \
|
||||
compress_test \
|
||||
crypto_test \
|
||||
download_test_assets \
|
||||
encoding_test \
|
||||
filepath_test \
|
||||
fmt_test \
|
||||
hash_test \
|
||||
i18n_test \
|
||||
image_test \
|
||||
linalg_glsl_math_test \
|
||||
match_test \
|
||||
math_test \
|
||||
net_test \
|
||||
noise_test \
|
||||
os_exit_test \
|
||||
reflect_test \
|
||||
slice_test \
|
||||
strings_test \
|
||||
thread_test
|
||||
|
||||
download_test_assets:
|
||||
$(PYTHON) download_assets.py
|
||||
@@ -44,6 +61,9 @@ filepath_test:
|
||||
reflect_test:
|
||||
$(ODIN) run reflect/test_core_reflect.odin -file -collection:tests=.. -out:test_core_reflect
|
||||
|
||||
slice_test:
|
||||
$(ODIN) run slice/test_core_slice.odin -file -out:test_core_slice
|
||||
|
||||
os_exit_test:
|
||||
$(ODIN) run os/test_core_os_exit.odin -file -out:test_core_os_exit && exit 1 || exit 0
|
||||
|
||||
@@ -61,3 +81,6 @@ net_test:
|
||||
|
||||
fmt_test:
|
||||
$(ODIN) run fmt -out:test_core_fmt
|
||||
|
||||
thread_test:
|
||||
$(ODIN) run thread -out:test_core_thread
|
||||
|
||||
@@ -66,6 +66,11 @@ echo Running core:reflect tests
|
||||
echo ---
|
||||
%PATH_TO_ODIN% run reflect %COMMON% %COLLECTION% -out:test_core_reflect.exe || exit /b
|
||||
|
||||
echo ---
|
||||
echo Running core:slice tests
|
||||
echo ---
|
||||
%PATH_TO_ODIN% run slice %COMMON% -out:test_core_slice.exe || exit /b
|
||||
|
||||
echo ---
|
||||
echo Running core:text/i18n tests
|
||||
echo ---
|
||||
@@ -85,3 +90,8 @@ echo ---
|
||||
echo Running core:container tests
|
||||
echo ---
|
||||
%PATH_TO_ODIN% run container %COMMON% %COLLECTION% -out:test_core_container.exe || exit /b
|
||||
|
||||
echo ---
|
||||
echo Running core:thread tests
|
||||
echo ---
|
||||
%PATH_TO_ODIN% run thread %COMMON% %COLLECTION% -out:test_core_thread.exe || exit /b
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package test_core_slice
|
||||
|
||||
import "core:slice"
|
||||
import "core:strings"
|
||||
import "core:testing"
|
||||
import "core:fmt"
|
||||
import "core:os"
|
||||
@@ -30,6 +31,7 @@ when ODIN_TEST {
|
||||
main :: proc() {
|
||||
t := testing.T{}
|
||||
test_sort_with_indices(&t)
|
||||
test_binary_search(&t)
|
||||
|
||||
fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count)
|
||||
if TEST_fail > 0 {
|
||||
@@ -180,3 +182,64 @@ test_sort_by_indices :: proc(t: ^testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@test
|
||||
test_binary_search :: proc(t: ^testing.T) {
|
||||
builder := strings.Builder{}
|
||||
defer strings.builder_destroy(&builder)
|
||||
|
||||
test_search :: proc(t: ^testing.T, b: ^strings.Builder, s: []i32, v: i32) -> (int, bool) {
|
||||
log(t, fmt.sbprintf(b, "Searching for %v in %v", v, s))
|
||||
strings.builder_reset(b)
|
||||
index, found := slice.binary_search(s, v)
|
||||
log(t, fmt.sbprintf(b, "index: %v, found: %v", index, found))
|
||||
strings.builder_reset(b )
|
||||
|
||||
return index, found
|
||||
}
|
||||
|
||||
index: int
|
||||
found: bool
|
||||
|
||||
s := []i32{0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55}
|
||||
|
||||
index, found = test_search(t, &builder, s, 13)
|
||||
expect(t, index == 9, "Expected index to be 9.")
|
||||
expect(t, found == true, "Expected found to be true.")
|
||||
|
||||
index, found = test_search(t, &builder, s, 4)
|
||||
expect(t, index == 7, "Expected index to be 7.")
|
||||
expect(t, found == false, "Expected found to be false.")
|
||||
|
||||
index, found = test_search(t, &builder, s, 100)
|
||||
expect(t, index == 13, "Expected index to be 13.")
|
||||
expect(t, found == false, "Expected found to be false.")
|
||||
|
||||
index, found = test_search(t, &builder, s, 1)
|
||||
expect(t, index >= 1 && index <= 4, "Expected index to be 1, 2, 3, or 4.")
|
||||
expect(t, found == true, "Expected found to be true.")
|
||||
|
||||
index, found = test_search(t, &builder, s, -1)
|
||||
expect(t, index == 0, "Expected index to be 0.")
|
||||
expect(t, found == false, "Expected found to be false.")
|
||||
|
||||
a := []i32{}
|
||||
|
||||
index, found = test_search(t, &builder, a, 13)
|
||||
expect(t, index == 0, "Expected index to be 0.")
|
||||
expect(t, found == false, "Expected found to be false.")
|
||||
|
||||
b := []i32{1}
|
||||
|
||||
index, found = test_search(t, &builder, b, 13)
|
||||
expect(t, index == 1, "Expected index to be 1.")
|
||||
expect(t, found == false, "Expected found to be false.")
|
||||
|
||||
index, found = test_search(t, &builder, b, 1)
|
||||
expect(t, index == 0, "Expected index to be 0.")
|
||||
expect(t, found == true, "Expected found to be true.")
|
||||
|
||||
index, found = test_search(t, &builder, b, 0)
|
||||
expect(t, index == 0, "Expected index to be 0.")
|
||||
expect(t, found == false, "Expected found to be false.")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
package test_core_thread
|
||||
|
||||
import "core:testing"
|
||||
import "core:thread"
|
||||
import "core:fmt"
|
||||
import "core:os"
|
||||
|
||||
TEST_count := 0
|
||||
TEST_fail := 0
|
||||
|
||||
t := &testing.T{}
|
||||
|
||||
when ODIN_TEST {
|
||||
expect :: testing.expect
|
||||
log :: testing.log
|
||||
} else {
|
||||
expect :: proc(t: ^testing.T, condition: bool, message: string, loc := #caller_location) {
|
||||
TEST_count += 1
|
||||
if !condition {
|
||||
TEST_fail += 1
|
||||
fmt.printf("[%v] %v\n", loc, message)
|
||||
return
|
||||
}
|
||||
}
|
||||
log :: proc(t: ^testing.T, v: any, loc := #caller_location) {
|
||||
fmt.printf("[%v] ", loc)
|
||||
fmt.printf("log: %v\n", v)
|
||||
}
|
||||
}
|
||||
|
||||
main :: proc() {
|
||||
poly_data_test(t)
|
||||
|
||||
if TEST_fail > 0 {
|
||||
os.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
@(test)
|
||||
poly_data_test :: proc(_t: ^testing.T) {
|
||||
MAX :: size_of(rawptr) * thread.MAX_USER_ARGUMENTS
|
||||
|
||||
@static poly_data_test_t: ^testing.T
|
||||
poly_data_test_t = _t
|
||||
|
||||
b: [MAX]byte = 8
|
||||
t1 := thread.create_and_start_with_poly_data(b, proc(b: [MAX]byte) {
|
||||
b_expect: [MAX]byte = 8
|
||||
expect(poly_data_test_t, b == b_expect, "thread poly data not correct")
|
||||
})
|
||||
defer free(t1)
|
||||
|
||||
b1: [3]uintptr = 1
|
||||
b2: [MAX / 2]byte = 3
|
||||
t2 := thread.create_and_start_with_poly_data2(b1, b2, proc(b: [3]uintptr, b2: [MAX / 2]byte) {
|
||||
b_expect: [3]uintptr = 1
|
||||
b2_expect: [MAX / 2]byte = 3
|
||||
expect(poly_data_test_t, b == b_expect, "thread poly data not correct")
|
||||
expect(poly_data_test_t, b2 == b2_expect, "thread poly data not correct")
|
||||
})
|
||||
defer free(t2)
|
||||
|
||||
t3 := thread.create_and_start_with_poly_data3(b1, b2, uintptr(333), proc(b: [3]uintptr, b2: [MAX / 2]byte, b3: uintptr) {
|
||||
b_expect: [3]uintptr = 1
|
||||
b2_expect: [MAX / 2]byte = 3
|
||||
|
||||
expect(poly_data_test_t, b == b_expect, "thread poly data not correct")
|
||||
expect(poly_data_test_t, b2 == b2_expect, "thread poly data not correct")
|
||||
expect(poly_data_test_t, b3 == 333, "thread poly data not correct")
|
||||
})
|
||||
defer free(t3)
|
||||
|
||||
t4 := thread.create_and_start_with_poly_data4(uintptr(111), b1, uintptr(333), u8(5), proc(n: uintptr, b: [3]uintptr, n2: uintptr, n4: u8) {
|
||||
b_expect: [3]uintptr = 1
|
||||
|
||||
expect(poly_data_test_t, n == 111, "thread poly data not correct")
|
||||
expect(poly_data_test_t, b == b_expect, "thread poly data not correct")
|
||||
expect(poly_data_test_t, n2 == 333, "thread poly data not correct")
|
||||
expect(poly_data_test_t, n4 == 5, "thread poly data not correct")
|
||||
})
|
||||
defer free(t4)
|
||||
|
||||
thread.join_multiple(t1, t2, t3, t4)
|
||||
}
|
||||
Vendored
BIN
Binary file not shown.
BIN
Binary file not shown.
Vendored
+8
-21
@@ -16,23 +16,9 @@ when ODIN_OS == .Windows {
|
||||
}
|
||||
} else when ODIN_OS == .Linux {
|
||||
when RAYGUI_SHARED {
|
||||
// Note(bumbread): can't panic here, because the users might be expecting to
|
||||
// only use raylib. Let's have them get the error at link-time instead..
|
||||
//#panic("Cannot link libraygui.so: not in the vendor collection")
|
||||
// Note(bumbread): unless we import something the rest of the bindings will
|
||||
// make a compile-time error. This is a bit ugly for now, but in the future
|
||||
// raygui probably needs to be in a separate package.
|
||||
foreign import lib {"_"}
|
||||
foreign import lib "linux/libraygui.so"
|
||||
} else {
|
||||
// #panic("Cannot link libraygui.a: not in the vendor collection")
|
||||
// TODO(bumbread): apparently this one was missing. This might need
|
||||
// to get rebuilt for linux
|
||||
// foreign import lib {
|
||||
// "linux/libraygui.a",
|
||||
// // "system:dl",
|
||||
// // "system:pthread",
|
||||
// }
|
||||
foreign import lib {"_"}
|
||||
foreign import lib "linux/libraygui.a"
|
||||
}
|
||||
} else when ODIN_OS == .Darwin {
|
||||
when ODIN_ARCH == .arm64 {
|
||||
@@ -238,6 +224,7 @@ SCROLLBAR_RIGHT_SIDE :: 1
|
||||
|
||||
@(default_calling_convention="c")
|
||||
foreign lib {
|
||||
@(link_name="raylib_version") version: cstring
|
||||
// Global gui state control functions
|
||||
|
||||
GuiEnable :: proc() --- // Enable gui controls (global state)
|
||||
@@ -293,17 +280,17 @@ foreign lib {
|
||||
// Basic controls set
|
||||
|
||||
GuiLabel :: proc(bounds: Rectangle, text: cstring) -> c.int --- // Label control, shows text
|
||||
GuiButton :: proc(bounds: Rectangle, text: cstring) -> c.int --- // Button control, returns true when clicked
|
||||
GuiLabelButton :: proc(bounds: Rectangle, text: cstring) -> c.int --- // Label button control, show true when clicked
|
||||
GuiButton :: proc(bounds: Rectangle, text: cstring) -> bool --- // Button control, returns true when clicked
|
||||
GuiLabelButton :: proc(bounds: Rectangle, text: cstring) -> bool --- // Label button control, show true when clicked
|
||||
GuiToggle :: proc(bounds: Rectangle, text: cstring, active: ^bool) -> c.int --- // Toggle Button control, returns true when active
|
||||
GuiToggleGroup :: proc(bounds: Rectangle, text: cstring, active: ^c.int) -> c.int --- // Toggle Group control, returns active toggle index
|
||||
GuiCheckBox :: proc(bounds: Rectangle, text: cstring, checked: ^bool) -> c.int --- // Check Box control, returns true when active
|
||||
GuiCheckBox :: proc(bounds: Rectangle, text: cstring, checked: ^bool) -> bool --- // Check Box control, returns true when active
|
||||
GuiComboBox :: proc(bounds: Rectangle, text: cstring, active: ^c.int) -> c.int --- // Combo Box control, returns selected item index
|
||||
|
||||
GuiDropdownBox :: proc(bounds: Rectangle, text: cstring, active: ^c.int, editMode: bool) -> c.int --- // Dropdown Box control, returns selected item
|
||||
GuiDropdownBox :: proc(bounds: Rectangle, text: cstring, active: ^c.int, editMode: bool) -> bool --- // Dropdown Box control, returns selected item
|
||||
GuiSpinner :: proc(bounds: Rectangle, text: cstring, value: ^c.int, minValue, maxValue: c.int, editMode: bool) -> c.int --- // Spinner control, returns selected value
|
||||
GuiValueBox :: proc(bounds: Rectangle, text: cstring, value: ^c.int, minValue, maxValue: c.int, editMode: bool) -> c.int --- // Value Box control, updates input text with numbers
|
||||
GuiTextBox :: proc(bounds: Rectangle, text: cstring, textSize: c.int, editMode: bool) -> c.int --- // Text Box control, updates input text
|
||||
GuiTextBox :: proc(bounds: Rectangle, text: cstring, textSize: c.int, editMode: bool) -> bool --- // Text Box control, updates input text
|
||||
|
||||
GuiSlider :: proc(bounds: Rectangle, textLeft: cstring, textRight: cstring, value: ^f32, minValue: f32, maxValue: f32) -> c.int --- // Slider control, returns selected value
|
||||
GuiSliderBar :: proc(bounds: Rectangle, textLeft: cstring, textRight: cstring, value: ^f32, minValue: f32, maxValue: f32) -> c.int --- // Slider Bar control, returns selected value
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
# TODO(flysand): Remove this file.
|
||||
|
||||
*.i
|
||||
Vendored
+651
@@ -0,0 +1,651 @@
|
||||
//+build linux, freebsd, openbsd
|
||||
package xlib
|
||||
|
||||
// Special values for many types. Most of these constants
|
||||
// aren't attached to a specific type.
|
||||
|
||||
None :: 0
|
||||
ParentRelative :: 1
|
||||
CopyFromParent :: 0
|
||||
PointerWindow :: 0
|
||||
InputFocus :: 1
|
||||
PointerRoot :: 1
|
||||
AnyPropertyType :: 0
|
||||
AnyKey :: 0
|
||||
AnyButton :: 0
|
||||
AllTemporary :: 0
|
||||
CurrentTime :: 0
|
||||
NoSymbol :: 0
|
||||
|
||||
XA_WM_CLASS :: Atom(67)
|
||||
XA_WM_CLIENT_MACHINE :: Atom(36)
|
||||
XA_WM_COMMAND :: Atom(34)
|
||||
XA_WM_HINTS :: Atom(35)
|
||||
XA_WM_ICON_NAME :: Atom(37)
|
||||
XA_WM_ICON_SIZE :: Atom(38)
|
||||
XA_WM_NAME :: Atom(39)
|
||||
XA_WM_NORMAL_HINTS :: Atom(40)
|
||||
XA_WM_SIZE_HINTS :: Atom(41)
|
||||
XA_WM_TRANSIENT_FOR :: Atom(68)
|
||||
XA_WM_ZOOM_HINTS :: Atom(42)
|
||||
|
||||
// NOTE(flysand): Some implementations return Status as enum, other return it
|
||||
// as an integer. I will make it a status.
|
||||
Status :: enum i32 {
|
||||
Success = 0,
|
||||
BadRequest = 1,
|
||||
BadValue = 2,
|
||||
BadWindow = 3,
|
||||
BadPixmap = 4,
|
||||
BadAtom = 5,
|
||||
BadCursor = 6,
|
||||
BadFont = 7,
|
||||
BadMatch = 8,
|
||||
BadDrawable = 9,
|
||||
BadAccess = 10,
|
||||
BadAlloc = 11,
|
||||
BadColor = 12,
|
||||
BadGC = 13,
|
||||
BadIDChoice = 14,
|
||||
BadName = 15,
|
||||
BadLength = 16,
|
||||
BadImplementation = 17,
|
||||
FirstExtensionError = 128,
|
||||
LastExtensionError = 255,
|
||||
}
|
||||
|
||||
ByteOrder :: enum i32 {
|
||||
LSBFirst = 0,
|
||||
MSBFirst = 1,
|
||||
}
|
||||
|
||||
Gravity :: enum i32 {
|
||||
ForgetGravity = 0,
|
||||
UnmapGravity = 0,
|
||||
NorthWestGravity = 1,
|
||||
NorthGravity = 2,
|
||||
NorthEastGravity = 3,
|
||||
WestGravity = 4,
|
||||
CenterGravity = 5,
|
||||
EastGravity = 6,
|
||||
SouthWestGravity = 7,
|
||||
SouthGravity = 8,
|
||||
SouthEastGravity = 9,
|
||||
StaticGravity = 10,
|
||||
}
|
||||
|
||||
BackingStore :: enum i32 {
|
||||
NotUseful = 0,
|
||||
WhenMapped = 1,
|
||||
Always = 2,
|
||||
}
|
||||
|
||||
MouseButton :: enum i32 {
|
||||
Button1 = 1,
|
||||
Button2 = 2,
|
||||
Button3 = 3,
|
||||
Button4 = 4,
|
||||
Button5 = 5,
|
||||
}
|
||||
|
||||
EventMask :: bit_set[EventMaskBits; int]
|
||||
EventMaskBits :: enum i32 {
|
||||
KeyPress = 0,
|
||||
KeyRelease = 1,
|
||||
ButtonPress = 2,
|
||||
ButtonRelease = 3,
|
||||
EnterWindow = 4,
|
||||
LeaveWindow = 5,
|
||||
PointerMotion = 6,
|
||||
PointerMotionHint = 7,
|
||||
Button1Motion = 8,
|
||||
Button2Motion = 9,
|
||||
Button3Motion = 10,
|
||||
Button4Motion = 11,
|
||||
Button5Motion = 12,
|
||||
ButtonMotion = 13,
|
||||
KeymapState = 14,
|
||||
Exposure = 15,
|
||||
VisibilityChange = 16,
|
||||
StructureNotify = 17,
|
||||
ResizeRedirect = 18,
|
||||
SubstructureNotify = 19,
|
||||
SubstructureRedirect = 20,
|
||||
FocusChange = 21,
|
||||
PropertyChange = 22,
|
||||
ColormapChange = 23,
|
||||
OwnerGrabButton = 24,
|
||||
}
|
||||
|
||||
EventType :: enum i32 {
|
||||
KeyPress = 2,
|
||||
KeyRelease = 3,
|
||||
ButtonPress = 4,
|
||||
ButtonRelease = 5,
|
||||
MotionNotify = 6,
|
||||
EnterNotify = 7,
|
||||
LeaveNotify = 8,
|
||||
FocusIn = 9,
|
||||
FocusOut = 10,
|
||||
KeymapNotify = 11,
|
||||
Expose = 12,
|
||||
GraphicsExpose = 13,
|
||||
NoExpose = 14,
|
||||
VisibilityNotify = 15,
|
||||
CreateNotify = 16,
|
||||
DestroyNotify = 17,
|
||||
UnmapNotify = 18,
|
||||
MapNotify = 19,
|
||||
MapRequest = 20,
|
||||
ReparentNotify = 21,
|
||||
ConfigureNotify = 22,
|
||||
ConfigureRequest = 23,
|
||||
GravityNotify = 24,
|
||||
ResizeRequest = 25,
|
||||
CirculateNotify = 26,
|
||||
CirculateRequest = 27,
|
||||
PropertyNotify = 28,
|
||||
SelectionClear = 29,
|
||||
SelectionRequest = 30,
|
||||
SelectionNotify = 31,
|
||||
ColormapNotify = 32,
|
||||
ClientMessage = 33,
|
||||
MappingNotify = 34,
|
||||
GenericEvent = 35,
|
||||
}
|
||||
|
||||
InputMask :: bit_set[InputMaskBits; i32]
|
||||
InputMaskBits :: enum {
|
||||
ShiftMask = 0,
|
||||
LockMask = 1,
|
||||
ControlMask = 2,
|
||||
Mod1Mask = 3,
|
||||
Mod2Mask = 4,
|
||||
Mod3Mask = 5,
|
||||
Mod4Mask = 6,
|
||||
Mod5Mask = 7,
|
||||
Button1Mask = 8,
|
||||
Button2Mask = 9,
|
||||
Button3Mask = 10,
|
||||
Button4Mask = 11,
|
||||
Button5Mask = 12,
|
||||
AnyModifier = 15,
|
||||
}
|
||||
|
||||
NotifyMode :: enum i32 {
|
||||
NotifyNormal = 0,
|
||||
NotifyGrab = 1,
|
||||
NotifyUngrab = 2,
|
||||
NotifyWhileGrabbed = 3,
|
||||
}
|
||||
|
||||
NotifyDetail :: enum i32 {
|
||||
NotifyAncestor = 0,
|
||||
NotifyVirtual = 1,
|
||||
NotifyInferior = 2,
|
||||
NotifyNonlinear = 3,
|
||||
NotifyNonlinearVirtual = 4,
|
||||
NotifyPointer = 5,
|
||||
NotifyPointerRoot = 6,
|
||||
NotifyDetailNone = 7,
|
||||
}
|
||||
|
||||
MappingRequest :: enum i32 {
|
||||
MappingModifier = 0,
|
||||
MappingKeyboard = 1,
|
||||
MappingPointer = 2,
|
||||
}
|
||||
|
||||
VisibilityState :: enum i32 {
|
||||
VisibilityUnobscured = 0,
|
||||
VisibilityPartiallyObscured = 1,
|
||||
VisibilityFullyObscured = 2,
|
||||
}
|
||||
|
||||
ColormapState :: enum i32 {
|
||||
ColormapUninstalled = 0,
|
||||
ColormapInstalled = 1,
|
||||
}
|
||||
|
||||
PropertyState :: enum i32 {
|
||||
PropertyNewValue = 0,
|
||||
PropertyDelete = 1,
|
||||
}
|
||||
|
||||
CloseMode :: enum i32 {
|
||||
DestroyAll = 0,
|
||||
RetainPermanent = 1,
|
||||
RetainTemporary = 2,
|
||||
}
|
||||
|
||||
EventQueueMode :: enum i32 {
|
||||
QueuedAlready = 0,
|
||||
QueuedAfterReading = 1,
|
||||
QueuedAfterFlush = 2,
|
||||
}
|
||||
|
||||
WindowAttributeMask :: bit_set[WindowAttributeMaskBits; int]
|
||||
WindowAttributeMaskBits :: enum {
|
||||
CWBackPixmap = 0,
|
||||
CWBackPixel = 1,
|
||||
CWBorderPixmap = 2,
|
||||
CWBorderPixel = 3,
|
||||
CWBitGravity = 4,
|
||||
CWWinGravity = 5,
|
||||
CWBackingStore = 6,
|
||||
CWBackingPlanes = 7,
|
||||
CWBackingPixel = 8,
|
||||
CWOverrideRedirect = 9,
|
||||
CWSaveUnder = 10,
|
||||
CWEventMask = 11,
|
||||
CWDontPropagate = 12,
|
||||
CWColormap = 13,
|
||||
CWCursor = 14,
|
||||
}
|
||||
|
||||
WindowClass :: enum i32 {
|
||||
CopyFromParent = 0,
|
||||
InputOutput = 1,
|
||||
InputOnly = 2,
|
||||
}
|
||||
|
||||
WindowChangesMask :: bit_set[WindowChangesMaskBits; i32]
|
||||
WindowChangesMaskBits :: enum {
|
||||
CWX = 0,
|
||||
CWY = 1,
|
||||
CWWidth = 2,
|
||||
CWHeight = 3,
|
||||
CWBorderWidth = 4,
|
||||
CWSibling = 5,
|
||||
CWStackMode = 6,
|
||||
}
|
||||
|
||||
WindowStacking :: enum i32 {
|
||||
Above = 0,
|
||||
Below = 1,
|
||||
TopIf = 2,
|
||||
BottomIf = 3,
|
||||
Opposite = 4,
|
||||
}
|
||||
|
||||
CirculationDirection :: enum i32 {
|
||||
RaiseLowest = 0,
|
||||
LowerHighest = 1,
|
||||
}
|
||||
|
||||
CirculationRequest :: enum i32 {
|
||||
PlaceOnTop = 0,
|
||||
PlaceOnBottom = 1,
|
||||
}
|
||||
|
||||
WindowMapState :: enum i32 {
|
||||
IsUnmapped = 0,
|
||||
IsUnviewable = 1,
|
||||
IsViewable = 2,
|
||||
}
|
||||
|
||||
KeyMask :: enum u32 {
|
||||
ShiftMask = 0,
|
||||
LockMask = 1,
|
||||
ControlMask = 2,
|
||||
Mod1Mask = 3,
|
||||
Mod2Mask = 4,
|
||||
Mod3Mask = 5,
|
||||
Mod4Mask = 6,
|
||||
Mod5Mask = 7,
|
||||
}
|
||||
|
||||
CursorShape :: enum u32 {
|
||||
XC_X_cursor = 0,
|
||||
XC_arrow = 2,
|
||||
XC_based_arrow_down = 4,
|
||||
XC_based_arrow_up = 6,
|
||||
XC_boat = 8,
|
||||
XC_bogosity = 10,
|
||||
XC_bottom_left_corner = 12,
|
||||
XC_bottom_right_corner = 14,
|
||||
XC_bottom_side = 16,
|
||||
XC_bottom_tee = 18,
|
||||
XC_box_spiral = 20,
|
||||
XC_center_ptr = 22,
|
||||
XC_circle = 24,
|
||||
XC_clock = 26,
|
||||
XC_coffee_mug = 28,
|
||||
XC_cross = 30,
|
||||
XC_cross_reverse = 32,
|
||||
XC_crosshair = 34,
|
||||
XC_diamond_cross = 36,
|
||||
XC_dot = 38,
|
||||
XC_dotbox = 40,
|
||||
XC_double_arrow = 42,
|
||||
XC_draft_large = 44,
|
||||
XC_draft_small = 46,
|
||||
XC_draped_box = 48,
|
||||
XC_exchange = 50,
|
||||
XC_fleur = 52,
|
||||
XC_gobbler = 54,
|
||||
XC_gumby = 56,
|
||||
XC_hand1 = 58,
|
||||
XC_hand2 = 60,
|
||||
XC_heart = 62,
|
||||
XC_icon = 64,
|
||||
XC_iron_cross = 66,
|
||||
XC_left_ptr = 68,
|
||||
XC_left_side = 70,
|
||||
XC_left_tee = 72,
|
||||
XC_leftbutton = 74,
|
||||
XC_ll_angle = 76,
|
||||
XC_lr_angle = 78,
|
||||
XC_man = 80,
|
||||
XC_middlebutton = 82,
|
||||
XC_mouse = 84,
|
||||
XC_pencil = 86,
|
||||
XC_pirate = 88,
|
||||
XC_plus = 90,
|
||||
XC_question_arrow = 92,
|
||||
XC_right_ptr = 94,
|
||||
XC_right_side = 96,
|
||||
XC_right_tee = 98,
|
||||
XC_rightbutton = 100,
|
||||
XC_rtl_logo = 102,
|
||||
XC_sailboat = 104,
|
||||
XC_sb_down_arrow = 106,
|
||||
XC_sb_h_double_arrow = 108,
|
||||
XC_sb_left_arrow = 110,
|
||||
XC_sb_right_arrow = 112,
|
||||
XC_sb_up_arrow = 114,
|
||||
XC_sb_v_double_arrow = 116,
|
||||
XC_shuttle = 118,
|
||||
XC_sizing = 120,
|
||||
XC_spider = 122,
|
||||
XC_spraycan = 124,
|
||||
XC_star = 126,
|
||||
XC_target = 128,
|
||||
XC_tcross = 130,
|
||||
XC_top_left_arrow = 132,
|
||||
XC_top_left_corner = 134,
|
||||
XC_top_right_corner = 136,
|
||||
XC_top_side = 138,
|
||||
XC_top_tee = 140,
|
||||
XC_trek = 142,
|
||||
XC_ul_angle = 144,
|
||||
XC_umbrella = 146,
|
||||
XC_ur_angle = 148,
|
||||
XC_watch = 150,
|
||||
XC_xterm = 152,
|
||||
XC_num_glyphs = 154,
|
||||
}
|
||||
|
||||
ColorFormat :: enum u32 {
|
||||
XcmsUndefinedFormat = 0x00000000,
|
||||
XcmsCIEXYZFormat = 0x00000001,
|
||||
XcmsCIEuvYFormat = 0x00000002,
|
||||
XcmsCIExyYFormat = 0x00000003,
|
||||
XcmsCIELabFormat = 0x00000004,
|
||||
XcmsCIELuvFormat = 0x00000005,
|
||||
XcmsTekHVCFormat = 0x00000006,
|
||||
XcmsRGBFormat = 0x80000000,
|
||||
XcmsRGBiFormat = 0x80000001,
|
||||
}
|
||||
|
||||
ColormapAlloc :: enum i32 {
|
||||
AllocNone = 0,
|
||||
AllocAll = 1,
|
||||
}
|
||||
|
||||
ColorFlags :: bit_set[ColorFlagsBits; i32]
|
||||
ColorFlagsBits :: enum {
|
||||
DoRed = 0,
|
||||
DoGreen = 1,
|
||||
DoBlue = 2,
|
||||
}
|
||||
|
||||
GCAttributeMask :: bit_set[GCAttributeMaskBits; uint]
|
||||
GCAttributeMaskBits :: enum {
|
||||
GCFunction = 0,
|
||||
GCPlaneMask = 1,
|
||||
GCForeground = 2,
|
||||
GCBackground = 3,
|
||||
GCLineWidth = 4,
|
||||
GCLineStyle = 5,
|
||||
GCCapStyle = 6,
|
||||
GCJoinStyle = 7,
|
||||
GCFillStyle = 8,
|
||||
GCFillRule = 9,
|
||||
GCTile = 10,
|
||||
GCStipple = 11,
|
||||
GCTileStipXOrigin = 12,
|
||||
GCTileStipYOrigin = 13,
|
||||
GCFont = 14,
|
||||
GCSubwindowMode = 15,
|
||||
GCGraphicsExposures= 16,
|
||||
GCClipXOrigin = 17,
|
||||
GCClipYOrigin = 18,
|
||||
GCClipMask = 19,
|
||||
GCDashOffset = 20,
|
||||
GCDashList = 21,
|
||||
GCArcMode = 22,
|
||||
}
|
||||
|
||||
GCFunction :: enum i32 {
|
||||
GXclear = 0x0, // 0
|
||||
GXand = 0x1, // src & dst
|
||||
GXandReverse = 0x2, // src & ~dst
|
||||
GXcopy = 0x3, // src
|
||||
GXandInverted = 0x4, // ~src & dst
|
||||
GXnoop = 0x5, // dst
|
||||
GXxor = 0x6, // src ~ dst
|
||||
GXor = 0x7, // src | dst
|
||||
GXnor = 0x8, // ~src & ~dst
|
||||
GXequiv = 0x9, // ~src ~ dst
|
||||
GXinvert = 0xa, // ~dst
|
||||
GXorReverse = 0xb, // src | ~dst
|
||||
GXcopyInverted = 0xc, // ~src
|
||||
GXorInverted = 0xd, // ~src | dst
|
||||
GXnand = 0xe, // ~src | ~dst
|
||||
GXset = 0xf, // 1
|
||||
}
|
||||
|
||||
LineStyle :: enum i32 {
|
||||
LineSolid = 0,
|
||||
LineOnOffDash = 1,
|
||||
LineDoubleDash = 2,
|
||||
}
|
||||
|
||||
CapStyle :: enum i32 {
|
||||
CapNotLast = 0,
|
||||
CapButt = 1,
|
||||
CapRound = 2,
|
||||
CapProjecting = 3,
|
||||
}
|
||||
|
||||
JoinStyle :: enum i32 {
|
||||
JoinMiter = 0,
|
||||
JoinRound = 1,
|
||||
JoinBevel = 2,
|
||||
}
|
||||
|
||||
FillStyle :: enum i32 {
|
||||
FillSolid = 0,
|
||||
FillTiled = 1,
|
||||
FillStippled = 2,
|
||||
FillOpaqueStippled = 3,
|
||||
}
|
||||
|
||||
FillRule :: enum i32 {
|
||||
EvenOddRule = 0,
|
||||
WindingRule = 1,
|
||||
}
|
||||
|
||||
ArcMode :: enum i32 {
|
||||
ArcChord = 0,
|
||||
ArcPieSlice = 1,
|
||||
}
|
||||
|
||||
SubwindowMode :: enum i32 {
|
||||
ClipByChildren = 0,
|
||||
IncludeInferiors = 1,
|
||||
}
|
||||
|
||||
CoordMode :: enum i32 {
|
||||
CoordModeOrigin = 0,
|
||||
CoordModePrevious = 1,
|
||||
}
|
||||
|
||||
Shape :: enum i32 {
|
||||
Complex = 0,
|
||||
Nonconvex = 1,
|
||||
Convex = 2,
|
||||
}
|
||||
|
||||
FontDirection :: enum i32 {
|
||||
FontLeftToRight = 0,
|
||||
FontRightToLeft = 1,
|
||||
}
|
||||
|
||||
ImageFormat :: enum i32 {
|
||||
XYBitmap = 0,
|
||||
XYPixmap = 1,
|
||||
ZPixmap = 2,
|
||||
}
|
||||
|
||||
SaveSetChangeMode :: enum i32 {
|
||||
SetModeInsert = 0,
|
||||
SetModeDelete = 1,
|
||||
}
|
||||
|
||||
|
||||
ScreenSaverBlanking :: enum i32 {
|
||||
DontPreferBlanking = 0,
|
||||
PreferBlanking = 1,
|
||||
DefaultBlanking = 2,
|
||||
}
|
||||
|
||||
ScreenSavingExposures :: enum i32 {
|
||||
DontAllowExposures = 0,
|
||||
AllowExposures = 1,
|
||||
DefaultExposures = 2,
|
||||
}
|
||||
|
||||
ScreenSaverForceMode :: enum i32 {
|
||||
ScreenSaverReset = 0,
|
||||
ScreenSaverActive = 1,
|
||||
}
|
||||
|
||||
AccessControlMode :: enum i32 {
|
||||
DisableAccess = 0,
|
||||
EnableAccess = 1,
|
||||
}
|
||||
|
||||
GrabMode :: enum i32 {
|
||||
GrabModeSync = 0,
|
||||
GrabModeAsync = 1,
|
||||
}
|
||||
|
||||
AllowEventsMode :: enum i32 {
|
||||
AsyncPointer = 0,
|
||||
SyncPointer = 1,
|
||||
ReplayPointer = 2,
|
||||
AsyncKeyboard = 3,
|
||||
SyncKeyboard = 4,
|
||||
ReplayKeyboard = 5,
|
||||
AsyncBoth = 6,
|
||||
SyncBoth = 7,
|
||||
}
|
||||
|
||||
FocusRevert :: enum i32 {
|
||||
RevertToNone = 0,
|
||||
RevertToPointerRoot = 1,
|
||||
RevertToParent = 2,
|
||||
}
|
||||
|
||||
KeyboardControlMask :: bit_set[KeyboardControlMaskBits; int]
|
||||
KeyboardControlMaskBits :: enum {
|
||||
KBKeyClickPercent = 0,
|
||||
KBBellPercent = 1,
|
||||
KBBellPitch = 2,
|
||||
KBBellDuration = 3,
|
||||
KBLed = 4,
|
||||
KBLedMode = 5,
|
||||
KBKey = 6,
|
||||
KBAutoRepeatMode = 7,
|
||||
}
|
||||
|
||||
KeyboardAutoRepeatMode :: enum i32 {
|
||||
AutoRepeatModeOff = 0,
|
||||
AutoRepeatModeOn = 1,
|
||||
AutoRepeatModeDefault = 2,
|
||||
}
|
||||
|
||||
KeyboardLedMode :: enum i32 {
|
||||
LedModeOff = 0,
|
||||
LedModeOn = 1,
|
||||
}
|
||||
|
||||
WMHints :: bit_set[WMHintsBits; uint]
|
||||
WMHintsBits :: enum {
|
||||
InputHint = 0,
|
||||
StateHint = 1,
|
||||
IconPixmapHint = 2,
|
||||
IconWindowHint = 3,
|
||||
IconPositionHint = 4,
|
||||
IconMaskHint = 5,
|
||||
WindowGroupHint = 6,
|
||||
XUrgencyHint = 8,
|
||||
}
|
||||
|
||||
WMHintState :: enum i32 {
|
||||
WithdrawnState = 0,
|
||||
NormalState = 1,
|
||||
IconicState = 3,
|
||||
}
|
||||
|
||||
AllHints :: WMHints{
|
||||
.InputHint,
|
||||
.StateHint,
|
||||
.IconPixmapHint,
|
||||
.IconWindowHint,
|
||||
.IconPositionHint,
|
||||
.IconMaskHint,
|
||||
.WindowGroupHint,
|
||||
}
|
||||
|
||||
SizeHints :: bit_set[SizeHintsBits; uint]
|
||||
SizeHintsBits :: enum {
|
||||
USPosition = 0,
|
||||
USSize = 1,
|
||||
PPosition = 2,
|
||||
PSize = 3,
|
||||
PMinSize = 4,
|
||||
PMaxSize = 5,
|
||||
PResizeInc = 6,
|
||||
PAspect = 7,
|
||||
PBaseSize = 8,
|
||||
PWinGravity = 9,
|
||||
}
|
||||
|
||||
VisualInfoMask :: bit_set[VisualInfoMaskBits; int]
|
||||
VisualInfoMaskBits :: enum {
|
||||
VisualIDMask = 0,
|
||||
VisualScreenMask = 1,
|
||||
VisualDepthMask = 2,
|
||||
VisualClassMask = 3,
|
||||
VisualRedMaskMask = 4,
|
||||
VisualGreenMaskMask = 5,
|
||||
VisualBlueMaskMask = 6,
|
||||
VisualColormapSizeMask = 7,
|
||||
VisualBitsPerRGBMask = 8,
|
||||
}
|
||||
|
||||
VisualNoMask :: VisualInfoMask {}
|
||||
VisualAllMask :: VisualInfoMask {
|
||||
.VisualIDMask,
|
||||
.VisualScreenMask,
|
||||
.VisualDepthMask,
|
||||
.VisualClassMask,
|
||||
.VisualRedMaskMask,
|
||||
.VisualGreenMaskMask,
|
||||
.VisualBlueMaskMask,
|
||||
.VisualColormapSizeMask,
|
||||
.VisualBitsPerRGBMask,
|
||||
}
|
||||
Vendored
+1681
File diff suppressed because it is too large
Load Diff
Vendored
+1908
File diff suppressed because it is too large
Load Diff
Vendored
+1307
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user