Add union parsing support and fix comment handling in struct/union scanners
- Added UnionDecl type to patterns - Implemented scanUnion() function similar to scanStruct() - Added writeUnion() code generation - Updated all switch statements to handle union_decl - Fixed multi-line comment detection to handle both /* and /** - Skip empty enums during code generation - Update dependency resolver to track union field dependencies
This commit is contained in:
parent
79dd39e36a
commit
d270b3fc84
|
|
@ -1,52 +0,0 @@
|
|||
import os
|
||||
import time
|
||||
import json
|
||||
import subprocess
|
||||
|
||||
class HeaderParser:
|
||||
|
||||
def __init__(self, headerList, target, headerName):
|
||||
self.headerList = headerList
|
||||
self.path = target
|
||||
self.headerName = headerName
|
||||
self.outputPrefix = "asts/" + headerName
|
||||
self.astJsonFile = os.path.join(orig_dir, self.headerName + ".ast.json")
|
||||
with open(self.astJsonFile) as f:
|
||||
self.jsonRepr = json.load(f)
|
||||
|
||||
orig_dir = os.path.abspath(os.path.dirname(__file__))
|
||||
inputList = []
|
||||
|
||||
def parseAll(sdl3IncludePath, headerList):
|
||||
parsedList = []
|
||||
for f in headerList:
|
||||
if f.endswith(".h"):
|
||||
headerName = f.split(".")[0]
|
||||
if "_" in headerName:
|
||||
headerName = headerName.split('_')[1]
|
||||
|
||||
print(headerName)
|
||||
parsedList.append(os.path.join(sdl3IncludePath, f))
|
||||
parsePath = os.path.join(sdl3IncludePath, 'SDL_gpu.h')
|
||||
# os.system(f"cheader2json convert {f} --prefix={self.headerName}")
|
||||
|
||||
def parse():
|
||||
global inputList
|
||||
sdl3IncludePath = os.path.join(orig_dir, 'SDL/include/SDL3')
|
||||
discoveredFiles = os.listdir(os.path.join(orig_dir, 'SDL/include/SDL3'))
|
||||
|
||||
parsedList = []
|
||||
|
||||
parseAll(sdl3IncludePath, discoveredFiles)
|
||||
|
||||
sdlHeaderList = []
|
||||
for file in discoveredFiles:
|
||||
sdlHeaderList.append(os.path.join(sdl3IncludePath, file))
|
||||
|
||||
parsed = HeaderParser(sdlHeaderList, os.path.join(sdl3IncludePath, 'SDL_gpu.h'), "gpu")
|
||||
|
||||
print("parsing list: ", inputList)
|
||||
|
||||
if __name__ == "__main__":
|
||||
while True:
|
||||
parse()
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
# SDL_video.h Parsing Analysis
|
||||
|
||||
## Current Status: ✅ MOSTLY WORKING
|
||||
|
||||
The SDL_video.h header parses successfully with only minor missing type warnings. All major functionality is captured.
|
||||
|
||||
## Statistics
|
||||
|
||||
- **Total declarations found**: 124
|
||||
- Opaque types: 2
|
||||
- Typedefs: 6
|
||||
- Function pointers: 0
|
||||
- Enums: 4
|
||||
- Structs: 2
|
||||
- Flags: 1
|
||||
- Functions: 109
|
||||
|
||||
## Successfully Resolved Dependencies
|
||||
|
||||
The parser successfully resolves and imports these types from dependency headers:
|
||||
|
||||
✅ **SDL_PixelFormat** (from SDL_pixels.h)
|
||||
✅ **SDL_Point** (from SDL_rect.h)
|
||||
✅ **SDL_Rect** (from SDL_rect.h)
|
||||
✅ **SDL_Surface** (from SDL_surface.h)
|
||||
✅ **SDL_PropertiesID** (from SDL_properties.h)
|
||||
|
||||
## Missing Type Definitions (7 types)
|
||||
|
||||
These types are referenced but not found in the included headers:
|
||||
|
||||
### 1. EGL-Related Types (5 types)
|
||||
|
||||
These are OpenGL ES/EGL integration types defined within SDL_video.h itself:
|
||||
|
||||
- **SDL_EGLConfig** - `typedef void *SDL_EGLConfig;`
|
||||
- **SDL_EGLDisplay** - `typedef void *SDL_EGLDisplay;`
|
||||
- **SDL_EGLSurface** - `typedef void *SDL_EGLSurface;`
|
||||
- **SDL_EGLAttribArrayCallback** - Function pointer typedef
|
||||
- **SDL_EGLIntArrayCallback** - Function pointer typedef
|
||||
|
||||
**Root Cause**: These are defined in SDL_video.h but the parser's typedef scanner is not picking them up properly.
|
||||
|
||||
**Issue**: The typedef scanner currently only processes simple typedefs and doesn't handle:
|
||||
- Pointer typedefs (`typedef void *Type;`)
|
||||
- Function pointer typedefs with complex signatures
|
||||
|
||||
### 2. OpenGL Types (2 types)
|
||||
|
||||
- **SDL_GLAttr** - Enum type for GL attributes
|
||||
- **SDL_GLContext** - `typedef struct SDL_GLContextState *SDL_GLContext;`
|
||||
|
||||
**Root Cause**: Similar to EGL types - these are typedef'd in SDL_video.h but not captured by the scanner.
|
||||
|
||||
### 3. Callback Types (1 type)
|
||||
|
||||
- **SDL_HitTest** - `typedef SDL_HitTestResult (SDLCALL *SDL_HitTest)(...);`
|
||||
|
||||
**Root Cause**: Function pointer typedef with calling convention modifier.
|
||||
|
||||
### 4. Generic Types (1 type)
|
||||
|
||||
- **SDL_FunctionPointer** - `typedef void (SDLCALL *SDL_FunctionPointer)(void);`
|
||||
|
||||
**Root Cause**: Function pointer typedef.
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
### Phase 1: Enhance Typedef Scanner ✅ PRIORITY
|
||||
|
||||
**Goal**: Make the typedef scanner capture all typedef forms in the same file being parsed.
|
||||
|
||||
**Tasks**:
|
||||
|
||||
1. **Add pointer typedef support**
|
||||
```c
|
||||
typedef void *SDL_EGLConfig;
|
||||
typedef struct SDL_GLContextState *SDL_GLContext;
|
||||
```
|
||||
- Pattern: `typedef <type> *<name>;`
|
||||
- Store as opaque pointer type
|
||||
|
||||
2. **Add function pointer typedef support**
|
||||
```c
|
||||
typedef SDL_HitTestResult (SDLCALL *SDL_HitTest)(SDL_Window *win, const SDL_Point *area, void *data);
|
||||
typedef void (SDLCALL *SDL_FunctionPointer)(void);
|
||||
```
|
||||
- Pattern: `typedef <return> (SDLCALL *<name>)(<params>);`
|
||||
- Store as function pointer type with signature
|
||||
|
||||
3. **Add enum typedef support**
|
||||
```c
|
||||
typedef enum SDL_GLAttr { ... } SDL_GLAttr;
|
||||
```
|
||||
- Pattern: Already handled, but verify it works for GL types
|
||||
|
||||
**Implementation Location**: `src/dependency_resolver.zig` - `scanFileForTypedefs()`
|
||||
|
||||
**Expected Result**: After this phase, all 7 missing types should be found and properly typed.
|
||||
|
||||
### Phase 2: Test and Validate
|
||||
|
||||
1. Run parser on SDL_video.h
|
||||
2. Verify all 14 originally missing types are now resolved (7 from deps, 7 from typedefs)
|
||||
3. Verify generated Zig code compiles
|
||||
4. Check that function signatures using these types are correct
|
||||
|
||||
### Phase 3: Apply to Other Headers
|
||||
|
||||
Once SDL_video.h parses completely clean, apply the same pattern to other headers with similar issues.
|
||||
|
||||
## Error Categories
|
||||
|
||||
### Category A: Typedef Scanner Limitations ⭐ PRIMARY ISSUE
|
||||
- **Impact**: 7/14 missing types (50%)
|
||||
- **Difficulty**: Medium
|
||||
- **Files affected**: SDL_video.h, potentially others
|
||||
- **Solution**: Enhance typedef scanner (Phase 1)
|
||||
|
||||
### Category B: Cross-header Dependencies ✅ SOLVED
|
||||
- **Impact**: 7/14 missing types (50%) - but these work!
|
||||
- **Difficulty**: N/A (already working)
|
||||
- **Solution**: Existing dependency resolver handles this correctly
|
||||
|
||||
## Success Metrics
|
||||
|
||||
After implementing Phase 1:
|
||||
- ⬜ Zero "Could not find definition" warnings for SDL_video.h
|
||||
- ⬜ Generated code compiles without errors
|
||||
- ⬜ All 124 declarations properly typed
|
||||
- ⬜ Can use as template for other complex headers
|
||||
|
||||
## Notes
|
||||
|
||||
The current parsing system is quite robust. The main gap is in the typedef scanner not recognizing all forms of typedef. This is a focused, solvable problem that will unlock SDL_video.h and similar headers.
|
||||
|
|
@ -99,6 +99,7 @@ pub const CodeGen = struct {
|
|||
.function_pointer_decl => |func_ptr_decl| try self.writeFunctionPointer(func_ptr_decl),
|
||||
.enum_decl => |enum_decl| try self.writeEnum(enum_decl),
|
||||
.struct_decl => |struct_decl| try self.writeStruct(struct_decl),
|
||||
.union_decl => |union_decl| try self.writeUnion(union_decl),
|
||||
.flag_decl => |flag_decl| try self.writeFlags(flag_decl),
|
||||
.function_decl => |func| {
|
||||
// Only write standalone functions (not methods)
|
||||
|
|
@ -206,6 +207,11 @@ pub const CodeGen = struct {
|
|||
}
|
||||
|
||||
fn writeEnum(self: *CodeGen, enum_decl: EnumDecl) !void {
|
||||
// Skip empty enums
|
||||
if (enum_decl.values.len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const zig_name = naming.typeNameToZig(enum_decl.name);
|
||||
|
||||
// Write doc comment if present
|
||||
|
|
@ -270,6 +276,36 @@ pub const CodeGen = struct {
|
|||
try self.output.appendSlice(self.allocator, "};\n\n");
|
||||
}
|
||||
|
||||
fn writeUnion(self: *CodeGen, union_decl: patterns.UnionDecl) !void {
|
||||
const zig_name = naming.typeNameToZig(union_decl.name);
|
||||
|
||||
// Write doc comment if present
|
||||
if (union_decl.doc_comment) |doc| {
|
||||
try self.writeDocComment(doc);
|
||||
}
|
||||
|
||||
// pub const Event = extern union {
|
||||
try self.output.writer(self.allocator).print("pub const {s} = extern union {{\n", .{zig_name});
|
||||
|
||||
// Write fields
|
||||
for (union_decl.fields) |field| {
|
||||
const zig_type = try types.convertType(field.type_name, self.allocator);
|
||||
defer self.allocator.free(zig_type);
|
||||
|
||||
if (field.comment) |comment| {
|
||||
try self.output.writer(self.allocator).print(" {s}: {s}, // {s}\n", .{
|
||||
field.name,
|
||||
zig_type,
|
||||
comment,
|
||||
});
|
||||
} else {
|
||||
try self.output.writer(self.allocator).print(" {s}: {s},\n", .{ field.name, zig_type });
|
||||
}
|
||||
}
|
||||
|
||||
try self.output.appendSlice(self.allocator, "};\n\n");
|
||||
}
|
||||
|
||||
fn writeFlags(self: *CodeGen, flag_decl: FlagDecl) !void {
|
||||
const zig_name = naming.typeNameToZig(flag_decl.name);
|
||||
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ pub const DependencyResolver = struct {
|
|||
.function_pointer_decl => |fp| fp.name,
|
||||
.enum_decl => |e| e.name,
|
||||
.struct_decl => |s| s.name,
|
||||
.union_decl => |u| u.name,
|
||||
.flag_decl => |f| f.name,
|
||||
.function_decl => continue,
|
||||
};
|
||||
|
|
@ -84,6 +85,11 @@ pub const DependencyResolver = struct {
|
|||
try self.scanType(field.type_name);
|
||||
}
|
||||
},
|
||||
.union_decl => |union_decl| {
|
||||
for (union_decl.fields) |field| {
|
||||
try self.scanType(field.type_name);
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
|
@ -251,6 +257,7 @@ pub fn extractTypeFromHeader(
|
|||
.typedef_decl => |t| t.name,
|
||||
.enum_decl => |e| e.name,
|
||||
.struct_decl => |s| s.name,
|
||||
.union_decl => |u| u.name,
|
||||
.flag_decl => |f| f.name,
|
||||
else => continue,
|
||||
};
|
||||
|
|
@ -300,6 +307,13 @@ fn cloneDeclaration(allocator: Allocator, decl: Declaration) !Declaration {
|
|||
.fields = try cloneFields(allocator, s.fields),
|
||||
},
|
||||
},
|
||||
.union_decl => |u| .{
|
||||
.union_decl = .{
|
||||
.name = try allocator.dupe(u8, u.name),
|
||||
.doc_comment = if (u.doc_comment) |doc| try allocator.dupe(u8, doc) else null,
|
||||
.fields = try cloneFields(allocator, u.fields),
|
||||
},
|
||||
},
|
||||
.flag_decl => |f| .{
|
||||
.flag_decl = .{
|
||||
.name = try allocator.dupe(u8, f.name),
|
||||
|
|
@ -407,6 +421,16 @@ fn freeDeclaration(allocator: Allocator, decl: Declaration) void {
|
|||
}
|
||||
allocator.free(s.fields);
|
||||
},
|
||||
.union_decl => |u| {
|
||||
allocator.free(u.name);
|
||||
if (u.doc_comment) |doc| allocator.free(doc);
|
||||
for (u.fields) |field| {
|
||||
allocator.free(field.name);
|
||||
allocator.free(field.type_name);
|
||||
if (field.comment) |c| allocator.free(c);
|
||||
}
|
||||
allocator.free(u.fields);
|
||||
},
|
||||
.flag_decl => |f| {
|
||||
allocator.free(f.name);
|
||||
allocator.free(f.underlying_type);
|
||||
|
|
|
|||
|
|
@ -97,6 +97,16 @@ pub fn main() !void {
|
|||
}
|
||||
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);
|
||||
|
|
@ -131,6 +141,7 @@ pub fn main() !void {
|
|||
var func_ptr_count: usize = 0;
|
||||
var enum_count: usize = 0;
|
||||
var struct_count: usize = 0;
|
||||
var union_count: usize = 0;
|
||||
var flag_count: usize = 0;
|
||||
var func_count: usize = 0;
|
||||
|
||||
|
|
@ -141,6 +152,7 @@ pub fn main() !void {
|
|||
.function_pointer_decl => func_ptr_count += 1,
|
||||
.enum_decl => enum_count += 1,
|
||||
.struct_decl => struct_count += 1,
|
||||
.union_decl => union_count += 1,
|
||||
.flag_decl => flag_count += 1,
|
||||
.function_decl => func_count += 1,
|
||||
}
|
||||
|
|
@ -151,6 +163,7 @@ pub fn main() !void {
|
|||
std.debug.print(" - Function pointers: {d}\n", .{func_ptr_count});
|
||||
std.debug.print(" - Enums: {d}\n", .{enum_count});
|
||||
std.debug.print(" - Structs: {d}\n", .{struct_count});
|
||||
std.debug.print(" - Unions: {d}\n", .{union_count});
|
||||
std.debug.print(" - Flags: {d}\n", .{flag_count});
|
||||
std.debug.print(" - Functions: {d}\n\n", .{func_count});
|
||||
|
||||
|
|
@ -392,6 +405,16 @@ fn freeDeclDeep(allocator: std.mem.Allocator, decl: patterns.Declaration) void {
|
|||
}
|
||||
allocator.free(s.fields);
|
||||
},
|
||||
.union_decl => |u| {
|
||||
allocator.free(u.name);
|
||||
if (u.doc_comment) |doc| allocator.free(doc);
|
||||
for (u.fields) |field| {
|
||||
allocator.free(field.name);
|
||||
allocator.free(field.type_name);
|
||||
if (field.comment) |c| allocator.free(c);
|
||||
}
|
||||
allocator.free(u.fields);
|
||||
},
|
||||
.flag_decl => |f| {
|
||||
allocator.free(f.name);
|
||||
allocator.free(f.underlying_type);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ pub const Declaration = union(enum) {
|
|||
opaque_type: OpaqueType,
|
||||
enum_decl: EnumDecl,
|
||||
struct_decl: StructDecl,
|
||||
union_decl: UnionDecl,
|
||||
flag_decl: FlagDecl,
|
||||
function_decl: FunctionDecl,
|
||||
typedef_decl: TypedefDecl,
|
||||
|
|
@ -35,6 +36,12 @@ pub const StructDecl = struct {
|
|||
doc_comment: ?[]const u8,
|
||||
};
|
||||
|
||||
pub const UnionDecl = struct {
|
||||
name: []const u8, // SDL_Event
|
||||
fields: []FieldDecl,
|
||||
doc_comment: ?[]const u8,
|
||||
};
|
||||
|
||||
pub const FieldDecl = struct {
|
||||
name: []const u8, // x
|
||||
type_name: []const u8, // float
|
||||
|
|
@ -111,6 +118,8 @@ pub const Scanner = struct {
|
|||
try decls.append(self.allocator, .{ .enum_decl = enum_decl });
|
||||
} else if (try self.scanStruct()) |struct_decl| {
|
||||
try decls.append(self.allocator, .{ .struct_decl = struct_decl });
|
||||
} else if (try self.scanUnion()) |union_decl| {
|
||||
try decls.append(self.allocator, .{ .union_decl = union_decl });
|
||||
} else if (try self.scanFlagTypedef()) |flag_decl| {
|
||||
// Flag typedef must come before simple typedef
|
||||
try decls.append(self.allocator, .{ .flag_decl = flag_decl });
|
||||
|
|
@ -500,12 +509,12 @@ pub const Scanner = struct {
|
|||
while (lines.next()) |line| {
|
||||
const trimmed = std.mem.trim(u8, line, " \t\r");
|
||||
|
||||
// Track multi-line comments
|
||||
if (std.mem.indexOf(u8, trimmed, "/**")) |_| {
|
||||
// Track multi-line comments (both /** and /*)
|
||||
if (std.mem.indexOf(u8, trimmed, "/*") != null) {
|
||||
in_multiline_comment = true;
|
||||
}
|
||||
if (in_multiline_comment) {
|
||||
if (std.mem.indexOf(u8, trimmed, "*/")) |_| {
|
||||
if (std.mem.indexOf(u8, trimmed, "*/") != null) {
|
||||
in_multiline_comment = false;
|
||||
}
|
||||
continue;
|
||||
|
|
@ -514,7 +523,6 @@ pub const Scanner = struct {
|
|||
// Skip comment/bracket/preprocessor lines
|
||||
if (trimmed.len == 0) continue;
|
||||
if (std.mem.startsWith(u8, trimmed, "//")) continue;
|
||||
if (std.mem.startsWith(u8, trimmed, "/*")) continue;
|
||||
if (std.mem.startsWith(u8, trimmed, "*")) continue;
|
||||
if (std.mem.startsWith(u8, trimmed, "#")) continue;
|
||||
|
||||
|
|
@ -542,6 +550,85 @@ pub const Scanner = struct {
|
|||
};
|
||||
}
|
||||
|
||||
fn scanUnion(self: *Scanner) !?UnionDecl {
|
||||
const start = self.pos;
|
||||
|
||||
if (!self.matchPrefix("typedef union ")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Find the opening brace and extract the name before it
|
||||
const name_start = self.pos;
|
||||
while (self.pos < self.source.len and self.source[self.pos] != '{') {
|
||||
self.pos += 1;
|
||||
}
|
||||
|
||||
if (self.pos >= self.source.len) {
|
||||
// No opening brace found - this is an opaque type, not a union
|
||||
self.pos = start;
|
||||
return null;
|
||||
}
|
||||
|
||||
// Extract name from between "typedef union " and "{"
|
||||
const name_slice = std.mem.trim(u8, self.source[name_start..self.pos], " \t\n\r");
|
||||
var iter = std.mem.tokenizeScalar(u8, name_slice, ' ');
|
||||
const name = iter.next() orelse {
|
||||
self.pos = start;
|
||||
return null;
|
||||
};
|
||||
|
||||
// Now we're at the opening brace, read the braced block
|
||||
const body = try self.readBracedBlock();
|
||||
defer self.allocator.free(body);
|
||||
|
||||
// Parse fields
|
||||
var fields = try std.ArrayList(FieldDecl).initCapacity(self.allocator, 20);
|
||||
var lines = std.mem.splitScalar(u8, body, '\n');
|
||||
var in_multiline_comment = false;
|
||||
|
||||
while (lines.next()) |line| {
|
||||
const trimmed = std.mem.trim(u8, line, " \t\r");
|
||||
|
||||
// Track multi-line comments (both /** and /*)
|
||||
if (std.mem.indexOf(u8, trimmed, "/*") != null) {
|
||||
in_multiline_comment = true;
|
||||
}
|
||||
if (in_multiline_comment) {
|
||||
if (std.mem.indexOf(u8, trimmed, "*/") != null) {
|
||||
in_multiline_comment = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip comment/bracket/preprocessor lines
|
||||
if (trimmed.len == 0) continue;
|
||||
if (std.mem.startsWith(u8, trimmed, "//")) continue;
|
||||
if (std.mem.startsWith(u8, trimmed, "*")) continue;
|
||||
if (std.mem.startsWith(u8, trimmed, "#")) continue;
|
||||
|
||||
// Reuse struct field parsing since unions have same field syntax
|
||||
if (try self.parseStructField(line)) |field| {
|
||||
try fields.append(self.allocator, field);
|
||||
} else {
|
||||
const multi_fields = try self.parseMultiFieldLine(line);
|
||||
if (multi_fields.len > 0) {
|
||||
for (multi_fields) |field| {
|
||||
try fields.append(self.allocator, field);
|
||||
}
|
||||
self.allocator.free(multi_fields);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const doc = self.consumePendingDocComment();
|
||||
|
||||
return UnionDecl{
|
||||
.name = try self.allocator.dupe(u8, name),
|
||||
.fields = try fields.toOwnedSlice(self.allocator),
|
||||
.doc_comment = doc,
|
||||
};
|
||||
}
|
||||
|
||||
fn parseStructField(self: *Scanner, line: []const u8) !?FieldDecl {
|
||||
const trimmed = std.mem.trim(u8, line, " \t\r");
|
||||
if (trimmed.len == 0) return null;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
const std = @import("std");
|
||||
pub const c = @import("c.zig").c;
|
||||
|
||||
pub const Window = opaque {};
|
||||
|
|
@ -240,11 +241,13 @@ pub inline fn pushEvent(event: ?*Event) bool {
|
|||
return c.SDL_PushEvent(event);
|
||||
}
|
||||
|
||||
pub const EventFilter = *const fn(userdata: ?*anyopaque, event: ?*Event) callconv(.C) bool;
|
||||
|
||||
pub inline fn setEventFilter(filter: EventFilter, userdata: ?*anyopaque) void {
|
||||
return c.SDL_SetEventFilter(filter, userdata);
|
||||
}
|
||||
|
||||
pub inline fn getEventFilter(filter: ?*EventFilter, userdata: void **) bool {
|
||||
pub inline fn getEventFilter(filter: ?*EventFilter, userdata: [*c]?*anyopaque) bool {
|
||||
return c.SDL_GetEventFilter(filter, userdata);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
const std = @import("std");
|
||||
pub const c = @import("c.zig").c;
|
||||
|
||||
pub const FColor = extern struct {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
const std = @import("std");
|
||||
pub const c = @import("c.zig").c;
|
||||
|
||||
pub const Scancode = enum(c_int) {
|
||||
|
|
@ -180,7 +181,6 @@ pub const Scancode = enum(c_int) {
|
|||
scancodeLshift,
|
||||
scancodeRctrl,
|
||||
scancodeRshift,
|
||||
scancodeMediaSelect,
|
||||
};
|
||||
|
||||
pub const Window = opaque {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
const std = @import("std");
|
||||
pub const c = @import("c.zig").c;
|
||||
|
||||
pub const PixelFormat = enum(c_int) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue