This commit is contained in:
gingerBill
2023-12-12 17:11:42 +00:00
38 changed files with 6245 additions and 328 deletions

View File

@@ -111,7 +111,7 @@ 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
if %release_mode% EQU 0 odin run examples/demo -- Hellope World
del *.obj > NUL 2> NUL

View File

@@ -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"
@@ -117,7 +119,7 @@ build_odin() {
}
run_demo() {
./odin run examples/demo/demo.odin -file
./odin run examples/demo/demo.odin -file -- Hellope World
}
if [ $# -eq 0 ]; then

View File

@@ -2856,7 +2856,7 @@ internal_int_random :: proc(dest: ^Int, bits: int, r: ^rnd.Rand = nil, allocator
dest.digit[digits - 1] &= ((1 << uint(bits)) - 1)
}
dest.used = digits
return nil
return internal_clamp(dest)
}
internal_random :: proc { internal_int_random, }

View File

@@ -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

View File

@@ -51,7 +51,7 @@ arena_init_growing :: proc(arena: ^Arena, reserved: uint = DEFAULT_ARENA_GROWING
// Initialization of an `Arena` to be a `.Static` variant.
// A static arena contains a single `Memory_Block` allocated with virtual memory.
@(require_results)
arena_init_static :: proc(arena: ^Arena, reserved: uint, commit_size: uint = DEFAULT_ARENA_STATIC_COMMIT_SIZE) -> (err: Allocator_Error) {
arena_init_static :: proc(arena: ^Arena, reserved: uint = DEFAULT_ARENA_STATIC_RESERVE_SIZE, commit_size: uint = DEFAULT_ARENA_STATIC_COMMIT_SIZE) -> (err: Allocator_Error) {
arena.kind = .Static
arena.curr_block = memory_block_alloc(commit_size, reserved, {}) or_return
arena.total_used = 0

View File

@@ -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)
}
}

View File

@@ -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

View File

@@ -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,

View File

@@ -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
}

View File

@@ -35,7 +35,7 @@ nil_allocator :: proc() -> Allocator {
when ODIN_OS == .Freestanding {
default_allocator_proc :: nil_allocator_proc
default_allocator :: nil_allocator
}
}
@@ -78,9 +78,7 @@ panic_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
panic_allocator :: proc() -> Allocator {
return Allocator{
procedure = nil_allocator_proc,
procedure = panic_allocator_proc,
data = nil,
}
}

View File

@@ -4,7 +4,7 @@ package runtime
import "core:intrinsics"
_os_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
ret := intrinsics.syscall(4, 1, uintptr(raw_data(data)), uintptr(len(data)))
ret := intrinsics.syscall(0x2000004, 1, uintptr(raw_data(data)), uintptr(len(data)))
if ret < 0 {
return 0, _OS_Errno(-ret)
}

View File

