mirror of
https://github.com/zoriya/zig-wayland.git
synced 2025-12-06 07:06:12 +00:00
scanner: refactor to use new std.fmt features
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
zig-cache
|
zig-cache
|
||||||
|
zig-out
|
||||||
|
|||||||
286
src/scanner.zig
286
src/scanner.zig
@@ -1,6 +1,7 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const fs = std.fs;
|
const fs = std.fs;
|
||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
|
const fmtId = std.zig.fmtId;
|
||||||
|
|
||||||
const xml = @import("xml.zig");
|
const xml = @import("xml.zig");
|
||||||
|
|
||||||
@@ -298,24 +299,21 @@ const Interface = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn emit(interface: Interface, side: Side, namespace: []const u8, writer: anytype) !void {
|
fn emit(interface: Interface, side: Side, namespace: []const u8, writer: anytype) !void {
|
||||||
var buf: [1024]u8 = undefined;
|
|
||||||
var fbs = std.io.fixedBufferStream(&buf);
|
|
||||||
try printIdentifier(fbs.writer(), case(.title, trimPrefix(interface.name)));
|
|
||||||
const title_case = fbs.getWritten();
|
|
||||||
try printIdentifier(fbs.writer(), trimPrefix(interface.name));
|
|
||||||
const snake_case = fbs.getWritten()[title_case.len..];
|
|
||||||
|
|
||||||
try writer.print(
|
try writer.print(
|
||||||
\\pub const {s} = opaque {{
|
\\pub const {[type]} = opaque {{
|
||||||
\\ pub const getInterface = common.{s}.{s}.getInterface;
|
\\ pub const getInterface = common.{[namespace]}.{[interface]}.getInterface;
|
||||||
, .{ title_case, namespace, snake_case });
|
, .{
|
||||||
|
.@"type" = titleCaseTrim(interface.name),
|
||||||
|
.namespace = fmtId(namespace),
|
||||||
|
.interface = fmtId(trimPrefix(interface.name)),
|
||||||
|
});
|
||||||
|
|
||||||
for (interface.enums.items) |e| {
|
for (interface.enums.items) |e| {
|
||||||
try writer.writeAll("pub const ");
|
try writer.print("pub const {[type]} = common.{[namespace]}.{[interface]}.{[type]};\n", .{
|
||||||
try printIdentifier(writer, case(.title, e.name));
|
.@"type" = titleCase(e.name),
|
||||||
try writer.print(" = common.{s}.{s}.", .{ namespace, snake_case });
|
.namespace = fmtId(namespace),
|
||||||
try printIdentifier(writer, case(.title, e.name));
|
.interface = fmtId(trimPrefix(interface.name)),
|
||||||
try writer.writeAll(";\n");
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (side == .client) {
|
if (side == .client) {
|
||||||
@@ -325,16 +323,19 @@ const Interface = struct {
|
|||||||
try writer.writeAll("};\n");
|
try writer.writeAll("};\n");
|
||||||
try writer.print(
|
try writer.print(
|
||||||
\\pub fn setListener(
|
\\pub fn setListener(
|
||||||
\\ _{s}: *{s},
|
\\ _{[interface]}: *{[type]},
|
||||||
\\ comptime T: type,
|
\\ comptime T: type,
|
||||||
\\ _listener: fn ({s}: *{s}, event: Event, data: T) void,
|
\\ _listener: fn ({[interface]}: *{[type]}, event: Event, data: T) void,
|
||||||
\\ _data: T,
|
\\ _data: T,
|
||||||
\\) callconv(.Inline) void {{
|
\\) callconv(.Inline) void {{
|
||||||
\\ const _proxy = @ptrCast(*client.wl.Proxy, _{s});
|
\\ const _proxy = @ptrCast(*client.wl.Proxy, _{[interface]});
|
||||||
\\ const _mut_data = @intToPtr(?*c_void, @ptrToInt(_data));
|
\\ const _mut_data = @intToPtr(?*c_void, @ptrToInt(_data));
|
||||||
\\ _proxy.addDispatcher(common.Dispatcher({s}, T).dispatcher, _listener, _mut_data);
|
\\ _proxy.addDispatcher(common.Dispatcher({[type]}, T).dispatcher, _listener, _mut_data);
|
||||||
\\}}
|
\\}}
|
||||||
, .{ snake_case, title_case, snake_case, title_case, snake_case, title_case });
|
, .{
|
||||||
|
.interface = fmtId(trimPrefix(interface.name)),
|
||||||
|
.@"type" = titleCaseTrim(interface.name),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (interface.requests.items) |request, opcode|
|
for (interface.requests.items) |request, opcode|
|
||||||
@@ -344,22 +345,17 @@ const Interface = struct {
|
|||||||
try writer.writeAll(@embedFile("client_display_functions.zig"));
|
try writer.writeAll(@embedFile("client_display_functions.zig"));
|
||||||
} else {
|
} else {
|
||||||
try writer.print(
|
try writer.print(
|
||||||
\\pub fn create(_client: *server.wl.Client, _version: u32, _id: u32) !*{s} {{
|
\\pub fn create(_client: *server.wl.Client, _version: u32, _id: u32) !*{(tc)} {{
|
||||||
\\ return @ptrCast(*{s}, try server.wl.Resource.create(_client, {s}, _version, _id));
|
\\ return @ptrCast(*{[type]}, try server.wl.Resource.create(_client, {[type]}, _version, _id));
|
||||||
|
\\}}pub fn destroy(_{[interface]}: *{[type]}) void {{
|
||||||
|
\\ return @ptrCast(*server.wl.Resource, _{[interface]}).destroy();
|
||||||
|
\\}}pub fn fromLink(_link: *server.wl.list.Link) *{[type]} {{
|
||||||
|
\\ return @ptrCast(*{[type]}, server.wl.Resource.fromLink(_link));
|
||||||
\\}}
|
\\}}
|
||||||
, .{ title_case, title_case, title_case });
|
, .{
|
||||||
|
.@"type" = titleCaseTrim(interface.name),
|
||||||
try writer.print(
|
.interface = fmtId(trimPrefix(interface.name)),
|
||||||
\\pub fn destroy(_{s}: *{s}) void {{
|
});
|
||||||
\\ return @ptrCast(*server.wl.Resource, _{s}).destroy();
|
|
||||||
\\}}
|
|
||||||
, .{ snake_case, title_case, snake_case });
|
|
||||||
|
|
||||||
try writer.print(
|
|
||||||
\\pub fn fromLink(_link: *server.wl.list.Link) *{s} {{
|
|
||||||
\\ return @ptrCast(*{s}, server.wl.Resource.fromLink(_link));
|
|
||||||
\\}}
|
|
||||||
, .{ title_case, title_case });
|
|
||||||
|
|
||||||
for ([_][2][]const u8{
|
for ([_][2][]const u8{
|
||||||
.{ "getLink", "*server.wl.list.Link" },
|
.{ "getLink", "*server.wl.list.Link" },
|
||||||
@@ -369,20 +365,28 @@ const Interface = struct {
|
|||||||
.{ "postNoMemory", "void" },
|
.{ "postNoMemory", "void" },
|
||||||
}) |func|
|
}) |func|
|
||||||
try writer.print(
|
try writer.print(
|
||||||
\\pub fn {s}(_{s}: *{s}) {s} {{
|
\\pub fn {[function]}(_{[interface]}: *{[type]}) {[return_type]} {{
|
||||||
\\ return @ptrCast(*server.wl.Resource, _{s}).{s}();
|
\\ return @ptrCast(*server.wl.Resource, _{[interface]}).{[function]}();
|
||||||
\\}}
|
\\}}
|
||||||
, .{ func[0], snake_case, title_case, func[1], snake_case, func[0] });
|
, .{
|
||||||
|
.function = camelCase(func[0]),
|
||||||
|
.interface = fmtId(trimPrefix(interface.name)),
|
||||||
|
.@"type" = titleCaseTrim(interface.name),
|
||||||
|
.return_type = camelCase(func[1]),
|
||||||
|
});
|
||||||
|
|
||||||
const has_error = for (interface.enums.items) |e| {
|
const has_error = for (interface.enums.items) |e| {
|
||||||
if (mem.eql(u8, e.name, "error")) break true;
|
if (mem.eql(u8, e.name, "error")) break true;
|
||||||
} else false;
|
} else false;
|
||||||
if (has_error) {
|
if (has_error) {
|
||||||
try writer.print(
|
try writer.print(
|
||||||
\\pub fn postError({s}: *{s}, _err: Error, _message: [*:0]const u8) void {{
|
\\pub fn postError({[interface]}: *{[type]}, _err: Error, _message: [*:0]const u8) void {{
|
||||||
\\ return @ptrCast(*server.wl.Resource, {s}).postError(@intCast(u32, @enumToInt(_err)), _message);
|
\\ return @ptrCast(*server.wl.Resource, {[interface]}).postError(@intCast(u32, @enumToInt(_err)), _message);
|
||||||
\\}}
|
\\}}
|
||||||
, .{ snake_case, title_case, snake_case });
|
, .{
|
||||||
|
.interface = fmtId(trimPrefix(interface.name)),
|
||||||
|
.@"type" = titleCaseTrim(interface.name),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (interface.requests.items.len > 0) {
|
if (interface.requests.items.len > 0) {
|
||||||
@@ -392,37 +396,40 @@ const Interface = struct {
|
|||||||
@setEvalBranchQuota(2500);
|
@setEvalBranchQuota(2500);
|
||||||
try writer.print(
|
try writer.print(
|
||||||
\\pub fn setHandler(
|
\\pub fn setHandler(
|
||||||
\\ _{s}: *{s},
|
\\ _{[interface]}: *{[type]},
|
||||||
\\ comptime T: type,
|
\\ comptime T: type,
|
||||||
\\ handle_request: fn ({s}: *{s}, request: Request, data: T) void,
|
\\ handle_request: fn ({[interface]}: *{[type]}, request: Request, data: T) void,
|
||||||
\\ comptime handle_destroy: ?fn ({s}: *{s}, data: T) void,
|
\\ comptime handle_destroy: ?fn ({[interface]}: *{[type]}, data: T) void,
|
||||||
\\ _data: T,
|
\\ _data: T,
|
||||||
\\) callconv(.Inline) void {{
|
\\) callconv(.Inline) void {{
|
||||||
\\ const _resource = @ptrCast(*server.wl.Resource, _{s});
|
\\ const _resource = @ptrCast(*server.wl.Resource, _{[interface]});
|
||||||
\\ _resource.setDispatcher(
|
\\ _resource.setDispatcher(
|
||||||
\\ common.Dispatcher({s}, T).dispatcher,
|
\\ common.Dispatcher({[type]}, T).dispatcher,
|
||||||
\\ handle_request,
|
\\ handle_request,
|
||||||
\\ @intToPtr(?*c_void, @ptrToInt(_data)),
|
\\ @intToPtr(?*c_void, @ptrToInt(_data)),
|
||||||
\\ if (handle_destroy) |_handler| struct {{
|
\\ if (handle_destroy) |_handler| struct {{
|
||||||
\\ fn _wrapper(__resource: *server.wl.Resource) callconv(.C) void {{
|
\\ fn _wrapper(__resource: *server.wl.Resource) callconv(.C) void {{
|
||||||
\\ @call(.{{ .modifier = .always_inline }}, _handler, .{{
|
\\ @call(.{{ .modifier = .always_inline }}, _handler, .{{
|
||||||
\\ @ptrCast(*{s}, __resource),
|
\\ @ptrCast(*{[type]}, __resource),
|
||||||
\\ @intToPtr(T, @ptrToInt(__resource.getUserData())),
|
\\ @intToPtr(T, @ptrToInt(__resource.getUserData())),
|
||||||
\\ }});
|
\\ }});
|
||||||
\\ }}
|
\\ }}
|
||||||
\\ }}._wrapper else null,
|
\\ }}._wrapper else null,
|
||||||
\\ );
|
\\ );
|
||||||
\\}}
|
\\}}
|
||||||
, .{ snake_case, title_case, snake_case, title_case, snake_case, title_case, snake_case, title_case, title_case });
|
, .{
|
||||||
|
.interface = fmtId(trimPrefix(interface.name)),
|
||||||
|
.@"type" = titleCaseTrim(interface.name),
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
try writer.print(
|
try writer.print(
|
||||||
\\pub fn setHandler(
|
\\pub fn setHandler(
|
||||||
\\ _{s}: *{s},
|
\\ _{[interface]}: *{[type]},
|
||||||
\\ comptime T: type,
|
\\ comptime T: type,
|
||||||
\\ comptime handle_destroy: ?fn ({s}: *{s}, data: T) void,
|
\\ comptime handle_destroy: ?fn ({[interface]}: *{[type]}, data: T) void,
|
||||||
\\ _data: T,
|
\\ _data: T,
|
||||||
\\) callconv(.Inline) void {{
|
\\) callconv(.Inline) void {{
|
||||||
\\ const _resource = @ptrCast(*server.wl.Resource, {s});
|
\\ const _resource = @ptrCast(*server.wl.Resource, {[interface]});
|
||||||
\\ _resource.setDispatcher(
|
\\ _resource.setDispatcher(
|
||||||
\\ null,
|
\\ null,
|
||||||
\\ null,
|
\\ null,
|
||||||
@@ -430,14 +437,17 @@ const Interface = struct {
|
|||||||
\\ if (handle_destroy) |_handler| struct {{
|
\\ if (handle_destroy) |_handler| struct {{
|
||||||
\\ fn _wrapper(__resource: *server.wl.Resource) callconv(.C) void {{
|
\\ fn _wrapper(__resource: *server.wl.Resource) callconv(.C) void {{
|
||||||
\\ @call(.{{ .modifier = .always_inline }}, _handler, .{{
|
\\ @call(.{{ .modifier = .always_inline }}, _handler, .{{
|
||||||
\\ @ptrCast(*{s}, __resource),
|
\\ @ptrCast(*{[type]}, __resource),
|
||||||
\\ @intToPtr(T, @ptrToInt(__resource.getUserData())),
|
\\ @intToPtr(T, @ptrToInt(__resource.getUserData())),
|
||||||
\\ }});
|
\\ }});
|
||||||
\\ }}
|
\\ }}
|
||||||
\\ }}._wrapper else null,
|
\\ }}._wrapper else null,
|
||||||
\\ );
|
\\ );
|
||||||
\\}}
|
\\}}
|
||||||
, .{ snake_case, title_case, snake_case, title_case, snake_case, title_case });
|
, .{
|
||||||
|
.interface = fmtId(trimPrefix(interface.name)),
|
||||||
|
.@"type" = titleCaseTrim(interface.name),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (interface.events.items) |event, opcode|
|
for (interface.events.items) |event, opcode|
|
||||||
@@ -448,8 +458,7 @@ const Interface = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn emitCommon(interface: Interface, writer: anytype) !void {
|
fn emitCommon(interface: Interface, writer: anytype) !void {
|
||||||
try writer.writeAll("pub const ");
|
try writer.print("pub const {}", .{fmtId(trimPrefix(interface.name))});
|
||||||
try printIdentifier(writer, trimPrefix(interface.name));
|
|
||||||
|
|
||||||
// TODO: stop linking libwayland generated interface structs when
|
// TODO: stop linking libwayland generated interface structs when
|
||||||
// https://github.com/ziglang/zig/issues/131 is implemented
|
// https://github.com/ziglang/zig/issues/131 is implemented
|
||||||
@@ -484,11 +493,11 @@ const Interface = struct {
|
|||||||
|
|
||||||
try writer.print(
|
try writer.print(
|
||||||
\\ = struct {{
|
\\ = struct {{
|
||||||
\\ extern const {s}_interface: common.Interface;
|
\\ extern const {[interface]s}_interface: common.Interface;
|
||||||
\\ pub fn getInterface() callconv(.Inline) *const common.Interface {{
|
\\ pub fn getInterface() callconv(.Inline) *const common.Interface {{
|
||||||
\\ return &{s}_interface;
|
\\ return &{[interface]s}_interface;
|
||||||
\\ }}
|
\\ }}
|
||||||
, .{ interface.name, interface.name });
|
, .{ .interface = interface.name });
|
||||||
|
|
||||||
for (interface.enums.items) |e| try e.emit(writer);
|
for (interface.enums.items) |e| try e.emit(writer);
|
||||||
try writer.writeAll("};");
|
try writer.writeAll("};");
|
||||||
@@ -574,7 +583,7 @@ const Message = struct {
|
|||||||
//}
|
//}
|
||||||
|
|
||||||
fn emitField(message: Message, side: Side, writer: anytype) !void {
|
fn emitField(message: Message, side: Side, writer: anytype) !void {
|
||||||
try printIdentifier(writer, message.name);
|
try writer.print("{s}", .{fmtId(message.name)});
|
||||||
if (message.args.items.len == 0) {
|
if (message.args.items.len == 0) {
|
||||||
try writer.writeAll(": void,");
|
try writer.writeAll(": void,");
|
||||||
return;
|
return;
|
||||||
@@ -582,17 +591,13 @@ const Message = struct {
|
|||||||
try writer.writeAll(": struct {");
|
try writer.writeAll(": struct {");
|
||||||
for (message.args.items) |arg| {
|
for (message.args.items) |arg| {
|
||||||
if (side == .server and arg.kind == .new_id and arg.kind.new_id == null) {
|
if (side == .server and arg.kind == .new_id and arg.kind.new_id == null) {
|
||||||
try writer.writeAll("interface_name: [*:0]const u8, version: u32,");
|
try writer.print("interface_name: [*:0]const u8, version: u32,{}: u32", .{fmtId(arg.name)});
|
||||||
try printIdentifier(writer, arg.name);
|
|
||||||
try writer.writeAll(": u32");
|
|
||||||
} else if (side == .client and arg.kind == .new_id) {
|
} else if (side == .client and arg.kind == .new_id) {
|
||||||
try printIdentifier(writer, arg.name);
|
try writer.print("{}: *", .{fmtId(arg.name)});
|
||||||
try writer.writeAll(": *");
|
|
||||||
try printAbsolute(.client, writer, arg.kind.new_id.?);
|
try printAbsolute(.client, writer, arg.kind.new_id.?);
|
||||||
std.debug.assert(!arg.allow_null);
|
std.debug.assert(!arg.allow_null);
|
||||||
} else {
|
} else {
|
||||||
try printIdentifier(writer, arg.name);
|
try writer.print("{}:", .{fmtId(arg.name)});
|
||||||
try writer.writeByte(':');
|
|
||||||
// See notes on NULL in doc comment for wl_message in wayland-util.h
|
// See notes on NULL in doc comment for wl_message in wayland-util.h
|
||||||
if (side == .client and arg.kind == .object and !arg.allow_null)
|
if (side == .client and arg.kind == .object and !arg.allow_null)
|
||||||
try writer.writeByte('?');
|
try writer.writeByte('?');
|
||||||
@@ -606,41 +611,34 @@ const Message = struct {
|
|||||||
fn emitFn(message: Message, side: Side, writer: anytype, interface: Interface, opcode: usize) !void {
|
fn emitFn(message: Message, side: Side, writer: anytype, interface: Interface, opcode: usize) !void {
|
||||||
try writer.writeAll("pub fn ");
|
try writer.writeAll("pub fn ");
|
||||||
if (side == .server) {
|
if (side == .server) {
|
||||||
try writer.writeAll("send");
|
try writer.print("send{}", .{titleCase(message.name)});
|
||||||
try printIdentifier(writer, case(.title, message.name));
|
|
||||||
} else {
|
} else {
|
||||||
try printIdentifier(writer, case(.camel, message.name));
|
try writer.print("{}", .{camelCase(message.name)});
|
||||||
}
|
}
|
||||||
try writer.writeAll("(_");
|
try writer.print("(_{}: *{}", .{
|
||||||
try printIdentifier(writer, trimPrefix(interface.name));
|
fmtId(trimPrefix(interface.name)),
|
||||||
try writer.writeAll(": *");
|
titleCaseTrim(interface.name),
|
||||||
try printIdentifier(writer, case(.title, trimPrefix(interface.name)));
|
});
|
||||||
for (message.args.items) |arg| {
|
for (message.args.items) |arg| {
|
||||||
if (side == .server and arg.kind == .new_id) {
|
if (side == .server and arg.kind == .new_id) {
|
||||||
try writer.writeAll(", _");
|
try writer.print(", _{s}:", .{arg.name});
|
||||||
try printIdentifier(writer, arg.name);
|
|
||||||
try writer.writeByte(':');
|
|
||||||
if (arg.allow_null) try writer.writeByte('?');
|
if (arg.allow_null) try writer.writeByte('?');
|
||||||
try writer.writeByte('*');
|
try writer.writeByte('*');
|
||||||
if (arg.kind.new_id) |iface|
|
if (arg.kind.new_id) |iface|
|
||||||
try printIdentifier(writer, case(.title, trimPrefix(iface)))
|
try writer.print("{}", .{titleCaseTrim(iface)})
|
||||||
else
|
else
|
||||||
try writer.writeAll("server.wl.Resource");
|
try writer.writeAll("server.wl.Resource");
|
||||||
} else if (side == .client and arg.kind == .new_id) {
|
} else if (side == .client and arg.kind == .new_id) {
|
||||||
if (arg.kind.new_id == null) try writer.writeAll(", comptime T: type, _version: u32");
|
if (arg.kind.new_id == null) try writer.writeAll(", comptime T: type, _version: u32");
|
||||||
} else {
|
} else {
|
||||||
try writer.writeAll(", _");
|
try writer.print(", _{s}:", .{arg.name});
|
||||||
try printIdentifier(writer, arg.name);
|
|
||||||
try writer.writeByte(':');
|
|
||||||
try arg.emitType(side, writer);
|
try arg.emitType(side, writer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (side == .server or message.kind != .constructor) {
|
if (side == .server or message.kind != .constructor) {
|
||||||
try writer.writeAll(") void {");
|
try writer.writeAll(") void {");
|
||||||
} else if (message.kind.constructor) |new_iface| {
|
} else if (message.kind.constructor) |new_iface| {
|
||||||
try writer.writeAll(") !*");
|
try writer.print(") !*{}{{", .{titleCaseTrim(new_iface)});
|
||||||
try printIdentifier(writer, case(.title, trimPrefix(new_iface)));
|
|
||||||
try writer.writeAll("{");
|
|
||||||
} else {
|
} else {
|
||||||
try writer.writeAll(") !*T {");
|
try writer.writeAll(") !*T {");
|
||||||
}
|
}
|
||||||
@@ -648,8 +646,7 @@ const Message = struct {
|
|||||||
try writer.writeAll("const _resource = @ptrCast(*server.wl.Resource,_")
|
try writer.writeAll("const _resource = @ptrCast(*server.wl.Resource,_")
|
||||||
else
|
else
|
||||||
try writer.writeAll("const _proxy = @ptrCast(*client.wl.Proxy,_");
|
try writer.writeAll("const _proxy = @ptrCast(*client.wl.Proxy,_");
|
||||||
try printIdentifier(writer, trimPrefix(interface.name));
|
try writer.print("{});", .{fmtId(trimPrefix(interface.name))});
|
||||||
try writer.writeAll(");");
|
|
||||||
if (message.args.items.len > 0) {
|
if (message.args.items.len > 0) {
|
||||||
try writer.writeAll("var _args = [_]common.Argument{");
|
try writer.writeAll("var _args = [_]common.Argument{");
|
||||||
for (message.args.items) |arg| {
|
for (message.args.items) |arg| {
|
||||||
@@ -667,14 +664,13 @@ const Message = struct {
|
|||||||
const c_type = if (arg.kind == .uint) "u32" else "i32";
|
const c_type = if (arg.kind == .uint) "u32" else "i32";
|
||||||
try writer.print(
|
try writer.print(
|
||||||
\\ )) {{
|
\\ )) {{
|
||||||
\\ .Enum => @intCast({s}, @enumToInt(_{s})),
|
\\ .Enum => @intCast({[ct]s}, @enumToInt(_{[an]})),
|
||||||
\\ .Struct => @bitCast(u32, _{s}),
|
\\ .Struct => @bitCast(u32, _{[an]}),
|
||||||
\\ else => unreachable,
|
\\ else => unreachable,
|
||||||
\\ }}
|
\\ }}
|
||||||
, .{ c_type, arg.name, arg.name });
|
, .{ .ct = c_type, .an = fmtId(arg.name) });
|
||||||
} else {
|
} else {
|
||||||
try writer.writeByte('_');
|
try writer.print("_{s}", .{arg.name});
|
||||||
try printIdentifier(writer, arg.name);
|
|
||||||
}
|
}
|
||||||
try writer.writeAll("},");
|
try writer.writeAll("},");
|
||||||
},
|
},
|
||||||
@@ -685,8 +681,7 @@ const Message = struct {
|
|||||||
} else {
|
} else {
|
||||||
try writer.writeAll(".{ .o = @ptrCast(*common.Object, _");
|
try writer.writeAll(".{ .o = @ptrCast(*common.Object, _");
|
||||||
}
|
}
|
||||||
try printIdentifier(writer, arg.name);
|
try writer.print("{s}) }},", .{arg.name});
|
||||||
try writer.writeAll(") },");
|
|
||||||
} else {
|
} else {
|
||||||
if (new_iface == null) {
|
if (new_iface == null) {
|
||||||
try writer.writeAll(
|
try writer.writeAll(
|
||||||
@@ -711,11 +706,10 @@ const Message = struct {
|
|||||||
},
|
},
|
||||||
.constructor => |new_iface| {
|
.constructor => |new_iface| {
|
||||||
if (new_iface) |i| {
|
if (new_iface) |i| {
|
||||||
try writer.writeAll("return @ptrCast(*");
|
try writer.print("return @ptrCast(*{[type]}, try _proxy.marshalConstructor({[opcode]}, &_args, {[type]}.getInterface()));", .{
|
||||||
try printIdentifier(writer, case(.title, trimPrefix(i)));
|
.@"type" = titleCaseTrim(i),
|
||||||
try writer.print(", try _proxy.marshalConstructor({}, &_args, ", .{opcode});
|
.opcode = opcode,
|
||||||
try printIdentifier(writer, case(.title, trimPrefix(i)));
|
});
|
||||||
try writer.writeAll(".getInterface()));");
|
|
||||||
} else {
|
} else {
|
||||||
try writer.print("return @ptrCast(*T, try _proxy.marshalConstructorVersioned({}, &_args, T.getInterface(), _version));", .{opcode});
|
try writer.print("return @ptrCast(*T, try _proxy.marshalConstructorVersioned({}, &_args, T.getInterface(), _version));", .{opcode});
|
||||||
}
|
}
|
||||||
@@ -813,14 +807,14 @@ const Arg = struct {
|
|||||||
if (arg.enum_name) |name| {
|
if (arg.enum_name) |name| {
|
||||||
if (mem.indexOfScalar(u8, name, '.')) |dot_index| {
|
if (mem.indexOfScalar(u8, name, '.')) |dot_index| {
|
||||||
// Turn a reference like wl_shm.format into common.wl.shm.Format
|
// Turn a reference like wl_shm.format into common.wl.shm.Format
|
||||||
try writer.writeAll("common.");
|
|
||||||
const us_index = mem.indexOfScalar(u8, name, '_') orelse 0;
|
const us_index = mem.indexOfScalar(u8, name, '_') orelse 0;
|
||||||
try writer.writeAll(name[0..us_index]);
|
try writer.print("common.{s}.{s}{}", .{
|
||||||
try writer.writeAll(".");
|
name[0..us_index],
|
||||||
try writer.writeAll(name[us_index + 1 .. dot_index + 1]);
|
name[us_index + 1 .. dot_index + 1],
|
||||||
try writer.writeAll(case(.title, name[dot_index + 1 ..]));
|
titleCase(name[dot_index + 1 ..]),
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
try writer.writeAll(case(.title, name));
|
try writer.print("{}", .{titleCase(name)});
|
||||||
}
|
}
|
||||||
} else if (arg.kind == .int) {
|
} else if (arg.kind == .int) {
|
||||||
try writer.writeAll("i32");
|
try writer.writeAll("i32");
|
||||||
@@ -895,8 +889,7 @@ const Enum = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn emit(e: Enum, writer: anytype) !void {
|
fn emit(e: Enum, writer: anytype) !void {
|
||||||
try writer.writeAll("pub const ");
|
try writer.print("pub const {}", .{titleCase(e.name)});
|
||||||
try printIdentifier(writer, case(.title, e.name));
|
|
||||||
|
|
||||||
if (e.bitfield) {
|
if (e.bitfield) {
|
||||||
var entries_emitted: u8 = 0;
|
var entries_emitted: u8 = 0;
|
||||||
@@ -904,7 +897,7 @@ const Enum = struct {
|
|||||||
for (e.entries.items) |entry| {
|
for (e.entries.items) |entry| {
|
||||||
const value = entry.intValue();
|
const value = entry.intValue();
|
||||||
if (value != 0 and std.math.isPowerOfTwo(value)) {
|
if (value != 0 and std.math.isPowerOfTwo(value)) {
|
||||||
try printIdentifier(writer, entry.name);
|
try writer.print("{s}", .{entry.name});
|
||||||
if (entries_emitted == 0) {
|
if (entries_emitted == 0) {
|
||||||
// Align the first field to ensure the entire packed
|
// Align the first field to ensure the entire packed
|
||||||
// struct matches the alignment of a u32. This allows
|
// struct matches the alignment of a u32. This allows
|
||||||
@@ -930,8 +923,7 @@ const Enum = struct {
|
|||||||
|
|
||||||
try writer.writeAll(" = extern enum(c_int) {");
|
try writer.writeAll(" = extern enum(c_int) {");
|
||||||
for (e.entries.items) |entry| {
|
for (e.entries.items) |entry| {
|
||||||
try printIdentifier(writer, entry.name);
|
try writer.print("{s}= {s},", .{ fmtId(entry.name), entry.value });
|
||||||
try writer.print("= {s},", .{entry.value});
|
|
||||||
}
|
}
|
||||||
// Always generate non-exhaustive enums to ensure forward compatability.
|
// Always generate non-exhaustive enums to ensure forward compatability.
|
||||||
// Entries have been added to wl_shm.format without bumping the version.
|
// Entries have been added to wl_shm.format without bumping the version.
|
||||||
@@ -993,46 +985,52 @@ fn trimPrefix(s: []const u8) []const u8 {
|
|||||||
return s[mem.indexOfScalar(u8, s, '_').? + 1 ..];
|
return s[mem.indexOfScalar(u8, s, '_').? + 1 ..];
|
||||||
}
|
}
|
||||||
|
|
||||||
var case_buf: [512]u8 = undefined;
|
const Case = enum { title, camel };
|
||||||
fn case(out_case: enum { title, camel }, snake_case: []const u8) []const u8 {
|
|
||||||
var i: usize = 0;
|
fn formatCaseImpl(case: Case, comptime trim: bool) type {
|
||||||
var upper = out_case == .title;
|
return struct {
|
||||||
for (snake_case) |ch| {
|
pub fn f(
|
||||||
if (ch == '_') {
|
bytes: []const u8,
|
||||||
upper = true;
|
comptime fmt: []const u8,
|
||||||
continue;
|
options: std.fmt.FormatOptions,
|
||||||
|
writer: anytype,
|
||||||
|
) !void {
|
||||||
|
var upper = case == .title;
|
||||||
|
var str = if (trim) trimPrefix(bytes) else bytes;
|
||||||
|
for (str) |c| {
|
||||||
|
if (c == '_') {
|
||||||
|
upper = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try writer.writeByte(if (upper) std.ascii.toUpper(c) else c);
|
||||||
|
upper = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case_buf[i] = if (upper) std.ascii.toUpper(ch) else ch;
|
};
|
||||||
i += 1;
|
}
|
||||||
upper = false;
|
|
||||||
}
|
fn titleCase(bytes: []const u8) std.fmt.Formatter(formatCaseImpl(.title, false).f) {
|
||||||
return case_buf[0..i];
|
return .{ .data = bytes };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn titleCaseTrim(bytes: []const u8) std.fmt.Formatter(formatCaseImpl(.title, true).f) {
|
||||||
|
return .{ .data = bytes };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn camelCase(bytes: []const u8) std.fmt.Formatter(formatCaseImpl(.camel, false).f) {
|
||||||
|
return .{ .data = bytes };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn camelCaseTrim(bytes: []const u8) std.fmt.Formatter(formatCaseImpl(.camel, true).f) {
|
||||||
|
return .{ .data = bytes };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn printAbsolute(side: Side, writer: anytype, interface: []const u8) !void {
|
fn printAbsolute(side: Side, writer: anytype, interface: []const u8) !void {
|
||||||
try writer.writeAll(@tagName(side));
|
try writer.print("{s}.{s}.{}", .{
|
||||||
try writer.writeByte('.');
|
@tagName(side),
|
||||||
try printIdentifier(writer, prefix(interface) orelse return error.MissingPrefix);
|
prefix(interface) orelse return error.MissingPrefix,
|
||||||
try writer.writeByte('.');
|
titleCaseTrim(interface),
|
||||||
try printIdentifier(writer, case(.title, trimPrefix(interface)));
|
});
|
||||||
}
|
|
||||||
|
|
||||||
fn printIdentifier(writer: anytype, identifier: []const u8) !void {
|
|
||||||
if (isValidIdentifier(identifier))
|
|
||||||
try writer.writeAll(identifier)
|
|
||||||
else
|
|
||||||
try writer.print("@\"{s}\"", .{identifier});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn isValidIdentifier(identifier: []const u8) bool {
|
|
||||||
// !keyword [A-Za-z_] [A-Za-z0-9_]*
|
|
||||||
if (identifier.len == 0) return false;
|
|
||||||
for (identifier) |ch, i| switch (ch) {
|
|
||||||
'A'...'Z', 'a'...'z', '_' => {},
|
|
||||||
'0'...'9' => if (i == 0) return false,
|
|
||||||
else => return false,
|
|
||||||
};
|
|
||||||
return std.zig.Token.getKeyword(identifier) == null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "parsing" {
|
test "parsing" {
|
||||||
|
|||||||
Reference in New Issue
Block a user