From 42364f2fcee1f0f588b006bf2b7e9bc6f88acb93 Mon Sep 17 00:00:00 2001 From: phillvancejr Date: Fri, 4 Feb 2022 13:15:43 -0500 Subject: [PATCH] sync with main --- core/bindgen/c-parser-evaluate.odin | 266 +++++++ core/bindgen/c-parser-helpers.odin | 267 +++++++ core/bindgen/c-parser-nodes.odin | 132 ++++ core/bindgen/c-parser.odin | 840 +++++++++++++++++++++++ core/bindgen/errors.odin | 44 ++ core/bindgen/generator-clean.odin | 284 ++++++++ core/bindgen/generator-export.odin | 166 +++++ core/bindgen/generator-helpers.odin | 392 +++++++++++ core/bindgen/generator.odin | 205 ++++++ vendor/stb/lib/darwin/libstb_image.a | Bin 0 -> 55744 bytes vendor/stb/lib/darwin/stb_image.a | Bin 0 -> 97544 bytes vendor/stb/lib/darwin/stb_image_resize.a | Bin 0 -> 36824 bytes vendor/stb/lib/darwin/stb_image_write.a | Bin 0 -> 32896 bytes vendor/stb/lib/darwin/stb_rect_pack.a | Bin 0 -> 5064 bytes vendor/stb/lib/darwin/stb_truetype.a | Bin 0 -> 67008 bytes wasm-ld | 1 + 16 files changed, 2597 insertions(+) create mode 100644 core/bindgen/c-parser-evaluate.odin create mode 100644 core/bindgen/c-parser-helpers.odin create mode 100644 core/bindgen/c-parser-nodes.odin create mode 100644 core/bindgen/c-parser.odin create mode 100644 core/bindgen/errors.odin create mode 100644 core/bindgen/generator-clean.odin create mode 100644 core/bindgen/generator-export.odin create mode 100644 core/bindgen/generator-helpers.odin create mode 100644 core/bindgen/generator.odin create mode 100644 vendor/stb/lib/darwin/libstb_image.a create mode 100644 vendor/stb/lib/darwin/stb_image.a create mode 100644 vendor/stb/lib/darwin/stb_image_resize.a create mode 100644 vendor/stb/lib/darwin/stb_image_write.a create mode 100644 vendor/stb/lib/darwin/stb_rect_pack.a create mode 100644 vendor/stb/lib/darwin/stb_truetype.a create mode 120000 wasm-ld diff --git a/core/bindgen/c-parser-evaluate.odin b/core/bindgen/c-parser-evaluate.odin new file mode 100644 index 000000000..13cb5042c --- /dev/null +++ b/core/bindgen/c-parser-evaluate.odin @@ -0,0 +1,266 @@ +package bindgen + +import "core:fmt" +import "core:strconv" + +// Evaluates an expression to a i64, without checking. +evaluate_i64 :: proc(data : ^ParserData) -> i64 { + ok : bool; + value : LiteralValue; + + value, ok = evaluate(data); + return value.(i64); +} + +// Evaluate an expression, returns whether it succeeded. +evaluate :: proc(data : ^ParserData) -> (LiteralValue, bool) { + return evaluate_level_5(data); +} + +// @note Evaluate levels numbers are based on +// https://en.cppreference.com/w/c/language/operator_precedence. + +// Bitwise shift level. +evaluate_level_5 :: proc(data : ^ParserData) -> (value : LiteralValue, ok : bool) { + value, ok = evaluate_level_4(data); + if !ok do return; + + invalid_value : LiteralValue; + token := peek_token(data); + + if token == "<<" { + v : LiteralValue; + eat_token(data); + + v, ok = evaluate_level_5(data); + if is_i64(v) do value = value.(i64) << cast(u64) v.(i64); + else do invalid_value = v; + } else if token == ">>" { + v : LiteralValue; + eat_token(data); + + v, ok = evaluate_level_5(data); + if is_i64(v) do value = value.(i64) >> cast(u64) v.(i64); + else do invalid_value = v; + } + + if invalid_value != nil { + print_warning("Invalid operand for bitwise shift ", invalid_value); + } + + return; +} + +// Additive level. +evaluate_level_4 :: proc(data : ^ParserData) -> (value : LiteralValue, ok : bool) { + value, ok = evaluate_level_3(data); + if !ok do return; + + token := peek_token(data); + if token == "+" { + v : LiteralValue; + eat_token(data); + v, ok = evaluate_level_4(data); + if is_i64(v) do value = value.(i64) + v.(i64); + else if is_f64(v) do value = value.(f64) + v.(f64); + } + else if token == "-" { + v : LiteralValue; + eat_token(data); + v, ok = evaluate_level_4(data); + if is_i64(v) do value = value.(i64) - v.(i64); + else if is_f64(v) do value = value.(f64) - v.(f64); + } + + return; +} + +// Multiplicative level. +evaluate_level_3 :: proc(data : ^ParserData) -> (value : LiteralValue, ok : bool) { + value, ok = evaluate_level_2(data); + if !ok do return; + + token := peek_token(data); + if token == "*" { + v : LiteralValue; + eat_token(data); + v, ok = evaluate_level_3(data); + if is_i64(v) do value = value.(i64) * v.(i64); + else if is_f64(v) do value = value.(f64) * v.(f64); + } + else if token == "/" { + v : LiteralValue; + eat_token(data); + v, ok = evaluate_level_3(data); + if is_i64(v) do value = value.(i64) / v.(i64); + else if is_f64(v) do value = value.(f64) / v.(f64); + } + + return; +} + +// Prefix level. +evaluate_level_2 :: proc(data : ^ParserData) -> (value : LiteralValue, ok : bool) { + token := peek_token(data); + + // Bitwise not + if token == "~" { + check_and_eat_token(data, "~"); + value, ok = evaluate_level_2(data); + value = ~value.(i64); + } + else { + // @note Should call evaluate_level_1, but we don't have that because we do not dereferenciation. + value, ok = evaluate_level_0(data); + } + + return; +} + +// Does not try to compose with arithmetics, it just evaluates one single expression. +evaluate_level_0 :: proc(data : ^ParserData) -> (value : LiteralValue, ok : bool) { + ok = true; + value = 0; + token := peek_token(data); + + // Parentheses + if token == "(" { + value, ok = evaluate_parentheses(data); + } // Number literal + else if (token[0] == '-') || (token[0] >= '0' && token[0] <= '9') { + value, ok = evaluate_number_literal(data); + } // String literal + else if token[0] == '"' { + value = evaluate_string_literal(data); + } // Function-like + else if token == "sizeof" { + value = evaluate_sizeof(data); + } // Knowned literal + else if token in data.knownedLiterals { + value = evaluate_knowned_literal(data); + } // Custom expression + else if token in data.options.customExpressionHandlers { + value = data.options.customExpressionHandlers[token](data); + } + else { + print_warning("Unknown token ", token, " for expression evaluation."); + ok = false; + } + + return; +} + +evaluate_sizeof :: proc(data : ^ParserData) -> LiteralValue { + print_warning("Using 'sizeof()'. Currently not able to precompute that. Please check generated code."); + + check_and_eat_token(data, "sizeof"); + check_and_eat_token(data, "("); + for data.bytes[data.offset] != ')' { + data.offset += 1; + } + check_and_eat_token(data, ")"); + return 1; +} + +evaluate_parentheses :: proc(data : ^ParserData) -> (value : LiteralValue, ok : bool) { + check_and_eat_token(data, "("); + + // Cast to int (via "(int)" syntax) + token := peek_token(data); + if token == "int" { + check_and_eat_token(data, "int"); + check_and_eat_token(data, ")"); + value, ok = evaluate(data); + return; + } // Cast to enum value (via "(enum XXX)" syntax) + else if token == "enum" { + check_and_eat_token(data, "enum"); + eat_token(data); + check_and_eat_token(data, ")"); + value, ok = evaluate(data); + return; + } + + value, ok = evaluate(data); + check_and_eat_token(data, ")"); + return; +} + +evaluate_number_literal :: proc(data : ^ParserData, loc := #caller_location) -> (value : LiteralValue, ok : bool) { + token := parse_any(data); + + // Unary - before numbers + numberLitteral := token; + for token == "-" { + token = parse_any(data); + numberLitteral = tcat(numberLitteral, token); + } + token = numberLitteral; + + // Check if any point or scientific notation in number + foundPointOrExp := false; + for c in token { + if c == '.' || c == 'e' || c == 'E' { + foundPointOrExp = true; + break; + } + } + + isHexadecimal := len(token) >= 2 && token[:2] == "0x"; + + // Computing postfix + tokenLength := len(token); + l := tokenLength - 1; + for l > 0 { + c := token[l]; + if c >= '0' && c <= '9' { break; } + if isHexadecimal && ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) { break; } + l -= 1; + } + + postfix : string; + if l != tokenLength - 1 { + postfix = token[l+1:]; + token = token[:l+1]; + } + + if postfix != "" && (postfix[0] == 'u' || postfix[0] == 'U') { + print_warning("Found number litteral '", token, "' with unsigned postfix, we cast it to an int64 internally."); + } + + // Floating point + if !isHexadecimal && (foundPointOrExp || postfix == "f") { + value, ok = strconv.parse_f64(token); + } // Integer + else { + value, ok = strconv.parse_i64(token); + } + + if !ok { + print_error(data, loc, "Expected number litteral but got '", token, "'."); + } + + return value, ok; +} + +evaluate_string_literal :: proc(data : ^ParserData) -> string { + token := parse_any(data); + return token; +} + +evaluate_knowned_literal :: proc(data : ^ParserData) -> LiteralValue { + token := parse_any(data); + return data.knownedLiterals[token]; +} + +is_i64 :: proc(value : LiteralValue) -> (ok : bool) { + v : i64; + v, ok = value.(i64); + return ok; +} + +is_f64 :: proc(value : LiteralValue) -> (ok : bool) { + v : f64; + v, ok = value.(f64); + return ok; +} diff --git a/core/bindgen/c-parser-helpers.odin b/core/bindgen/c-parser-helpers.odin new file mode 100644 index 000000000..a99d83dd2 --- /dev/null +++ b/core/bindgen/c-parser-helpers.odin @@ -0,0 +1,267 @@ +package bindgen + +import "core:os" +import "core:fmt" +import "core:strings" +import "core:strconv" + +// Extract from start (included) to end (excluded) offsets +extract_string :: proc(data : ^ParserData, startOffset : u32, endOffset : u32) -> string { + return strings.string_from_ptr(&data.bytes[startOffset], cast(int) (endOffset - startOffset)); +} + +// Peek the end offset of the next token +peek_token_end :: proc(data : ^ParserData) -> u32 { + offset : u32; + + for true { + eat_whitespaces_and_comments(data); + if data.offset >= data.bytesLength { + return data.bytesLength; + } + offset = data.offset; + + // Identifier + if (data.bytes[offset] >= 'a' && data.bytes[offset] <= 'z') || + (data.bytes[offset] >= 'A' && data.bytes[offset] <= 'Z') || + (data.bytes[offset] == '_') { + offset += 1; + for (data.bytes[offset] >= 'a' && data.bytes[offset] <= 'z') || + (data.bytes[offset] >= 'A' && data.bytes[offset] <= 'Z') || + (data.bytes[offset] >= '0' && data.bytes[offset] <= '9') || + (data.bytes[offset] == '_') { + offset += 1; + } + } + if offset != data.offset { + // Nothing to do: we found an identifier + } // Number literal + else if (data.bytes[offset] >= '0' && data.bytes[offset] <= '9') { + offset += 1; + // Hexademical literal + if data.bytes[offset - 1] == '0' && data.bytes[offset] == 'x' { + offset += 1; + for (data.bytes[offset] >= '0' && data.bytes[offset] <= '9') || + (data.bytes[offset] >= 'a' && data.bytes[offset] <= 'f') || + (data.bytes[offset] >= 'A' && data.bytes[offset] <= 'F') { + offset += 1; + } + } // Basic number literal + else { + for (data.bytes[offset] >= '0' && data.bytes[offset] <= '9') || + data.bytes[offset] == '.' { + offset += 1; + } + + if (data.bytes[offset] == 'e' || data.bytes[offset] == 'E') { + offset += 1; + if data.bytes[offset] == '-' { + offset += 1; + } + } + + for (data.bytes[offset] >= '0' && data.bytes[offset] <= '9') { + offset += 1; + } + } + + // Number suffix? + for (data.bytes[offset] == 'u' || data.bytes[offset] == 'U') || + (data.bytes[offset] == 'l' || data.bytes[offset] == 'L') || + (data.bytes[offset] == 'f') { + offset += 1; + } + } // String literal + else if data.bytes[offset] == '"' { + offset += 1; + for data.bytes[offset-1] == '\\' || data.bytes[offset] != '"' { + offset += 1; + } + offset += 1; + } // Possible shifts + else if data.bytes[offset] == '<' || data.bytes[offset] == '>' { + offset += 1; + if data.bytes[offset] == data.bytes[offset-1] { + offset += 1; + } + } // Single character + else { + offset += 1; + } + + token := extract_string(data, data.offset, offset); + + // Ignore __attribute__ + if token == "__attribute__" { + print_warning("__attribute__ is ignored."); + + for data.bytes[offset] != '(' { + offset += 1; + } + + parenthesesCount := 1; + for true { + offset += 1; + if data.bytes[offset] == '(' do parenthesesCount += 1; + else if data.bytes[offset] == ')' do parenthesesCount -= 1; + if parenthesesCount == 0 do break; + } + offset += 1; + + data.offset = offset; + } // Ignore certain keywords + else if (token == "inline" || token == "__inline" || token == "static" + || token == "restrict" || token == "__restrict" + || token == "volatile" + || token == "__extension__") { + data.offset = offset; + } // Ignore ignored tokens ;) + else { + for ignoredToken in data.options.ignoredTokens { + if token == ignoredToken { + data.offset = offset; + break; + } + } + } + + if data.offset != offset { + break; + } + } + + return offset; +} + +// Peek the next token (just eating whitespaces and comment) +peek_token :: proc(data : ^ParserData) -> string { + tokenEnd := peek_token_end(data); + if tokenEnd == data.bytesLength { + return "EOF"; + } + return extract_string(data, data.offset, tokenEnd); +} + +// Find the end of the define directive (understanding endline backslashes) +// @note Tricky cases like comments hiding a backslash effect are not handled. +peek_define_end :: proc(data : ^ParserData) -> u32 { + defineEndOffset := data.offset; + for data.bytes[defineEndOffset-1] == '\\' || data.bytes[defineEndOffset] != '\n' { + defineEndOffset += 1; + } + return defineEndOffset; +} + +eat_comment :: proc(data : ^ParserData) { + if data.offset >= data.bytesLength || data.bytes[data.offset] != '/' { + return; + } + + // Line comment + if data.bytes[data.offset + 1] == '/' { + eat_line(data); + } // Range comment + else if data.bytes[data.offset + 1] == '*' { + data.offset += 2; + for data.bytes[data.offset] != '*' || data.bytes[data.offset + 1] != '/' { + data.offset += 1; + } + data.offset += 2; + } +} + +// Eat whitespaces +eat_whitespaces :: proc(data : ^ParserData) { + // Effective whitespace + for data.offset < data.bytesLength && + (data.bytes[data.offset] == ' ' || data.bytes[data.offset] == '\t' || + data.bytes[data.offset] == '\r' || data.bytes[data.offset] == '\n') { + if data.bytes[data.offset] == '\n' && data.bytes[data.offset] != '\\' { + data.foundFullReturn = true; + } + data.offset += 1; + } +} + +// Removes whitespaces and comments +eat_whitespaces_and_comments :: proc(data : ^ParserData) { + startOffset : u32 = 0xFFFFFFFF; + for startOffset != data.offset { + startOffset = data.offset; + eat_whitespaces(data); + eat_comment(data); + } +} + +// Eat full line +eat_line :: proc(data : ^ParserData) { + for ; data.bytes[data.offset] != '\n'; data.offset += 1 { + } +} + +// Eat a line, and repeat if it ends with a backslash +eat_define_lines :: proc(data : ^ParserData) { + for data.bytes[data.offset-1] == '\\' || data.bytes[data.offset] != '\n' { + data.offset += 1; + } +} + +// Eat next token +eat_token :: proc(data : ^ParserData) { + data.offset = peek_token_end(data); +} + +// Eat next token +check_and_eat_token :: proc(data : ^ParserData, expectedToken : string, loc := #caller_location) { + token := peek_token(data); + if token != expectedToken { + print_error(data, loc, "Expected ", expectedToken, " but found ", token, "."); + } + data.offset += cast(u32) len(token); +} + +// Check whether the next token is outside #define range +is_define_end :: proc(data : ^ParserData) -> bool { + defineEnd := peek_define_end(data); + tokenEnd := peek_token_end(data); + + return (defineEnd < tokenEnd); +} + +// Check if the current #define is a macro definition +is_define_macro :: proc(data : ^ParserData) -> bool { + startOffset := data.offset; + defer data.offset = startOffset; + + token := parse_any(data); + if token != "(" do return false; + + // Find the other parenthesis + parenthesesCount := 1; + for parenthesesCount != 0 { + token = parse_any(data); + if token == "(" do parenthesesCount += 1; + else if token == ")" do parenthesesCount -= 1; + } + + // Its a macro if after the parentheses, it's not the end + return !is_define_end(data); +} + +// @note Very slow function to get line number, +// use only for errors. +// @todo Well, this does not seem to work properly, UTF-8 problem? +get_line_column :: proc(data : ^ParserData) -> (u32, u32) { + line : u32 = 1; + column : u32 = 0; + for i : u32 = 0; i < data.offset; i += 1 { + if data.bytes[i] == '\n' { + column = 0; + line += 1; + } + else { + column += 1; + } + } + return line, column; +} diff --git a/core/bindgen/c-parser-nodes.odin b/core/bindgen/c-parser-nodes.odin new file mode 100644 index 000000000..0620e0187 --- /dev/null +++ b/core/bindgen/c-parser-nodes.odin @@ -0,0 +1,132 @@ +package bindgen + +DefineNode :: struct { + name : string, + value : LiteralValue, +} + +StructDefinitionNode :: struct { + name : string, + members : [dynamic]StructOrUnionMember, + forwardDeclared : bool, +} + +UnionDefinitionNode :: struct { + name : string, + members : [dynamic]StructOrUnionMember, +} + +EnumDefinitionNode :: struct { + name : string, + members : [dynamic]EnumMember, +} + +FunctionDeclarationNode :: struct { + name : string, + returnType : Type, + parameters : [dynamic]FunctionParameter, +} + +TypedefNode :: struct { + name : string, + type : Type, +} + +Nodes :: struct { + defines : [dynamic]DefineNode, + enumDefinitions : [dynamic]EnumDefinitionNode, + unionDefinitions : [dynamic]UnionDefinitionNode, + structDefinitions : [dynamic]StructDefinitionNode, + functionDeclarations : [dynamic]FunctionDeclarationNode, + typedefs : [dynamic]TypedefNode, +} + +LiteralValue :: union { + i64, + f64, + string, +} + +// Type, might be an array +Type :: struct { + base : BaseType, + dimensions : [dynamic]u64, // Array dimensions +} + +BaseType :: union { + BuiltinType, + PointerType, + IdentifierType, + FunctionType, + FunctionPointerType, +} + +BuiltinType :: enum { + Unknown, + Void, + Int, + UInt, + LongInt, + ULongInt, + LongLongInt, + ULongLongInt, + ShortInt, + UShortInt, + Char, + SChar, + UChar, + Float, + Double, + LongDouble, + + // Not defined by C language but in + Int8, + Int16, + Int32, + Int64, + UInt8, + UInt16, + UInt32, + UInt64, + Size, + SSize, + PtrDiff, + UIntPtr, + IntPtr, +} + +PointerType :: struct { + type : ^Type, // Pointer is there to prevent definition cycle. Null means void. +} + +IdentifierType :: struct { + name : string, + anonymous : bool, // An anonymous identifier can be hard-given a name in some contexts. +} + +FunctionType :: struct { + returnType : ^Type, // Pointer is there to prevent definition cycle. Null means void. + parameters : [dynamic]FunctionParameter, +} + +FunctionPointerType :: struct { + name : string, + returnType : ^Type, // Pointer is there to prevent definition cycle. Null means void. + parameters : [dynamic]FunctionParameter, +} + +EnumMember :: struct { + name : string, + value : i64, + hasValue : bool, +} + +StructOrUnionMember :: struct { + name : string, + type : Type, +} + +FunctionParameter :: struct { + name : string, + type : Type, +} diff --git a/core/bindgen/c-parser.odin b/core/bindgen/c-parser.odin new file mode 100644 index 000000000..c3ef4937f --- /dev/null +++ b/core/bindgen/c-parser.odin @@ -0,0 +1,840 @@ +package bindgen + +import "core:os" +import "core:fmt" +import "core:strings" +import "core:strconv" + +// Global counters +anonymousStructCount := 0; +anonymousUnionCount := 0; +anonymousEnumCount := 0; + +knownTypeAliases : map[string]Type; + +CustomHandler :: proc(data : ^ParserData); +CustomExpressionHandler :: proc(data : ^ParserData) -> LiteralValue; + +ParserOptions :: struct { + ignoredTokens : []string, + + // Handlers + customHandlers : map[string]CustomHandler, + customExpressionHandlers : map[string]CustomExpressionHandler, +} + +ParserData :: struct { + bytes : []u8, + bytesLength : u32, + offset : u32, + + // References + nodes : Nodes, + options : ^ParserOptions, + + // Knowned values + knownedLiterals : map[string]LiteralValue, + + // Whether we have eaten a '\n' character that has no backslash just before + foundFullReturn : bool, +} + +is_identifier :: proc(token : string) -> bool { + return (token[0] >= 'a' && token[0] <= 'z') || + (token[0] >= 'A' && token[0] <= 'Z') || + (token[0] == '_'); +} + +parse :: proc(bytes : []u8, options : ParserOptions, loc := #caller_location) -> Nodes { + options := options; + + data : ParserData; + data.bytes = bytes; + data.bytesLength = cast(u32) len(bytes); + data.options = &options; + + for data.offset = 0; data.offset < data.bytesLength; { + token := peek_token(&data); + if data.offset == data.bytesLength do break; + + if token in options.customHandlers { + options.customHandlers[token](&data); + } + else if token == "{" || token == "}" || token == ";" { + eat_token(&data); + } + else if token == "extern" { + check_and_eat_token(&data, "extern"); + } + else if token == "\"C\"" { + check_and_eat_token(&data, "\"C\""); + } + else if token == "#" { + parse_directive(&data); + } + else if token == "typedef" { + parse_typedef(&data); + } + else if is_identifier(token) { + parse_variable_or_function_declaration(&data); + } + else { + print_error(&data, loc, "Unexpected token: ", token, "."); + return data.nodes; + } + } + + return data.nodes; +} + +parse_any :: proc(data : ^ParserData) -> string { + offset := peek_token_end(data); + identifier := extract_string(data, data.offset, offset); + data.offset = offset; + return identifier; +} + +parse_identifier :: proc(data : ^ParserData, loc := #caller_location) -> string { + identifier := parse_any(data); + + if (identifier[0] < 'a' || identifier[0] > 'z') && + (identifier[0] < 'A' || identifier[0] > 'Z') && + (identifier[0] != '_') { + print_error(data, loc, "Expected identifier but found ", identifier, "."); + } + + return identifier; +} + +parse_type_dimensions :: proc(data : ^ParserData, type : ^Type) { + token := peek_token(data); + for token == "[" { + eat_token(data); + token = peek_token(data); + if token == "]" { + pointerType : PointerType; + pointerType.type = new(Type); + pointerType.type^ = type^; // Copy + type.base = pointerType; + delete(type.dimensions); + } else { + dimension := evaluate_i64(data); + append(&type.dimensions, cast(u64) dimension); + } + check_and_eat_token(data, "]"); + token = peek_token(data); + } +} + +// This will parse anything that look like a type: +// Builtin: char/int/float/... +// Struct-like: struct A/struct { ... }/enum E +// Function pointer: void (*f)(...) +// +// Definition permitted: If a struct-like definition is found, it will generate +// the according Node and return a corresponding type. +parse_type :: proc(data : ^ParserData, definitionPermitted := false) -> Type { + type : Type; + + // Eat qualifiers + token := peek_token(data); + if token == "const" { + eat_token(data); + token = peek_token(data); + } + + // Parse main type + if token == "struct" { + type.base = parse_struct_type(data, definitionPermitted); + } + else if token == "union" { + type.base = parse_union_type(data); + } + else if token == "enum" { + type.base = parse_enum_type(data); + } + else { + // Test builtin type + type.base = parse_builtin_type(data); + if type.base.(BuiltinType) == BuiltinType.Unknown { + // Basic identifier type + identifierType : IdentifierType; + identifierType.name = parse_identifier(data); + type.base = identifierType; + } + } + + // Eat qualifiers + token = peek_token(data); + if token == "const" { + eat_token(data); + token = peek_token(data); + } + + // Check if pointer + for token == "*" { + check_and_eat_token(data, "*"); + token = peek_token(data); + + pointerType : PointerType; + pointerType.type = new(Type); + pointerType.type^ = type; // Copy + + type.base = pointerType; + + // Eat qualifiers + if token == "const" { + eat_token(data); + token = peek_token(data); + } + } + + // Parse array dimensions if any. + parse_type_dimensions(data, &type); + + // ----- Function pointer type + + if token == "(" { + check_and_eat_token(data, "("); + check_and_eat_token(data, "*"); + + functionPointerType : FunctionPointerType; + functionPointerType.returnType = new(Type); + functionPointerType.returnType^ = type; + functionPointerType.name = parse_identifier(data); + + check_and_eat_token(data, ")"); + parse_function_parameters(data, &functionPointerType.parameters); + + type.base = functionPointerType; + } + + return type; +} + +parse_builtin_type :: proc(data : ^ParserData) -> BuiltinType { + previousBuiltinType := BuiltinType.Unknown; + intFound := false; + shortFound := false; + signedFound := false; + unsignedFound := false; + longCount := 0; + + for true { + token := peek_token(data); + + // Attribute + attributeFound := true; + if token == "long" do longCount += 1; + else if token == "short" do shortFound = true; + else if token == "unsigned" do unsignedFound = true; + else if token == "signed" do signedFound = true; + else do attributeFound = false; + if attributeFound { eat_token(data); continue; } + + // Known type alias + if token in knownTypeAliases { + builtinType, ok := knownTypeAliases[token].base.(BuiltinType); + if ok { + eat_token(data); + previousBuiltinType = builtinType; + } + break; + } + + // Classic type and standard types + if token == "void" { eat_token(data); return BuiltinType.Void; } + else if token == "int" { + eat_token(data); + intFound = true; + } + else if token == "float" { eat_token(data); return BuiltinType.Float; } + else if token == "double" { + eat_token(data); + if longCount == 0 do return BuiltinType.Double; + else do return BuiltinType.LongDouble; + } + else if token == "char" { + eat_token(data); + if signedFound do return BuiltinType.SChar; + else if unsignedFound do return BuiltinType.UChar; + else do return BuiltinType.Char; + } + else if token == "__int8" { + // @note :MicrosoftDumminess __intX are Microsoft's fixed-size integers + // https://docs.microsoft.com/fr-fr/cpp/cpp/int8-int16-int32-int64 + // and for unsigned version, they prefixed it with "unsigned"... + eat_token(data); + if unsignedFound do return BuiltinType.UInt8; + else do return BuiltinType.Int8; + } + else if token == "__int16" { + eat_token(data); + if unsignedFound do return BuiltinType.UInt16; + else do return BuiltinType.Int16; + } + else if token == "__int32" { + eat_token(data); + if unsignedFound do return BuiltinType.UInt32; + else do return BuiltinType.Int32; + } + else if token == "__int64" { + eat_token(data); + if unsignedFound do return BuiltinType.UInt64; + else do return BuiltinType.Int64; + } + else if token == "int8_t" { eat_token(data); return BuiltinType.Int8; } + else if token == "int16_t" { eat_token(data); return BuiltinType.Int16; } + else if token == "int32_t" { eat_token(data); return BuiltinType.Int32; } + else if token == "int64_t" { eat_token(data); return BuiltinType.Int64; } + else if token == "uint8_t" { eat_token(data); return BuiltinType.UInt8; } + else if token == "uint16_t" { eat_token(data); return BuiltinType.UInt16; } + else if token == "uint32_t" { eat_token(data); return BuiltinType.UInt32; } + else if token == "uint64_t" { eat_token(data); return BuiltinType.UInt64; } + else if token == "size_t" { eat_token(data); return BuiltinType.Size; } + else if token == "ssize_t" { eat_token(data); return BuiltinType.SSize; } + else if token == "ptrdiff_t" { eat_token(data); return BuiltinType.PtrDiff; } + else if token == "uintptr_t" { eat_token(data); return BuiltinType.UIntPtr; } + else if token == "intptr_t" { eat_token(data); return BuiltinType.IntPtr; } + + break; + } + + // Adapt previous builtin type + if previousBuiltinType == BuiltinType.ShortInt { + shortFound = true; + } + else if previousBuiltinType == BuiltinType.Int { + intFound = true; + } + else if previousBuiltinType == BuiltinType.LongInt { + longCount += 1; + } + else if previousBuiltinType == BuiltinType.LongLongInt { + longCount += 2; + } + else if previousBuiltinType == BuiltinType.UShortInt { + unsignedFound = true; + shortFound = true; + } + else if previousBuiltinType == BuiltinType.UInt { + unsignedFound = true; + } + else if previousBuiltinType == BuiltinType.ULongInt { + unsignedFound = true; + longCount += 1; + } + else if previousBuiltinType == BuiltinType.ULongLongInt { + unsignedFound = true; + longCount += 2; + } + else if (previousBuiltinType != BuiltinType.Unknown) { + return previousBuiltinType; // float, void, etc. + } + + // Implicit and explicit int + if intFound || shortFound || unsignedFound || signedFound || longCount > 0 { + if unsignedFound { + if shortFound do return BuiltinType.UShortInt; + if longCount == 0 do return BuiltinType.UInt; + if longCount == 1 do return BuiltinType.ULongInt; + if longCount == 2 do return BuiltinType.ULongLongInt; + } else { + if shortFound do return BuiltinType.ShortInt; + if longCount == 0 do return BuiltinType.Int; + if longCount == 1 do return BuiltinType.LongInt; + if longCount == 2 do return BuiltinType.LongLongInt; + } + } + + return BuiltinType.Unknown; +} + +parse_struct_type :: proc(data : ^ParserData, definitionPermitted : bool) -> IdentifierType { + check_and_eat_token(data, "struct"); + + type : IdentifierType; + token := peek_token(data); + + if !definitionPermitted || token != "{" { + type.name = parse_identifier(data); + token = peek_token(data); + } else { + type.name = tcat("AnonymousStruct", anonymousStructCount); + type.anonymous = true; + anonymousStructCount += 1; + } + + if token == "{" { + node := parse_struct_definition(data); + node.name = type.name; + } else if definitionPermitted { + // @note Whatever happens, we create a definition of the struct, + // as it might be used to forward declare it and then use it only with a pointer. + // This for instance the pattern for xcb_connection_t which definition + // is never known from user API. + node : StructDefinitionNode; + node.forwardDeclared = false; + node.name = type.name; + append(&data.nodes.structDefinitions, node); + } + + return type; +} + +parse_union_type :: proc(data : ^ParserData) -> IdentifierType { + check_and_eat_token(data, "union"); + + type : IdentifierType; + token := peek_token(data); + + if token != "{" { + type.name = parse_identifier(data); + token = peek_token(data); + } else { + type.name = tcat("AnonymousUnion", anonymousUnionCount); + type.anonymous = true; + anonymousUnionCount += 1; + } + + if token == "{" { + node := parse_union_definition(data); + node.name = type.name; + } + + return type; +} + +parse_enum_type :: proc(data : ^ParserData) -> IdentifierType { + check_and_eat_token(data, "enum"); + + type : IdentifierType; + token := peek_token(data); + + if token != "{" { + type.name = parse_identifier(data); + token = peek_token(data); + } else { + type.name = tcat("AnonymousEnum", anonymousEnumCount); + type.anonymous = true; + anonymousEnumCount += 1; + } + + if token == "{" { + node := parse_enum_definition(data); + node.name = type.name; + } + + return type; +} + +/** + * We only care about defines of some value + */ +parse_directive :: proc(data : ^ParserData) { + check_and_eat_token(data, "#"); + + token := peek_token(data); + if token == "define" { + parse_define(data); + } // We ignore all other directives + else { + eat_line(data); + } +} + +parse_define :: proc(data : ^ParserData) { + check_and_eat_token(data, "define"); + data.foundFullReturn = false; + + node : DefineNode; + node.name = parse_identifier(data); + + // Does it look like end? It might be a #define with no expression + if is_define_end(data) { + node.value = 1; + append(&data.nodes.defines, node); + data.knownedLiterals[node.name] = node.value; + } // Macros are ignored + else if is_define_macro(data) { + print_warning("Ignoring define macro for ", node.name, "."); + } + else { + literalValue, ok := evaluate(data); + if ok { + node.value = literalValue; + append(&data.nodes.defines, node); + data.knownedLiterals[node.name] = node.value; + } + else { + print_warning("Ignoring define expression for ", node.name, "."); + } + } + + // Evaluating the expression, we might have already eaten a full return, + // if so, do nothing. + if !data.foundFullReturn { + eat_define_lines(data); + } +} + +// @fixme Move +change_anonymous_node_name :: proc (data : ^ParserData, oldName : string, newName : string) -> bool { + for i := 0; i < len(data.nodes.structDefinitions); i += 1 { + if data.nodes.structDefinitions[i].name == oldName { + data.nodes.structDefinitions[i].name = newName; + return true; + } + } + + for i := 0; i < len(data.nodes.enumDefinitions); i += 1 { + if data.nodes.enumDefinitions[i].name == oldName { + data.nodes.enumDefinitions[i].name = newName; + return true; + } + } + + for i := 0; i < len(data.nodes.unionDefinitions); i += 1 { + if data.nodes.unionDefinitions[i].name == oldName { + data.nodes.unionDefinitions[i].name = newName; + return true; + } + } + + return false; +} + +/** + * Type aliasing. + * typedef ; + */ +parse_typedef :: proc(data : ^ParserData) { + check_and_eat_token(data, "typedef"); + + // @note Struct-like definitions (and such) + // are generated within type parsing. + // + // So that typedef struct { int foo; }* Ap; is valid. + + // Parsing type + node : TypedefNode; + node.type = parse_type(data, true); + + if sourceType, ok := node.type.base.(FunctionPointerType); ok { + node.name = sourceType.name; + } else { + node.name = parse_identifier(data); + } + + // Checking if function type + token := peek_token(data); + if token == "(" { + functionType : FunctionType; + functionType.returnType = new(Type); + functionType.returnType^ = node.type; + + parse_function_parameters(data, &functionType.parameters); + + node.type.base = functionType; + } + + // Checking if array + parse_type_dimensions(data, &node.type); + + // If the underlying type is anonymous, + // we just affect it the name. + addTypedefNode := true; + if identifierType, ok := node.type.base.(IdentifierType); ok { + if identifierType.anonymous { + addTypedefNode = !change_anonymous_node_name(data, identifierType.name, node.name); + } + } + + if addTypedefNode { + knownTypeAliases[node.name] = node.type; + append(&data.nodes.typedefs, node); + } + + check_and_eat_token(data, ";"); + + // @note Commented tool for debug + // fmt.println("Typedef: ", node.type, node.name); +} + +parse_struct_definition :: proc(data : ^ParserData) -> ^StructDefinitionNode { + node : StructDefinitionNode; + node.forwardDeclared = false; + parse_struct_or_union_members(data, &node.members); + + append(&data.nodes.structDefinitions, node); + return &data.nodes.structDefinitions[len(data.nodes.structDefinitions) - 1]; +} + +parse_union_definition :: proc(data : ^ParserData) -> ^UnionDefinitionNode { + node : UnionDefinitionNode; + parse_struct_or_union_members(data, &node.members); + + append(&data.nodes.unionDefinitions, node); + return &data.nodes.unionDefinitions[len(data.nodes.unionDefinitions) - 1]; +} + +parse_enum_definition :: proc(data : ^ParserData) -> ^EnumDefinitionNode { + node : EnumDefinitionNode; + parse_enum_members(data, &node.members); + + append(&data.nodes.enumDefinitions, node); + return &data.nodes.enumDefinitions[len(data.nodes.enumDefinitions) - 1]; +} + +/** + * { + * = , + * , + * } + */ +parse_enum_members :: proc(data : ^ParserData, members : ^[dynamic]EnumMember) { + check_and_eat_token(data, "{"); + + nextMemberValue : i64 = 0; + token := peek_token(data); + for token != "}" { + member : EnumMember; + member.name = parse_identifier(data); + member.hasValue = false; + + token = peek_token(data); + if token == "=" { + check_and_eat_token(data, "="); + + member.hasValue = true; + member.value = evaluate_i64(data); + nextMemberValue = member.value; + token = peek_token(data); + } else { + member.value = nextMemberValue; + } + + data.knownedLiterals[member.name] = member.value; + nextMemberValue += 1; + + // Eat until end, as this might be a complex expression that we couldn't understand + if token != "," && token != "}" { + print_warning("Parser cannot understand fully the expression of enum member ", member.name, "."); + for token != "," && token != "}" { + eat_token(data); + token = peek_token(data); + } + } + if token == "," { + check_and_eat_token(data, ","); + token = peek_token(data); + } + + append(members, member); + } + + check_and_eat_token(data, "}"); +} + +/** + * { + * ; + * , ; + * []; + * } + */ +parse_struct_or_union_members :: proc(data : ^ParserData, structOrUnionMembers : ^[dynamic]StructOrUnionMember) { + check_and_eat_token(data, "{"); + + // To ensure unique id + unamedCount := 0; + + token := peek_token(data); + for token != "}" { + member : StructOrUnionMember; + member.type = parse_type(data, true); + + for true { + // In the case of function pointer types, the name has been parsed + // during type inspection. + if type, ok := member.type.base.(FunctionPointerType); ok { + member.name = type.name; + } + else { + // Unamed (struct or union) + token = peek_token(data); + if !is_identifier(token) { + member.name = tcat("unamed", unamedCount); + unamedCount += 1; + } + else { + member.name = parse_identifier(data); + } + } + + parse_type_dimensions(data, &member.type); + + token = peek_token(data); + if token == ":" { + check_and_eat_token(data, ":"); + print_warning("Found bitfield in struct, which is not handled correctly."); + evaluate_i64(data); + token = peek_token(data); + } + + append(structOrUnionMembers, member); + + // Multiple declarations on one line + if token == "," { + check_and_eat_token(data, ","); + continue; + } + + break; + } + + check_and_eat_token(data, ";"); + token = peek_token(data); + } + + check_and_eat_token(data, "}"); +} + +parse_variable_or_function_declaration :: proc(data : ^ParserData) { + type := parse_type(data, true); + + // If it's just a type, it might be a struct definition + token := peek_token(data); + if token == ";" { + check_and_eat_token(data, ";"); + return; + } + + // Eat array declaration if any + // @fixme The return type of a function declaration will be wrong! + for data.bytes[data.offset] == '[' { + for data.bytes[data.offset] != ']' { + data.offset += 1; + } + data.offset += 1; + } + + name := parse_identifier(data); + + token = peek_token(data); + if token == "(" { + functionDeclarationNode := parse_function_declaration(data); + functionDeclarationNode.returnType = type; + functionDeclarationNode.name = name; + return; + } else if token == "[" { + // Eat whole array declaration + for data.bytes[data.offset] == '[' { + for data.bytes[data.offset] != ']' { + data.offset += 1; + } + data.offset += 1; + } + } + + // Global variable declaration (with possible multiple declarations) + token = peek_token(data); + + for true { + if token == "," { + print_warning("Found global variable declaration '", name, "', we won't generated any binding for it."); + check_and_eat_token(data, ","); + + name = parse_identifier(data); + token = peek_token(data); + continue; + } + else if token == ";" { + if name != "" { + print_warning("Found global variable declaration '", name, "', we won't generated any binding for it."); + } + check_and_eat_token(data, ";"); + break; + } + + // Global variable assignment, considered as constant define. + node : DefineNode; + + check_and_eat_token(data, "="); + literalValue, ok := evaluate(data); + if ok { + node.name = name; + node.value = literalValue; + append(&data.nodes.defines, node); + } + else { + print_warning("Ignoring global variable expression for '", name, "'."); + } + + name = ""; + token = peek_token(data); + } +} + +parse_function_declaration :: proc(data : ^ParserData) -> ^FunctionDeclarationNode { + node : FunctionDeclarationNode; + + parse_function_parameters(data, &node.parameters); + + // Function definition? Ignore it. + token := peek_token(data); + if token == "{" { + bracesCount := 1; + for true { + data.offset += 1; + if data.bytes[data.offset] == '{' do bracesCount += 1; + else if data.bytes[data.offset] == '}' do bracesCount -= 1; + if bracesCount == 0 do break; + } + data.offset += 1; + } // Function declaration + else { + check_and_eat_token(data, ";"); + } + + append(&data.nodes.functionDeclarations, node); + return &data.nodes.functionDeclarations[len(data.nodes.functionDeclarations) - 1]; +} + +parse_function_parameters :: proc(data : ^ParserData, parameters : ^[dynamic]FunctionParameter) { + check_and_eat_token(data, "("); + + token := peek_token(data); + for token != ")" { + parameter : FunctionParameter; + + token = peek_token(data); + if token == "." { + print_warning("A function accepts variadic arguments, this is currently not handled within generated code."); + + check_and_eat_token(data, "."); + check_and_eat_token(data, "."); + check_and_eat_token(data, "."); + break; + } else { + parameter.type = parse_type(data); + } + + // Check if named parameter + token = peek_token(data); + if token != ")" && token != "," { + parameter.name = parse_identifier(data); + parse_type_dimensions(data, ¶meter.type); + token = peek_token(data); + } + + if token == "," { + eat_token(data); + token = peek_token(data); + } + + append(parameters, parameter); + } + + check_and_eat_token(data, ")"); +} diff --git a/core/bindgen/errors.odin b/core/bindgen/errors.odin new file mode 100644 index 000000000..9564c5244 --- /dev/null +++ b/core/bindgen/errors.odin @@ -0,0 +1,44 @@ +package bindgen + +import "core:fmt" +import "core:os" + +seenWarnings : map[string]bool; + +print_warning :: proc(args : ..any) { + message := tcat(..args); + + if !seenWarnings[message] { + fmt.eprint("[bindgen] Warning: ", message, "\n"); + seenWarnings[message] = true; + } +} + +print_error :: proc(data : ^ParserData, loc := #caller_location, args : ..any) { + message := tcat(..args); + + min : u32 = 0; + for i := data.offset - 1; i > 0; i -= 1 { + if data.bytes[i] == '\n' { + min = i + 1; + break; + } + } + + max := min + 200; + for i := min + 1; i < max; i += 1 { + if data.bytes[i] == '\n' { + max = i; + break; + } + } + + line, _ := get_line_column(data); + + fmt.eprint("[bindgen] Error: ", message, "\n"); + fmt.eprint("[bindgen] ... from ", loc.procedure, "\n"); + fmt.eprint("[bindgen] ... at line ", line, " within this context:\n"); + fmt.eprint("> ", extract_string(data, min, max), "\n"); + + os.exit(1); +} diff --git a/core/bindgen/generator-clean.odin b/core/bindgen/generator-clean.odin new file mode 100644 index 000000000..8dd837b10 --- /dev/null +++ b/core/bindgen/generator-clean.odin @@ -0,0 +1,284 @@ +package bindgen + +import "core:fmt" + +// Prevent keywords clashes and other tricky cases +clean_identifier :: proc(name : string) -> string { + name := name; + + if name == "" { + return name; + } + + // Starting with _? Try removing that. + for true { + if name[0] == '_' { + name = name[1:]; + } + else { + break; + } + } + + // Number + if name[0] >= '0' && name[0] <= '9' { + return tcat("_", name); + } // Keywords clash + else if name == "map" || name == "proc" || name == "opaque" || name == "in" { + return tcat("_", name); + } // Jai keywords clash + else if name == "context" || + name == "float32" || name == "float64" || + name == "s8" || name == "s16" || name == "s32" || name == "s64" || + name == "u8" || name == "u16" || name == "u32" || name == "u64" { + return tcat("_", name); + } + + return name; +} + +clean_variable_name :: proc(name : string, options : ^GeneratorOptions) -> string { + name := name; + name = change_case(name, options.variableCase); + return clean_identifier(name); +} + +clean_pseudo_type_name :: proc(structName : string, options : ^GeneratorOptions) -> string { + structName := structName; + structName = remove_postfixes(structName, options.pseudoTypePostfixes, options.pseudoTypeTransparentPostfixes); + structName = remove_prefixes(structName, options.pseudoTypePrefixes, options.pseudoTypeTransparentPrefixes); + structName = change_case(structName, options.pseudoTypeCase); + return structName; +} + +// Clean up the enum name so that it can be used to remove the prefix from enum values. +clean_enum_name_for_prefix_removal :: proc(enumName : string, options : ^GeneratorOptions) -> (string, [dynamic]string) { + enumName := enumName; + + if !options.enumValueNameRemove { + return enumName, nil; + } + + // Remove postfix and use same case convention as the enum values + removedPostfixes : [dynamic]string; + enumName, removedPostfixes = remove_postfixes_with_removed(enumName, options.enumValueNameRemovePostfixes); + enumName = change_case(enumName, options.enumValueCase); + return enumName, removedPostfixes; +} + +clean_enum_value_name :: proc(valueName : string, enumName : string, postfixes : []string, options : ^GeneratorOptions) -> string { + valueName := valueName; + + valueName = remove_prefixes(valueName, options.enumValuePrefixes, options.enumValueTransparentPrefixes); + valueName = remove_postfixes(valueName, postfixes, options.enumValueTransparentPostfixes); + + if options.enumValueNameRemove { + valueName = remove_prefixes(valueName, []string{enumName}); + } + + valueName = change_case(valueName, options.enumValueCase); + + return clean_identifier(valueName); +} + +clean_function_name :: proc(functionName : string, options : ^GeneratorOptions) -> string { + functionName := functionName; + functionName = remove_prefixes(functionName, options.functionPrefixes, options.functionTransparentPrefixes); + functionName = remove_postfixes(functionName, options.definePostfixes, options.defineTransparentPostfixes); + functionName = change_case(functionName, options.functionCase); + return functionName; +} + +clean_define_name :: proc(defineName : string, options : ^GeneratorOptions) -> string { + defineName := defineName; + defineName = remove_prefixes(defineName, options.definePrefixes, options.defineTransparentPrefixes); + defineName = remove_postfixes(defineName, options.definePostfixes, options.defineTransparentPostfixes); + defineName = change_case(defineName, options.defineCase); + return defineName; +} + +// Convert to Odin's types +clean_type :: proc(data : ^GeneratorData, type : Type, baseTab : string = "", explicitSharpType := true) -> string { + output := ""; + + for dimension in type.dimensions { + output = tcat(output, "[", dimension, "]"); + } + output = tcat(output, clean_base_type(data, type.base, baseTab, explicitSharpType)); + + return output; +} + +clean_base_type :: proc(data : ^GeneratorData, baseType : BaseType, baseTab : string = "", explicitSharpType := true) -> string { + options := data.options; + + if _type, ok := baseType.(BuiltinType); ok { + if _type == BuiltinType.Void do return options.mode == "jai" ? "void" : ""; + else if _type == BuiltinType.Int do return options.mode == "jai" ? "s64" : "_c.int"; + else if _type == BuiltinType.UInt do return options.mode == "jai" ? "u64" :"_c.uint"; + else if _type == BuiltinType.LongInt do return options.mode == "jai" ? "s64" :"_c.long"; + else if _type == BuiltinType.ULongInt do return options.mode == "jai" ? "u64" :"_c.ulong"; + else if _type == BuiltinType.LongLongInt do return options.mode == "jai" ? "s64" :"_c.longlong"; + else if _type == BuiltinType.ULongLongInt do return options.mode == "jai" ? "u64" :"_c.ulonglong"; + else if _type == BuiltinType.ShortInt do return options.mode == "jai" ? "s16" :"_c.short"; + else if _type == BuiltinType.UShortInt do return options.mode == "jai" ? "u16" :"_c.ushort"; + else if _type == BuiltinType.Char do return options.mode == "jai" ? "u8" :"_c.char"; + else if _type == BuiltinType.SChar do return options.mode == "jai" ? "s8" :"_c.schar"; + else if _type == BuiltinType.UChar do return options.mode == "jai" ? "u8" :"_c.uchar"; + else if _type == BuiltinType.Float do return options.mode == "jai" ? "float32" :"_c.float"; + else if _type == BuiltinType.Double do return options.mode == "jai" ? "float64" :"_c.double"; + else if _type == BuiltinType.LongDouble { + print_warning("Found long double which is currently not supported. Fallback to double in generated code."); + return options.mode == "jai" ? "double" :"_c.double"; + } + else if _type == BuiltinType.Int8 do return options.mode == "jai" ? "s8" :"i8"; + else if _type == BuiltinType.Int16 do return options.mode == "jai" ? "s16" :"i16"; + else if _type == BuiltinType.Int32 do return options.mode == "jai" ? "s32" :"i32"; + else if _type == BuiltinType.Int64 do return options.mode == "jai" ? "s64" :"i64"; + else if _type == BuiltinType.UInt8 do return options.mode == "jai" ? "u8" :"u8"; + else if _type == BuiltinType.UInt16 do return options.mode == "jai" ? "u16" :"u16"; + else if _type == BuiltinType.UInt32 do return options.mode == "jai" ? "u32" :"u32"; + else if _type == BuiltinType.UInt64 do return options.mode == "jai" ? "u64" :"u64"; + else if _type == BuiltinType.Size do return options.mode == "jai" ? "u64" :"_c.size_t"; + else if _type == BuiltinType.SSize do return options.mode == "jai" ? "u64" :"_c.ssize_t"; + else if _type == BuiltinType.PtrDiff do return options.mode == "jai" ? "s64" :"_c.ptrdiff_t"; + else if _type == BuiltinType.UIntPtr do return options.mode == "jai" ? "u64" :"_c.uintptr_t"; + else if _type == BuiltinType.IntPtr do return options.mode == "jai" ? "s64" :"_c.intptr_t"; + } + else if _type, ok := baseType.(PointerType); ok { + if options.mode == "jai" { + // Hide pointers to types that were not declared. + if !is_known_base_type(data, _type.type.base) { + print_warning("*", _type.type.base.(IdentifierType).name, " replaced by *void as the pointed type is unknown."); + return "*void"; + } + } else { + if __type, ok := _type.type.base.(BuiltinType); ok { + if __type == BuiltinType.Void do return "rawptr"; + else if __type == BuiltinType.Char do return "cstring"; + } + } + name := clean_type(data, _type.type^, baseTab); + return tcat(options.mode == "jai" ? "*" :"^", name); + } + else if _type, ok := baseType.(IdentifierType); ok { + return clean_pseudo_type_name(_type.name, options); + } + else if _type, ok := baseType.(FunctionType); ok { + output : string; + if explicitSharpType { + output = "#type "; + } + output = tcat(output, options.mode == "jai" ? "(" :"proc("); + parameters := clean_function_parameters(data, _type.parameters, baseTab); + output = tcat(output, parameters, ")"); + + returnType := clean_type(data, _type.returnType^); + if len(returnType) > 0 && returnType != "void" { + output = tcat(output, " -> ", returnType); + } + return output; + } + else if _type, ok := baseType.(FunctionPointerType); ok { + output : string; + if explicitSharpType { + output = "#type "; + } + output = tcat(output, options.mode == "jai" ? "(" :"proc("); + parameters := clean_function_parameters(data, _type.parameters, baseTab); + output = tcat(output, parameters, ")"); + + returnType := clean_type(data, _type.returnType^); + if len(returnType) > 0 && returnType != "void" { + output = tcat(output, " -> ", returnType); + } + + if options.mode == "jai" { + output = tcat(output, " #foreign"); + } + return output; + } + + return ""; +} + +clean_function_parameters :: proc(data : ^GeneratorData, parameters : [dynamic]FunctionParameter, baseTab : string) -> string { + output := ""; + options := data.options; + + // Special case: function(void) does not really have a parameter + if len(parameters) == 1 { + if _type, ok := parameters[0].type.base.(BuiltinType); ok { + if _type == BuiltinType.Void { + return ""; + } + } + } + + tab := ""; + if options.mode == "jai" { // @note :OdinCodingStyle Odin forces a coding style, now. Ugh. + if (len(parameters) > 1) { + output = tcat(output, "\n"); + tab = tcat(baseTab, " "); + } + } + + unamedParametersCount := 0; + for parameter, i in parameters { + type := clean_type(data, parameter.type); + + name : string; + if len(parameter.name) != 0 { + name = clean_variable_name(parameter.name, options); + } else { + name = tcat("unamed", unamedParametersCount); + unamedParametersCount += 1; + } + + output = tcat(output, tab, name, " : ", type); + + if i != len(parameters) - 1 { + if options.mode == "jai" { // @note :OdinCodingStyle + output = tcat(output, ",\n"); + } else { + output = tcat(output, ", "); + } + } + } + + if (len(parameters) > 1) { + if options.mode == "jai" { // @note :OdinCodingStyle + output = tcat(output, "\n", baseTab); + } + } + + return output; +} + +is_known_base_type :: proc(data : ^GeneratorData, baseType : BaseType) -> bool { + if _type, ok := baseType.(IdentifierType); ok { + for it in data.nodes.typedefs { + if _type.name == it.name { + return true; + } + } + for it in data.nodes.structDefinitions { + if _type.name == it.name { + return true; + } + } + for it in data.nodes.enumDefinitions { + if _type.name == it.name { + return true; + } + } + for it in data.nodes.unionDefinitions { + if _type.name == it.name { + return true; + } + } + return false; + } + + return true; +} diff --git a/core/bindgen/generator-export.odin b/core/bindgen/generator-export.odin new file mode 100644 index 000000000..a04113ed9 --- /dev/null +++ b/core/bindgen/generator-export.odin @@ -0,0 +1,166 @@ +package bindgen + +import "core:os" +import "core:fmt" + +export_defines :: proc(data : ^GeneratorData) { + for node in data.nodes.defines { + defineName := clean_define_name(node.name, data.options); + + // @fixme fprint of float numbers are pretty badly handled, + // just has a 10^-3 precision. + fcat(data.handle, defineName, " :: ", node.value, ";\n"); + } + fcat(data.handle, "\n"); +} + +export_typedefs :: proc(data : ^GeneratorData) { + for node in data.nodes.typedefs { + name := clean_pseudo_type_name(node.name, data.options); + type := clean_type(data, node.type, "", true); + if name == type do continue; + fcat(data.handle, name, " :: ", type, ";\n"); + } + fcat(data.handle, "\n"); +} + +export_enums :: proc(data : ^GeneratorData) { + for node in data.nodes.enumDefinitions { + enumName := clean_pseudo_type_name(node.name, data.options); + + if data.options.mode == "jai" { + consideredFlags := false; + for postfix in data.options.enumConsideredFlagsPostfixes { + if ends_with(node.name, postfix) { + consideredFlags = true; + break; + } + } + + if consideredFlags { + fcat(data.handle, enumName, " :: enum_flags u32 {"); + } else { + fcat(data.handle, enumName, " :: enum s32 {"); + } + } else { + fcat(data.handle, enumName, " :: enum i32 {"); + } + + postfixes : [dynamic]string; + enumName, postfixes = clean_enum_name_for_prefix_removal(enumName, data.options); + + // Changing the case of postfixes to the enum value one, + // so that they can be removed. + enumValueCase := find_case(node.members[0].name); + for postfix, i in postfixes { + postfixes[i] = change_case(postfix, enumValueCase); + } + + // And changing the case of enumName to the enum value one + enumName = change_case(enumName, enumValueCase); + + // Merging enum value postfixes with postfixes that have been removed from the enum name. + for postfix in data.options.enumValuePostfixes { + append(&postfixes, postfix); + } + + export_enum_members(data, node.members, enumName, postfixes[:]); + fcat(data.handle, data.options.mode == "jai" ? "}\n" : "};\n"); + fcat(data.handle, "\n"); + } +} + +export_structs :: proc(data : ^GeneratorData) { + for node in data.nodes.structDefinitions { + structName := clean_pseudo_type_name(node.name, data.options); + fcat(data.handle, structName, " :: struct {"); + export_struct_or_union_members(data, node.members); + fcat(data.handle, data.options.mode == "jai" ? "}\n" : "};\n"); + fcat(data.handle, "\n"); + } +} + +export_unions :: proc(data : ^GeneratorData) { + for node in data.nodes.unionDefinitions { + unionName := clean_pseudo_type_name(node.name, data.options); + fcat(data.handle, unionName, data.options.mode == "jai" ? " :: union {" : " :: struct #raw_union {"); + export_struct_or_union_members(data, node.members); + fcat(data.handle, data.options.mode == "jai" ? "}\n" : "};\n"); + fcat(data.handle, "\n"); + } +} + +export_functions :: proc(data : ^GeneratorData) { + for node in data.nodes.functionDeclarations { + functionName := clean_function_name(node.name, data.options); + if data.options.mode == "jai" { + fcat(data.handle, functionName, " :: ("); + } else { + fcat(data.handle, " @(link_name=\"", node.name, "\")\n"); + fcat(data.handle, " ", functionName, " :: proc("); + } + parameters := clean_function_parameters(data, node.parameters, data.options.mode == "jai" ? "" : " "); + fcat(data.handle, parameters, ")"); + returnType := clean_type(data, node.returnType); + if len(returnType) > 0 { + fcat(data.handle, " -> ", returnType); + } + if data.options.mode == "jai" { + fcat(data.handle, " #foreign ", data.foreignLibrary, " \"", node.name ,"\";\n"); + } else { + fcat(data.handle, " ---;\n"); + } + fcat(data.handle, "\n"); + } +} + +export_enum_members :: proc(data : ^GeneratorData, members : [dynamic]EnumMember, enumName : string, postfixes : []string) { + if (len(members) > 0) { + fcat(data.handle, "\n"); + } + + cleanedMembers : [dynamic]EnumMember; + for member in members { + cleanedMember : EnumMember; + cleanedMember.hasValue = member.hasValue; + cleanedMember.value = member.value; + cleanedMember.name = clean_enum_value_name(member.name, enumName, postfixes, data.options); + + if len(cleanedMember.name) == 0 { + // print_warning("Enum member ", member.name, " resolves to an empty name. Ignoring it."); + continue; + } + + // Ensuring that we don't collide with an other enum member. + foundCopy := false; + for existingCleanedMember in cleanedMembers { + if cleanedMember.name == existingCleanedMember.name && + cleanedMember.hasValue == existingCleanedMember.hasValue && + cleanedMember.value == existingCleanedMember.value { + print_warning("Enum member ", member.name, " is duplicated once cleaned. Keeping only one copy."); + foundCopy = true; + break; + } + } + if foundCopy do continue; + + fcat(data.handle, " ", cleanedMember.name); + if member.hasValue { + fcat(data.handle, data.options.mode == "jai" ? " :: " : " = ", member.value); + } + fcat(data.handle, data.options.mode == "jai" ? ";\n" : ",\n"); + + append(&cleanedMembers, cleanedMember); + } +} + +export_struct_or_union_members :: proc(data : ^GeneratorData, members : [dynamic]StructOrUnionMember) { + if (len(members) > 0) { + fcat(data.handle, "\n"); + } + for member in members { + type := clean_type(data, member.type, " "); + name := clean_variable_name(member.name, data.options); + fcat(data.handle, " ", name, " : ", type, data.options.mode == "jai" ? ";\n" : ",\n"); + } +} diff --git a/core/bindgen/generator-helpers.odin b/core/bindgen/generator-helpers.odin new file mode 100644 index 000000000..a3b37f4f6 --- /dev/null +++ b/core/bindgen/generator-helpers.odin @@ -0,0 +1,392 @@ +package bindgen + +import "core:fmt" +import "core:os" +import "core:io" +import "core:strings" +import "core:unicode/utf8" + +Case :: enum { + Unknown, + Camel, + Constant, + Kebab, + Pascal, + Snake, +} + +WordCase :: enum { + Unknown, + Up, + Low, + FirstUp, + // When first upping, numbers are followed always by a capital + FirstUpNumberReset, +} + +// Change a character to a capital. +to_uppercase :: proc(c : rune) -> rune { + c := c; + if c >= 'a' && c <= 'z' { + c = c - 'a' + 'A'; + } + return c; +} + +// Change a character to lowercase. +to_lowercase :: proc(c : rune) -> rune { + c := c; + if c >= 'A' && c <= 'Z' { + c = c - 'A' + 'a'; + } + return c; +} + +// @note Stolen tprint and fprint from fmt package, because it was confusing due to args: ..any and sep default parameter. +tcat :: proc(args: ..any) -> string { + return fmt.tprint(args=args, sep=""); +} + +fcat :: proc(fd: os.Handle, args: ..any) -> int { + return fmt.fprint(fd=fd, args=args, sep=""); +} + +// Change the case convention of a word. +change_word_case :: proc(str : string, targetCase : WordCase) -> string { + newStr : string; + if targetCase == WordCase.Up { + for c in str { + newStr = tcat(newStr, to_uppercase(c)); + } + } + else if targetCase == WordCase.Low { + for c in str { + newStr = tcat(newStr, to_lowercase(c)); + } + } + else if targetCase == WordCase.FirstUp { + for c, i in str { + if i == 0 { + newStr = tcat(newStr, to_uppercase(c)); + } else { + newStr = tcat(newStr, to_lowercase(c)); + } + } + } + else if targetCase == WordCase.FirstUpNumberReset { + for c, i in str { + if i == 0 || (str[i - 1] >= '0' && str[i - 1] <= '9') { + newStr = tcat(newStr, to_uppercase(c)); + } else { + newStr = tcat(newStr, to_lowercase(c)); + } + } + } + return newStr; +} + +// Change the case convention of a string by detecting original convention, +// then splitting it into words. +change_case :: proc(str : string, targetCase : Case) -> string { + if targetCase == Case.Unknown { + return str; + } + + // Split + parts := autosplit_string(str); + + // Join + newStr : string; + if targetCase == Case.Pascal { + for part, i in parts { + newStr = tcat(newStr, change_word_case(part, WordCase.FirstUpNumberReset)); + } + } + else if targetCase == Case.Snake { + for part, i in parts { + newStr = tcat(newStr, change_word_case(part, WordCase.Low), (i != len(parts) - 1) ? "_" : ""); + } + } + else if targetCase == Case.Kebab { + for part, i in parts { + newStr = tcat(newStr, change_word_case(part, WordCase.Low), (i != len(parts) - 1) ? "-" : ""); + } + } + else if targetCase == Case.Camel { + for part, i in parts { + if i == 0 { + newStr = tcat(newStr, change_word_case(part, WordCase.Low)); + } else { + newStr = tcat(newStr, change_word_case(part, WordCase.FirstUpNumberReset)); + } + } + } + else if targetCase == Case.Constant { + for part, i in parts { + newStr = tcat(newStr, change_word_case(part, WordCase.Up), (i != len(parts) - 1) ? "_" : ""); + } + } + + return newStr; +} + +// Identify the case of the provided string. +// Full lowercase with no separator is identified as camelCase. +find_case :: proc(str : string) -> Case { + refuted : bool; + + // CONSTANT_CASE + refuted = false; + for c in str { + if (c != '_') && (c < 'A' || c > 'Z') && (c < '0' || c > '9') { + refuted = true; + break; + } + } + if !refuted do return Case.Constant; + + for c in str { + // snake_case + if c == '_' { + return Case.Snake; + } // kebab-case + else if c == '-' { + return Case.Kebab; + } + } + + // PascalCase + if str[0] >= 'A' && str[0] <= 'Z' { + return Case.Pascal; + } + + // camelCase + return Case.Camel; +} + +// Splits the string according to detected case. +// HeyBuddy -> {"Hey", "Buddy"} +// hey-buddy -> {"hey", "buddy"} +// _hey_buddy -> {"", "hey", "buddy"} +// and such... +autosplit_string :: proc(str : string) -> [dynamic]string { + lowCount := 0; + upCount := 0; + for c in str { + // If any '_', split according to that (CONSTANT_CASE or snake_case) + if c == '_' { + return split_from_separator(str, '_'); + } // If any '-', split according to that (kebab-case) + else if c == '-' { + return split_from_separator(str, '-'); + } + else if c >= 'a' && c <= 'z' { + lowCount += 1; + } + else if c >= 'A' && c <= 'Z' { + upCount += 1; + } + } + + // If it seems to be only one word + if lowCount == 0 || upCount == 0 { + parts : [dynamic]string; + append(&parts, str); + return parts; + } + + // Split at each uppercase letter (PascalCase or camelCase) + return split_from_capital(str); +} + +split_from_separator :: proc(str : string, sep : rune) -> [dynamic]string { + parts : [dynamic]string; + + lastI := 0; + + // Empty strings for starting separators in string + for c in str { + if c == sep { + append(&parts, ""); + lastI += 1; + } else { + break; + } + } + + // Ignore non letter prefix + if lastI == 0 { + for c in str { + if (c < 'a' || c > 'z') && (c < 'A' || c > 'Z') { + lastI += 1; + } + else { + break; + } + } + } + + for c, i in str { + if i > lastI + 1 && c == sep { + append(&parts, str[lastI:i]); + lastI = i + 1; + } + } + + append(&parts, str[lastI:]); + + return parts; +} + +split_from_capital :: proc(str : string) -> [dynamic]string { + parts : [dynamic]string; + + // Ignore non letter prefix + lastI := 0; + for c in str { + if (c < 'a' || c > 'z') && (c < 'A' || c > 'Z') { + lastI += 1; + } + else { + break; + } + } + + // We want to handle: + // myBrainIsCRAZY -> my Brain Is Crazy + // myCRAZYBrain -> my CRAZY Brain + // SOLO -> SOLO + + // Do split + for i := 1; i < len(str); i += 1 { + if str[i] >= 'A' && str[i] <= 'Z' { + // Do not split too much if it seems to be a capitalized word + if (lastI == i - 1) && (str[lastI] >= 'A' && str[lastI] <= 'Z') { + for ; i + 1 < len(str); i += 1 { + if str[i + 1] < 'A' || str[i + 1] > 'Z' { + break; + } + } + if (i + 1 == len(str)) && (str[i] >= 'A' && str[i] <= 'Z') { + i += 1; + } + } + + append(&parts, str[lastI:i]); + lastI = i; + } + } + + if lastI != len(str) { + append(&parts, str[lastI:]); + } + + return parts; +} + +// Check if str if prefixed with any of the provided strings, +// even combinaisons of those, and remove them. +remove_prefixes :: proc(str : string, prefixes : []string, transparentPrefixes : []string = nil) -> string { + str := str; + transparentStr := ""; + + found := true; + for found { + found = false; + + // Remove effective prefixes + for prefix in prefixes { + if len(str) >= len(prefix) && + str[:len(prefix)] == prefix { + str = str[len(prefix):]; + if len(str) != 0 && (str[0] == '_' || str[0] == '-') { + str = str[1:]; + } + found = true; + break; + } + } + + if found do continue; + + // Remove transparent ones, only one by one, + // as we want effective ones to be fully removed. + for prefix in transparentPrefixes { + if len(str) >= len(prefix) && + str[:len(prefix)] == prefix { + str = str[len(prefix):]; + transparentStr = tcat(transparentStr, prefix); + if len(str) != 0 && (str[0] == '_' || str[0] == '-') { + str = str[1:]; + transparentStr = tcat(transparentStr, '_'); + } + found = true; + break; + } + } + } + + return tcat(transparentStr, str); +} + +// Check if str if postfixes with any of the provided strings, +// even combinaisons of those, and remove them. +remove_postfixes_with_removed :: proc( + str : string, + postfixes : []string, + transparentPostfixes : []string = nil) -> (string, [dynamic]string) { + str := str; + removedPostfixes : [dynamic]string; + transparentStr := ""; + + found := true; + for found { + found = false; + + // Remove effective postfixes + for postfix in postfixes { + if ends_with(str, postfix) { + str = str[:len(str) - len(postfix)]; + if len(str) != 0 && (str[len(str)-1] == '_' || str[len(str)-1] == '-') { + str = str[:len(str)-1]; + } + append(&removedPostfixes, postfix); + found = true; + break; + } + } + + if found do continue; + + // Remove transparent ones, only one by one, + // as we want effective ones to be fully removed. + for postfix in transparentPostfixes { + if ends_with(str, postfix) { + str = str[:len(str) - len(postfix)]; + transparentStr = tcat(postfix, transparentStr); + if len(str) != 0 && (str[len(str)-1] == '_' || str[len(str)-1] == '-') { + str = str[:len(str)-1]; + transparentStr = tcat('_', transparentStr); + } + found = true; + break; + } + } + } + + return tcat(str, transparentStr), removedPostfixes; +} + +remove_postfixes :: proc( + str : string, + postfixes : []string, + transparentPostfixes : []string = nil) -> string { + str := str; + removedPostfixes : [dynamic]string; + str, removedPostfixes = remove_postfixes_with_removed(str, postfixes, transparentPostfixes); + return str; +} + +ends_with :: proc(str : string, postfix : string) -> bool { + return len(str) >= len(postfix) && str[len(str) - len(postfix):] == postfix; +} diff --git a/core/bindgen/generator.odin b/core/bindgen/generator.odin new file mode 100644 index 000000000..3ef3d69c0 --- /dev/null +++ b/core/bindgen/generator.odin @@ -0,0 +1,205 @@ +/** + * Odin binding generator from C header data. + */ + +package bindgen + +import "core:os" +import "core:fmt" +import "core:runtime" + +GeneratorOptions :: struct { + mode : string, // "odin" or "jai" + + // Variable + variableCase : Case, + + // Defines + definePrefixes : []string, + defineTransparentPrefixes : []string, + definePostfixes : []string, + defineTransparentPostfixes : []string, + defineCase : Case, + + // Pseudo-types + pseudoTypePrefixes : []string, + pseudoTypeTransparentPrefixes : []string, + pseudoTypePostfixes : []string, + pseudoTypeTransparentPostfixes : []string, + pseudoTypeCase : Case, + + // Enums + enumConsideredFlagsPostfixes : []string, + + // Functions + functionPrefixes : []string, + functionTransparentPrefixes : []string, + functionPostfixes : []string, + functionTransparentPostfixes : []string, + functionCase : Case, + + // Enum values + enumValuePrefixes : []string, + enumValueTransparentPrefixes : []string, + enumValuePostfixes : []string, + enumValueTransparentPostfixes : []string, + enumValueCase : Case, + enumValueNameRemove : bool, + enumValueNameRemovePostfixes : []string, + + parserOptions : ParserOptions, +} + +GeneratorData :: struct { + handle : os.Handle, + nodes : Nodes, + + // References + foreignLibrary : string, + options : ^GeneratorOptions, +} + +generate :: proc( + packageName : string, + foreignLibrary : string, + outputFile : string, + headerFiles : []string, + options : GeneratorOptions, +) { + options := options; + data : GeneratorData; + data.options = &options; + data.foreignLibrary = foreignLibrary; + + if options.mode == "" { + options.mode = "odin"; + } + + // Outputing odin file + errno : os.Errno; + + // chmod 664 when creating file + mode: int = 0; + when os.OS == "linux" || os.OS == "darwin" { + mode = os.S_IRUSR | os.S_IWUSR | os.S_IRGRP | os.S_IWGRP | os.S_IROTH; + } + + data.handle, errno = os.open(outputFile, os.O_WRONLY | os.O_CREATE | os.O_TRUNC, mode); + if errno != 0 { + fmt.eprint("[bindgen] Unable to write to output file ", outputFile, " (", errno ,")\n"); + return; + } + defer os.close(data.handle); + + if options.mode == "jai" { + fcat(data.handle, foreignLibrary, " :: #foreign_library \"", foreignLibrary, "\";\n"); + fcat(data.handle, "\n"); + } else { + fcat(data.handle, "package ", packageName, "\n"); + fcat(data.handle, "\n"); + fcat(data.handle, "foreign import \"", foreignLibrary, "\"\n"); + fcat(data.handle, "\n"); + fcat(data.handle, "import _c \"core:c\"\n"); + fcat(data.handle, "\n"); + } + + // Parsing header files + anonymousStructCount = 0; + anonymousUnionCount = 0; + anonymousEnumCount = 0; + + for headerFile in headerFiles { + bytes, ok := os.read_entire_file(headerFile); + if !ok { + fmt.eprint("[bindgen] Unable to read file ", headerFile, "\n"); + return; + } + + // We fuse the SOAs + headerNodes := parse(bytes, options.parserOptions); + merge_generic_nodes(&data.nodes.defines, &headerNodes.defines); + merge_generic_nodes(&data.nodes.enumDefinitions, &headerNodes.enumDefinitions); + merge_generic_nodes(&data.nodes.unionDefinitions, &headerNodes.unionDefinitions); + merge_forward_declared_nodes(&data.nodes.structDefinitions, &headerNodes.structDefinitions); + merge_generic_nodes(&data.nodes.functionDeclarations, &headerNodes.functionDeclarations); + merge_generic_nodes(&data.nodes.typedefs, &headerNodes.typedefs); + } + + // Exporting + export_defines(&data); + export_typedefs(&data); + export_enums(&data); + export_structs(&data); + export_unions(&data); + + // Foreign block for functions + if options.mode != "jai" { + foreignLibrarySimple := simplify_library_name(foreignLibrary); + fcat(data.handle, "@(default_calling_convention=\"c\")\n"); + fcat(data.handle, "foreign ", foreignLibrarySimple, " {\n"); + fcat(data.handle, "\n"); + } + + export_functions(&data); + + if options.mode != "jai" { + fcat(data.handle, "}\n"); + } +} + +// system:foo.lib -> foo +simplify_library_name :: proc(libraryName : string) -> string { + startOffset := 0; + endOffset := len(libraryName); + + for c, i in libraryName { + if startOffset == 0 && c == ':' { + startOffset = i + 1; + } + else if c == '.' { + endOffset = i; + break; + } + } + + return libraryName[startOffset:endOffset]; +} + +merge_generic_nodes :: proc(nodes : ^$T, headerNodes : ^T) { + for headerNode in headerNodes { + // Check that there are no duplicated nodes (due to forward declaration or such) + duplicatedIndex := -1; + for i := 0; i < len(nodes); i += 1 { + node := nodes[i]; + if node.name == headerNode.name { + duplicatedIndex = i; + break; + } + } + + if duplicatedIndex < 0 { + append(nodes, headerNode); + } + } +} + +merge_forward_declared_nodes :: proc(nodes : ^$T, headerNodes : ^T) { + for headerNode in headerNodes { + // Check that there are no duplicated nodes (due to forward declaration or such) + duplicatedIndex := -1; + for i := 0; i < len(nodes); i += 1 { + node := nodes[i]; + if node.name == headerNode.name { + duplicatedIndex = i; + break; + } + } + + if duplicatedIndex < 0 { + append(nodes, headerNode); + } + else if !headerNode.forwardDeclared && len(headerNode.members) > 0 { + nodes[duplicatedIndex] = headerNode; + } + } +} diff --git a/vendor/stb/lib/darwin/libstb_image.a b/vendor/stb/lib/darwin/libstb_image.a new file mode 100644 index 0000000000000000000000000000000000000000..06ce4432192e21268b40c487d33f54d0d4ec0007 GIT binary patch literal 55744 zcmdsg4}4rzmH(tkOIli9szr)|3<_GTDJ`_vQVJ8yzyJ*fXb=&Yq{*a-O_Pv6kameC zOa}7$I#707MFlo1h^VZs+LlrXCQzGztfW%0x|JQUY6c?&sS;Quzwh_n^WMDqmlW6E z?(etnlQ-wxd(J)g+;h)8_wRc-^}LFv%9`_Me00&7XD#$5u0`i8K6~j|XD|HJ60dj3 z!bL!6^rD3e&sn_K>s_?y?6Wj=`HWz2!Bw9tDfVCFz3MYpuJRXqaEhv(V=bcE2`G{cfrJ^&P8e;dt6d$e3RN~#g@UVFtE)pz z84&9rK|^I$L~u=OsJXehc7tsxZl*eIf+Sc2V-Gb|*Hx^^z_7kSqqEE6P>4|Q0v=Ch zKXum9WpGiM{M3@giq3=KYjOB{X~9b8TgLJ z^M3dn1UfWE{|19~wJo8hin_&iIGNwW!e^!=+IySFLpJu6S|rG)oKtXhb2Djz!Q!G- zMK*P!T;4>K$Iat?u6RB={BEjfBEwXEyG6c-B;63?;}zTE@f-*Eeicgm1Z}}2DwSWU z=-n*EgL zw_lX@Ao#g2x2%i@zlQqegu$fpE4R~&-L+Yh%Ga>2v7(Yb;^x}=s$g(su{-~Aq~{eo zR>QVCJ*s|7AA>A9DoMm(FjNCqSFtXnk*V_e*s0?hWo6>J=IffD4tYGtrpA6IJPY?+ z+^U|88J=mld7Xi~0C(UCji(T#D@S-U;Q;Pgil3(xVO|u8_lI#)?Lfcht1MvtHejt_ zy73bNmgoAXsuviibSXZ@DL#+FherwmX8TycY9AXWCJ^3RaQ#!pDbOtOX8Svq{~ePq zC2M+3BRQG=vGEhEk})&i$$CI(L^DoEP`z2@-#Oxiz5Pm~wQ;PiLnS|TXSR--Wg`I#k`MTp5ascY z4fqy1j~%=Dhzp3(0MrvOJBL(IJ@(m{%94>l&Y%z+Ob`s>F}eDregff+}`IgBGf`)z&{4yi7!QA z!|j9l+jF}8j~QJwVgw6}Eqw@Y^gp(E{Incn*I=M>e<1v}$LKnRiK8n%)Jd>pi2}2V z0QS6_Ct1bGSTX7PEUB&bK4@atT8Q76RS<4JfQoP5Zni#bmOW%d*x-OUXyuzF55%V- z1o2J(1D5{*B;9VcK5UgeWcE9y81N6WRF1`2`Qf)97(2d{xCotm{Brz+SHM`tK~=;6 z1TebjH&jMF@#%Q9CFrsIJ*NM0Ep*ASwFnB0S+fI`C65RCU&_%^SkNU+mqrlY+lb1V z)V>4e&U}b)6b2r!wkpab%l*G-;nhz2hkbcbGs?zcU$7^Zu>`g?J7AU;1gtCa0p|v+ zOW;NVUZ6ojn=YD1(gEM%4y{QxhaCIS-5kaOQXCA?+E~ZzYv1|G)RQ;gM4KqoeBY>_#z&MllHYUZzZ{eUMHnrRV80TOT*ecDuTO z9Z6ll4$HrT{@-eS+$!6h=y}HCA0pG}itY{42p2tVJ`*1E1PuSr;4kg|p!9!Bf3OI> zT>F^WdgS`2RR5;K906Vb6#efT#%%vPZx{vqnJuG6w||}-UodO*W{*ecZYUuiHAb`f z7tA^^0e&~fU%KMY*qb)09Da?X%ESEK8pChEj2}5#oB{IaQa4!LdMrvR&5E*3% zSNwiuMG>;XU~!DV(xJ*IIdlAGMm(d8-$@>p&MMkV+M?a;1dGLjU?@h{axx6}QV@hb zsM!~&^wGHlXTV~WoMsNPQc)NMgFJqMBJO3B7Cs>-C`l5q(g(PMh<66K3}ApuwYdhk z9bkM^^8@$z0ApaYWEi8*!)Rd~ePS4Jk=ON%VFKbSTQSD9(eu!2Aa=|QEJXVnvsw@9 zf~bx?F*7hbns&F6V6yiFE^FdTXm{S6W48zivVaEuEw_pWI^1$PuKB zbM7*r9y!>z)KglMFjb2;A_j;p-TFKCvRqDsNQ{S%)}ExaKS~&-&Lz8F`4{BwhdUK# zGN}#GwFI6VX z9|O4`HHrr|{apFNTz(O3x*UbnQBh%x3z6kxdk7m~UF}e=$i?tW(yC6m1S>?C&tqYJz zwOLA_R{G3Ho~s0WhQmrKfm%<%e8ch=_!nU`pFZnYX_jDYhTD9u*nD9R%_%U@4_4!* zf3GSou>(2zMDVGIPx6SlG#|;;zdNCukJ+&mK?VHBgQuWFz&;q|B&TB)E~Q1LPJQ;+GICgfUKKL74PdA~#2ECt1ZHFq zU?6f3zp5Li|64iB294-?)tnSvpfXCrfUzyAn5dC|A7dJSQOgt?mpzKY6>^nfZp8&SJGEWSigWY7=^4>C$% zMjj%tc51n{GW00Z3~S}ykCbzU%NebjV3;K_%xDgwr4PXv5$}HpeF^*-*Fu3qi&<#_ z7j1t?Ybw0A+_itg`H{?#DX`v+p$wQQaZ?7fA2VOe;dL9gYk!98ucHJ05!P3@eI(zA zu2j`54ppthWA`DtgapOLuDlNvFY7nD=8!15V#*g1{aKuoORZb~h-z*l@$aCyNf)Ty zFT^lT=>Vag|4|ou?R5xI5Ev@x>{E|i3GSF+lS2Gwf%2ScM%bYfV)=M^=OB0(;dz=9 z^x3U&<}-oLC)pnd%*~AOZCvE*ZXJ(*no-~pZd-`Pu}FnP0gRq3IeqOuKibtUKiZhy z;Yyj`vNXN|RX}U~JOw-Z^~!YFn04jifcew$A!R+RN3&0ffWFY$r4)0<>zwfB-mx3; zruq%HAA#e%T+t=%1|=A)EBJ&w)JS4lm+hNqg61?rY))A@icY&}Um^2Zj{~ zu4~jQN69Ml<{Nja;g#hd9H8&<#4jXIRiEAhJ&HgGNX)uCaW9e473JA7Tm#O^jCIxf z=Au>hspkRTT%?ulobTZY+c~I8*vItcMKg`Auah$}3NOt!B4?|B+KB>z$7-Aj`87+A zrTZ$&Q*8P2RGFBEt$$>ucv?5=BszdSL=H4BD7G%n3z!2=s)P(?(M8 zO6I;jxyV7~I1m{m64yXvuk-Y{^RydJY!CyH?M~do&eKEkgw-)-&P`l1+M}Ly#6Xc0 z(hf?|?4YuhfYr-1N*=DdsAYhG$cQkHm%?(xy)0Lb8%MF?i-8l(Cz!C`1ho~t2fyYs zov&PS;hImI(H4Y^E}kP%DXa)13Re{sUt)AEfne^~;>-Pr{Ro<%JNC-r0AjC9;ox7j zvef8Wib`?QUUm7EEk@UB^p^3bQBeaCDvL5pajl({Q58CV{c$WIb&b-iCB^89w<_&! zLun#@DQE^FiUv%=y-YpJ=o0E*rcj>*YPVidL)0>{@a7m@9JhieQSeh!jIK+QBJzx` zWl0g(@S2wtQQ#=y537?^c0#%kW|Y<&?&a?^;|?k3zLbP7VjiJsa*ar8ZgvITm6GV& z?nHP-!(;o)jW58n6;b)da@4Y-Wc!&E4r`D~nUK4ZpgA+TMG4Jccppjqp_J5TAaz>8 z%_<>(6AAxRk*uas?7F8VWOK(*7{57=ntqa!@DY_znL~If_;WNY<`HhoOPKOQDe1n1 zbRE6QIT?}rkZ4h#rR(LTDL6LpXfC4mu&J0Y82;C7R31+h_@B(#C$gG1!}BT&V~_7! z^s_fVC1Fm*-gL0bFU~W+!(Pt2UBCeK}}4Rg33wDyMm_OCkF> z$Smdh7X3^q@lC7}(3h`Ozq!j5&M}|`DanVY)5G+E-h<0hPs>$GBfJ$cQY_`NtSIUF zQD6NY6YB2nI(`%pSx9mwCz;|RaWT(j^ghiTtH;b#%}4kU{~Sin@lzqS?K^G#`Gd*T zd>m-R#{|M{`H7~mG==cD`3cMHdI4p2jN@db0A=ei1iDGxL(wGS-$Sx+uj(}&|NX}s zl4aNk8eKV}Q`^b@JcY0VgxYoFrPl_%z7hVE5+>nYQxzt)k*cppsIQA4vDmN`$Pd4i z!)9gsw5wBO`8n2xw9wK+;Iv8q%Q?%293wg*CB^+np+_9tDvPnc+Bm@EDb<0<4utUl zo_rFX%Zo6hIy0q6nAwx0+UzQM7EmWpRnO@7V=T%|lkmJEh3DzaJJAybDzEgqCv8Q> zHXNziO8(uOj^|)0HP^2)SMbnYI{x6abklq0y5wsAC(szXR8OE>|7l2_YAT~CX@ZI` z2R!gfUL+6(b|+qx@3OtKK#au>5a+7qy<9yTQ4Ea4MDgH>ADc$T;hu5ZuYt7G(9eu) zLQJ?<4FiqH3LwPiU<_y6M(3_g!HiUaFwT+PZcY~@j35YzG8I3isAS1>mYf&sEV0rh zveel}&(LB&|*W7fKpzs)MVDW|iiLpUhdd--vLL1l#dIib52WGN=kXZJ%xg*xt7tj5mE~q?f=eYM06*8SwaAcYL(8+%JOQkj7v&2 zd2>XcEagc|i7fSx)T(_{j7=K{k|#T(`3X=tXEa^?U$|}N6ypw#aHS+letSUI^(7$E z99C+?OuK$J(T!lCQRzj`Q7}cvVrN28*4D>WK-H`j$gZxBqe;a-0)9?4khxQ@v=1|2 zPt>&`TF#W*HcTdA!Kh(XFqg002UKcn|K-)mt^FIIu_E^%_33!>Dxb2}iR&Mpt9qes z_$t~z>H6aZoiDL#>YhcPU~N^AujF^WtRjy`ReG$QD)LoN=kFNl>t4b^GL~rYo8$yP z%4jXUYli7APkcW%_Hhtf>6EPt^!DLvGg6Ld-IOi$j4c^1HzXEzoz;Ki6np)ylfzw|{UW{FcA3TmA0y<&0ykJKTq@twUJ;8Vq#y(_XNU4OvS15TvCb*cac$fr^E^ zQutn!%r}6k3fKqWHkr#L+?B3Q09ZtPmh42)fkDkEc8=@i`< zVVT`IsU=Iv#i=7z=g%XUQZh7pRkDe5VJp~Il-^2Ga+50Ti}$chq4eDTwlayTY|SN? ziB3DEOm=NeTBgB`MY$|mcTt)iQ}T35rfSPd&ojjuC$x~%I!nn*l-d_p)_4jlD7xY@ zOu68ze+Ui2SKo-xoMEGf+=n4(p27R;|6(XzlXdg$pKZWd!L7yLs@zbb_;T(Ps;&rkfoV6X=(E9yi^N{ zqd}#VMveU8RGqxiq!)$Q`f=L-X$`QOsJ8412~10^ zk(3-AE#1R1J%u8s(rj z{2R+9`m)uRTrRGjr&L|=sLO@=E1IUtXBJIKwV0G_ozi`UrMnAxq-2|Bqmx?9Bsn^* zLfNSFg{^38=nKDfvGVgFg!X(a#n0P)VWsK|IZYCOp4J^!Z{7o%51=pPLeKY5F!y~} z;?6-|csFi0j?cHD5Bwu;KF<*7rnv!q;g4~j2YiP9ut1+5k-l1W)6VldXjI&v=9xkJ zd;{tEhKfFaf$qQ)|2}?HF!~`~=h)YFzf0IhqD?kRttWM@wu3H8IreeJpoxi@e{{M3 zh@p<%C@EZY?h`UNouE$steYIfJc7}t6?a$Umvo>>4cnq6Yo9AVahIMWzUzDew_5&;43*|l^p4R z33dn;C7K1|t+LUaXH4|^$>(Jj+UG~ivco9&s9t~T;+B*OI(ooa2(yo|)K^R$3p{K@ zwVK<9HSKmqP>F-N`rPC&=)r~uD)2@rBnVg==BdM0m8~)82Is8~7ti;{0_F?F=93sL z42|zM@uD#P$_~#ji!B=}GPd*=b-a{QWbEqKQ&q|_sMzvM*B#6eEehv*)e^p{1`(Vn zoJc&Z&(Aoglx{~Of>5b4A9l-3!L;0}@-A`Lqv$5DSnpfO_sGoNax{;Cx$_zTbL%SpMoaOFmsM6O5DfrWQ3k?q6+BA!r?xST;{E2< zVud3;4l6QXMtvk~=hCU33+N0im4T%)uv7+E!BScCEDW@e2n6!5Fsbsk?q%LwpDZ@7 zJ54XPnvpuh#izg@E_ynV%tBXXv#=WTtgRG7*SZ;5if1ge6C@VeuPK(XrEuJiZhs)M zm^8S;y?i>xh_)j-AfFN75{xx9A81&}K|HFJI2z%sxrj9R&Ji60(cAGTl)Dp@eKzG_ zf^u_$^6ms>k4^cILm6pgIc&C(HXRZfI&AuGmm>0UGL_|+zcPX&vFb5*Wn^cuaX`n0j6nGxP}VrndD zlX@b{QHz$^Q7cnW)-j;WiFFp=h6XYa`6Re7XsM^=svt)66op&p;P|v$Wo$%Waj3Dq zM{OJ1x}sE#1apg{+s(*Hh_E6|=TH?#Hz!Dj%*b3KttidZQuH`dqD%cgW7`yCTZA@^ znbVVjoc(xV4*`h_R1P7^p}umi79LotCRgR^kgBerawmD=*c4iRzIu8A$<>p~VQP8R z{v-vD=kX_@9EG61;?JR*b?Q_Oidj-|k!wJ~4R7pB!Q2?qC~M~`JfHDXQ$gWN{VBeD zh~I>6AAG41C`ReRESjt93^jsEqBC%v8Pi|e$an^y{x8FVuhYN#*uT5KxdE?)rVSS! zQ**i)_nz<>3`C6KNGA^m4&mJFl%nl9#ohkr>=@>!H`z<&t8>{gch4;tYM@XRA}B}2v|v)L;ck1SgDr#&=S zqZqEKWT@J_0%LWY8}96v0ppMw<#7=VZ$YRf=nP74>o8 zJXIh02<>?npYuqq53bgwC=NAf*T*hhAG=h2AX@69`wA=^s_J0BiB)WuD%5iJt?699 zKuT7}E?phFRCUM#F=Ex)=P1@9)wZJ7p_XdG8YQbk^*!K%LCU#K+KdB?q*w{*KqjF%UC$?GIEw8BjZ> zr!ZY~MF%#HP?Iy36U@35p*?)RAyJb7`?E!p?GlcHp|eZ)8w65{^b=;tA_a20OJ1}K z_v?=K7tzE01CTfo{^D2FVCl`by1BE_8Z&lXKBe|)v{fM659Pdt-xtlnuf7TY)f(%@ zJW!G3WGA@@WiI*k1o$cP<~HTxlwE1~*XqI6uowY`&9;WmpoS-@wSU)Tb$F_=SU1Cvix(4t+E0*lNf67pjmbRP7u4P&lY2c&nhWMn^TnSWlMk| zfPA-A@~p89-QBj5y=KY7KrQ* z&!8as^9L*`bb!NNJdrWvGq&vWb?+p8V}!q1y6el}dEr!coUorNIF(wBQic9^ z$W!cjB>oub{V1#-D)ASD`;O@!&eb2Ug0Do>Al@OuI|0l64;f)$@Vq<24PY?f-;RvH zXZvz&YlXMXROSzD`{r6D4?~gLospWq8wEHRz-ZHcbEfPdx+EO5fv&>6{KZQglF=>h zjAkPv%m8uz?IM-e1Ir=uZ9-Y$ru;qTqLwPp(0qP_tE5|ox9BOm2mD*q7|;KJ>EFDl z&+Ny1z1#9XZ0-x-t(Y9V*;UpNZr={|a`J@<4Mjo~v4D6nFvr}=hyi~OBP@T4Ld2IrVqXzPxt z+rJHBnBZUGU|@oJwkU@wuuy~yTcND2ZJ>2862+U4%w^~*3nR+mDMVEDC??o#wf4+! z-4dw$X%;(7)Zh=1N&Li&jP<(%rpSmP;xJ`5t7xxs{V%tP?8VY^hMD zhLn)zi`3=6A>Z_J7fme9;{3@?GFtLBtoij4kFqF+VPbJIn? zFJ1J%*)2TwcUSl|c|S~!cfob1)ZK&W<<06m?Zz^h^HiN2`2PLc zODUy)UU5vSt;f=(pTIpsesRxp!O!KM8BDH_RQG%z1^BxbX}Qf&54%=_Ib3Kg^Q2+G z&o)MVa?~G&lP7UE20wbbx-YK)E)>oQD^U3SVagaRzSqu66+z0eT~Tk3``?g3W%RH4 zX>*z1B1&cn5DjbKe#~d^tad&AiFi>wJ|v$YOSL8g+2 zbH-NX7{5`8*yAzoKqvg(#fjgJ4jDznn)QHgwNR!MG0)iaW@et#-dhp-$MeF!&z-Q8 z#;#tMS};<}De51aQWTEm;vJ~5Y})a4F9WH&1`wQH6n-h!kI{OzRK+~~38m&`RqD8! z08OCOi4_3zz$>bYGwUud{4!KAfrTjJ%9eV{WU1rdN5_c@#f$0R&|PSvLi3GHzd|J^ zYfRbfF%wFZX0!d{)55>Uvc&{uo3TQtqC&9=|DG$f|E)Y!D&G5)eK{r{PRWW~ldtg~iz0>#}Y zCZ__EMMdG?Q8QSM&YYD$!vDwI-byGr$L1iTF8VpJM}11=T6jKCe0gb zSy@_J?os4DHEU|Lwn_8GJNsGk&Y3K=>LC+9vgpvoId--_S{)+@x8H;2-3I?6qbzlJ zBCK}V@v6qPKw#sQ{f*vt#RusV{kLGS62UE5y)d0hi>`9NuX}NUK9#{~l*%El-ZniI z;z5F3Y?WqNb^ZBAAV74<1*a0sy6mHv9d1jW9qOrGve;$HmP_;|}Jkjv;Bzv4;na^W3?Z_?h@X0vPy>4s*PG^=Tfor?$8&KPD`v zAQR{hC(t0Fd_qFmw)TU?M*nO4ml*hO8fpKJ0N?-8#}Uo4QHYl7KQiAxYWhc@=K1*S zu|9EW`iE86&KsXlR$)6M`<=GK#+@f9Veo!i%((Md^^8-0@5H&RiW6wA=p&5A8V{n8 zpM1*_YDt{1nx3=wk%*OnYPIcKncEFU(M{QoQ_qkklY9{aTmv4xj-9};#1qgAhT z@HAv)`yr()*Pg5wB4AJU^^;@|EA{0>ytD{oh~XE?)Sq@-fM+zcQEU&yj7R1K`rnq< zMG=YfYb7!4xqw#r!dQGC-4Ut9+7(gabsN3qEcTHmKQ@j>VS7m);6a$6A75>0AHg>= zaqja`ta|DFH&?OFP%_$Y_(WIC&Q`u_zzt0YqgB?T{1ceN*h5hN0e~338hJ3G0=!-c z?>x+pLEeo_l6R`3O^Ct=@TZ;ylV+*$kw8!%&MkrR_jBj^4dW9}zhT@k_=a(9KM2(} z7@nV2_2Q2BlkvI!KN;8dQC~@1@Jal<&56??x7uzzq4KK{g$;$}c#kK#M#&h%FYC`G z{3VE?q}|w-OOo_pilj*b5D5WhLIAshouxEvedyD}Oo6(vy)mjd@xCtnVZz@R)780r zK9A96Y0cUVJAR*5or^QK8C$jcd{UDCM}8ye&H4{USCvvvO0$+e0BC;#o!kc`NH7qB zf)xjn;2yQ`l~wKGZ3pp(js8E_4kF1JyYwUN7pKc$ju=p(azw4QOdEuJVu zU@Aw*XzCag;=!}Wi~JKc>Q3B4LX~80esU5ZGACIFOnhQ#FC_`?3AFZcn?%v6pK$vy z`f?0%A3|C9GD6a+3Di_d{Ww*k&d+1CG7^5tQ0I!Js#H8qgu80a{v_vYcm}BueFPmo zx<8f=WB%%+JRtSvTWb4-H3+}_8?;V`I)FIktJItQHp3w|343Og1|KRD2K{cV96_f| z=mR0DXk7?8?+18cf9#}DHDgwwV0j5%a+nS@$|A!og_wia8O)LqbH6%d{`|}Mz%9)E z)E6+6!`lQZap|1rUolHbsDh0JXS`tIdlxVgHBOT6gEGHS+5s{PzjO>g2-Jn0eN}&n zX!#n8cwxq?*EH^sZ5Sk;qd#MSg+ud&@V*=qXHzPl>|QyQ|CnvmDxK5+NjpPiX(INbr4!_DUhIWTBy6wbh+T%edV%O6d?reXe@`0vsrmqsm)zv?R!wU)c zSdo1|W15>@CK#Z{d6uLE^NibccdeBiuo~y$;{ZzjGBNQlN?2+*!+yD*;vj_Hq%?`X?diWbrxMlj#h*j z;jlLkm2fNG9J03PsVk~kKj~x~+o<&FwC;eSAydts?JL|%CIv>cf}ATAv9(DN>bD;B ziFv01Sv$FHy6gq#gLjvr6=*w*Tn9}25FEFvom2_!vzMVyTxC`d^xUtSWW28C`(X)=u(Bq+E!QuX{&9 z7d4QNJW}e|C0d8*EUxnc_ z)+gvRoRb&|XPCi?Ldgl>Brpoa{}cTSIVjfsDSyK;0W+E0L6pv5KRSNqX-ddnsn;8GK zMzP~B8W`yVQTByc$6q|de7(DC7BkkIl!PQv-#`dNcM=8B3dY>|D<6*&7_jS;fG4l` zcTvX!k$eeS>S?)>+lX@0KokX*@Q z;Kz^v|B;HNi!x)~Z*JuyyUwm9J|^K*Y+vLx=3%F_Uru8MJ^_w8i*R4AsknuERWY1T z2zpb5=mSSxKzN`)<>1CGvzSx&R%Q}k?-XOU5#i9wHW8;roQ&cDhxUERw22d;eaC8{ z^y%*CihqLM-5NO?!l-s2je(XjU$jrv7*TPF*QO+Vo1#S{lpJQEl$L{!o$O>G;6#{~ zBX0K_K|2|lyHn{}{l@2@u_e{D{k_VO>4)Idj-(v}MYwN6ZqAb=755~NTwC3}eYJ2U`Yvsh%? z46{UfJtA6OG|#y8Z0Z3+e;flGRvliVr0xmOXLUl5VbF$wA_j&SRpGnriI3oy4R`0n zKLI*h7JY`+&Mk4gJ3a$MU{I)h8t27$jaB;&D{mwJBXA-jeBMU%Rr(|*gscR$K8H30Rl2q~UD3POz2-M}~H>cAq!-9~LLHNAR$#TXw_JzUOtHbfr4q_Wt#RNUypfC|Hoifv}(+Fi!4*s;h48Nn07!}`7iA5F@6=&X%4VU zXUL61-2Kj$f62j(1*%-`xZ!S0pWH0Dww7=y`stH+$6inFeC{PkXML0NJ19m^<|vr@ z7tbiU|A_hz5y%zze76}EVAm2;LN2DNRc@|rYJQ3r>7i@9$Ic1LKgr6iJ9F21KVLBb zJtvo(jg48Q1$YBJF$``!f-&%|s;ZSBzI?^m%!yy9DnJCs1RIA$#;hi!9yMRbs{Hf6 zW5lsdbIc|%R;cj4e6xva9K#H6u5m|%qlc9D*|k3~TlsbiD0MSN!@{%vcN6wo0S``h zS-PAk*M_5}LdsNCv*E<(l6epT5FdFxW53Ba9)@-!^YQsS_+J)G9_L)#Wm z$5;*Exy;+nL|kY45K?~0nfYDhPV_|(V6~0IU;j}2NfuB|+Su<829&R5iz{mEoY$LYi zLxkv(F^sa{i*7+^Pt5KFl~rTWPU%Tc2TI1Cw?F&fEU_zl#CkbQ|Mc&C$K&ZA%dtw{ z>3pdSvs&zmPRG<+;hue#xG4&EHX1PAByw=07+3a>8QQsqM;Wr5Zeb8zAxzRmoZ zxu0w7uukQ7yFR5V{BZx+bZ!grbu8>GT{!3YVe`T{Sd&%3rh+r}!SK-^oUVAFm%_jZ zm8|0+PE6~$y`JfNo( zhd$2OwI!c(qUB{V{T_pzBl`oTF0~pYD^pMxg0eEDS+pNE9@)~ysgqeI+h$4Y*QLsT zVVMh6g1(v+z$u1*H+p+Cc*HT6X!~wmpW(fwG!OWBS?^kyc%Kd&V&H&=hjm)?-yTyR zRadD{~3W(7nE%)?8=6}hn;I%Z&CS6@=d7-6@hmtKB*EHs6>CDlhNjvz3u-(~ zwF`i04mO6Gf|WHD_4T1T?}`=PrQTa^@n*p-I>&>|nXOl`^0usR40%>pRCycg*La(2 z*Qn>F(2c>$hINf9keY>OU29!SZDU=?dr6@9N=3p4Z(XR~)6&r3t*dBS6Y?xN^QeES5XB?1pPs^2;U*)Z+Cc{gLi&p9I>QHq_}P`xg+&Z8cxDq0juG1T={*%Yd12?e1$shOsVn@Jq3 zXGJs@o?p9e4W3aSX_506A)6L&sJ@|fO^sKTtJ!0hLF>W^-dtPNQsYs)<}V^=#Z5;r zc(zBxfl6B;PfJrpeRE?)Q>eajJ!;&^`>Z5M7Eh2$P*tH|ZDUPCeaItaaabi1*WVOs zY6(KK>nd72w&i%wU*TQk{n*F6PQ-aDyo)^xoh;p{AmRk(zm(R`>e^6OyV_e5s;CMz zv4$F(Ld~HTZ&hujM$?`U)m+<9?@^?c4NXn0jg*PzT>)EJ-CA9Z#3%&RBq48I?K;Vz zxpqUSSzBpCRS1T$rlqD?M1v5)rVxtSjOKzy=S6uSH|44U*L4;3-by4=5mmL#EpXOo z>$7HjaE52R%rhGviykfYLPw-7I(J_0g(e^Lyvc(%dGNM**!WB|AoJw^KXy(3Z@!Mn za@lH`I>}Wq`+c7LW2R4=G49K<#OMtd6GAIk%z4Z>VV~Exmjjxb$U+4&B0d@?h4$UxchN)rJ@se z4w&SCNe-CgK#@66Vh#orIT*y`U=)<&#k~->4|lmI>jhS-ys70&Ef4F;t}naJ?0U27 z&aOY!A;&hnStj187mhpfV)jXwS3<0BTxocpiuQQ2r7su!Vhz*M_XvJ>7JRv+xG@Vp zCiwd_Oyl3dip8}@gEYL4ipBMi25IXrU%*Pkm5u+9;GfWB zY4UAmW#h`mzm!IROIm$e`f|Z@tc@!T-za#Pa7O&*N$}eR@6D2aXcGLW;4jgVrOD@` zQRB*HpXGwD&}3=phXl{J`3LWL5(;k3%*0}_h!L+rQy7q1z&&@hrG_uQvT8pYkXMSaa#Fe(y%_y&MJfc zwlC4?zm^5xcb>*)YoDWn|G6eh%YSHvMsUFiR~o(mvtC|8mWD4Ce3{0i;kRSP&ufnE z2h#9E#Tw5s01u{=@+iih%2+;Hw%7V7JT0%_))>{ z$&!A1jYj-Bi~cuD!PjOC&4Q0+!F$^^;)*Qg>-eI^iy5bv zPw9fo}6r@Y@2q zZlPN&`DDuXao}wEc27We7`Uaix*Rf3$SB`TlzX$#$#^{@-D1$?uhsmd-Djk`4s<<2 zC*z}xbX}mE$8U$?ny4HPgRW2LCX(*}=$6)NeiO;Z<>?`zn<(GY&^ButG`}Y%(DO>R z;l|1HZ2{fgLg%bDWU#AyK-VF3G7QeBzrB=C=;lr!-w5c+kAiLv=7iS>op%C$=Yg*D zDCnv{7Z5s`r(`V0CeStV{dZgwwWA%Ns}Z`23FJEjy6r+I7WTg8f z=ti5ge6LK9?<(?Z)^swj$;j^(&<(X{y5CR0?*Y)=-Kyy(@@l<=q0hHlh2@1ayys&U3ToC*4p+Js$?$H9~jp z1pH>gsW%E;#{_hXK{qILKc0Z@I`V7N@=Zk71-iNGHJ!|(GM3|E&=vfHru)PM`5quY zp}TAXx_3b56FQk+Wz6@qW1v5wli^B6x|N{YE_5>A%1GA&x{AG@Z=&>aTdLqaF>#EkjQJl5lh37yOrGtw;v-P|8*`Q}ZK?{%Q_ z9t9m=$DAj06OGp%23?=f$$T=Sd15BUk*5sX#UW!tF)X{UQZclWcJpUguu@*5$)Ax$Uq z(TsF+umQ6BfTojqX-2y9K)3l9noj1Y8R@FXPv|}(a%XBEJaOJ9bkPauc7Sf)L7lJ6 zTQlZ+2z2GY)O4W<_~jjk_91jKkIl&Mlc4kbO7oNXY(~0Opu1b>WL}$*?iSE({&&q! z=C>K?9-w?e_uUD~@hs>T9@6}>*}ZkE@@<8cfY*CGg+J-k;az}e%Y~hQj4$c%cvb;^ z2=F?zu2zh ze+kHR-k0uS0j85Ak!@Xyasf~3(Nz=VXTukVc>&(+rn}{rvE%3)1M2-^#2LR ze>>oQz-}y;egkkN!q*Bc1Z28-fJ`@bv&VBA!ao9J{2oBY-zMQs3D*HqE}y`+ZqoEe z07?G~K;l~@zCq#xfL9|v2as|Mw&H9W%JDrw(su%)jTK%c;bj6(7Wi(9F2`>GS*}MV zd^+GNgdc9wa(oMra{L$z3oJ(;Aj9tiWcgl)gJV9A08%ek14a-&8Ibxs+@RC_2O!h! zknlDMUk_Lcx)l9e^d!rzPP|z{?Om8}L%#PX?r(XA1l&8e{2Lr|(ai;9zH8QK`2v8H@BM&`|3fuC#{jqwj&vj7 zE`bjUydIF{Iv0@XJ|ysuRXTk?pbzowtF^yq2Bds-0z(3G;Z)8_5aV8>U_Qi$b7m0 zFF?9i0_yz8x}O1_=<(e91mFh&e*j3n4*`Ok0WJgn z=g6F}O5k4+V7T!dE$>=D(pLeJ?bsnj379jcT{{+@j0eyhXZ#f|I`_D6U z_%DDA_euCM34a%GA?Pb5{sxJ^5b#dKe{!Bq|8YR3AN#ltzX8bbHv!Lt9xOlb^5yinSQ2(kCE_!k7)dJfW-d*kaB!o;=e5M z>m`1*#9uG*K8Zg~;!lzImrvDve+@{!|0>~!By0gPpB9O4koaj5|C(2)e+7`~e=OlX z34a}s_II1W2El(p@I?|nPr@Gsgvk{)pQ6tB6)pgT3JUN0upal61G1fb5|DQIet~bF ztiv6EFvY@40bx>wKZY^0Uittj-%Wrpt-@6j{~3w@%?H)_!@?PWq@M~%`q2|To{z)c zUIwHdwgTe1_eMaNLgC4PsKP>ipM-KAL1Vfd@C881*#HPe8vi3emg5>g z=6e+&^IZWr2jSu4b^LDt8UH*Ws;=-~0Z|2o9e}q1o(sr)3jmq#bU>)C@ULJp9q^}s zjK2#IDlTjTB>m+Qe=#8GmjmVj9w+ff-mmGN0c8580HNB#Zvc|-4HADYAmv{INI6dg zMAa0&{63w2Hz3o0ACT!c12Uh>CH^CTsET`Wd{p_NmuKsKdOsjkd+)=5P~FL!08aqC z5s>m<3`oAm0;0%;4`T4f@Yevt2%CVUyI$gp0jcjJ5SH{NAc|U81;})Ki#t!Ycqb z0iF#=e#Zck{?%hOzxx0w?;=3*%L63-?HQWiD}Ye>$p-N4j@D*d@^72`7$8s z?*t^DHGr(&4@-O=AoDv2Cf%Uh56JZ21_Z0Z8zg=yAV>>Gr>Vmy>ka~v95;i1p;p1--*dXvE zK!{v;C73YZj{%bZDS*uPO*k8fQ20GS#@`A^{xAfofL3;8cKnrxplh?gH_^Cow zZ3Z*}k(Otqk86`~Bj9R;%O!jbU=D=@uw0-|pjV(rU<~$)$7y{6djxg}EEnh# z=oJW{(w(;id*@Kb%JVb~RB=5g&odqRJq|kBeJd%k=7st?4soRq>hSA=9}@hxP#)3` zOZZOWAy_$XUKbLN=a_`A7Q7Fg0*u0B`@GZ`;#eLIW_W!Q{)=JzyzbS) zuTSs?s4tcu<4|6!sV{`>^Rc%GfBU>`Bk}M_<+p2k?p2cBJ}>)>)NgEo#`j8k`#kLV zcK)zqUf+|jects4B9DE(^?nK4=UM;6{BYMu{=>F@&e!}d6?*&p>OV{V_IcGWgN*Xp z=Tm=BtQH7>8Zk??0|Z;+u+!e>Z0CgDpZfBXFChoye)^Q=5OLwQY+cM18Uy!Lt4B|>kXUwvKl zWuI4FY1_*hE$?ZPpMBo*7(2hU8eebgf1M83i2m&JnH*O!fBQV#A z$mf&%n}yy!5BUh`ahD7JL(CuHn1sJ+<2P#g^KHC@e=G8ieo^Bul=@lNp~Hg!Ebrz{ z9p*m#anQlS2X*)j2``l}_x*`KPs04?Aq@K@JYT}a68?sS0}{@c@Jb2qMEx3wv)`{6 zhW#;YzmG9R!uIKr;M0(mc>8^da}dw4{eA|= zyA1btO&_o8ayD zokEBs-hO}TdcoW8E0qYo0CvDDjC@pibkOrl371Q_Qol3(| zs-{ec`s#)Z(fkZRb(Z*S(a1bKWAzq)>KoxAl!JqmjSV;3vFcrRip5vib03g0;aS4YE91fHx{5VHyrO+tOWjSU)z;%BYawZ^$BWwX6@m4^hI;+kgG`iswY;{n zqONW|xYagJNV_IjT~S-t+7!Zj+7-O5(y~7T-mXO=cHKWrO?Wd^=BklAw;}-E2oRw^ZQ0e^$=wipsTi zbV@VGfOc9!8qR49sTfy#$b`~{pAloXid3Xy{POZX!c}pFxnnOXwFBwq>Khx3>gp%!gvTIzmAUm>oZEd3`7(~kqu5M^(X~q{L z5Y}H|uss0q!HVW)e%+y|rQXIuQu{f%y*UIa?T~CxwzbVIYlBr4O*hxt$%D15@O2f5 z2wl&qF-auazT6}mR=3vHRRyIYZ7H;M^4lHA9RX+&GAPk(l9X1YTCI)C+>Vk+Y`v!X zrX-@2Jl51Ttgfh=IFn?WY`G*;X>(x3!RSH@>iX;{s54L3JdB=A)YYzQ`WYRg!_((?m0bu_nz`sS7ex&W!2*Mjx@e9q)# zZHmlphw^0=TSVn97U;sj5p1Ykv!TKk&E3k^!96xq2G_LW!zBE?h%|3@jdnpcgc_>l zd7_jKc~ht|RC`m%4u{$r)dz!6`bN}3ON)cySj7Hhi4XB4rptpYTjc(ZRa2go({JwZbG`fBLApDP-pp zOfeWcy<=-EY(;&gLl4)5?$jMT`z!|C4q{DfMN^f{sVM|+<%Bk9Rolplsw(xtn4tRX zkR7|OqH1yG=(96Lx7MANDY~L6Lp0lLM!zI^6R$=|E}tQTD_c6Y5jt5roRM9yrG}r( znVf4fp*?KS9}H4`7ObFY&1#!$@`l;mSa}rfl2qDy-R;HchINz6K#_z%r^1%$;b2ie zXm0^0L$0=h68)^iWG$tgLN~Ec8+ueHO4^t^($z?ms}x#SBXLKoMv@e<0mi)4&cOX_ z3y6^q)bEhceWy+Y@ckmky}5^ciFn#eZF3?Fmm(e|5odE=kNHn3zonER5iQ=3ZN#Qb NM4g=;br$D{{|6{&o+bbQ literal 0 HcmV?d00001 diff --git a/vendor/stb/lib/darwin/stb_image.a b/vendor/stb/lib/darwin/stb_image.a new file mode 100644 index 0000000000000000000000000000000000000000..1379d6f9e70c8dd9a853de55e1f5346d8d17f244 GIT binary patch literal 97544 zcmeFa3wTsTwlChDZjufJDk^GJggC|-qK*7<+ylPZo?_bHaqpxe#O)um8qT^3#U%Lb(%-D;cteWer+~a zw#`;#J}H6T?=zp(=JQGO`3Lj)s`=byK0h#@$INFwU=y4|^Lc~${E_(#n9mjF^Iy&9 zM)SGHeE!XRo;061SrYEq=JP7^=`){|=JQeW`OoI_x8`$)`P^$hKQ^CP4hi>s^I2*> z=a|p1`TSS&x!HWaZ9ZL2S^iS zfV^=2gJ#*e_f!$E`|-GU_5%;hJ~et_#q9g%n9=hdn0@b@^2(|?sfY(F=UZtAB5D2u z9kPprHP%S)~;zk8m)@B3*$TiIoDI{eI(zLlWe zy)_UK`p0}>c`7Xvb}BjpFp&||q{MV;rbVYylX}`jLUek`wV7}I<78%)iJ7$%=k(hS zQAVVswIVYTWKXYMWIh%8z4IzhQ*mWlX){k>KA;NCq&{f$2Xx^ae|hEo^A?m7@6RJx zso`N(^$j^PIiE82JI+i%kK8}+?(%!)RLs9;PWjz|%E~zwZ=@$Y01W0=^ix76l;0be zvvA?Ud5>5_0}v_4os9c@f#x(`ohcqRK~l^as@|i891fGrYxYJm@LZgUbs-ctI9ORER2Um_X~TY zGT@z=7Ei$xyoYC35y0~DOn3z*e$ScZ3V|Q}O_^%9QCrUvZ@oX|7Gh>pUwBcIFY}BY_?d>q(6_^FP0gret3i|csJ<4(_yv+9IcS%6A%yCw5 z^4sxyV8QGP5{ZlEJ$O%fxlff4Gfx1wsVlpHa7(ffvfP3Xd_CofwpY?qd%fQq11l6-BySvAwl_E zP*j`ojND_ljRZ3To^1;L(O<~?cNw1R@sDKIfAw#=#{Z`2-_!Uu zjW_xDr#}9kk00~!4w2^NjT%2Bf^t~->O%ALwxN_n4J zwVIE+QHRRIANM4aUjCYwzp3$~Uf!eWf_cz7jeA<~MugT3V`MU!)VR`)7#GEGrOnF9 zl~#@aq(iHxeyWy<-Ay$VqCbuEr{p7ohtFu}K$Sk8lr7O$H6zx`SG7_iM;-6__(wi| zSk(n?A{UVXMsjy&|*glwXS!ySWlskcfClp%3QsukM*5N559(aZmV@fK$=)id43~1OGnvR`duEUcR01zrqvlTz0m~J4$xePP^HzM26;R z$(ZJD4s=-EnYhqX@3`%@A zI1c@lwD~V2oN_eX)2!+v75zFzKgY*E1g-)vA8!MfjQnQu{6AJXl~wj={0+$}G(0j` z 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 VgvCIU*OUwPCyoSGl89s9wlAP9^WFde literal 0 HcmV?d00001 diff --git a/vendor/stb/lib/darwin/stb_image_resize.a b/vendor/stb/lib/darwin/stb_image_resize.a new file mode 100644 index 0000000000000000000000000000000000000000..f39c507a6c92d777f16c781d44a9dd3b623c42f9 GIT binary patch literal 36824 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�v~7pkgTJ;d*1^hn>h_iu?g+9QcFkLJdSa5i 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 literal 0 HcmV?d00001 diff --git a/vendor/stb/lib/darwin/stb_rect_pack.a b/vendor/stb/lib/darwin/stb_rect_pack.a new file mode 100644 index 0000000000000000000000000000000000000000..3b55ab8025d7dca76643a92399f45397e35f46e7 GIT binary patch literal 5064 zcma)A4{Q_H89x&fjB7XpX$g#Wx8k-~t3#ZG1TT=~;Ep`AJN_jeOe4L7V2DNjfPF5Z zvPmWr#M@y&TQ`k~Zb*|hG-(5EMd}#a9D+z`vNnON)!J&KU8@#cCQ7C>&<*ct z5G7B3_j}*>{l4#g@7=q1&-b-e_2Gub3j0#;@}ffSVeyuh6#IOorQVesx1!Js2E*(v zEG#W4;W+P#QcA9~D@sB2cVt0a$5n6KQX>is6pmb=+<>}(;xiQ2Qmg}1BI=ItUM18L zQWdp6ygR6xs=f6Mdz5gnL5-N2NKlRLRqC6XTK6lhQB`T(r8Ebd$6FhN(QqiDh8iF? zDU*(?=+WaUDO*XWq0SDe=?N$#m4a41-dp!?KbXZZmK=~QP_0mHGvLBOg|Z0h5n`C6 zha713H+H&P)Q+7Qpvp_xsFQ|Cf~=htfHs_o~0^1FPu0wgK17wxOOX2MLMrMh+!6E(6TRWq7Mqz*TvcJ16-s zMj*O`w=P4;s+9;=72^FXd#YA}OC@M4X}??fZ}S1ZrWz$aYeRSlHQepI#vVHd_s)<1 z%j0)Ya&4aXDz>3a7fPh^{l2%NcTsWVuh_V(3d)b<#qtw@R@Ocu? z=}kfCRF60a{Z{sfeFSd)jtrnj=+z(6n@@u)B^Yc8rzumykOz!gzNn86 zIm;!!yvAj1FDn-Z<4zWCv7d|%dM`1M|IE6lxjyBqcK?QPtP$2(GPhuiF+2d^ViUjwICzo zk40aJD{hyyW}E1XGO=Mvi=U7?Z?lIE1BcgY8Nody;SmXcz#f?oL-pf6Kkh+E-i9>4 z&9~^_zj@yh7km6mSXC1K1pmVr@hN@8Ft+xUWST8qFy@Z(_11Q`CZ7UzY+kwC7ju-? z_Qw}OOP!f^V!033_QUY>?&2wu)6IRb2#^*{q0V8X87o6GR)!YrkhJC#?4j>NqNI-; zd5|xMyV)L-HNnNnFbQFVU)KWtJa+Q9((2cc&5tD)hqSrAdGWbO+YIy91&iiQga;%o za74nnNZV%5i5qwXy*C2e?uc;6Lml=_gF99J8AqK!9`d)ek zdJQseClzvng$c`qL_nF8$YLKacC%a5dwV-{K_YJYf zf2!Z-Dx0s6J@!Lr3rTB{H^pCoCL{W~w>$N_g&}N4eyHhL*9K!V9#C$X93?x=Lqii zc+1~KJS5_Gczjv(U5Wif!1KsFWX%GZ0F+#Pi=>-eaZiUiR+#z=H=#W`M?mQ@C~q5- z^@MUei&6$ki1K@bvYk*)!)0ugJcDw=psXd7UuIE0*KI4B4GMYPU8u{V6oU*Mtv4v& zB$Vf}C{Ba&oI&|Ip%j=DLg9$+OsJ0tSP0W-mZyvcOy>AP^~_{;@>(XP&43C1uNr!WgG0)|wwV*`gXHi6 zML!GDW00XSu9lewlJhE*3I2}*n{uO#|oy@;t3VZz& z_Cr(He>H_Yj}F)J(iXD@l$H#jfI4?upPI=_M>&4{BiCIT;lQWN5kHcZe$n!Fwbl=F6u7e42 z$#_14x|#CmdYHf?{gdrz4dsz_p%=6NszmP5(cX>z1>pac^67n^5SR4d1iaU$!Fw5a z-P7P*1m2&g!TSh!f0zc(0f(bkr@<=$-q|U5S73pVzi1Z$f&Tb;iod1!3u-?}O0O7Bo=M_NsJ^5oQ9|nYeo?K03Hz53; zd>@psusyfno)IKF67jzS>xb|c1A@x)xV|VE&uI|gm)k+Hj$$Q6jv_pTxieJ7ez4(9~sfpG8zQ_hmozH}^?0P7>eT z7td4K+y}`Uo!HHN?@ekSyU($}G2bhtU?;Nq9@#@>b3gkTl>zip3s<0z7P1G9mCdg( z<6p|g`%>9Q-uWhDicdY{i;vP84($%L)Hgw6XD|#OLzMbRBp6neu-anAne1zj9-vV_ zU>M&h!ol$_qel)?{qRduK|^cP&Vpjo@QA?}j3Sef?K*16Ixl6pO&ZucS>RE_BLjPx F{{yO}#B2Zn literal 0 HcmV?d00001 diff --git a/vendor/stb/lib/darwin/stb_truetype.a b/vendor/stb/lib/darwin/stb_truetype.a new file mode 100644 index 0000000000000000000000000000000000000000..c4a895b54b69c674e69c31dc2464951a929cc3a4 GIT binary patch literal 67008 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 r6E3W