From aaa8ffba477cde454e1a3afd8afdaac82b812a00 Mon Sep 17 00:00:00 2001 From: peterino2 Date: Sun, 25 Jan 2026 13:43:46 -0800 Subject: [PATCH] can parse all major header files now tested with Dofficial and castholm repos --- AGENTS.md | 56 ++++++++++++++++ json/error.json | 28 -------- json/render.json | 26 -------- src/dependency_resolver.zig | 8 --- src/io.zig | 10 +++ src/parser.zig | 127 ++++++++---------------------------- src/patterns.zig | 123 +++++----------------------------- src/types.zig | 104 +++++++++++++---------------- v2/error.zig | 10 --- v2/render.zig | 9 --- 10 files changed, 153 insertions(+), 348 deletions(-) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..7e3931b --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,56 @@ +# SDL3 Header Parser - Agent Documentation + +## Project Overview + +This is an SDL3 header parser that converts C header files into Zig interfaces, JSON objects, and C mocks. Built specifically for SDL3 headers (developed against SDL 3.2.10), it focuses on generating Zig APIs. + +**Key Points:** +- Not a real C parser - best-effort text transformation specifically for SDL3 headers +- Does not do proper AST elaboration or tokenization +- Simple to modify but brittle +- Requires Zig 0.15.2 and git + +## Architecture + +The codebase consists of several modules: +- `parser.zig` - Main entry point and orchestration +- `patterns.zig` - SDL3 pattern matching and declaration scanning +- `codegen.zig` - Zig code generation +- `mock_codegen.zig` - C mock generation +- `json_serializer.zig` - JSON output generation +- `dependency_resolver.zig` - Type dependency resolution +- `header_cache.zig` - Header caching for cross-file type resolution +- `io.zig` - Error handling utilities +- `types.zig` - Type mapping and conversions +- `naming.zig` - Naming conventions + +## Developing + +### Error Handling +**CRITICAL:** Whenever actual errors are encountered (parsing failures, invalid declarations, missing types, etc.), you MUST call `io.emitError` to report them properly. Do NOT use `std.debug.print` for actual errors. + +```zig +// Good - proper error reporting +try io.emitError(allocator, "Failed to parse struct field: {s}", .{field_name}); + +// Bad - don't use for errors +std.debug.print("Error: Failed to parse...\n", .{}); +``` + +### Validation Process +After generating Zig code: +1. Output written to `tmp/` directory +2. `zig ast-check` runs on the temporary file +3. If passes: `zig fmt` runs, then copied to final destination +4. If fails: debug output written to `debug/` with `_fmterror.zig` suffix + +### Memory Management +- Two cleanup functions exist with identical logic: + - `freeDecls()` - frees a slice of declarations + - `freeDeclDeep()` - frees a single declaration +- Both free all nested allocations (names, types, doc comments, params/fields/values/flags) + +### Main APIs (Priority) +Focus areas: gpu, video, gamepad, joystick, input, event + +Anything beyond these is not actively maintained. diff --git a/json/error.json b/json/error.json index d453d68..8fc1d5a 100644 --- a/json/error.json +++ b/json/error.json @@ -9,34 +9,6 @@ "unions": [], "flags": [], "functions": [ - { - "name": "SDL_SetError", - "return_type": "bool", - "parameters": [ - { - "name": "fmt", - "type": "const char *" - }, - { - "name": "", - "type": "..." - } - ] - }, - { - "name": "SDL_SetErrorV", - "return_type": "bool", - "parameters": [ - { - "name": "fmt", - "type": "const char *" - }, - { - "name": "ap", - "type": "va_list" - } - ] - }, { "name": "SDL_OutOfMemory", "return_type": "bool", diff --git a/json/render.json b/json/render.json index 0322d31..948b905 100644 --- a/json/render.json +++ b/json/render.json @@ -1638,32 +1638,6 @@ "type": "const char *" } ] - }, - { - "name": "SDL_RenderDebugTextFormat", - "return_type": "bool", - "parameters": [ - { - "name": "renderer", - "type": "SDL_Renderer *" - }, - { - "name": "x", - "type": "float" - }, - { - "name": "y", - "type": "float" - }, - { - "name": "fmt", - "type": "const char *" - }, - { - "name": "", - "type": "..." - } - ] } ] } \ No newline at end of file diff --git a/src/dependency_resolver.zig b/src/dependency_resolver.zig index b7f4ac2..46588cc 100644 --- a/src/dependency_resolver.zig +++ b/src/dependency_resolver.zig @@ -49,14 +49,6 @@ pub const DependencyResolver = struct { return try missing.toOwnedSlice(allocator); } - /// Get hardcoded declarations for special types that can't be resolved from headers - /// Currently unused - function pointer typedefs are now handled as c_type_alias in patterns - pub fn getHardcodedDeclarations(self: *DependencyResolver, allocator: Allocator) ![]Declaration { - _ = self; - var hardcoded = std.ArrayList(Declaration){}; - return try hardcoded.toOwnedSlice(allocator); - } - fn collectDefinedTypes(self: *DependencyResolver, decls: []const Declaration) !void { for (decls) |decl| { const type_name = switch (decl) { diff --git a/src/io.zig b/src/io.zig index d3e3f48..783d6d6 100644 --- a/src/io.zig +++ b/src/io.zig @@ -11,4 +11,14 @@ pub fn initWriter() void { stdout = &stdout_writer.interface; } +pub fn emitError(src: std.builtin.SourceLocation, errorMessage: []const u8) void { + std.debug.print("----- Error occured -----\n", .{}); + std.debug.print("in {s}:{d} module: {s}", .{ src.file, src.line, src.module }); + std.debug.print("function: {s}", .{src.fn_name}); + std.debug.print("message: '{s}'", .{errorMessage}); + std.debug.dumpCurrentStackTrace(null); + std.debug.print("---- /Error occured -----\n", .{}); +} + pub const std = @import("std"); +const buildOptions = @import("buildOptions"); diff --git a/src/parser.zig b/src/parser.zig index d906815..9ee137c 100644 --- a/src/parser.zig +++ b/src/parser.zig @@ -6,6 +6,13 @@ const json_serializer = @import("json_serializer.zig"); const io = @import("io.zig"); const header_cache = @import("header_cache.zig"); +pub fn freeDecls(allocator: std.mem.Allocator, decls: []patterns.Declaration) void { + for (decls) |decl| { + freeDeclDeep(allocator, decl); + } + allocator.free(decls); +} + pub fn main() !void { const allocator = std.heap.smp_allocator; @@ -74,87 +81,7 @@ pub fn main() !void { // Parse declarations var scanner = patterns.Scanner.init(allocator, source); const decls = try scanner.scan(); - defer { - for (decls) |decl| { - switch (decl) { - .opaque_type => |opaque_decl| { - allocator.free(opaque_decl.name); - if (opaque_decl.doc_comment) |doc| allocator.free(doc); - }, - .typedef_decl => |typedef_decl| { - allocator.free(typedef_decl.name); - allocator.free(typedef_decl.underlying_type); - if (typedef_decl.doc_comment) |doc| allocator.free(doc); - }, - .function_pointer_decl => |func_ptr_decl| { - allocator.free(func_ptr_decl.name); - allocator.free(func_ptr_decl.return_type); - if (func_ptr_decl.doc_comment) |doc| allocator.free(doc); - for (func_ptr_decl.params) |param| { - allocator.free(param.name); - allocator.free(param.type_name); - } - allocator.free(func_ptr_decl.params); - }, - .c_type_alias => |alias| { - allocator.free(alias.name); - if (alias.doc_comment) |doc| allocator.free(doc); - }, - .enum_decl => |enum_decl| { - allocator.free(enum_decl.name); - if (enum_decl.doc_comment) |doc| allocator.free(doc); - for (enum_decl.values) |val| { - allocator.free(val.name); - if (val.value) |v| allocator.free(v); - if (val.comment) |c| allocator.free(c); - } - allocator.free(enum_decl.values); - }, - .struct_decl => |struct_decl| { - allocator.free(struct_decl.name); - if (struct_decl.doc_comment) |doc| allocator.free(doc); - for (struct_decl.fields) |field| { - allocator.free(field.name); - allocator.free(field.type_name); - if (field.comment) |c| allocator.free(c); - } - allocator.free(struct_decl.fields); - }, - .union_decl => |union_decl| { - allocator.free(union_decl.name); - if (union_decl.doc_comment) |doc| allocator.free(doc); - for (union_decl.fields) |field| { - allocator.free(field.name); - allocator.free(field.type_name); - if (field.comment) |c| allocator.free(c); - } - allocator.free(union_decl.fields); - }, - .flag_decl => |flag_decl| { - allocator.free(flag_decl.name); - allocator.free(flag_decl.underlying_type); - if (flag_decl.doc_comment) |doc| allocator.free(doc); - for (flag_decl.flags) |flag| { - allocator.free(flag.name); - allocator.free(flag.value); - if (flag.comment) |c| allocator.free(c); - } - allocator.free(flag_decl.flags); - }, - .function_decl => |func| { - allocator.free(func.name); - allocator.free(func.return_type); - if (func.doc_comment) |doc| allocator.free(doc); - for (func.params) |param| { - allocator.free(param.name); - allocator.free(param.type_name); - } - allocator.free(func.params); - }, - } - } - allocator.free(decls); - } + defer freeDecls(allocator, decls); std.debug.print("Found {d} declarations\n", .{decls.len}); @@ -240,17 +167,17 @@ pub fn main() !void { } // Get hardcoded declarations for special types (like SDL_HitTest) - const hardcoded_decls = try resolver.getHardcodedDeclarations(allocator); - defer { - for (hardcoded_decls) |hd| { - freeDeclDeep(allocator, hd); - } - allocator.free(hardcoded_decls); - } + // const hardcoded_decls = try resolver.getHardcodedDeclarations(allocator); + // defer { + // for (hardcoded_decls) |hd| { + // freeDeclDeep(allocator, hd); + // } + // allocator.free(hardcoded_decls); + // } - if (hardcoded_decls.len > 0) { - std.debug.print("Adding {d} hardcoded type declarations\n", .{hardcoded_decls.len}); - } + // if (hardcoded_decls.len > 0) { + // std.debug.print("Adding {d} hardcoded type declarations\n", .{hardcoded_decls.len}); + // } var dependency_decls = std.ArrayList(patterns.Declaration){}; defer { @@ -275,7 +202,7 @@ pub fn main() !void { // PHASE 2: Resolve dependencies via cache lookup with recursive dependency resolution std.debug.print("Resolving dependencies from cache...\n", .{}); - + // Track which types we've already added to avoid duplicates var added_types = std.StringHashMap(void).init(allocator); defer { @@ -285,17 +212,17 @@ pub fn main() !void { } added_types.deinit(); } - + for (missing_types) |missing_type| { // Skip if already added if (added_types.contains(missing_type)) continue; - + // Look up type with all its dependencies const resolved_decls = cache.lookupTypeWithDependencies(missing_type) catch |err| { std.debug.print(" Warning: Could not resolve {s}: {}\n", .{ missing_type, err }); continue; }; - + // Add all resolved declarations for (resolved_decls) |resolved_decl| { const decl_type_name = switch (resolved_decl) { @@ -309,11 +236,11 @@ pub fn main() !void { .flag_decl => |f| f.name, .function_decl => continue, // Skip functions }; - + if (!added_types.contains(decl_type_name)) { try dependency_decls.append(allocator, resolved_decl); try added_types.put(try allocator.dupe(u8, decl_type_name), {}); - + if (std.mem.eql(u8, decl_type_name, missing_type)) { std.debug.print(" Found {s} in cache\n", .{missing_type}); } else { @@ -324,7 +251,7 @@ pub fn main() !void { freeDeclDeep(allocator, resolved_decl); } } - + allocator.free(resolved_decls); } @@ -332,12 +259,12 @@ pub fn main() !void { } // Combine declarations (hardcoded first, then dependencies, then primary!) - std.debug.print("Combining {d} hardcoded + {d} dependency declarations with primary declarations...\n", .{ hardcoded_decls.len, dependency_decls.items.len }); + std.debug.print("Combining {d} dependency declarations with primary declarations...\n", .{dependency_decls.items.len}); var all_decls = std.ArrayList(patterns.Declaration){}; defer all_decls.deinit(allocator); - try all_decls.appendSlice(allocator, hardcoded_decls); + // try all_decls.appendSlice(allocator, hardcoded_decls); try all_decls.appendSlice(allocator, dependency_decls.items); try all_decls.appendSlice(allocator, decls); diff --git a/src/patterns.zig b/src/patterns.zig index bcc9f27..51d0af9 100644 --- a/src/patterns.zig +++ b/src/patterns.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const io = @import("io"); const Allocator = std.mem.Allocator; fn fixupZigName(name: []const u8) []u8 { @@ -603,7 +604,7 @@ pub const Scanner = struct { const body = try self.readBracedBlock(); defer self.allocator.free(body); - // Check if struct contains unions - C unions can't be represented in other languages + // Check if struct contains unions - C embedded unions can't be represented in other languages const has_unions = std.mem.indexOf(u8, body, "union ") != null or std.mem.indexOf(u8, body, "union{") != null or std.mem.indexOf(u8, body, "union\n") != null or @@ -876,7 +877,7 @@ pub const Scanner = struct { const type_parts = parts_list[0 .. parts_count - 1]; // Reconstruct type with array notation - var type_buf: [128]u8 = undefined; + var type_buf: [256]u8 = undefined; var fbs = std.io.fixedBufferStream(&type_buf); const writer = fbs.writer(); for (type_parts, 0..) |part, i| { @@ -889,6 +890,7 @@ pub const Scanner = struct { return null; }; } + writer.writeAll(bracket_part) catch { if (comment) |c| self.allocator.free(c); return null; @@ -1176,12 +1178,15 @@ pub const Scanner = struct { "SDL_PRINTF_VARARG_FUNCV", "SDL_WPRINTF_VARARG_FUNC", "SDL_SCANF_VARARG_FUNC", + }; + + // these mean nothing in any other language than C, we just blow it away + const clang_acqrel = [_][]const u8{ "SDL_ACQUIRE", "SDL_RELEASE", }; - for (vararg_macros) |macro| { + for (clang_acqrel) |macro| { if (std.mem.indexOf(u8, text, macro)) |pos| { - // Find semicolon after this position if (std.mem.indexOfScalarPos(u8, text, pos, ';')) |semi_pos| { // Find the closing ) before semicolon var paren_pos = semi_pos; @@ -1201,6 +1206,13 @@ pub const Scanner = struct { } } + for (vararg_macros) |macro| { + if (std.mem.indexOf(u8, text, macro)) |pos| { + _ = pos; + return null; // we dont attempt to generate vararg functions. + } + } + // Find SDLCALL to split return type and function name const sdlcall_pos = std.mem.indexOf(u8, text, "SDLCALL ") orelse return null; const return_type_str = std.mem.trim(u8, text[0..sdlcall_pos], " \t\n"); @@ -1479,106 +1491,3 @@ pub const Scanner = struct { return comment; } }; - -test "scan opaque typedef" { - const source = "typedef struct SDL_GPUDevice SDL_GPUDevice;"; - var arena = std.heap.ArenaAllocator.init(std.testing.allocator); - defer arena.deinit(); - const allocator = arena.allocator(); - - var scanner = Scanner.init(allocator, source); - const decls = try scanner.scan(); - - try std.testing.expectEqual(@as(usize, 1), decls.len); - try std.testing.expect(decls[0] == .opaque_type); - try std.testing.expectEqualStrings("SDL_GPUDevice", decls[0].opaque_type.name); -} - -test "scan function declaration" { - const source = - \\extern SDL_DECLSPEC bool SDLCALL SDL_GPUSupportsShaderFormats( - \\ SDL_GPUShaderFormat format_flags, - \\ const char *name); - ; - var arena = std.heap.ArenaAllocator.init(std.testing.allocator); - defer arena.deinit(); - const allocator = arena.allocator(); - - var scanner = Scanner.init(allocator, source); - const decls = try scanner.scan(); - - try std.testing.expectEqual(@as(usize, 1), decls.len); - try std.testing.expect(decls[0] == .function_decl); - const func = decls[0].function_decl; - try std.testing.expectEqualStrings("SDL_GPUSupportsShaderFormats", func.name); - try std.testing.expectEqualStrings("bool", func.return_type); -} - -test "scan flag typedef with newline before defines" { - const source = - \\typedef Uint32 SDL_GPUTextureUsageFlags; - \\ - \\#define SDL_GPU_TEXTUREUSAGE_SAMPLER (1u << 0) - \\#define SDL_GPU_TEXTUREUSAGE_COLOR_TARGET (1u << 1) - \\#define SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET (1u << 2) - ; - var arena = std.heap.ArenaAllocator.init(std.testing.allocator); - defer arena.deinit(); - const allocator = arena.allocator(); - - var scanner = Scanner.init(allocator, source); - const decls = try scanner.scan(); - - try std.testing.expectEqual(@as(usize, 1), decls.len); - try std.testing.expect(decls[0] == .flag_decl); - const flag = decls[0].flag_decl; - try std.testing.expectEqualStrings("SDL_GPUTextureUsageFlags", flag.name); - try std.testing.expectEqualStrings("Uint32", flag.underlying_type); - try std.testing.expectEqual(@as(usize, 3), flag.flags.len); - try std.testing.expectEqualStrings("SDL_GPU_TEXTUREUSAGE_SAMPLER", flag.flags[0].name); - try std.testing.expectEqualStrings("SDL_GPU_TEXTUREUSAGE_COLOR_TARGET", flag.flags[1].name); - try std.testing.expectEqualStrings("SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET", flag.flags[2].name); -} - -test "scan flag typedef with multiple blank lines" { - const source = - \\typedef Uint32 SDL_GPUBufferUsageFlags; - \\ - \\ - \\#define SDL_GPU_BUFFERUSAGE_VERTEX (1u << 0) - \\#define SDL_GPU_BUFFERUSAGE_INDEX (1u << 1) - ; - var arena = std.heap.ArenaAllocator.init(std.testing.allocator); - defer arena.deinit(); - const allocator = arena.allocator(); - - var scanner = Scanner.init(allocator, source); - const decls = try scanner.scan(); - - try std.testing.expectEqual(@as(usize, 1), decls.len); - try std.testing.expect(decls[0] == .flag_decl); - const flag = decls[0].flag_decl; - try std.testing.expectEqual(@as(usize, 2), flag.flags.len); -} - -test "scan flag typedef with comments before defines" { - const source = - \\typedef Uint32 SDL_GPUColorComponentFlags; - \\ - \\/* Comment here */ - ; - var arena = std.heap.ArenaAllocator.init(std.testing.allocator); - defer arena.deinit(); - const allocator = arena.allocator(); - - var scanner = Scanner.init(allocator, source); - const decls = try scanner.scan(); - - // Should still parse the typedef even if no #defines follow - try std.testing.expectEqual(@as(usize, 1), decls.len); - try std.testing.expect(decls[0] == .flag_decl); - const flag = decls[0].flag_decl; - try std.testing.expectEqualStrings("SDL_GPUColorComponentFlags", flag.name); - // No flags found, but that's ok - try std.testing.expectEqual(@as(usize, 0), flag.flags.len); -} diff --git a/src/types.zig b/src/types.zig index 2c6f2b3..3818a7c 100644 --- a/src/types.zig +++ b/src/types.zig @@ -1,6 +1,8 @@ const std = @import("std"); const Allocator = std.mem.Allocator; +const io = @import("io"); +var fmtBuffer: [256]u8 = undefined; /// Convert C type to Zig type /// Simple table-based conversion for SDL3 types pub fn convertType(c_type: []const u8, allocator: Allocator) ![]const u8 { @@ -21,14 +23,34 @@ pub fn convertType(c_type: []const u8, allocator: Allocator) ![]const u8 { // Handle array types: "Uint8[2]" -> "[2]u8" if (std.mem.indexOf(u8, trimmed, "[")) |bracket_pos| { const base_type = std.mem.trim(u8, trimmed[0..bracket_pos], " \t"); - const array_part = trimmed[bracket_pos..]; // "[2]" - + var array_part = trimmed[bracket_pos..]; // "[2]" + // Recursively convert the base type const zig_base = try convertType(base_type, allocator); defer allocator.free(zig_base); - + + const inner = array_part[1 .. array_part.len - 1]; + if (inner.len > 0) { + var alias_to_c: bool = false; + + _ = std.fmt.parseInt(u32, inner, 0) catch { + // not a real error + alias_to_c = true; + }; + + if (alias_to_c) { + var b = std.io.fixedBufferStream(&fmtBuffer); + _ = try b.write("["); + _ = try b.write("c."); + _ = try b.write(inner); + _ = try b.write("]"); + array_part = b.getWritten(); + std.debug.print("arrya_part = {s}\n", .{array_part}); + } + } + // Return Zig array notation: [size]Type - return try std.fmt.allocPrint(allocator, "{s}{s}", .{array_part, zig_base}); + return try std.fmt.allocPrint(allocator, "{s}{s}", .{ array_part, zig_base }); } // Primitives @@ -86,7 +108,7 @@ pub fn convertType(c_type: []const u8, allocator: Allocator) ![]const u8 { return std.fmt.allocPrint(allocator, "[*c][*c]{s}", .{base_type}); } } - + // Handle primitive pointer types if (std.mem.eql(u8, trimmed, "int *")) return try allocator.dupe(u8, "*c_int"); if (std.mem.eql(u8, trimmed, "bool *")) return try allocator.dupe(u8, "*bool"); @@ -102,7 +124,7 @@ pub fn convertType(c_type: []const u8, allocator: Allocator) ![]const u8 { if (std.mem.eql(u8, trimmed, "Sint16 *")) return try allocator.dupe(u8, "*i16"); if (std.mem.eql(u8, trimmed, "Sint32 *")) return try allocator.dupe(u8, "*i32"); if (std.mem.eql(u8, trimmed, "const bool *")) return try allocator.dupe(u8, "*const bool"); - + if (std.mem.startsWith(u8, trimmed, "const ")) { const rest = trimmed[6..]; if (std.mem.endsWith(u8, rest, " *") or std.mem.endsWith(u8, rest, "*")) { @@ -144,7 +166,7 @@ pub fn convertType(c_type: []const u8, allocator: Allocator) ![]const u8 { return std.fmt.allocPrint(allocator, "*const {s}", .{struct_name}); } } - + // Handle "Foo *" for any remaining types (fallback to C pointer) if (std.mem.endsWith(u8, trimmed, " *")) { const base_type = trimmed[0 .. trimmed.len - 2]; @@ -190,26 +212,26 @@ pub fn getCastType(zig_type: []const u8) CastType { /// Example: Sint64 (SDLCALL *size)(void *userdata) -> *const fn (?*anyopaque) callconv(.C) i64 fn convertFunctionPointerType(c_type: []const u8, allocator: Allocator) ![]const u8 { // Pattern: ReturnType (SDLCALL *name)(params) or ReturnType (*name)(params) - + // Find the return type (everything before the opening paren) const open_paren = std.mem.indexOf(u8, c_type, "(") orelse return try allocator.dupe(u8, c_type); const return_type_str = std.mem.trim(u8, c_type[0..open_paren], " \t"); - + // Find the parameters (between the last ( and the last )) const last_open_paren = std.mem.lastIndexOf(u8, c_type, "(") orelse return try allocator.dupe(u8, c_type); const last_close_paren = std.mem.lastIndexOf(u8, c_type, ")") orelse return try allocator.dupe(u8, c_type); - + if (last_close_paren <= last_open_paren) return try allocator.dupe(u8, c_type); - + const params_str = std.mem.trim(u8, c_type[last_open_paren + 1 .. last_close_paren], " \t"); - + // Convert return type (but don't recursively convert function pointers) const zig_return = if (std.mem.indexOf(u8, return_type_str, "(") != null) try allocator.dupe(u8, return_type_str) else try convertType(return_type_str, allocator); defer allocator.free(zig_return); - + // Convert parameters var params_list = std.ArrayList([]const u8).init(allocator); defer { @@ -218,18 +240,18 @@ fn convertFunctionPointerType(c_type: []const u8, allocator: Allocator) ![]const } params_list.deinit(); } - + // Parse comma-separated parameters var param_iter = std.mem.splitScalar(u8, params_str, ','); while (param_iter.next()) |param| { const trimmed_param = std.mem.trim(u8, param, " \t"); if (trimmed_param.len == 0) continue; - + // Extract just the type (remove parameter name if present) // Pattern: "void *userdata" -> "void *" // Pattern: "Sint64 offset" -> "Sint64" var param_type: []const u8 = trimmed_param; - + // Find the last space that separates type from name if (std.mem.lastIndexOf(u8, trimmed_param, " ")) |space_pos| { // Check if what comes after is an identifier (not a *) @@ -238,7 +260,7 @@ fn convertFunctionPointerType(c_type: []const u8, allocator: Allocator) ![]const param_type = std.mem.trimRight(u8, trimmed_param[0..space_pos], " \t"); } } - + // Don't recursively convert function pointers in params const zig_param = if (std.mem.indexOf(u8, param_type, "(") != null) try allocator.dupe(u8, param_type) @@ -246,21 +268,21 @@ fn convertFunctionPointerType(c_type: []const u8, allocator: Allocator) ![]const try convertType(param_type, allocator); try params_list.append(zig_param); } - + // Build Zig function pointer type var result = std.ArrayList(u8).init(allocator); defer result.deinit(); - + try result.appendSlice("?*const fn ("); - + for (params_list.items, 0..) |param, i| { if (i > 0) try result.appendSlice(", "); try result.appendSlice(param); } - + try result.appendSlice(") callconv(.C) "); try result.appendSlice(zig_return); - + return try result.toOwnedSlice(); } @@ -271,41 +293,3 @@ pub const CastType = enum { int_from_enum, enum_from_int, }; - -test "convert primitive types" { - const t1 = try convertType("float", std.testing.allocator); - defer std.testing.allocator.free(t1); - try std.testing.expectEqualStrings("f32", t1); - - const t2 = try convertType("Uint32", std.testing.allocator); - defer std.testing.allocator.free(t2); - try std.testing.expectEqualStrings("u32", t2); - - const t3 = try convertType("bool", std.testing.allocator); - defer std.testing.allocator.free(t3); - try std.testing.expectEqualStrings("bool", t3); -} - -test "convert SDL types" { - const t1 = try convertType("SDL_GPUDevice", std.testing.allocator); - defer std.testing.allocator.free(t1); - try std.testing.expectEqualStrings("GPUDevice", t1); - - const t2 = try convertType("SDL_GPUDevice *", std.testing.allocator); - defer std.testing.allocator.free(t2); - try std.testing.expectEqualStrings("?*GPUDevice", t2); - - const t3 = try convertType("const SDL_GPUViewport *", std.testing.allocator); - defer std.testing.allocator.free(t3); - try std.testing.expectEqualStrings("*const GPUViewport", t3); -} - -test "convert pointer types" { - const t1 = try convertType("const char *", std.testing.allocator); - defer std.testing.allocator.free(t1); - try std.testing.expectEqualStrings("[*c]const u8", t1); - - const t2 = try convertType("void *", std.testing.allocator); - defer std.testing.allocator.free(t2); - try std.testing.expectEqualStrings("?*anyopaque", t2); -} diff --git a/v2/error.zig b/v2/error.zig index 91ba5bd..1954227 100644 --- a/v2/error.zig +++ b/v2/error.zig @@ -1,16 +1,6 @@ const std = @import("std"); pub const c = @import("c.zig").c; -pub inline fn setError(fmt: [*c]const u8, ...) bool { - return c.SDL_SetError( - fmt, - ); -} - -pub inline fn setErrorV(fmt: [*c]const u8, ap: std.builtin.VaList) bool { - return c.SDL_SetErrorV(fmt, ap); -} - pub inline fn outOfMemory() bool { return c.SDL_OutOfMemory(); } diff --git a/v2/render.zig b/v2/render.zig index f50ce41..703b480 100644 --- a/v2/render.zig +++ b/v2/render.zig @@ -1039,15 +1039,6 @@ pub const Renderer = opaque { pub inline fn renderDebugText(renderer: *Renderer, x: f32, y: f32, str: [*c]const u8) bool { return c.SDL_RenderDebugText(renderer, x, y, str); } - - pub inline fn renderDebugTextFormat(renderer: *Renderer, x: f32, y: f32, fmt: [*c]const u8, ...) bool { - return c.SDL_RenderDebugTextFormat( - renderer, - x, - y, - fmt, - ); - } }; pub const Texture = opaque {