@@ -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,93 @@ 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) #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) {
@@ -463,6 +510,40 @@ min_max :: proc(s: $S/[]$T) -> (min, max: T, ok: bool) where intrinsics.type_is_
return
}
// Find the index of the (first) minimum element in a slice.
@(require_results)
min_index :: proc(s: $S/[]$T) -> (min_index: int, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok {
if len(s) == 0 {
return -1, false
}
min_index = 0
min_value := s[0]
for v, i in s[1:] {
if v < min_value {
min_value = v
min_index = i+1
}
}
return min_index, true
}
// Find the index of the (first) maximum element in a slice.
@(require_results)
max_index :: proc(s: $S/[]$T) -> (max_index: int, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok {
if len(s) == 0 {
return -1, false
}
max_index = 0
max_value := s[0]
for v, i in s[1:] {
if v > max_value {
max_value = v
max_index = i+1
}
}
return max_index, true
}
@(require_results)
any_of :: proc(s: $S/[]$T, value: T) -> bool where intrinsics.type_is_comparable(T) {
for v in s {

View File

@@ -885,6 +885,7 @@ Splits a string into parts based on a separator. If n < count of seperators, the
Inputs:
- s: The string to split.
- sep: The separator string used to split the input string.
- n: The maximum amount of parts to split the string into.
- allocator: (default is context.allocator)
Returns:

View File

@@ -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,

View File

@@ -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]

View File

@@ -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 {

View File

@@ -291,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 ---
@@ -354,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,
@@ -422,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 ---

View File

@@ -1971,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

View File

@@ -161,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 ---
@@ -311,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

View File

@@ -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 {

View File

@@ -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

View File

@@ -44,7 +44,13 @@ the_basics :: proc() {
fmt.println("\n# the basics")
{ // The Basics
fmt.println("Hellope")
// os.args holds the path to the current executable and any arguments passed to it.
if len(os.args) == 1 {
fmt.printf("Hellope from %v.\n", os.args[0])
} else {
fmt.printf("%v, %v! from %v.\n", os.args[1], os.args[2], os.args[0])
}
// Lexical elements and literals
// A comment

View File

@@ -6123,9 +6123,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);
@@ -6136,6 +6133,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);

View File

@@ -21,8 +21,8 @@
#include "llvm_backend_stmt.cpp"
#include "llvm_backend_proc.cpp"
char *get_default_microarchitecture() {
char * default_march = "generic";
String get_default_microarchitecture() {
String default_march = str_lit("generic");
if (build_context.metrics.arch == TargetArch_amd64) {
// NOTE(bill): x86-64-v2 is more than enough for everyone
//
@@ -32,9 +32,9 @@ char *get_default_microarchitecture() {
// 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";
default_march = str_lit("x86-64");
} else {
default_march = "x86-64-v2";
default_march = str_lit("x86-64-v2");
}
}
}
@@ -2509,16 +2509,16 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
code_mode = LLVMCodeModelKernel;
}
char const *host_cpu_name = LLVMGetHostCPUName();
char const *llvm_cpu = get_default_microarchitecture();
String host_cpu_name = copy_string(permanent_allocator(), make_string_c(LLVMGetHostCPUName()));
String llvm_cpu = get_default_microarchitecture();
char const *llvm_features = "";
if (build_context.microarch.len != 0) {
if (build_context.microarch == "native") {
llvm_cpu = host_cpu_name;
} else {
llvm_cpu = alloc_cstring(permanent_allocator(), build_context.microarch);
llvm_cpu = copy_string(permanent_allocator(), build_context.microarch);
}
if (gb_strcmp(llvm_cpu, host_cpu_name) == 0) {
if (llvm_cpu == host_cpu_name) {
llvm_features = LLVMGetHostCPUFeatures();
}
}
@@ -2578,7 +2578,7 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
for (auto const &entry : gen->modules) {
LLVMTargetMachineRef target_machine = LLVMCreateTargetMachine(
target, target_triple, llvm_cpu,
target, target_triple, (const char *)llvm_cpu.text,
llvm_features,
code_gen_level,
reloc_mode,

View File

@@ -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,237 +1642,240 @@ 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");
@@ -1880,74 +1883,77 @@ gb_internal void print_show_help(String const arg0, String const &command) {
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, "");
}
@@ -1956,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
@@ -2538,6 +2544,7 @@ int main(int arg_count, char const **arg_ptr) {
}
}
String default_march = get_default_microarchitecture();
if (print_microarch_list) {
if (build_context.microarch != "?") {
gb_printf("Unknown microarchitecture '%.*s'.\n", LIT(build_context.microarch));
@@ -2548,8 +2555,6 @@ int main(int arg_count, char const **arg_ptr) {
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;
@@ -2568,6 +2573,7 @@ int main(int arg_count, char const **arg_ptr) {
}
if (build_context.show_debug_messages) {
debugf("Selected microarch: %.*s\n", LIT(default_march));
for_array(i, build_context.build_paths) {
String build_path = path_to_string(heap_allocator(), build_context.build_paths[i]);
debugf("build_paths[%ld]: %.*s\n", i, LIT(build_path));

View File

@@ -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

View File

@@ -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

View File

@@ -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.")
}

View File

@@ -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)
}

BIN
vendor/raylib/linux/libraygui.a vendored Normal file

Binary file not shown.

BIN
vendor/raylib/linux/libraygui.so.3.6 vendored Executable file

Binary file not shown.

View File

@@ -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

View File

@@ -163,21 +163,21 @@ PixelFormatEnum :: enum u32 {
ABGR32 = ABGR8888 when ODIN_ENDIAN == .Big else RGBA8888,
YV12 = /**< Planar mode: Y + V + U (3 planes) */
'Y'<<24 | 'V'<<16 | '1'<<8 | '2'<<0,
'Y'<<0 | 'V'<<8 | '1'<<16 | '2'<<24,
IYUV = /**< Planar mode: Y + U + V (3 planes) */
'I'<<24 | 'Y'<<16 | 'U'<<8 | 'V'<<0,
'I'<<0 | 'Y'<<8 | 'U'<<16 | 'V'<<24,
YUY2 = /**< Packed mode: Y0+U0+Y1+V0 (1 plane) */
'Y'<<24 | 'U'<<16 | 'Y'<<8 | '2'<<0,
'Y'<<0 | 'U'<<8 | 'Y'<<16 | '2'<<24,
UYVY = /**< Packed mode: U0+Y0+V0+Y1 (1 plane) */
'U'<<24 | 'Y'<<16 | 'V'<<8 | 'Y'<<0,
'U'<<0 | 'Y'<<8 | 'V'<<16 | 'Y'<<24,
YVYU = /**< Packed mode: Y0+V0+Y1+U0 (1 plane) */
'Y'<<24 | 'V'<<16 | 'Y'<<8 | 'U'<<0,
'Y'<<0 | 'V'<<8 | 'Y'<<16 | 'U'<<24,
NV12 = /**< Planar mode: Y + U/V interleaved (2 planes) */
'N'<<24 | 'V'<<16 | '1'<<8 | '2'<<0,
'N'<<0 | 'V'<<8 | '1'<<16 | '2'<<24,
NV21 = /**< Planar mode: Y + V/U interleaved (2 planes) */
'N'<<24 | 'V'<<16 | '2'<<8 | '1'<<0,
'N'<<0 | 'V'<<8 | '2'<<16 | '1'<<24,
EXTERNAL_OES = /**< Android video texture format */
'O'<<24 | 'E'<<16 | 'S'<<8 | ' '<<0,
'O'<<0 | 'E'<<8 | 'S'<<16 | ' '<<24,
}

4
vendor/x11/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
# TODO(flysand): Remove this file.
*.i

651
vendor/x11/xlib/xlib_const.odin vendored Normal file
View File

@@ -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,
}

1681
vendor/x11/xlib/xlib_keysym.odin vendored Normal file

File diff suppressed because it is too large Load Diff

1909
vendor/x11/xlib/xlib_procs.odin vendored Normal file

File diff suppressed because it is too large Load Diff

1307
vendor/x11/xlib/xlib_types.odin vendored Normal file

File diff suppressed because it is too large Load Diff