Updates Zig

This commit is contained in:
Mason Remaley 2026-04-13 23:40:46 -07:00
parent 1673ed636a
commit a6bdcb3836
3 changed files with 63 additions and 61 deletions

5
.gitignore vendored
View file

@ -1,2 +1,3 @@
.zig-cache /.zig-cache/
zig-out /zig-out/
/zig-pkg/

View file

@ -2,7 +2,7 @@
.name = .dear_imgui, .name = .dear_imgui,
.fingerprint = 0xc1cc609af54040bd, .fingerprint = 0xc1cc609af54040bd,
.version = "1.0.0", .version = "1.0.0",
.minimum_zig_version = "0.16.0-dev.2193+fc517bd01", .minimum_zig_version = "0.16.0-dev.3153+d6f43caad",
.dependencies = .{ .dependencies = .{
.@"dear-imgui" = .{ .@"dear-imgui" = .{
// Using a patched version of v1.92.5-docking that has a UBSAN fix. The equivalent to // Using a patched version of v1.92.5-docking that has a UBSAN fix. The equivalent to

View file

@ -9,29 +9,27 @@ const DeclarationKind = enum {
import, // Assumed to be normal, but external import, // Assumed to be normal, but external
}; };
const Declarations = std.StringArrayHashMap(DeclarationKind); const Declarations = std.array_hash_map.String(DeclarationKind);
const Symbols = struct { const Symbols = struct {
public: std.StringArrayHashMap(void), public: std.array_hash_map.String(void),
front_buf: std.StringArrayHashMap(void), front_buf: std.array_hash_map.String(void),
pub fn init(allocator: Allocator) @This() { pub const empty: @This() = .{
return .{ .public = .empty,
.public = .init(allocator), .front_buf = .empty,
.front_buf = .init(allocator),
}; };
}
pub fn deinit(self: *@This()) void { pub fn deinit(self: *@This(), gpa: Allocator) void {
self.public.deinit(); self.public.deinit(gpa);
self.front_buf.deinit(); self.front_buf.deinit(gpa);
} }
/// Returns true if there's already a public symbol with this name. /// Returns true if there's already a public symbol with this name.
pub fn put(self: *@This(), name: []const u8) !bool { pub fn put(self: *@This(), gpa: Allocator, name: []const u8) !bool {
const trimmed = std.mem.trimEnd(u8, name, "_"); const trimmed = std.mem.trimEnd(u8, name, "_");
if (self.public.contains(trimmed)) return false; if (self.public.contains(trimmed)) return false;
try self.front_buf.put(trimmed, {}); try self.front_buf.put(gpa, trimmed, {});
return true; return true;
} }
@ -207,8 +205,8 @@ pub fn main(init: std.process.Init) !void {
} }
// Build a list of symbols so we can skip duplicates of public symbols in the internal headers // Build a list of symbols so we can skip duplicates of public symbols in the internal headers
var symbols: Symbols = .init(allocator); var symbols: Symbols = .empty;
defer symbols.deinit(); defer symbols.deinit(allocator);
// Write the source // Write the source
const main_source = try Dir.cwd().readFileAlloc(io, in_path, allocator, .limited(max_size)); const main_source = try Dir.cwd().readFileAlloc(io, in_path, allocator, .limited(max_size));
@ -254,43 +252,43 @@ pub fn main(init: std.process.Init) !void {
} }
fn writeSource( fn writeSource(
allocator: Allocator, gpa: Allocator,
source: []const u8, source: []const u8,
writer: *Io.Writer, writer: *Io.Writer,
symbols: *Symbols, symbols: *Symbols,
internal: bool, internal: bool,
) !void { ) !void {
const header = try std.json.parseFromSlice(Header, allocator, source, .{ const header = try std.json.parseFromSlice(Header, gpa, source, .{
.ignore_unknown_fields = true, .ignore_unknown_fields = true,
}); });
defer header.deinit(); defer header.deinit();
// We need the list of declarations up front. // We need the list of declarations up front.
var declarations = try getDeclarations(allocator, &header.value); var declarations = try getDeclarations(gpa, &header.value);
defer declarations.deinit(); defer declarations.deinit(gpa);
// Write all defines as private constants. // Write all defines as private constants.
try writeDefines(writer, internal, symbols, &header.value); try writeDefines(gpa, writer, internal, symbols, &header.value);
// Write all typedefs as private constants. // Write all typedefs as private constants.
try writeTypedefs(writer, &header.value, symbols, &declarations); try writeTypedefs(gpa, writer, &header.value, symbols, &declarations);
// Write all cimgui functions as private extern functions. // Write all cimgui functions as private extern functions.
try writeExternFunctions(writer, &header.value, symbols, &declarations); try writeExternFunctions(gpa, writer, &header.value, symbols, &declarations);
// Alias cimgui free functions under Zig friendly names. // Alias cimgui free functions under Zig friendly names.
try writeFreeFunctions(writer, &header.value, symbols); try writeFreeFunctions(gpa, writer, &header.value, symbols);
// Get a list of cimgui methods. These were already written as externs, and can be aliased // Get a list of cimgui methods. These were already written as externs, and can be aliased
// when we write their respective types. // when we write their respective types.
var methods = try Methods.get(allocator, &header.value); var methods = try Methods.get(gpa, &header.value);
defer methods.deinit(allocator); defer methods.deinit(gpa);
// Write cimgui enums as Zig enums. // Write cimgui enums as Zig enums.
try writeEnums(allocator, writer, internal, &header.value, symbols); try writeEnums(gpa, writer, internal, &header.value, symbols);
// Write cimgui structs as Zig structs and unions. // Write cimgui structs as Zig structs and unions.
try writeStructs(writer, &header.value, &declarations, &methods, symbols); try writeStructs(gpa, writer, &header.value, &declarations, &methods, symbols);
// Write helpers used by the other generated code. We skip this for the internal header // Write helpers used by the other generated code. We skip this for the internal header
// since we're going to concatenate it with the main header, so this stuff will already be // since we're going to concatenate it with the main header, so this stuff will already be
@ -300,9 +298,9 @@ fn writeSource(
} }
} }
fn getDeclarations(allocator: Allocator, header: *const Header) !Declarations { fn getDeclarations(gpa: Allocator, header: *const Header) !Declarations {
var declarations = Declarations.init(allocator); var declarations: Declarations = .empty;
errdefer declarations.deinit(); errdefer declarations.deinit(gpa);
for (header.structs) |ty| { for (header.structs) |ty| {
if (skip(ty.conditionals)) continue; if (skip(ty.conditionals)) continue;
@ -337,20 +335,20 @@ fn getDeclarations(allocator: Allocator, header: *const Header) !Declarations {
}; };
} }
try declarations.put(trimmed, kind); try declarations.put(gpa, trimmed, kind);
} }
for (header.enums) |e| { for (header.enums) |e| {
if (skip(e.conditionals)) continue; if (skip(e.conditionals)) continue;
const trimmed = std.mem.trimEnd(u8, e.name, "_"); const trimmed = std.mem.trimEnd(u8, e.name, "_");
try declarations.put(trimmed, .normal); try declarations.put(gpa, trimmed, .normal);
} }
return declarations; return declarations;
} }
fn writeDefines(writer: anytype, internal: bool, symbols: *Symbols, header: *const Header) !void { fn writeDefines(gpa: Allocator, writer: anytype, internal: bool, symbols: *Symbols, header: *const Header) !void {
// We skip defines from the internal namespace for now // We skip defines from the internal namespace for now
if (internal) return; if (internal) return;
@ -358,7 +356,7 @@ fn writeDefines(writer: anytype, internal: bool, symbols: *Symbols, header: *con
if (define.is_internal != internal) continue; if (define.is_internal != internal) continue;
if (skip(define.conditionals)) continue; if (skip(define.conditionals)) continue;
if (define.content) |content| { if (define.content) |content| {
if (try symbols.put(define.name)) { if (try symbols.put(gpa, define.name)) {
if (std.mem.startsWith(u8, content, "(")) { if (std.mem.startsWith(u8, content, "(")) {
const end = std.mem.indexOfScalar(u8, content, ')').?; const end = std.mem.indexOfScalar(u8, content, ')').?;
const ty = content[1..end]; const ty = content[1..end];
@ -375,6 +373,7 @@ fn writeDefines(writer: anytype, internal: bool, symbols: *Symbols, header: *con
} }
fn writeTypedefs( fn writeTypedefs(
gpa: Allocator,
writer: anytype, writer: anytype,
header: *const Header, header: *const Header,
symbols: *Symbols, symbols: *Symbols,
@ -392,7 +391,7 @@ fn writeTypedefs(
std.mem.eql(u8, typedef.name, typedef.type.declaration.?)) continue; std.mem.eql(u8, typedef.name, typedef.type.declaration.?)) continue;
// Write the typedef prefix // Write the typedef prefix
if (try symbols.put(typedef.name)) { if (try symbols.put(gpa, typedef.name)) {
try writer.writeAll("pub const "); try writer.writeAll("pub const ");
try writeTypeName(writer, typedef.name); try writeTypeName(writer, typedef.name);
try writer.writeAll(" = "); try writer.writeAll(" = ");
@ -403,6 +402,7 @@ fn writeTypedefs(
} }
fn writeExternFunctions( fn writeExternFunctions(
gpa: Allocator,
writer: anytype, writer: anytype,
header: *const Header, header: *const Header,
symbols: *Symbols, symbols: *Symbols,
@ -412,7 +412,7 @@ fn writeExternFunctions(
if (skip(function.conditionals)) continue; if (skip(function.conditionals)) continue;
if (argsContainsVaList(function.arguments)) continue; if (argsContainsVaList(function.arguments)) continue;
if (try symbols.put(function.name)) { if (try symbols.put(gpa, function.name)) {
try writer.print("extern fn {s}(", .{function.name}); try writer.print("extern fn {s}(", .{function.name});
for (function.arguments) |argument| { for (function.arguments) |argument| {
if (argument.type) |ty| { if (argument.type) |ty| {
@ -446,13 +446,13 @@ fn argsContainsVaList(arguments: []const Header.Function.Argument) bool {
return false; return false;
} }
fn writeFreeFunctions(writer: anytype, header: *const Header, symbols: *Symbols) !void { fn writeFreeFunctions(gpa: Allocator, writer: anytype, header: *const Header, symbols: *Symbols) !void {
for (header.functions) |function| { for (header.functions) |function| {
if (skip(function.conditionals)) continue; if (skip(function.conditionals)) continue;
if (function.original_class != null) continue; if (function.original_class != null) continue;
if (argsContainsVaList(function.arguments)) continue; if (argsContainsVaList(function.arguments)) continue;
if (try symbols.put(function.name)) { if (try symbols.put(gpa, function.name)) {
try writer.writeAll("pub const "); try writer.writeAll("pub const ");
try writeFunctionName(writer, function.name); try writeFunctionName(writer, function.name);
try writer.print(" = {s};\n", .{function.name}); try writer.print(" = {s};\n", .{function.name});
@ -461,19 +461,19 @@ fn writeFreeFunctions(writer: anytype, header: *const Header, symbols: *Symbols)
} }
const Methods = struct { const Methods = struct {
types: std.StringArrayHashMap(std.ArrayList([]const u8)), types: std.array_hash_map.String(std.ArrayList([]const u8)),
fn get(allocator: Allocator, header: *const Header) !Methods { fn get(gpa: Allocator, header: *const Header) !Methods {
// Initialize an empty method list for each type // Initialize an empty method list for each type
var types = std.StringArrayHashMap(std.ArrayList([]const u8)).init(allocator); var types: std.array_hash_map.String(std.ArrayList([]const u8)) = .empty;
errdefer types.deinit(); errdefer types.deinit(gpa);
errdefer for (types.values()) |*methods| { errdefer for (types.values()) |*methods| {
methods.deinit(allocator); methods.deinit(gpa);
}; };
for (header.structs) |ty| { for (header.structs) |ty| {
var methods: std.ArrayList([]const u8) = .empty; var methods: std.ArrayList([]const u8) = .empty;
errdefer methods.deinit(allocator); errdefer methods.deinit(gpa);
try types.put(ty.name, methods); try types.put(gpa, ty.name, methods);
} }
// Fill in the method lists // Fill in the method lists
@ -483,24 +483,24 @@ const Methods = struct {
if (function.original_class) |class| { if (function.original_class) |class| {
const methods = types.getPtr(class).?; const methods = types.getPtr(class).?;
try methods.append(allocator, function.name); try methods.append(gpa, function.name);
} }
} }
return .{ .types = types }; return .{ .types = types };
} }
fn deinit(self: *Methods, allocator: Allocator) void { fn deinit(self: *Methods, gpa: Allocator) void {
for (self.types.values()) |*methods| { for (self.types.values()) |*methods| {
methods.deinit(allocator); methods.deinit(gpa);
} }
self.types.deinit(); self.types.deinit(gpa);
self.* = undefined; self.* = undefined;
} }
}; };
fn writeEnums( fn writeEnums(
allocator: Allocator, gpa: Allocator,
writer: anytype, writer: anytype,
internal: bool, internal: bool,
header: *const Header, header: *const Header,
@ -509,7 +509,7 @@ fn writeEnums(
for (header.enums) |e| { for (header.enums) |e| {
if (skip(e.conditionals)) continue; if (skip(e.conditionals)) continue;
if (try symbols.put(e.name)) { if (try symbols.put(gpa, e.name)) {
try writer.writeAll("pub const "); try writer.writeAll("pub const ");
try writeTypeName(writer, e.name); try writeTypeName(writer, e.name);
try writer.writeAll(" = "); try writer.writeAll(" = ");
@ -517,7 +517,7 @@ fn writeEnums(
if (e.is_flags_enum) { if (e.is_flags_enum) {
try writeFlagsEnum(writer, internal, e); try writeFlagsEnum(writer, internal, e);
} else { } else {
try writeNormalEnum(allocator, writer, internal, e); try writeNormalEnum(gpa, writer, internal, e);
} }
} }
} }
@ -572,13 +572,13 @@ fn writeFlagsEnum(writer: anytype, internal: bool, e: Header.Enum) !void {
} }
fn writeNormalEnum( fn writeNormalEnum(
allocator: Allocator, gpa: Allocator,
writer: anytype, writer: anytype,
internal: bool, internal: bool,
e: Header.Enum, e: Header.Enum,
) !void { ) !void {
var values = std.AutoArrayHashMap(i64, void).init(allocator); var values: std.array_hash_map.Auto(i64, void) = .empty;
defer values.deinit(); defer values.deinit(gpa);
try writer.writeAll("enum("); try writer.writeAll("enum(");
switch (e.storage_type.declaration) { switch (e.storage_type.declaration) {
@ -602,7 +602,7 @@ fn writeNormalEnum(
// We skip duplicate values, these are sometimes present e.g. in the keys enum which // We skip duplicate values, these are sometimes present e.g. in the keys enum which
// contains the mods enum and therefore two "none" options that are identical. // contains the mods enum and therefore two "none" options that are identical.
if (values.contains(element.value)) continue; if (values.contains(element.value)) continue;
try values.put(element.value, {}); try values.put(gpa, element.value, {});
// Write the element // Write the element
try writer.writeAll(" "); try writer.writeAll(" ");
@ -632,6 +632,7 @@ fn writeNormalEnum(
} }
fn writeStructs( fn writeStructs(
gpa: Allocator,
writer: anytype, writer: anytype,
header: *const Header, header: *const Header,
declarations: *const Declarations, declarations: *const Declarations,
@ -648,7 +649,7 @@ fn writeStructs(
const decl_kind = declarations.get(ty.name).?; const decl_kind = declarations.get(ty.name).?;
if (decl_kind == .import) continue; if (decl_kind == .import) continue;
if (try symbols.put(ty.name)) { if (try symbols.put(gpa, ty.name)) {
// Write the struct // Write the struct
try writer.writeAll("pub const "); try writer.writeAll("pub const ");
try writeTypeName(writer, ty.name); try writeTypeName(writer, ty.name);