diff --git a/lib/sdl3/parser/src/codegen.zig b/lib/sdl3/parser/src/codegen.zig index 7c89def..5681282 100644 --- a/lib/sdl3/parser/src/codegen.zig +++ b/lib/sdl3/parser/src/codegen.zig @@ -603,6 +603,11 @@ pub const CodeGen = struct { trimmed = std.mem.trim(u8, trimmed[inner_start..], " \t)"); } + // Strip 'u' or 'U' suffix from C literals (e.g., "0x00000010u" -> "0x00000010") + if (trimmed.len > 0 and (trimmed[trimmed.len - 1] == 'u' or trimmed[trimmed.len - 1] == 'U')) { + trimmed = trimmed[0 .. trimmed.len - 1]; + } + // Look for bit shift pattern: "1u << N" or "1 << N" if (std.mem.indexOf(u8, trimmed, "<<")) |shift_pos| { const after_shift = std.mem.trim(u8, trimmed[shift_pos + 2 ..], " \t)"); diff --git a/lib/sdl3/parser/src/patterns.zig b/lib/sdl3/parser/src/patterns.zig index 17f32ce..98d485f 100644 --- a/lib/sdl3/parser/src/patterns.zig +++ b/lib/sdl3/parser/src/patterns.zig @@ -1097,12 +1097,25 @@ pub const Scanner = struct { if (trimmed.len == 0) continue; // Find the last identifier (parameter name) + // Handle array syntax like "char *argv[]" -> type:"char **" name:"argv" + var working_param = trimmed; + var is_array = false; + + // Check for array brackets [] and remove them + if (std.mem.lastIndexOfScalar(u8, working_param, '[')) |bracket_pos| { + // Find matching ] + if (std.mem.indexOfScalar(u8, working_param[bracket_pos..], ']')) |_| { + is_array = true; + working_param = std.mem.trimRight(u8, working_param[0..bracket_pos], " \t"); + } + } + // Simple heuristic: last space or * separates type from name var name_start: usize = 0; - var i = trimmed.len; + var i = working_param.len; while (i > 0) { i -= 1; - const c = trimmed[i]; + const c = working_param[i]; if (c == ' ' or c == '*' or c == '\t') { name_start = i + 1; break; @@ -1113,11 +1126,31 @@ pub const Scanner = struct { // No space found - might be just a type (like "void") try params_list.append(self.allocator, ParamDecl{ .name = "", - .type_name = try self.allocator.dupe(u8, trimmed), + .type_name = try self.allocator.dupe(u8, working_param), }); } else { - const param_type = std.mem.trim(u8, trimmed[0..name_start], " \t"); - const param_name = std.mem.trim(u8, trimmed[name_start..], " \t"); + var param_type = std.mem.trim(u8, working_param[0..name_start], " \t"); + const param_name = std.mem.trim(u8, working_param[name_start..], " \t"); + + // If this was an array parameter, convert pointer level + // e.g., "char *" becomes "[*c][*c]char" for argv[] + var type_buf: [256]u8 = undefined; + if (is_array) { + // For array parameters like argv[], we need pointer-to-pointer + // Input: "char *argv[]" -> after strip: "char *" + // Output type should be: "[*c][*c]char" + // But for simplicity in generated code, we can use the original type + pointer + // Check if type already ends with * + const trimmed_type = std.mem.trimRight(u8, param_type, " \t"); + if (std.mem.endsWith(u8, trimmed_type, "*")) { + // Already has pointer, add another without space + const type_copy = try std.fmt.bufPrint(&type_buf, "{s}*", .{trimmed_type}); + param_type = type_copy; + } else { + const type_copy = try std.fmt.bufPrint(&type_buf, "{s} *", .{param_type}); + param_type = type_copy; + } + } try params_list.append(self.allocator, ParamDecl{ .name = try self.allocator.dupe(u8, param_name), diff --git a/lib/sdl3/parser/src/types.zig b/lib/sdl3/parser/src/types.zig index 8d626d7..4278c21 100644 --- a/lib/sdl3/parser/src/types.zig +++ b/lib/sdl3/parser/src/types.zig @@ -45,6 +45,8 @@ pub fn convertType(c_type: []const u8, allocator: Allocator) ![]const u8 { if (std.mem.eql(u8, trimmed, "const char **")) return try allocator.dupe(u8, "[*c][*c]const u8"); if (std.mem.eql(u8, trimmed, "const char * const *")) return try allocator.dupe(u8, "[*c]const [*c]const u8"); if (std.mem.eql(u8, trimmed, "char *")) return try allocator.dupe(u8, "[*c]u8"); + if (std.mem.eql(u8, trimmed, "char **")) return try allocator.dupe(u8, "[*c][*c]u8"); + if (std.mem.eql(u8, trimmed, "char**")) return try allocator.dupe(u8, "[*c][*c]u8"); if (std.mem.eql(u8, trimmed, "void *")) return try allocator.dupe(u8, "?*anyopaque"); if (std.mem.eql(u8, trimmed, "const void *")) return try allocator.dupe(u8, "?*const anyopaque"); if (std.mem.eql(u8, trimmed, "void **")) return try allocator.dupe(u8, "[*c]?*anyopaque"); diff --git a/lib/sdl3/v2/init.zig b/lib/sdl3/v2/init.zig index fe42b68..1f917b6 100644 --- a/lib/sdl3/v2/init.zig +++ b/lib/sdl3/v2/init.zig @@ -44,17 +44,25 @@ pub const Event = extern union { }; pub const InitFlags = packed struct(u32) { - pad0: u31 = 0, + initAudio: bool = false, // `SDL_INIT_AUDIO` implies `SDL_INIT_EVENTS` + initVideo: bool = false, // `SDL_INIT_VIDEO` implies `SDL_INIT_EVENTS`, should be initialized on the main thread + initJoystick: bool = false, // `SDL_INIT_JOYSTICK` implies `SDL_INIT_EVENTS`, should be initialized on the same thread as SDL_INIT_VIDEO on Windows if you don't set SDL_HINT_JOYSTICK_THREAD + initHaptic: bool = false, + initGamepad: bool = false, // `SDL_INIT_GAMEPAD` implies `SDL_INIT_JOYSTICK` + initEvents: bool = false, + initSensor: bool = false, // `SDL_INIT_SENSOR` implies `SDL_INIT_EVENTS` + initCamera: bool = false, // `SDL_INIT_CAMERA` implies `SDL_INIT_EVENTS` + pad0: u23 = 0, rsvd: bool = false, }; -pub const AppInit_func = *const fn(appstate: [*c]?*anyopaque, argc: c_int, argv[]: [*c]u8) callconv(.C) AppResult; +pub const AppInit_func = *const fn (appstate: [*c]?*anyopaque, argc: c_int, argv: [*c][*c]u8) callconv(.C) AppResult; -pub const AppIterate_func = *const fn(appstate: ?*anyopaque) callconv(.C) AppResult; +pub const AppIterate_func = *const fn (appstate: ?*anyopaque) callconv(.C) AppResult; -pub const AppEvent_func = *const fn(appstate: ?*anyopaque, event: ?*Event) callconv(.C) AppResult; +pub const AppEvent_func = *const fn (appstate: ?*anyopaque, event: ?*Event) callconv(.C) AppResult; -pub const AppQuit_func = *const fn(appstate: ?*anyopaque, result: AppResult) callconv(.C) void; +pub const AppQuit_func = *const fn (appstate: ?*anyopaque, result: AppResult) callconv(.C) void; pub inline fn init(flags: InitFlags) bool { return c.SDL_Init(@bitCast(flags)); @@ -80,7 +88,7 @@ pub inline fn isMainThread() bool { return c.SDL_IsMainThread(); } -pub const MainThreadCallback = *const fn(userdata: ?*anyopaque) callconv(.C) void; +pub const MainThreadCallback = *const fn (userdata: ?*anyopaque) callconv(.C) void; pub inline fn runOnMainThread(callback: MainThreadCallback, userdata: ?*anyopaque, wait_complete: bool) bool { return c.SDL_RunOnMainThread(callback, userdata, wait_complete); @@ -97,4 +105,3 @@ pub inline fn setAppMetadataProperty(name: [*c]const u8, value: [*c]const u8) bo pub inline fn getAppMetadataProperty(name: [*c]const u8) [*c]const u8 { return c.SDL_GetAppMetadataProperty(name); } - diff --git a/lib/sdl3/v2/surface.zig b/lib/sdl3/v2/surface.zig index 36aeeb8..e2aef7c 100644 --- a/lib/sdl3/v2/surface.zig +++ b/lib/sdl3/v2/surface.zig @@ -96,7 +96,11 @@ pub const Colorspace = enum(c_int) { pub const PropertiesID = u32; pub const SurfaceFlags = packed struct(u32) { - pad0: u31 = 0, + surfacePreallocated: bool = false, // Surface uses preallocated pixel memory + surfaceLockNeeded: bool = false, // Surface needs to be locked to access pixels + surfaceLocked: bool = false, // Surface is currently locked + surfaceSimdAligned: bool = false, // Surface uses pixel memory allocated with SDL_aligned_alloc() + pad0: u27 = 0, rsvd: bool = false, };