Added support for C printf/scanf format attribute macros and variadic argument
lists, unlocking 2 more perfect APIs.
## Features Added
### 1. Format Attribute Macro Stripping
Strips compiler attribute macros from function declarations:
- `SDL_PRINTF_FORMAT_STRING`
- `SDL_WPRINTF_FORMAT_STRING`
- `SDL_SCANF_FORMAT_STRING`
- `SDL_PRINTF_VARARG_FUNC(N)`
- `SDL_PRINTF_VARARG_FUNCV(N)`
- `SDL_WPRINTF_VARARG_FUNC(N)`
- `SDL_SCANF_VARARG_FUNC(N)`
**Before** (C):
```c
extern SDL_DECLSPEC bool SDLCALL SDL_SetError(
SDL_PRINTF_FORMAT_STRING const char *fmt, ...
) SDL_PRINTF_VARARG_FUNC(1);
```
**After** (Zig):
```zig
pub inline fn setError(fmt: [*c]const u8, ...) bool {
return c.SDL_SetError(fmt, ...);
}
```
### 2. Variadic Arguments Support
Added `va_list` type conversion:
- C type: `va_list`
- Zig type: `std.builtin.VaList`
**Implementation**: Added `const std = @import("std");` to generated headers
to make `std.builtin.VaList` available.
### 3. Double Void Pointer Support
Added conversion for `void **`:
- C type: `void **userdata`
- Zig type: `userdata: [*c]?*anyopaque`
## Implementation Details
### Macro Stripping Algorithm (patterns.zig)
1. **Format String Macros**: Scan function text for format macros
- Pattern: `SDL_PRINTF_FORMAT_STRING const char *fmt`
- Remove macro, keep type: `const char *fmt`
- Handle: PRINTF, WPRINTF, SCANF variants
2. **Vararg Function Macros**: Find and remove end-of-declaration macros
- Pattern: `) SDL_PRINTF_VARARG_FUNC(1);`
- Locate macro position
- Find closing `)` and remove from macro to `)`
- Handle: PRINTF, WPRINTF, SCANF, FUNCV variants
3. **Safe String Manipulation**:
- Create new string with `std.fmt.allocPrint`
- Clear and repopulate ArrayList (avoids aliasing)
- Defer cleanup of temporary strings
### Type Conversions (types.zig)
```zig
// Variadic lists
"va_list" → "std.builtin.VaList"
// Double void pointers
"void **" → "[*c]?*anyopaque"
```
### Header Generation (codegen.zig)
Added std import to all generated files:
```zig
const std = @import("std");
pub const c = @import("c.zig").c;
```
## Results
### Before
- 22/43 APIs perfect (51%)
- Format macros: NOT STRIPPED
- va_list: NOT SUPPORTED
- void **: PARTIALLY SUPPORTED
### After
- **24/43 APIs perfect (56%)** ✅
- Format macros: FULLY STRIPPED
- va_list: FULLY SUPPORTED
- void **: FULLY SUPPORTED
**Progress: +5% (+2 APIs)**
### New Perfect APIs
✅ **SDL_error.h** (24 lines)
- Error handling API
- `SDL_SetError()` uses printf-style formatting
- Had 1 error: format macros + va_list
- Now perfect!
✅ **SDL_log.h** (148 lines)
- Logging system with priority levels
- Multiple printf-style log functions
- Custom log output callbacks
- Had 1 error: format macros + void**
- Now perfect!
## Testing
Tested against all 43 SDL3 headers:
- **24 compile perfectly** (56%) ✅
- 19 have 1-13 errors
- 0 complete failures
**Cumulative Progress**:
- Session start: 15 APIs (35%)
- After function pointers: 19 APIs (44%)
- After arrays/comments: 22 APIs (51%)
- After format macros: **24 APIs (56%)** 🎉
**More than HALF of SDL3 APIs generate perfectly!**
## Impact
**Immediate**: +2 perfect APIs (5% improvement)
**Unlocked**: Printf-style functions now work everywhere
**Fixed**: Variadic argument handling
## Code Changes
### src/patterns.zig (+60 lines)
- `scanFunction()`: Strip format and vararg macros
- Safe string manipulation with allocPrint
- Handles all format macro variants
### src/types.zig (+2 lines)
- Added `va_list` → `std.builtin.VaList` conversion
- Added `void **` → `[*c]?*anyopaque` conversion
### src/codegen.zig (+2 lines)
- Added `const std = @import("std");` to generated headers
- Updated test expectations
## Known Limitations
Function pointer fields in structs not yet supported:
```c
Sint64 (SDLCALL *size)(void *userdata); // Struct field
```
This affects:
- SDL_iostream.h (IOStreamInterface)
- SDL_storage.h (StorageInterface)
- SDL_dialog.h (DialogFileFilter callback)
Will be addressed in future commits.
---
Printf-style functions now work perfectly across SDL3!
|
||
|---|---|---|
| .. | ||
| docs | ||
| src | ||
| test | ||
| API_COVERAGE.md | ||
| API_STATUS.md | ||
| DOCUMENTATION_COMPLETE.md | ||
| PROJECT_STRUCTURE.md | ||
| README.md | ||
| build.zig | ||
| build.zig.zon | ||
| test_small.h | ||
README.md
SDL3 Header Parser
A Zig tool that automatically generates idiomatic Zig bindings from SDL3 C headers with automatic dependency resolution.
Features
✅ Automatic Dependency Resolution - Detects and extracts missing types from included headers
✅ Multi-Field Struct Parsing - Handles compact C syntax like int x, y;
✅ Type Conversion - Converts C types to idiomatic Zig types
✅ Method Organization - Groups functions as methods on opaque types
✅ Mock Generation - Creates C stub implementations for testing
✅ Production Ready - 100% dependency resolution for SDL_gpu.h
Quick Start
Installation
cd parser/
zig build # Build the parser
zig build test # Run tests (26+ tests)
Basic Usage
# Generate Zig bindings
zig build run -- ../SDL/include/SDL3/SDL_gpu.h --output=gpu.zig
# Generate with C mocks for testing
zig build run -- ../SDL/include/SDL3/SDL_gpu.h --output=gpu.zig --mocks=gpu_mock.c
Example Output
Input (SDL_gpu.h):
typedef struct SDL_GPUDevice SDL_GPUDevice;
extern SDL_DECLSPEC void SDLCALL SDL_DestroyGPUDevice(SDL_GPUDevice *device);
Output (gpu.zig):
pub const GPUDevice = opaque {
pub inline fn destroyGPUDevice(gpudevice: *GPUDevice) void {
return c.SDL_DestroyGPUDevice(gpudevice);
}
};
Supported C Patterns
Type Declarations
- Opaque types:
typedef struct SDL_Type SDL_Type; - Structs:
typedef struct { int x, y; } SDL_Rect;(multi-field support!) - Enums:
typedef enum { VALUE1, VALUE2 } SDL_Enum; - Flags: Bitfield enums with
#definevalues - Typedefs:
typedef Uint32 SDL_PropertiesID;
Functions
- Extern functions:
extern SDL_DECLSPEC RetType SDLCALL SDL_Func(...); - Method grouping: Functions with opaque first parameter become methods
Automatic Type Conversion
| C Type | Zig Type |
|---|---|
bool |
bool |
Uint32 |
u32 |
int |
c_int |
SDL_Type* |
?*Type |
const SDL_Type* |
*const Type |
void* |
?*anyopaque |
Dependency Resolution
The parser automatically:
- Detects types referenced but not defined
- Searches included headers for definitions
- Extracts required types
- Generates unified output with all dependencies
Example:
SDL_gpu.h references SDL_Window
→ Parser finds #include <SDL3/SDL_video.h>
→ Extracts SDL_Window definition
→ Includes in output automatically
Success Rate: 100% for SDL_gpu.h (5/5 dependencies)
Documentation
Start Here: Getting Started Guide
User Guides
- Getting Started - Installation and first steps
- Quickstart - Quick reference
- API Reference - All command-line options
Technical Docs
- Architecture - How the parser works
- Dependency Resolution - Automatic type extraction
- Known Issues - Current limitations
Development
- Development Guide - Contributing and extending
- Roadmap - Future plans
Complete Index
- Documentation Index - All documentation
Project Status
Production Ready ✅
- SDL_gpu.h: 100% working
- 26+ tests passing
- Comprehensive documentation
- Zero manual intervention needed
Tested Headers
| Header | Status | Dependencies | Notes |
|---|---|---|---|
| SDL_gpu.h | ✅ Complete | 5/5 (100%) | Production ready |
| SDL_keyboard.h | ⚠️ Partial | 6/6 resolved | Enum syntax issues |
| SDL_video.h | ⚠️ Partial | 5/14 resolved | Needs fixes |
| SDL_events.h | ⚠️ Partial | Unknown | Needs fixes |
See Known Issues for details.
Performance
- Small headers (<100 decls): ~100ms
- Large headers (SDL_gpu.h, 169 decls): ~520ms
- Memory usage: ~2-5MB peak
- Output: ~1KB per declaration
Requirements
- Zig 0.15+
- SDL3 headers (included in parent directory)
Examples
Parse a Header
zig build run -- ../SDL/include/SDL3/SDL_gpu.h --output=gpu.zig
Use Generated Bindings
const gpu = @import("gpu.zig");
pub fn main() !void {
const device = gpu.createGPUDevice(true);
defer if (device) |d| d.destroyGPUDevice();
// All dependency types available automatically
}
Run Tests
zig build test
Contributing
See DEVELOPMENT.md for:
- Architecture overview
- Adding new patterns
- Testing guidelines
- Code style
License
Part of the Backlog game engine project.
Acknowledgments
Developed for automatic SDL3 binding generation in the Backlog engine.
Version: 2.1
Status: Production ready for SDL_gpu.h
Last Updated: 2026-01-22