commit efd6ded716a027f7d47fe5c38df17785c8e2a2e2 (tree) parent 9b5851f0019c6cf2b5a54ffa54acd7f13b941a07 Author: Ryan Liptak <squeek502@noreply.codeberg.org> Date: Sat, 27 Jun 2026 22:19:19 +0200 Merge pull request 'ConfigHeader standalone tests rework' (#35643) from fardragon/zig:fardragon/configheader-tests into master Reviewed-on: https://codeberg.org/ziglang/zig/pulls/35643 Reviewed-by: Ryan Liptak <squeek502@noreply.codeberg.org> Diffstat:
30 files changed, 887 insertions(+), 593 deletions(-)
diff --git a/lib/compiler/Maker/Step/ConfigHeader.zig b/lib/compiler/Maker/Step/ConfigHeader.zig @@ -11,8 +11,10 @@ const Step = @import("../Step.zig"); const Maker = @import("../../Maker.zig"); const header_text = "This file was generated by ConfigHeader using the Zig Build System."; -const c_generated_line = "/* " ++ header_text ++ " */\n"; -const asm_generated_line = "; " ++ header_text ++ "\n"; +const c_generated_line = "/* " ++ header_text ++ " */"; +const asm_generated_line = "; " ++ header_text; + +const os_newline = if (@import("builtin").os.tag == .windows) "\r\n" else "\n"; /// Table value is whether the value is used. const ValueMap = std.array_hash_map.String(bool); @@ -160,6 +162,11 @@ fn ensureAllValuesUsed( if (any_errors) return error.MakeFailed; } +fn detectNewline(contents: []const u8) []const u8 { + const lf_index = std.mem.findScalar(u8, contents, '\n') orelse return os_newline; + return if (lf_index > 0 and contents[lf_index - 1] == '\r') "\r\n" else "\n"; +} + fn renderAutoConfUndef( maker: *Maker, step: *Step, @@ -170,23 +177,28 @@ fn renderAutoConfUndef( src_path: Path, ) !void { const conf = &maker.scanned_config.configuration; + const newline = detectNewline(contents); try w.writeAll(c_generated_line); + try w.writeAll(newline); var any_errors = false; var line_index: u32 = 0; var line_it = std.mem.splitScalar(u8, contents, '\n'); - while (line_it.next()) |line| : (line_index += 1) { + while (line_it.next()) |raw_line| : (line_index += 1) { + const last_line = line_it.index == line_it.buffer.len; + const line = std.mem.trimEnd(u8, raw_line, "\r"); + if (!std.mem.startsWith(u8, line, "#")) { try w.writeAll(line); - try w.writeByte('\n'); + if (!last_line) try w.writeAll(newline); continue; } var it = std.mem.tokenizeAny(u8, line[1..], " \t\r"); const undef = it.next().?; if (!std.mem.eql(u8, undef, "undef")) { try w.writeAll(line); - try w.writeByte('\n'); + if (!last_line) try w.writeAll(newline); continue; } const name = it.next().?; @@ -198,7 +210,7 @@ fn renderAutoConfUndef( continue; }; value_map.values()[index] = true; // Set to used. - try renderValueC(conf, w, name, value_pairs[index].index); + try renderValueC(conf, w, newline, name, value_pairs[index].index); } try ensureAllValuesUsed(maker, step, value_map, src_path); @@ -216,14 +228,17 @@ fn renderAutoconfAt( ) !void { const w = &aw.writer; const conf = &maker.scanned_config.configuration; + const newline = detectNewline(contents); try w.writeAll(c_generated_line); + try w.writeAll(newline); var any_errors = false; var line_index: u32 = 0; var line_it = std.mem.splitScalar(u8, contents, '\n'); - while (line_it.next()) |line| : (line_index += 1) { + while (line_it.next()) |raw_line| : (line_index += 1) { const last_line = line_it.index == line_it.buffer.len; + const line = std.mem.trimEnd(u8, raw_line, "\r"); const old_len = aw.written().len; expandVariablesAutoconfAt(w, line, conf, value_pairs, value_map) catch |err| switch (err) { @@ -244,7 +259,7 @@ fn renderAutoconfAt( continue; }, }; - if (!last_line) try w.writeByte('\n'); + if (!last_line) try w.writeAll(newline); } try ensureAllValuesUsed(maker, step, value_map, src_path); @@ -262,16 +277,19 @@ fn renderCmake( src_path: Path, ) !void { const conf = &maker.scanned_config.configuration; + const newline = detectNewline(contents); try w.writeAll(c_generated_line); + try w.writeAll(newline); var any_errors = false; var line_index: u32 = 0; var line_it = std.mem.splitScalar(u8, contents, '\n'); while (line_it.next()) |raw_line| : (line_index += 1) { const last_line = line_it.index == line_it.buffer.len; + const stripped_line = std.mem.trimEnd(u8, raw_line, "\r"); - const line = expandVariablesCmake(arena, raw_line, conf, value_pairs, value_map) catch |err| switch (err) { + const line = expandVariablesCmake(arena, stripped_line, conf, value_pairs, value_map) catch |err| switch (err) { error.InvalidCharacter => { try step.addError(maker, "{f}:{d}: invalid character in a variable name", .{ src_path, line_index + 1, @@ -290,7 +308,7 @@ fn renderCmake( const line_start = std.mem.findNone(u8, line, " \t\r") orelse { try w.writeAll(line); - if (!last_line) try w.writeByte('\n'); + if (!last_line) try w.writeAll(newline); continue; }; const whitespace_prefix = line[0..line_start]; @@ -298,7 +316,7 @@ fn renderCmake( if (!std.mem.startsWith(u8, trimmed_line, "#")) { try w.writeAll(line); - if (!last_line) try w.writeByte('\n'); + if (!last_line) try w.writeAll(newline); continue; } @@ -311,7 +329,7 @@ fn renderCmake( false else { try w.writeAll(line); - if (!last_line) try w.writeByte('\n'); + if (!last_line) try w.writeAll(newline); continue; }; @@ -335,7 +353,7 @@ fn renderCmake( try w.writeAll(whitespace_prefix); if (booldefine) { - try renderValueCBool(w, name, switch (value.unpack(conf)) { + try renderValueCBool(w, newline, name, switch (value.unpack(conf)) { .undef, .defined => false, .bool => |b| b, inline .u64, .i64 => |i| i != 0, @@ -343,9 +361,9 @@ fn renderCmake( .ident => false, }); } else if (value != .undef) { - try renderValueCIdent(w, name, it.rest()); + try renderValueCIdent(w, newline, name, it.rest()); } else { - try renderValueC(conf, w, name, value); + try renderValueC(conf, w, newline, name, value); } } @@ -362,6 +380,7 @@ fn renderBlank( include_guard_override: ?[]const u8, ) !void { try w.writeAll(c_generated_line); + try w.writeAll(os_newline); const include_guard_fmt: IncludeGuardFmt = .{ .include_path = include_path, @@ -369,17 +388,13 @@ fn renderBlank( }; try w.print( - \\#ifndef {[0]f} - \\#define {[0]f} - \\ - , .{include_guard_fmt}); + "#ifndef {[0]f}{[1]s}#define {[0]f}{[1]s}", + .{ include_guard_fmt, os_newline }, + ); - for (value_map.keys(), value_pairs) |name, pair| try renderValueC(conf, w, name, pair.index); + for (value_map.keys(), value_pairs) |name, pair| try renderValueC(conf, w, os_newline, name, pair.index); - try w.print( - \\#endif /* {f} */ - \\ - , .{include_guard_fmt}); + try w.print("#endif /* {f} */{s}", .{ include_guard_fmt, os_newline }); } const IncludeGuardFmt = struct { @@ -403,36 +418,42 @@ fn renderNasm( value_map: *const ValueMap, ) !void { try w.writeAll(asm_generated_line); - for (value_map.keys(), value_pairs) |name, pair| try renderValueNasm(conf, w, name, pair.index); + try w.writeAll(os_newline); + for (value_map.keys(), value_pairs) |name, pair| try renderValueNasm(conf, w, os_newline, name, pair.index); } -fn renderValueC(conf: *const Configuration, w: *Writer, name: []const u8, value: Value.Index) !void { +fn renderValueC(conf: *const Configuration, w: *Writer, newline: []const u8, name: []const u8, value: Value.Index) !void { switch (value.unpack(conf)) { - .undef => try w.print("/* #undef {s} */\n", .{name}), - .defined => try w.print("#define {s}\n", .{name}), - .bool => |b| return renderValueCBool(w, name, b), - inline .u64, .i64 => |i| try w.print("#define {s} {d}\n", .{ name, i }), - .ident => |ident| return renderValueCIdent(w, name, ident), - .string => |string| try w.print("#define {s} \"{f}\"\n", .{ name, std.zig.fmtString(string) }), + .undef => try w.print("/* #undef {s} */{s}", .{ name, newline }), + .defined => try w.print("#define {s}{s}", .{ name, newline }), + .bool => |b| return renderValueCBool(w, newline, name, b), + inline .u64, .i64 => |i| try w.print("#define {s} {d}{s}", .{ name, i, newline }), + .ident => |ident| return renderValueCIdent(w, newline, name, ident), + .string => |string| try w.print("#define {s} \"{f}\"{s}", .{ name, std.zig.fmtString(string), newline }), } } -fn renderValueCIdent(w: *Writer, name: []const u8, ident: []const u8) Writer.Error!void { - return w.print("#define {s} {s}\n", .{ name, ident }); +fn renderValueCIdent(w: *Writer, newline: []const u8, name: []const u8, ident: []const u8) Writer.Error!void { + try w.print("#define {s}", .{name}); + if (ident.len > 0) { + try w.writeByte(' '); + try w.writeAll(ident); + } + return w.writeAll(newline); } -fn renderValueCBool(w: *Writer, name: []const u8, b: bool) Writer.Error!void { - return w.print("#define {s} {c}\n", .{ name, @as(u8, '0') + @intFromBool(b) }); +fn renderValueCBool(w: *Writer, newline: []const u8, name: []const u8, b: bool) Writer.Error!void { + return w.print("#define {s} {c}{s}", .{ name, @as(u8, '0') + @intFromBool(b), newline }); } -fn renderValueNasm(conf: *const Configuration, w: *Writer, name: []const u8, value: Value.Index) !void { +fn renderValueNasm(conf: *const Configuration, w: *Writer, newline: []const u8, name: []const u8, value: Value.Index) !void { switch (value.unpack(conf)) { - .undef => try w.print("; %undef {s}\n", .{name}), - .defined => try w.print("%define {s}\n", .{name}), - .bool => |b| try w.print("%define {s} {c}\n", .{ name, @as(u8, '0') + @intFromBool(b) }), - inline .u64, .i64 => |i| try w.print("%define {s} {d}\n", .{ name, i }), - .ident => |ident| try w.print("%define {s} {s}\n", .{ name, ident }), - .string => |string| try w.print("%define {s} \"{f}\"\n", .{ name, std.zig.fmtString(string) }), + .undef => try w.print("; %undef {s}{s}", .{ name, newline }), + .defined => try w.print("%define {s}{s}", .{ name, newline }), + .bool => |b| try w.print("%define {s} {c}{s}", .{ name, @as(u8, '0') + @intFromBool(b), newline }), + inline .u64, .i64 => |i| try w.print("%define {s} {d}{s}", .{ name, i, newline }), + .ident => |ident| try w.print("%define {s} {s}{s}", .{ name, ident, newline }), + .string => |string| try w.print("%define {s} \"{f}\"{s}", .{ name, std.zig.fmtString(string), newline }), } } diff --git a/test/standalone/build.zig.zon b/test/standalone/build.zig.zon @@ -141,9 +141,6 @@ .strip_struct_init = .{ .path = "strip_struct_init", }, - .cmakedefine = .{ - .path = "cmakedefine", - }, .zerolength_check = .{ .path = "zerolength_check", }, diff --git a/test/standalone/cmakedefine/build.zig b/test/standalone/cmakedefine/build.zig @@ -1,104 +0,0 @@ -const std = @import("std"); -const ConfigHeader = std.Build.Step.ConfigHeader; - -pub fn build(b: *std.Build) void { - const config_header = b.addConfigHeader( - .{ - .style = .{ .cmake = b.path("config.h.in") }, - .include_path = "config.h", - }, - .{ - .noval = null, - .trueval = true, - .falseval = false, - .zeroval = 0, - .oneval = 1, - .tenval = 10, - .stringval = "test", - - .boolnoval = {}, - .booltrueval = true, - .boolfalseval = false, - .boolzeroval = 0, - .booloneval = 1, - .booltenval = 10, - .boolstringval = "test", - }, - ); - - const pwd_sh = b.addConfigHeader( - .{ - .style = .{ .cmake = b.path("pwd.sh.in") }, - .include_path = "pwd.sh", - }, - .{ .DIR = "${PWD}" }, - ); - - const sigil_header = b.addConfigHeader( - .{ - .style = .{ .cmake = b.path("sigil.h.in") }, - .include_path = "sigil.h", - }, - .{}, - ); - - const stack_header = b.addConfigHeader( - .{ - .style = .{ .cmake = b.path("stack.h.in") }, - .include_path = "stack.h", - }, - .{ - .UNDERSCORE = "_", - .NEST_UNDERSCORE_PROXY = "UNDERSCORE", - .NEST_PROXY = "NEST_UNDERSCORE_PROXY", - }, - ); - - const wrapper_header = b.addConfigHeader( - .{ - .style = .{ .cmake = b.path("wrapper.h.in") }, - .include_path = "wrapper.h", - }, - .{ - .DOLLAR = "$", - .TEXT = "TRAP", - - .STRING = "TEXT", - .STRING_AT = "@STRING@", - .STRING_CURLY = "{STRING}", - .STRING_VAR = "${STRING}", - }, - ); - - const check_exe = b.addExecutable(.{ - .name = "check", - .root_module = b.createModule(.{ - .target = b.graph.host, - .root_source_file = b.path("check.zig"), - }), - }); - - const test_step = b.step("test", "Test it"); - b.default_step = test_step; - test_step.dependOn(addCheck(b, check_exe, config_header)); - test_step.dependOn(addCheck(b, check_exe, pwd_sh)); - test_step.dependOn(addCheck(b, check_exe, sigil_header)); - test_step.dependOn(addCheck(b, check_exe, stack_header)); - test_step.dependOn(addCheck(b, check_exe, wrapper_header)); -} - -fn addCheck( - b: *std.Build, - check_exe: *std.Build.Step.Compile, - ch: *ConfigHeader, -) *std.Build.Step { - // We expect `ch.include_path` to only be a basename to infer where the expected output is. - std.debug.assert(std.fs.path.dirname(ch.include_path) == null); - const expected_path = b.fmt("expected_{s}", .{ch.include_path}); - - const run_check = b.addRunArtifact(check_exe); - run_check.addFileArg(ch.getOutputFile()); - run_check.addFileArg(b.path(expected_path)); - - return &run_check.step; -} diff --git a/test/standalone/cmakedefine/check.zig b/test/standalone/cmakedefine/check.zig @@ -1,26 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); - -pub fn main(init: std.process.Init) !void { - const arena = init.arena.allocator(); - const io = init.io; - const args = try init.minimal.args.toSlice(arena); - - if (args.len != 3) return error.BadUsage; - const actual_path = args[1]; - const expected_path = args[2]; - - const actual = try std.Io.Dir.cwd().readFileAlloc(io, actual_path, arena, .limited(1024 * 1024)); - const expected = try std.Io.Dir.cwd().readFileAlloc(io, expected_path, arena, .limited(1024 * 1024)); - - // The actual output starts with a comment which we should strip out before comparing. - const comment_str = "/* This file was generated by ConfigHeader using the Zig Build System. */\n"; - if (!std.mem.startsWith(u8, actual, comment_str)) { - return error.MissingOrMalformedComment; - } - const actual_without_comment = actual[comment_str.len..]; - - if (builtin.os.tag == .windows) return; // https://codeberg.org/ziglang/zig/issues/30138 - - try std.testing.expectEqualStrings(expected, actual_without_comment); -} diff --git a/test/standalone/cmakedefine/config.h.in b/test/standalone/cmakedefine/config.h.in @@ -1,147 +0,0 @@ -// cmakedefine -// undefined -#cmakedefine noval unreachable - -// 1 -#cmakedefine trueval 1 - -// undefined -#cmakedefine falseval unreachable - -// undefined -#cmakedefine zeroval unreachable - -// 1 -#cmakedefine oneval 1 - -// 1 -#cmakedefine tenval 1 - -// 1 -#cmakedefine stringval 1 - -// whitespace test - #cmakedefine stringval 1 - #cmakedefine stringval 1 - - -// cmakedefine01 -// 0 -#cmakedefine01 boolnoval - -// 1 -#cmakedefine01 booltrueval - -// 0 -#cmakedefine01 boolfalseval - -// 0 -#cmakedefine01 boolzeroval - -// 1 -#cmakedefine01 booloneval - -// 1 -#cmakedefine01 booltenval - -// 1 -#cmakedefine01 boolstringval - - -// @ substition - -// no substition -// @noval@ - -// no substition -// @noval@@noval@ - -// no substition -// @noval@.@noval@ - -// 1 -// @trueval@ - -// 0 -// @falseval@ - -// 10 -// @trueval@@falseval@ - -// 0.1 -// @falseval@.@trueval@ - -// 0 -// @zeroval@ - -// 1 -// @oneval@ - -// 10 -// @tenval@ - -// 01 -// @zeroval@@oneval@ - -// 0.10 -// @zeroval@.@tenval@ - -// test -// @stringval@ - -// testtest -// @stringval@@stringval@ - -// test.test -// @stringval@.@stringval@ - -// test10 -// @noval@@stringval@@trueval@@zeroval@ - -// no substition -// ${noval} - -// no substition -// ${noval}${noval} - -// no substition -// ${noval}.${noval} - -// 1 -// ${trueval} - -// 0 -// ${falseval} - -// 10 -// ${trueval}${falseval} - -// 0.1 -// ${falseval}.${trueval} - -// 0 -// ${zeroval} - -// 1 -// ${oneval} - -// 10 -// ${tenval} - -// 01 -// ${zeroval}${oneval} - -// 0.10 -// ${zeroval}.${tenval} - -// test -// ${stringval} - -// testtest -// ${stringval}${stringval} - -// test.test -// ${stringval}.${stringval} - -// test10 -// ${noval}${stringval}${trueval}${zeroval} diff --git a/test/standalone/cmakedefine/expected_config.h b/test/standalone/cmakedefine/expected_config.h @@ -1,147 +0,0 @@ -// cmakedefine -// undefined -/* #undef noval */ - -// 1 -#define trueval 1 - -// undefined -/* #undef falseval */ - -// undefined -/* #undef zeroval */ - -// 1 -#define oneval 1 - -// 1 -#define tenval 1 - -// 1 -#define stringval 1 - -// whitespace test - #define stringval 1 - #define stringval 1 - - -// cmakedefine01 -// 0 -#define boolnoval 0 - -// 1 -#define booltrueval 1 - -// 0 -#define boolfalseval 0 - -// 0 -#define boolzeroval 0 - -// 1 -#define booloneval 1 - -// 1 -#define booltenval 1 - -// 1 -#define boolstringval 1 - - -// @ substition - -// no substition -// - -// no substition -// - -// no substition -// . - -// 1 -// 1 - -// 0 -// 0 - -// 10 -// 10 - -// 0.1 -// 0.1 - -// 0 -// 0 - -// 1 -// 1 - -// 10 -// 10 - -// 01 -// 01 - -// 0.10 -// 0.10 - -// test -// test - -// testtest -// testtest - -// test.test -// test.test - -// test10 -// test10 - -// no substition -// - -// no substition -// - -// no substition -// . - -// 1 -// 1 - -// 0 -// 0 - -// 10 -// 10 - -// 0.1 -// 0.1 - -// 0 -// 0 - -// 1 -// 1 - -// 10 -// 10 - -// 01 -// 01 - -// 0.10 -// 0.10 - -// test -// test - -// testtest -// testtest - -// test.test -// test.test - -// test10 -// test10 diff --git a/test/standalone/cmakedefine/expected_pwd.sh b/test/standalone/cmakedefine/expected_pwd.sh @@ -1 +0,0 @@ -echo ${PWD} diff --git a/test/standalone/cmakedefine/expected_sigil.h b/test/standalone/cmakedefine/expected_sigil.h @@ -1,4 +0,0 @@ -#define AT @ -#define ATAT @@ -#define ATATAT @@@ -#define ATATATAT @@@@ diff --git a/test/standalone/cmakedefine/expected_stack.h b/test/standalone/cmakedefine/expected_stack.h @@ -1,3 +0,0 @@ -#define NEST_UNDERSCORE_PROXY NEST_UNDERSCORE_PROXY - -#define NEST_UNDERSCORE_PROXY NEST_UNDERSCORE_PROXY diff --git a/test/standalone/cmakedefine/expected_wrapper.h b/test/standalone/cmakedefine/expected_wrapper.h @@ -1,30 +0,0 @@ -// becomes TEXT -#define TEXT -#define TEXT - -// becomes `at`TEXT`at` -#define @TEXT@ -#define @TEXT@ - -// becomes TRAP -#define TRAP - -// becomes `dollar sign`{STRING} -#define ${STRING} -#define ${STRING} - -// becomes `dollar sign`{STRING} -#define ${STRING} -#define ${STRING} - -// becomes `dollar sign`{TEXT} -#define ${TEXT} -#define ${TEXT} - -// becomes `at`STRING`at` -#define @STRING@ -#define @STRING@ - -#define \@STRING_VAR\@ -#define \${STRING} -#define $\{STRING_VAR} diff --git a/test/standalone/cmakedefine/sigil.h.in b/test/standalone/cmakedefine/sigil.h.in @@ -1,4 +0,0 @@ -#define AT @ -#define ATAT @@ -#define ATATAT @@@ -#define ATATATAT @@@@ diff --git a/test/standalone/cmakedefine/stack.h.in b/test/standalone/cmakedefine/stack.h.in @@ -1,3 +0,0 @@ -#define NEST_UNDERSCORE_PROXY ${NEST${UNDERSCORE}PROXY} - -#define NEST_UNDERSCORE_PROXY ${NEST${${NEST_UNDERSCORE${UNDERSCORE}PROXY}}PROXY} diff --git a/test/standalone/cmakedefine/wrapper.h.in b/test/standalone/cmakedefine/wrapper.h.in @@ -1,30 +0,0 @@ -// becomes TEXT -#define @STRING@ -#define ${STRING} - -// becomes `at`TEXT`at` -#define @${STRING}@ -#define @@STRING@@ - -// becomes TRAP -#define ${@STRING@} - -// becomes `dollar sign`{STRING} -#define $@STRING_CURLY@ -#define $${STRING_CURLY} - -// becomes `dollar sign`{STRING} -#define @STRING_VAR@ -#define ${STRING_VAR} - -// becomes `dollar sign`{TEXT} -#define ${DOLLAR}{${STRING}} -#define @DOLLAR@{${STRING}} - -// becomes `at`STRING`at` -#define ${STRING_AT} -#define @STRING_AT@ - -#define \@STRING_VAR\@ -#define \${STRING_VAR} -#define $\{STRING_VAR} diff --git a/test/standalone/config_header/autoconf_at/autoconf_at.h b/test/standalone/config_header/autoconf_at/autoconf_at.h @@ -0,0 +1,63 @@ +/* This file was generated by ConfigHeader using the Zig Build System. */ +/* Some Comment */ +int foo(); +// empty strings are preserved + +// line with misc content is preserved +#define KEPT_VALUE no substitution + +// empty @ sigils are preserved +#define AT_SIGIL_1 @ +#define AT_SIGIL_2 @@ +#define AT_SIGIL_3 @@@ +#define AT_SIGIL_4 @@@@ + +// simple substitution +#define SIMPLE_UNDEFINED +#define SIMPLE_DEFINED +#define SIMPLE_BOOL_TRUE 1 +#define SIMPLE_BOOL_FALSE 0 +#define SIMPLE_INTEGER 42 +#define SIMPLE_STRING text + +// double packed substitution +#define DOUBLE_PACKED texttext + +// triple packed substitution +#define TRIPLE_PACKED text42text + +// double separated substitution +#define DOUBLE_SEPARATED 42.42 + +// triple separated substitution +#define TRIPLE_SEPARATED 42.1.42 + +// misc prefix is preserved +#define MISC_PREFIX false is 0 + +// misc suffix is preserved +#define MISC_SUFFIX 1 is true + +// surrounding content is preserved +#define SURROUNDING what is 6*7? 42! + +// incomplete key is preserved +#define INCOMPLETE_KEY @undefined + +// @-vars resolved only when they wrap valid characters, otherwise considered literals +#define DOUBLE_WRAPPED @text@ + +// expanded variables are considered strings after expansion +#define EXPANDED_STRING @string@ + +// variable name with underscores +#define UNDERSCORED_VAR value + +// backslash before at-sigil does not prevent resolution +#define BACKSLASH_AT \text + +// value that is an at-sign itself +#define AT_SIGN_VALUE @ + +// incomplete key mid-line is preserved, trailing content kept +#define INCOMPLETE_MID @incomplete trailing content diff --git a/test/standalone/config_header/autoconf_at/autoconf_at.h.in b/test/standalone/config_header/autoconf_at/autoconf_at.h.in @@ -0,0 +1,62 @@ +/* Some Comment */ +int foo(); +// empty strings are preserved + +// line with misc content is preserved +#define KEPT_VALUE no substitution + +// empty @ sigils are preserved +#define AT_SIGIL_1 @ +#define AT_SIGIL_2 @@ +#define AT_SIGIL_3 @@@ +#define AT_SIGIL_4 @@@@ + +// simple substitution +#define SIMPLE_UNDEFINED @undefined@ +#define SIMPLE_DEFINED @defined@ +#define SIMPLE_BOOL_TRUE @boolean_true@ +#define SIMPLE_BOOL_FALSE @boolean_false@ +#define SIMPLE_INTEGER @integer@ +#define SIMPLE_STRING @string@ + +// double packed substitution +#define DOUBLE_PACKED @string@@string@ + +// triple packed substitution +#define TRIPLE_PACKED @string@@integer@@string@ + +// double separated substitution +#define DOUBLE_SEPARATED @integer@.@integer@ + +// triple separated substitution +#define TRIPLE_SEPARATED @integer@.@boolean_true@.@integer@ + +// misc prefix is preserved +#define MISC_PREFIX false is @boolean_false@ + +// misc suffix is preserved +#define MISC_SUFFIX @boolean_true@ is true + +// surrounding content is preserved +#define SURROUNDING what is 6*7? @integer@! + +// incomplete key is preserved +#define INCOMPLETE_KEY @undefined + +// @-vars resolved only when they wrap valid characters, otherwise considered literals +#define DOUBLE_WRAPPED @@string@@ + +// expanded variables are considered strings after expansion +#define EXPANDED_STRING @string_at@ + +// variable name with underscores +#define UNDERSCORED_VAR @underscored_var@ + +// backslash before at-sigil does not prevent resolution +#define BACKSLASH_AT \@string@ + +// value that is an at-sign itself +#define AT_SIGN_VALUE @at_sign@ + +// incomplete key mid-line is preserved, trailing content kept +#define INCOMPLETE_MID @incomplete trailing content diff --git a/test/standalone/config_header/autoconf_undef/config.h b/test/standalone/config_header/autoconf_undef/config.h @@ -0,0 +1,32 @@ +/* This file was generated by ConfigHeader using the Zig Build System. */ +/* Some Comment */ + +int foo(); + +/* #undef SOME_NO */ +#define SOME_TRUE 1 +#define SOME_FALSE 0 +#define SOME_ZERO 0 +#define SOME_ONE 1 +#define SOME_TEN 10 +#define SOME_ENUM foo +#define SOME_ENUM_LITERAL test +#define SOME_STRING "test" + +// Used twice +#define SOME_TRUE 1 + +/* #undef PREFIX_SPACE */ +/* #undef PREFIX_TAB */ +/* #undef POSTFIX_SPACE */ +/* #undef POSTFIX_TAB */ + +// #undef with underscored variable name +#define SOME_UNDERSCORED 1 + +// #undef with extra tokens after variable name (ignored) +#define SOME_ONE 1 + +// non-#undef # lines pass through unchanged +#define KEPT_DEFINE value +#include <kept.h> diff --git a/test/standalone/config_header/autoconf_undef/config.h.in b/test/standalone/config_header/autoconf_undef/config.h.in @@ -0,0 +1,31 @@ +/* Some Comment */ + +int foo(); + +#undef SOME_NO +#undef SOME_TRUE +#undef SOME_FALSE +#undef SOME_ZERO +#undef SOME_ONE +#undef SOME_TEN +#undef SOME_ENUM +#undef SOME_ENUM_LITERAL +#undef SOME_STRING + +// Used twice +#undef SOME_TRUE + +#undef PREFIX_SPACE +#undef PREFIX_TAB +#undef POSTFIX_SPACE +#undef POSTFIX_TAB + +// #undef with underscored variable name +#undef SOME_UNDERSCORED + +// #undef with extra tokens after variable name (ignored) +#undef SOME_ONE extra ignored tokens + +// non-#undef # lines pass through unchanged +#define KEPT_DEFINE value +#include <kept.h> diff --git a/test/standalone/config_header/blank/config.h b/test/standalone/config_header/blank/config.h @@ -0,0 +1,13 @@ +/* This file was generated by ConfigHeader using the Zig Build System. */ +#ifndef CONFIG_H +#define CONFIG_H +/* #undef UNDEFINED */ +#define DEFINED +#define TRUE 1 +#define FALSE 0 +#define ZERO 0 +#define ONE 1 +#define TEN 10 +#define IDENT identifier +#define STRING "test" +#endif /* CONFIG_H */ diff --git a/test/standalone/config_header/build.zig b/test/standalone/config_header/build.zig @@ -1,8 +1,11 @@ const std = @import("std"); pub fn build(b: *std.Build) void { + const test_step = b.step("test", "Test it"); + b.default_step = test_step; + const config_header = b.addConfigHeader( - .{ .style = .{ .autoconf_undef = b.path("config.h.in") } }, + .{ .style = .{ .autoconf_undef = b.path("autoconf_undef/config.h.in") } }, .{ .SOME_NO = null, .SOME_TRUE = true, @@ -13,16 +16,164 @@ pub fn build(b: *std.Build) void { .SOME_ENUM = @as(enum { foo, bar }, .foo), .SOME_ENUM_LITERAL = .@"test", .SOME_STRING = "test", - .PREFIX_SPACE = null, .PREFIX_TAB = null, .POSTFIX_SPACE = null, .POSTFIX_TAB = null, + .SOME_UNDERSCORED = true, }, ); + const check_config_header = b.addCheckFile(config_header.getOutputFile(), .{ + .expected_exact = @embedFile("autoconf_undef/config.h"), + }); + test_step.dependOn(&check_config_header.step); - const check_config_header = b.addCheckFile(config_header.getOutputFile(), .{ .expected_exact = @embedFile("config.h") }); + const config_header_autoconf_at = b.addConfigHeader( + .{ .style = .{ .autoconf_at = b.path("autoconf_at/autoconf_at.h.in") } }, + .{ + .undefined = null, + .defined = {}, + .boolean_true = true, + .boolean_false = false, + .integer = 42, + .string = "text", + .string_at = "@string@", + .underscored_var = "value", + .at_sign = "@", + }, + ); + const check_config_header_autoconf_at = b.addCheckFile(config_header_autoconf_at.getOutputFile(), .{ + .expected_exact = @embedFile("autoconf_at/autoconf_at.h"), + }); + test_step.dependOn(&check_config_header_autoconf_at.step); - const test_step = b.step("test", "Test it"); + const config_header_blank = b.addConfigHeader( + .{ + .style = .blank, + .include_path = "config.h", + }, + .{ + .UNDEFINED = null, + .DEFINED = {}, + .TRUE = true, + .FALSE = false, + .ZERO = 0, + .ONE = 1, + .TEN = 10, + .IDENT = @as(enum { identifier }, .identifier), + .STRING = "test", + }, + ); + const check_config_header_blank = b.addCheckFile(config_header_blank.getOutputFile(), .{ + .expected_exact = @embedFile("blank/config.h"), + }); + test_step.dependOn(&check_config_header_blank.step); + + const config_header_nasm = b.addConfigHeader( + .{ + .style = .nasm, + .include_path = "config.asm", + }, + .{ + .UNDEFINED = null, + .DEFINED = {}, + .TRUE = true, + .FALSE = false, + .ZERO = 0, + .ONE = 1, + .TEN = 10, + .IDENT = @as(enum { identifier }, .identifier), + .STRING = "test", + }, + ); + const check_config_header_nasm = b.addCheckFile(config_header_nasm.getOutputFile(), .{ + .expected_exact = @embedFile("nasm/config.asm"), + }); + test_step.dependOn(&check_config_header_nasm.step); + + addCmakeChecks(b, test_step); +} + +fn addCmakeChecks(b: *std.Build, test_step: *std.Build.Step) void { + const config_header = b.addConfigHeader( + .{ .style = .{ .cmake = b.path("cmake/config.h.in") } }, + .{ + .NOVAL = null, + .TRUEVAL = true, + .FALSEVAL = false, + .ZEROVAL = 0, + .ONEVAL = 1, + .TENVAL = 10, + .STRINGVAL = "test", + .BOOLNOVAL = {}, + .BOOLTRUEVAL = true, + .BOOLFALSEVAL = false, + .BOOLZEROVAL = 0, + .BOOLONEVAL = 1, + .BOOLTENVAL = 10, + .BOOLSTRINGVAL = "test", + }, + ); + const check_config_header = b.addCheckFile(config_header.getOutputFile(), .{ + .expected_exact = @embedFile("cmake/config.h"), + }); test_step.dependOn(&check_config_header.step); + + const pwd_sh = b.addConfigHeader( + .{ .style = .{ .cmake = b.path("cmake/pwd.sh.in") } }, + .{ .DIR = "${PWD}" }, + ); + const check_pwd_sh = b.addCheckFile(pwd_sh.getOutputFile(), .{ + .expected_exact = @embedFile("cmake/pwd.sh"), + }); + test_step.dependOn(&check_pwd_sh.step); + + const config_header_edge_cases = b.addConfigHeader( + .{ .style = .{ .cmake = b.path("cmake/edge_cases.h.in") } }, + .{ + .DOLLAR = "$", + .UNDERSCORE = "_", + .STRING = "text", + .STRING_PROXY = "STRING", + .STRING_AT = "@STRING@", + .STRING_CURLY = "{STRING}", + .STRING_VAR = "${STRING}", + .NEST_UNDERSCORE_PROXY = "UNDERSCORE", + .NEST_PROXY = "NEST_UNDERSCORE_PROXY", + }, + ); + const check_config_header_edge_cases = b.addCheckFile(config_header_edge_cases.getOutputFile(), .{ + .expected_exact = @embedFile("cmake/edge_cases.h"), + }); + test_step.dependOn(&check_config_header_edge_cases.step); + + const config_header_cmakedefine_edge_cases = b.addConfigHeader( + .{ + .style = .{ .cmake = b.path("cmake/cmakedefine_edge_cases.h.in") }, + .include_path = "cmakedefine_edge_cases_renamed.h", + }, + .{ + .MULTI_WORD = true, + .MULTI_WORD_FALSE = false, + .NO_VALUE = true, + .NO_VALUE_FALSE = false, + .WITH_UNDERSCORE_TRUE = true, + .WITH_UNDERSCORE_FALSE = false, + ._LEADING = true, + .TRAILING_ = true, + ._UNDER_01 = true, + .UNDER_01_ = true, + .SUBST_VAL = true, + .SUBST_VAL_FALSE = false, + .STRING = "text", + .VAR_NAME = "ACTUAL_VAR", + .ACTUAL_VAR = true, + .AT_SIGN = "@", + .DOLLAR_SIGN = "$", + }, + ); + const check_config_header_cmakedefine_edge_cases = b.addCheckFile(config_header_cmakedefine_edge_cases.getOutputFile(), .{ + .expected_exact = @embedFile("cmake/cmakedefine_edge_cases.h"), + }); + test_step.dependOn(&check_config_header_cmakedefine_edge_cases.step); } diff --git a/test/standalone/config_header/cmake/cmakedefine_edge_cases.h b/test/standalone/config_header/cmake/cmakedefine_edge_cases.h @@ -0,0 +1,42 @@ +/* This file was generated by ConfigHeader using the Zig Build System. */ +// cmakedefine with multi-word string value (truthy) +#define MULTI_WORD "hello world" + +// cmakedefine with multi-word string value (falsy) +/* #undef MULTI_WORD_FALSE */ + +// cmakedefine with no replacement value (truthy) +#define NO_VALUE + +// cmakedefine with no replacement value (falsy) +/* #undef NO_VALUE_FALSE */ + +// cmakedefine01 with underscored variable names (truthy) +#define WITH_UNDERSCORE_TRUE 1 + +// cmakedefine01 with underscored variable names (falsy) +#define WITH_UNDERSCORE_FALSE 0 + +// cmakedefine with leading/trailing underscores (truthy) +#define _LEADING 1 +#define TRAILING_ 1 + +// cmakedefine01 with leading/trailing underscores (truthy) +#define _UNDER_01 1 +#define UNDER_01_ 1 + +// cmakedefine with @ substitution in the replacement value (truthy) +#define SUBST_VAL text + +// cmakedefine with @ substitution in the replacement value (falsy) +/* #undef SUBST_VAL_FALSE */ + +// cmakedefine with @ substitution as the variable name +#define ACTUAL_VAR custom_val + +// cmakedefine with dollar-curly substitution as the variable name +#define ACTUAL_VAR custom_val + +// @ and $ as literal config values +@ +$ diff --git a/test/standalone/config_header/cmake/cmakedefine_edge_cases.h.in b/test/standalone/config_header/cmake/cmakedefine_edge_cases.h.in @@ -0,0 +1,41 @@ +// cmakedefine with multi-word string value (truthy) +#cmakedefine MULTI_WORD "hello world" + +// cmakedefine with multi-word string value (falsy) +#cmakedefine MULTI_WORD_FALSE "hello world" + +// cmakedefine with no replacement value (truthy) +#cmakedefine NO_VALUE + +// cmakedefine with no replacement value (falsy) +#cmakedefine NO_VALUE_FALSE + +// cmakedefine01 with underscored variable names (truthy) +#cmakedefine01 WITH_UNDERSCORE_TRUE + +// cmakedefine01 with underscored variable names (falsy) +#cmakedefine01 WITH_UNDERSCORE_FALSE + +// cmakedefine with leading/trailing underscores (truthy) +#cmakedefine _LEADING 1 +#cmakedefine TRAILING_ 1 + +// cmakedefine01 with leading/trailing underscores (truthy) +#cmakedefine01 _UNDER_01 +#cmakedefine01 UNDER_01_ + +// cmakedefine with @ substitution in the replacement value (truthy) +#cmakedefine SUBST_VAL @STRING@ + +// cmakedefine with @ substitution in the replacement value (falsy) +#cmakedefine SUBST_VAL_FALSE @STRING@ + +// cmakedefine with @ substitution as the variable name +#cmakedefine @VAR_NAME@ custom_val + +// cmakedefine with dollar-curly substitution as the variable name +#cmakedefine ${VAR_NAME} custom_val + +// @ and $ as literal config values +@AT_SIGN@ +${DOLLAR_SIGN} diff --git a/test/standalone/config_header/cmake/config.h b/test/standalone/config_header/cmake/config.h @@ -0,0 +1,144 @@ +/* This file was generated by ConfigHeader using the Zig Build System. */ +// cmakedefine — value is null (undefined) → /* #undef */ +/* #undef NOVAL */ + +// cmakedefine — value is true → #define ... 1 +#define TRUEVAL 1 + +// cmakedefine — value is false → /* #undef */ +/* #undef FALSEVAL */ + +// cmakedefine — value is 0 (falsy) → /* #undef */ +/* #undef ZEROVAL */ + +// cmakedefine — value is 1 (truthy) → #define ... 1 +#define ONEVAL 1 + +// cmakedefine — value is 10 (truthy) → #define ... 1 +#define TENVAL 1 + +// cmakedefine — value is non-empty string (truthy) → #define ... 1 +#define STRINGVAL 1 + +// cmakedefine — leading whitespace preserved in output + #define STRINGVAL 1 + #define STRINGVAL 1 + + +// cmakedefine01 — value is {} (defined, no value) → 0 +#define BOOLNOVAL 0 + +// cmakedefine01 — value is true → 1 +#define BOOLTRUEVAL 1 + +// cmakedefine01 — value is false → 0 +#define BOOLFALSEVAL 0 + +// cmakedefine01 — value is 0 (falsy) → 0 +#define BOOLZEROVAL 0 + +// cmakedefine01 — value is 1 (truthy) → 1 +#define BOOLONEVAL 1 + +// cmakedefine01 — value is 10 (truthy) → 1 +#define BOOLTENVAL 1 + +// cmakedefine01 — value is non-empty string (truthy) → 1 +#define BOOLSTRINGVAL 1 + + +// @-substitution — value is null → empty string +// + +// @-substitution — null values produce nothing even when packed +// + +// @-substitution — null values produce nothing even when separated +// . + +// @-substitution — value is true → "1" +// 1 + +// @-substitution — value is false → "0" +// 0 + +// @-substitution — true + false packed → "10" +// 10 + +// @-substitution — false + true separated → "0.1" +// 0.1 + +// @-substitution — value is 0 → "0" +// 0 + +// @-substitution — value is 1 → "1" +// 1 + +// @-substitution — value is 10 → "10" +// 10 + +// @-substitution — 0 + 1 packed → "01" +// 01 + +// @-substitution — 0 + 10 separated → "0.10" +// 0.10 + +// @-substitution — value is string "test" → "test" +// test + +// @-substitution — strings packed → "testtest" +// testtest + +// @-substitution — strings separated → "test.test" +// test.test + +// @-substitution — mixed null/string/true/zero → "test10" +// test10 + +// dollar-curly substitution — value is null → empty string +// + +// dollar-curly substitution — null values produce nothing even when packed +// + +// dollar-curly substitution — null values produce nothing even when separated +// . + +// dollar-curly substitution — value is true → "1" +// 1 + +// dollar-curly substitution — value is false → "0" +// 0 + +// dollar-curly substitution — true + false packed → "10" +// 10 + +// dollar-curly substitution — false + true separated → "0.1" +// 0.1 + +// dollar-curly substitution — value is 0 → "0" +// 0 + +// dollar-curly substitution — value is 1 → "1" +// 1 + +// dollar-curly substitution — value is 10 → "10" +// 10 + +// dollar-curly substitution — 0 + 1 packed → "01" +// 01 + +// dollar-curly substitution — 0 + 10 separated → "0.10" +// 0.10 + +// dollar-curly substitution — value is string "test" → "test" +// test + +// dollar-curly substitution — strings packed → "testtest" +// testtest + +// dollar-curly substitution — strings separated → "test.test" +// test.test + +// dollar-curly substitution — mixed null/string/true/zero → "test10" +// test10 diff --git a/test/standalone/config_header/cmake/config.h.in b/test/standalone/config_header/cmake/config.h.in @@ -0,0 +1,143 @@ +// cmakedefine — value is null (undefined) → /* #undef */ +#cmakedefine NOVAL unreachable + +// cmakedefine — value is true → #define ... 1 +#cmakedefine TRUEVAL 1 + +// cmakedefine — value is false → /* #undef */ +#cmakedefine FALSEVAL unreachable + +// cmakedefine — value is 0 (falsy) → /* #undef */ +#cmakedefine ZEROVAL unreachable + +// cmakedefine — value is 1 (truthy) → #define ... 1 +#cmakedefine ONEVAL 1 + +// cmakedefine — value is 10 (truthy) → #define ... 1 +#cmakedefine TENVAL 1 + +// cmakedefine — value is non-empty string (truthy) → #define ... 1 +#cmakedefine STRINGVAL 1 + +// cmakedefine — leading whitespace preserved in output + #cmakedefine STRINGVAL 1 + #cmakedefine STRINGVAL 1 + + +// cmakedefine01 — value is {} (defined, no value) → 0 +#cmakedefine01 BOOLNOVAL + +// cmakedefine01 — value is true → 1 +#cmakedefine01 BOOLTRUEVAL + +// cmakedefine01 — value is false → 0 +#cmakedefine01 BOOLFALSEVAL + +// cmakedefine01 — value is 0 (falsy) → 0 +#cmakedefine01 BOOLZEROVAL + +// cmakedefine01 — value is 1 (truthy) → 1 +#cmakedefine01 BOOLONEVAL + +// cmakedefine01 — value is 10 (truthy) → 1 +#cmakedefine01 BOOLTENVAL + +// cmakedefine01 — value is non-empty string (truthy) → 1 +#cmakedefine01 BOOLSTRINGVAL + + +// @-substitution — value is null → empty string +// @NOVAL@ + +// @-substitution — null values produce nothing even when packed +// @NOVAL@@NOVAL@ + +// @-substitution — null values produce nothing even when separated +// @NOVAL@.@NOVAL@ + +// @-substitution — value is true → "1" +// @TRUEVAL@ + +// @-substitution — value is false → "0" +// @FALSEVAL@ + +// @-substitution — true + false packed → "10" +// @TRUEVAL@@FALSEVAL@ + +// @-substitution — false + true separated → "0.1" +// @FALSEVAL@.@TRUEVAL@ + +// @-substitution — value is 0 → "0" +// @ZEROVAL@ + +// @-substitution — value is 1 → "1" +// @ONEVAL@ + +// @-substitution — value is 10 → "10" +// @TENVAL@ + +// @-substitution — 0 + 1 packed → "01" +// @ZEROVAL@@ONEVAL@ + +// @-substitution — 0 + 10 separated → "0.10" +// @ZEROVAL@.@TENVAL@ + +// @-substitution — value is string "test" → "test" +// @STRINGVAL@ + +// @-substitution — strings packed → "testtest" +// @STRINGVAL@@STRINGVAL@ + +// @-substitution — strings separated → "test.test" +// @STRINGVAL@.@STRINGVAL@ + +// @-substitution — mixed null/string/true/zero → "test10" +// @NOVAL@@STRINGVAL@@TRUEVAL@@ZEROVAL@ + +// dollar-curly substitution — value is null → empty string +// ${NOVAL} + +// dollar-curly substitution — null values produce nothing even when packed +// ${NOVAL}${NOVAL} + +// dollar-curly substitution — null values produce nothing even when separated +// ${NOVAL}.${NOVAL} + +// dollar-curly substitution — value is true → "1" +// ${TRUEVAL} + +// dollar-curly substitution — value is false → "0" +// ${FALSEVAL} + +// dollar-curly substitution — true + false packed → "10" +// ${TRUEVAL}${FALSEVAL} + +// dollar-curly substitution — false + true separated → "0.1" +// ${FALSEVAL}.${TRUEVAL} + +// dollar-curly substitution — value is 0 → "0" +// ${ZEROVAL} + +// dollar-curly substitution — value is 1 → "1" +// ${ONEVAL} + +// dollar-curly substitution — value is 10 → "10" +// ${TENVAL} + +// dollar-curly substitution — 0 + 1 packed → "01" +// ${ZEROVAL}${ONEVAL} + +// dollar-curly substitution — 0 + 10 separated → "0.10" +// ${ZEROVAL}.${TENVAL} + +// dollar-curly substitution — value is string "test" → "test" +// ${STRINGVAL} + +// dollar-curly substitution — strings packed → "testtest" +// ${STRINGVAL}${STRINGVAL} + +// dollar-curly substitution — strings separated → "test.test" +// ${STRINGVAL}.${STRINGVAL} + +// dollar-curly substitution — mixed null/string/true/zero → "test10" +// ${NOVAL}${STRINGVAL}${TRUEVAL}${ZEROVAL} diff --git a/test/standalone/config_header/cmake/edge_cases.h b/test/standalone/config_header/cmake/edge_cases.h @@ -0,0 +1,43 @@ +/* This file was generated by ConfigHeader using the Zig Build System. */ +// empty lines are preserved + +// double-wrapped at-sigils work like single-wrapped +@text@ +@text@ + +// at-var lookup happens inside dollar-curly before dollar-curly lookup +text + +// expanded variables are treated as strings and can be re-substituted +@STRING@ +@STRING@ +${STRING} +${STRING} +${STRING} +${STRING} +${text} +${text} +${text} + +// nested dollar-curly expansion from the inside out +STRING +STRING + +// nested dollar-curly — only completed brace blocks are expanded +NEST_UNDERSCORE_PROXY +NEST_UNDERSCORE_PROXY + +// backslash is invalid in at-var names — preserved as literal +\@STRING\@ + +// backslash does not affect dollar-curly expansion +\text + +// backslash before opening brace breaks dollar-curly identification +$\{STRING} + +// bare at-sigils pass through unchanged with no variable map +#define AT @ +#define ATAT @@ +#define ATATAT @@@ +#define ATATATAT @@@@ diff --git a/test/standalone/config_header/cmake/edge_cases.h.in b/test/standalone/config_header/cmake/edge_cases.h.in @@ -0,0 +1,42 @@ +// empty lines are preserved + +// double-wrapped at-sigils work like single-wrapped +@@STRING@@ +@${STRING}@ + +// at-var lookup happens inside dollar-curly before dollar-curly lookup +${@STRING_PROXY@} + +// expanded variables are treated as strings and can be re-substituted +@STRING_AT@ +${STRING_AT} +$@STRING_CURLY@ +$${STRING_CURLY} +${STRING_VAR} +@STRING_VAR@ +${DOLLAR}{${STRING}} +@DOLLAR@{${STRING}} +@DOLLAR@{@STRING@} + +// nested dollar-curly expansion from the inside out +${STRING${UNDERSCORE}PROXY} +${STRING@UNDERSCORE@PROXY} + +// nested dollar-curly — only completed brace blocks are expanded +${NEST${UNDERSCORE}PROXY} +${NEST${${NEST_UNDERSCORE${UNDERSCORE}PROXY}}PROXY} + +// backslash is invalid in at-var names — preserved as literal +\@STRING\@ + +// backslash does not affect dollar-curly expansion +\${STRING} + +// backslash before opening brace breaks dollar-curly identification +$\{STRING} + +// bare at-sigils pass through unchanged with no variable map +#define AT @ +#define ATAT @@ +#define ATATAT @@@ +#define ATATATAT @@@@ diff --git a/test/standalone/config_header/cmake/pwd.sh b/test/standalone/config_header/cmake/pwd.sh @@ -0,0 +1,2 @@ +/* This file was generated by ConfigHeader using the Zig Build System. */ +echo ${PWD} diff --git a/test/standalone/cmakedefine/pwd.sh.in b/test/standalone/config_header/cmake/pwd.sh.in diff --git a/test/standalone/config_header/config.h b/test/standalone/config_header/config.h @@ -1,23 +0,0 @@ -/* This file was generated by ConfigHeader using the Zig Build System. */ -/* Some Comment */ - -int foo(); - -/* #undef SOME_NO */ -#define SOME_TRUE 1 -#define SOME_FALSE 0 -#define SOME_ZERO 0 -#define SOME_ONE 1 -#define SOME_TEN 10 -#define SOME_ENUM foo -#define SOME_ENUM_LITERAL test -#define SOME_STRING "test" - -// Used twice -#define SOME_TRUE 1 - -/* #undef PREFIX_SPACE */ -/* #undef PREFIX_TAB */ -/* #undef POSTFIX_SPACE */ -/* #undef POSTFIX_TAB */ - diff --git a/test/standalone/config_header/config.h.in b/test/standalone/config_header/config.h.in @@ -1,21 +0,0 @@ -/* Some Comment */ - -int foo(); - -#undef SOME_NO -#undef SOME_TRUE -#undef SOME_FALSE -#undef SOME_ZERO -#undef SOME_ONE -#undef SOME_TEN -#undef SOME_ENUM -#undef SOME_ENUM_LITERAL -#undef SOME_STRING - -// Used twice -#undef SOME_TRUE - -#undef PREFIX_SPACE -#undef PREFIX_TAB -#undef POSTFIX_SPACE -#undef POSTFIX_TAB diff --git a/test/standalone/config_header/nasm/config.asm b/test/standalone/config_header/nasm/config.asm @@ -0,0 +1,10 @@ +; This file was generated by ConfigHeader using the Zig Build System. +; %undef UNDEFINED +%define DEFINED +%define TRUE 1 +%define FALSE 0 +%define ZERO 0 +%define ONE 1 +%define TEN 10 +%define IDENT identifier +%define STRING "test"