authorgravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2026-06-27 22:19:19+02:00
committergravatar for squeek502@hotmail.comRyan Liptak <squeek502@hotmail.com> 2026-06-27 22:19:19+02:00
logefd6ded716a027f7d47fe5c38df17785c8e2a2e2
tree0720112c36d14b27d2789bd39cabd3ab591c6110
parent9b5851f0019c6cf2b5a54ffa54acd7f13b941a07
parent1467054baeaa05668129ef491be6ac1b3b82d80d

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>

31 files changed, 888 insertions(+), 594 deletions(-)

lib/compiler/Maker/Step/ConfigHeader.zig+64-43
...@@ -11,8 +11,10 @@ const Step = @import("../Step.zig");...@@ -11,8 +11,10 @@ const Step = @import("../Step.zig");
11const Maker = @import("../../Maker.zig");11const Maker = @import("../../Maker.zig");
1212
13const header_text = "This file was generated by ConfigHeader using the Zig Build System.";13const header_text = "This file was generated by ConfigHeader using the Zig Build System.";
14const c_generated_line = "/* " ++ header_text ++ " */\n";14const c_generated_line = "/* " ++ header_text ++ " */";
15const asm_generated_line = "; " ++ header_text ++ "\n";15const asm_generated_line = "; " ++ header_text;
16
17const os_newline = if (@import("builtin").os.tag == .windows) "\r\n" else "\n";
1618
17/// Table value is whether the value is used.19/// Table value is whether the value is used.
18const ValueMap = std.array_hash_map.String(bool);20const ValueMap = std.array_hash_map.String(bool);
...@@ -160,6 +162,11 @@ fn ensureAllValuesUsed(...@@ -160,6 +162,11 @@ fn ensureAllValuesUsed(
160 if (any_errors) return error.MakeFailed;162 if (any_errors) return error.MakeFailed;
161}163}
162164
165fn detectNewline(contents: []const u8) []const u8 {
166 const lf_index = std.mem.findScalar(u8, contents, '\n') orelse return os_newline;
167 return if (lf_index > 0 and contents[lf_index - 1] == '\r') "\r\n" else "\n";
168}
169
163fn renderAutoConfUndef(170fn renderAutoConfUndef(
164 maker: *Maker,171 maker: *Maker,
165 step: *Step,172 step: *Step,
...@@ -170,23 +177,28 @@ fn renderAutoConfUndef(...@@ -170,23 +177,28 @@ fn renderAutoConfUndef(
170 src_path: Path,177 src_path: Path,
171) !void {178) !void {
172 const conf = &maker.scanned_config.configuration;179 const conf = &maker.scanned_config.configuration;
180 const newline = detectNewline(contents);
173181
174 try w.writeAll(c_generated_line);182 try w.writeAll(c_generated_line);
183 try w.writeAll(newline);
175184
176 var any_errors = false;185 var any_errors = false;
177 var line_index: u32 = 0;186 var line_index: u32 = 0;
178 var line_it = std.mem.splitScalar(u8, contents, '\n');187 var line_it = std.mem.splitScalar(u8, contents, '\n');
179 while (line_it.next()) |line| : (line_index += 1) {188 while (line_it.next()) |raw_line| : (line_index += 1) {
189 const last_line = line_it.index == line_it.buffer.len;
190 const line = std.mem.trimEnd(u8, raw_line, "\r");
191
180 if (!std.mem.startsWith(u8, line, "#")) {192 if (!std.mem.startsWith(u8, line, "#")) {
181 try w.writeAll(line);193 try w.writeAll(line);
182 try w.writeByte('\n');194 if (!last_line) try w.writeAll(newline);
183 continue;195 continue;
184 }196 }
185 var it = std.mem.tokenizeAny(u8, line[1..], " \t\r");197 var it = std.mem.tokenizeAny(u8, line[1..], " \t\r");
186 const undef = it.next().?;198 const undef = it.next().?;
187 if (!std.mem.eql(u8, undef, "undef")) {199 if (!std.mem.eql(u8, undef, "undef")) {
188 try w.writeAll(line);200 try w.writeAll(line);
189 try w.writeByte('\n');201 if (!last_line) try w.writeAll(newline);
190 continue;202 continue;
191 }203 }
192 const name = it.next().?;204 const name = it.next().?;
...@@ -198,7 +210,7 @@ fn renderAutoConfUndef(...@@ -198,7 +210,7 @@ fn renderAutoConfUndef(
198 continue;210 continue;
199 };211 };
200 value_map.values()[index] = true; // Set to used.212 value_map.values()[index] = true; // Set to used.
201 try renderValueC(conf, w, name, value_pairs[index].index);213 try renderValueC(conf, w, newline, name, value_pairs[index].index);
202 }214 }
203215
204 try ensureAllValuesUsed(maker, step, value_map, src_path);216 try ensureAllValuesUsed(maker, step, value_map, src_path);
...@@ -216,14 +228,17 @@ fn renderAutoconfAt(...@@ -216,14 +228,17 @@ fn renderAutoconfAt(
216) !void {228) !void {
217 const w = &aw.writer;229 const w = &aw.writer;
218 const conf = &maker.scanned_config.configuration;230 const conf = &maker.scanned_config.configuration;
231 const newline = detectNewline(contents);
219232
220 try w.writeAll(c_generated_line);233 try w.writeAll(c_generated_line);
234 try w.writeAll(newline);
221235
222 var any_errors = false;236 var any_errors = false;
223 var line_index: u32 = 0;237 var line_index: u32 = 0;
224 var line_it = std.mem.splitScalar(u8, contents, '\n');238 var line_it = std.mem.splitScalar(u8, contents, '\n');
225 while (line_it.next()) |line| : (line_index += 1) {239 while (line_it.next()) |raw_line| : (line_index += 1) {
226 const last_line = line_it.index == line_it.buffer.len;240 const last_line = line_it.index == line_it.buffer.len;
241 const line = std.mem.trimEnd(u8, raw_line, "\r");
227242
228 const old_len = aw.written().len;243 const old_len = aw.written().len;
229 expandVariablesAutoconfAt(w, line, conf, value_pairs, value_map) catch |err| switch (err) {244 expandVariablesAutoconfAt(w, line, conf, value_pairs, value_map) catch |err| switch (err) {
...@@ -244,7 +259,7 @@ fn renderAutoconfAt(...@@ -244,7 +259,7 @@ fn renderAutoconfAt(
244 continue;259 continue;
245 },260 },
246 };261 };
247 if (!last_line) try w.writeByte('\n');262 if (!last_line) try w.writeAll(newline);
248 }263 }
249264
250 try ensureAllValuesUsed(maker, step, value_map, src_path);265 try ensureAllValuesUsed(maker, step, value_map, src_path);
...@@ -262,16 +277,19 @@ fn renderCmake(...@@ -262,16 +277,19 @@ fn renderCmake(
262 src_path: Path,277 src_path: Path,
263) !void {278) !void {
264 const conf = &maker.scanned_config.configuration;279 const conf = &maker.scanned_config.configuration;
280 const newline = detectNewline(contents);
265281
266 try w.writeAll(c_generated_line);282 try w.writeAll(c_generated_line);
283 try w.writeAll(newline);
267284
268 var any_errors = false;285 var any_errors = false;
269 var line_index: u32 = 0;286 var line_index: u32 = 0;
270 var line_it = std.mem.splitScalar(u8, contents, '\n');287 var line_it = std.mem.splitScalar(u8, contents, '\n');
271 while (line_it.next()) |raw_line| : (line_index += 1) {288 while (line_it.next()) |raw_line| : (line_index += 1) {
272 const last_line = line_it.index == line_it.buffer.len;289 const last_line = line_it.index == line_it.buffer.len;
290 const stripped_line = std.mem.trimEnd(u8, raw_line, "\r");
273291
274 const line = expandVariablesCmake(arena, raw_line, conf, value_pairs, value_map) catch |err| switch (err) {292 const line = expandVariablesCmake(arena, stripped_line, conf, value_pairs, value_map) catch |err| switch (err) {
275 error.InvalidCharacter => {293 error.InvalidCharacter => {
276 try step.addError(maker, "{f}:{d}: invalid character in a variable name", .{294 try step.addError(maker, "{f}:{d}: invalid character in a variable name", .{
277 src_path, line_index + 1,295 src_path, line_index + 1,
...@@ -290,7 +308,7 @@ fn renderCmake(...@@ -290,7 +308,7 @@ fn renderCmake(
290308
291 const line_start = std.mem.findNone(u8, line, " \t\r") orelse {309 const line_start = std.mem.findNone(u8, line, " \t\r") orelse {
292 try w.writeAll(line);310 try w.writeAll(line);
293 if (!last_line) try w.writeByte('\n');311 if (!last_line) try w.writeAll(newline);
294 continue;312 continue;
295 };313 };
296 const whitespace_prefix = line[0..line_start];314 const whitespace_prefix = line[0..line_start];
...@@ -298,7 +316,7 @@ fn renderCmake(...@@ -298,7 +316,7 @@ fn renderCmake(
298316
299 if (!std.mem.startsWith(u8, trimmed_line, "#")) {317 if (!std.mem.startsWith(u8, trimmed_line, "#")) {
300 try w.writeAll(line);318 try w.writeAll(line);
301 if (!last_line) try w.writeByte('\n');319 if (!last_line) try w.writeAll(newline);
302 continue;320 continue;
303 }321 }
304322
...@@ -311,7 +329,7 @@ fn renderCmake(...@@ -311,7 +329,7 @@ fn renderCmake(
311 false329 false
312 else {330 else {
313 try w.writeAll(line);331 try w.writeAll(line);
314 if (!last_line) try w.writeByte('\n');332 if (!last_line) try w.writeAll(newline);
315 continue;333 continue;
316 };334 };
317335
...@@ -335,7 +353,7 @@ fn renderCmake(...@@ -335,7 +353,7 @@ fn renderCmake(
335 try w.writeAll(whitespace_prefix);353 try w.writeAll(whitespace_prefix);
336354
337 if (booldefine) {355 if (booldefine) {
338 try renderValueCBool(w, name, switch (value.unpack(conf)) {356 try renderValueCBool(w, newline, name, switch (value.unpack(conf)) {
339 .undef, .defined => false,357 .undef, .defined => false,
340 .bool => |b| b,358 .bool => |b| b,
341 inline .u64, .i64 => |i| i != 0,359 inline .u64, .i64 => |i| i != 0,
...@@ -343,9 +361,9 @@ fn renderCmake(...@@ -343,9 +361,9 @@ fn renderCmake(
343 .ident => false,361 .ident => false,
344 });362 });
345 } else if (value != .undef) {363 } else if (value != .undef) {
346 try renderValueCIdent(w, name, it.rest());364 try renderValueCIdent(w, newline, name, it.rest());
347 } else {365 } else {
348 try renderValueC(conf, w, name, value);366 try renderValueC(conf, w, newline, name, value);
349 }367 }
350 }368 }
351369
...@@ -362,6 +380,7 @@ fn renderBlank(...@@ -362,6 +380,7 @@ fn renderBlank(
362 include_guard_override: ?[]const u8,380 include_guard_override: ?[]const u8,
363) !void {381) !void {
364 try w.writeAll(c_generated_line);382 try w.writeAll(c_generated_line);
383 try w.writeAll(os_newline);
365384
366 const include_guard_fmt: IncludeGuardFmt = .{385 const include_guard_fmt: IncludeGuardFmt = .{
367 .include_path = include_path,386 .include_path = include_path,
...@@ -369,17 +388,13 @@ fn renderBlank(...@@ -369,17 +388,13 @@ fn renderBlank(
369 };388 };
370389
371 try w.print(390 try w.print(
372 \\#ifndef {[0]f}391 "#ifndef {[0]f}{[1]s}#define {[0]f}{[1]s}",
373 \\#define {[0]f}392 .{ include_guard_fmt, os_newline },
374 \\393 );
375 , .{include_guard_fmt});
376394
377 for (value_map.keys(), value_pairs) |name, pair| try renderValueC(conf, w, name, pair.index);395 for (value_map.keys(), value_pairs) |name, pair| try renderValueC(conf, w, os_newline, name, pair.index);
378396
379 try w.print(397 try w.print("#endif /* {f} */{s}", .{ include_guard_fmt, os_newline });
380 \\#endif /* {f} */
381 \\
382 , .{include_guard_fmt});
383}398}
384399
385const IncludeGuardFmt = struct {400const IncludeGuardFmt = struct {
...@@ -403,36 +418,42 @@ fn renderNasm(...@@ -403,36 +418,42 @@ fn renderNasm(
403 value_map: *const ValueMap,418 value_map: *const ValueMap,
404) !void {419) !void {
405 try w.writeAll(asm_generated_line);420 try w.writeAll(asm_generated_line);
406 for (value_map.keys(), value_pairs) |name, pair| try renderValueNasm(conf, w, name, pair.index);421 try w.writeAll(os_newline);
422 for (value_map.keys(), value_pairs) |name, pair| try renderValueNasm(conf, w, os_newline, name, pair.index);
407}423}
408424
409fn renderValueC(conf: *const Configuration, w: *Writer, name: []const u8, value: Value.Index) !void {425fn renderValueC(conf: *const Configuration, w: *Writer, newline: []const u8, name: []const u8, value: Value.Index) !void {
410 switch (value.unpack(conf)) {426 switch (value.unpack(conf)) {
411 .undef => try w.print("/* #undef {s} */\n", .{name}),427 .undef => try w.print("/* #undef {s} */{s}", .{ name, newline }),
412 .defined => try w.print("#define {s}\n", .{name}),428 .defined => try w.print("#define {s}{s}", .{ name, newline }),
413 .bool => |b| return renderValueCBool(w, name, b),429 .bool => |b| return renderValueCBool(w, newline, name, b),
414 inline .u64, .i64 => |i| try w.print("#define {s} {d}\n", .{ name, i }),430 inline .u64, .i64 => |i| try w.print("#define {s} {d}{s}", .{ name, i, newline }),
415 .ident => |ident| return renderValueCIdent(w, name, ident),431 .ident => |ident| return renderValueCIdent(w, newline, name, ident),
416 .string => |string| try w.print("#define {s} \"{f}\"\n", .{ name, std.zig.fmtString(string) }),432 .string => |string| try w.print("#define {s} \"{f}\"{s}", .{ name, std.zig.fmtString(string), newline }),
417 }433 }
418}434}
419435
420fn renderValueCIdent(w: *Writer, name: []const u8, ident: []const u8) Writer.Error!void {436fn renderValueCIdent(w: *Writer, newline: []const u8, name: []const u8, ident: []const u8) Writer.Error!void {
421 return w.print("#define {s} {s}\n", .{ name, ident });437 try w.print("#define {s}", .{name});
438 if (ident.len > 0) {
439 try w.writeByte(' ');
440 try w.writeAll(ident);
441 }
442 return w.writeAll(newline);
422}443}
423444
424fn renderValueCBool(w: *Writer, name: []const u8, b: bool) Writer.Error!void {445fn renderValueCBool(w: *Writer, newline: []const u8, name: []const u8, b: bool) Writer.Error!void {
425 return w.print("#define {s} {c}\n", .{ name, @as(u8, '0') + @intFromBool(b) });446 return w.print("#define {s} {c}{s}", .{ name, @as(u8, '0') + @intFromBool(b), newline });
426}447}
427448
428fn renderValueNasm(conf: *const Configuration, w: *Writer, name: []const u8, value: Value.Index) !void {449fn renderValueNasm(conf: *const Configuration, w: *Writer, newline: []const u8, name: []const u8, value: Value.Index) !void {
429 switch (value.unpack(conf)) {450 switch (value.unpack(conf)) {
430 .undef => try w.print("; %undef {s}\n", .{name}),451 .undef => try w.print("; %undef {s}{s}", .{ name, newline }),
431 .defined => try w.print("%define {s}\n", .{name}),452 .defined => try w.print("%define {s}{s}", .{ name, newline }),
432 .bool => |b| try w.print("%define {s} {c}\n", .{ name, @as(u8, '0') + @intFromBool(b) }),453 .bool => |b| try w.print("%define {s} {c}{s}", .{ name, @as(u8, '0') + @intFromBool(b), newline }),
433 inline .u64, .i64 => |i| try w.print("%define {s} {d}\n", .{ name, i }),454 inline .u64, .i64 => |i| try w.print("%define {s} {d}{s}", .{ name, i, newline }),
434 .ident => |ident| try w.print("%define {s} {s}\n", .{ name, ident }),455 .ident => |ident| try w.print("%define {s} {s}{s}", .{ name, ident, newline }),
435 .string => |string| try w.print("%define {s} \"{f}\"\n", .{ name, std.zig.fmtString(string) }),456 .string => |string| try w.print("%define {s} \"{f}\"{s}", .{ name, std.zig.fmtString(string), newline }),
436 }457 }
437}458}
438459
test/standalone/build.zig.zon-3
...@@ -141,9 +141,6 @@...@@ -141,9 +141,6 @@
141 .strip_struct_init = .{141 .strip_struct_init = .{
142 .path = "strip_struct_init",142 .path = "strip_struct_init",
143 },143 },
144 .cmakedefine = .{
145 .path = "cmakedefine",
146 },
147 .zerolength_check = .{144 .zerolength_check = .{
148 .path = "zerolength_check",145 .path = "zerolength_check",
149 },146 },
test/standalone/cmakedefine/build.zig deleted-104
...@@ -1,104 +0,0 @@
1const std = @import("std");
2const ConfigHeader = std.Build.Step.ConfigHeader;
3
4pub fn build(b: *std.Build) void {
5 const config_header = b.addConfigHeader(
6 .{
7 .style = .{ .cmake = b.path("config.h.in") },
8 .include_path = "config.h",
9 },
10 .{
11 .noval = null,
12 .trueval = true,
13 .falseval = false,
14 .zeroval = 0,
15 .oneval = 1,
16 .tenval = 10,
17 .stringval = "test",
18
19 .boolnoval = {},
20 .booltrueval = true,
21 .boolfalseval = false,
22 .boolzeroval = 0,
23 .booloneval = 1,
24 .booltenval = 10,
25 .boolstringval = "test",
26 },
27 );
28
29 const pwd_sh = b.addConfigHeader(
30 .{
31 .style = .{ .cmake = b.path("pwd.sh.in") },
32 .include_path = "pwd.sh",
33 },
34 .{ .DIR = "${PWD}" },
35 );
36
37 const sigil_header = b.addConfigHeader(
38 .{
39 .style = .{ .cmake = b.path("sigil.h.in") },
40 .include_path = "sigil.h",
41 },
42 .{},
43 );
44
45 const stack_header = b.addConfigHeader(
46 .{
47 .style = .{ .cmake = b.path("stack.h.in") },
48 .include_path = "stack.h",
49 },
50 .{
51 .UNDERSCORE = "_",
52 .NEST_UNDERSCORE_PROXY = "UNDERSCORE",
53 .NEST_PROXY = "NEST_UNDERSCORE_PROXY",
54 },
55 );
56
57 const wrapper_header = b.addConfigHeader(
58 .{
59 .style = .{ .cmake = b.path("wrapper.h.in") },
60 .include_path = "wrapper.h",
61 },
62 .{
63 .DOLLAR = "$",
64 .TEXT = "TRAP",
65
66 .STRING = "TEXT",
67 .STRING_AT = "@STRING@",
68 .STRING_CURLY = "{STRING}",
69 .STRING_VAR = "${STRING}",
70 },
71 );
72
73 const check_exe = b.addExecutable(.{
74 .name = "check",
75 .root_module = b.createModule(.{
76 .target = b.graph.host,
77 .root_source_file = b.path("check.zig"),
78 }),
79 });
80
81 const test_step = b.step("test", "Test it");
82 b.default_step = test_step;
83 test_step.dependOn(addCheck(b, check_exe, config_header));
84 test_step.dependOn(addCheck(b, check_exe, pwd_sh));
85 test_step.dependOn(addCheck(b, check_exe, sigil_header));
86 test_step.dependOn(addCheck(b, check_exe, stack_header));
87 test_step.dependOn(addCheck(b, check_exe, wrapper_header));
88}
89
90fn addCheck(
91 b: *std.Build,
92 check_exe: *std.Build.Step.Compile,
93 ch: *ConfigHeader,
94) *std.Build.Step {
95 // We expect `ch.include_path` to only be a basename to infer where the expected output is.
96 std.debug.assert(std.fs.path.dirname(ch.include_path) == null);
97 const expected_path = b.fmt("expected_{s}", .{ch.include_path});
98
99 const run_check = b.addRunArtifact(check_exe);
100 run_check.addFileArg(ch.getOutputFile());
101 run_check.addFileArg(b.path(expected_path));
102
103 return &run_check.step;
104}
test/standalone/cmakedefine/check.zig deleted-26
...@@ -1,26 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3
4pub fn main(init: std.process.Init) !void {
5 const arena = init.arena.allocator();
6 const io = init.io;
7 const args = try init.minimal.args.toSlice(arena);
8
9 if (args.len != 3) return error.BadUsage;
10 const actual_path = args[1];
11 const expected_path = args[2];
12
13 const actual = try std.Io.Dir.cwd().readFileAlloc(io, actual_path, arena, .limited(1024 * 1024));
14 const expected = try std.Io.Dir.cwd().readFileAlloc(io, expected_path, arena, .limited(1024 * 1024));
15
16 // The actual output starts with a comment which we should strip out before comparing.
17 const comment_str = "/* This file was generated by ConfigHeader using the Zig Build System. */\n";
18 if (!std.mem.startsWith(u8, actual, comment_str)) {
19 return error.MissingOrMalformedComment;
20 }
21 const actual_without_comment = actual[comment_str.len..];
22
23 if (builtin.os.tag == .windows) return; // https://codeberg.org/ziglang/zig/issues/30138
24
25 try std.testing.expectEqualStrings(expected, actual_without_comment);
26}
test/standalone/cmakedefine/config.h.in deleted-147
...@@ -1,147 +0,0 @@
1// cmakedefine
2// undefined
3#cmakedefine noval unreachable
4
5// 1
6#cmakedefine trueval 1
7
8// undefined
9#cmakedefine falseval unreachable
10
11// undefined
12#cmakedefine zeroval unreachable
13
14// 1
15#cmakedefine oneval 1
16
17// 1
18#cmakedefine tenval 1
19
20// 1
21#cmakedefine stringval 1
22
23// whitespace test
24 #cmakedefine stringval 1
25 #cmakedefine stringval 1
26
27
28// cmakedefine01
29// 0
30#cmakedefine01 boolnoval
31
32// 1
33#cmakedefine01 booltrueval
34
35// 0
36#cmakedefine01 boolfalseval
37
38// 0
39#cmakedefine01 boolzeroval
40
41// 1
42#cmakedefine01 booloneval
43
44// 1
45#cmakedefine01 booltenval
46
47// 1
48#cmakedefine01 boolstringval
49
50
51// @ substition
52
53// no substition
54// @noval@
55
56// no substition
57// @noval@@noval@
58
59// no substition
60// @noval@.@noval@
61
62// 1
63// @trueval@
64
65// 0
66// @falseval@
67
68// 10
69// @trueval@@falseval@
70
71// 0.1
72// @falseval@.@trueval@
73
74// 0
75// @zeroval@
76
77// 1
78// @oneval@
79
80// 10
81// @tenval@
82
83// 01
84// @zeroval@@oneval@
85
86// 0.10
87// @zeroval@.@tenval@
88
89// test
90// @stringval@
91
92// testtest
93// @stringval@@stringval@
94
95// test.test
96// @stringval@.@stringval@
97
98// test10
99// @noval@@stringval@@trueval@@zeroval@
100
101// no substition
102// ${noval}
103
104// no substition
105// ${noval}${noval}
106
107// no substition
108// ${noval}.${noval}
109
110// 1
111// ${trueval}
112
113// 0
114// ${falseval}
115
116// 10
117// ${trueval}${falseval}
118
119// 0.1
120// ${falseval}.${trueval}
121
122// 0
123// ${zeroval}
124
125// 1
126// ${oneval}
127
128// 10
129// ${tenval}
130
131// 01
132// ${zeroval}${oneval}
133
134// 0.10
135// ${zeroval}.${tenval}
136
137// test
138// ${stringval}
139
140// testtest
141// ${stringval}${stringval}
142
143// test.test
144// ${stringval}.${stringval}
145
146// test10
147// ${noval}${stringval}${trueval}${zeroval}
test/standalone/cmakedefine/expected_config.h deleted-147
...@@ -1,147 +0,0 @@
1// cmakedefine
2// undefined
3/* #undef noval */
4
5// 1
6#define trueval 1
7
8// undefined
9/* #undef falseval */
10
11// undefined
12/* #undef zeroval */
13
14// 1
15#define oneval 1
16
17// 1
18#define tenval 1
19
20// 1
21#define stringval 1
22
23// whitespace test
24 #define stringval 1
25 #define stringval 1
26
27
28// cmakedefine01
29// 0
30#define boolnoval 0
31
32// 1
33#define booltrueval 1
34
35// 0
36#define boolfalseval 0
37
38// 0
39#define boolzeroval 0
40
41// 1
42#define booloneval 1
43
44// 1
45#define booltenval 1
46
47// 1
48#define boolstringval 1
49
50
51// @ substition
52
53// no substition
54//
55
56// no substition
57//
58
59// no substition
60// .
61
62// 1
63// 1
64
65// 0
66// 0
67
68// 10
69// 10
70
71// 0.1
72// 0.1
73
74// 0
75// 0
76
77// 1
78// 1
79
80// 10
81// 10
82
83// 01
84// 01
85
86// 0.10
87// 0.10
88
89// test
90// test
91
92// testtest
93// testtest
94
95// test.test
96// test.test
97
98// test10
99// test10
100
101// no substition
102//
103
104// no substition
105//
106
107// no substition
108// .
109
110// 1
111// 1
112
113// 0
114// 0
115
116// 10
117// 10
118
119// 0.1
120// 0.1
121
122// 0
123// 0
124
125// 1
126// 1
127
128// 10
129// 10
130
131// 01
132// 01
133
134// 0.10
135// 0.10
136
137// test
138// test
139
140// testtest
141// testtest
142
143// test.test
144// test.test
145
146// test10
147// test10
test/standalone/cmakedefine/expected_pwd.sh deleted-1
...@@ -1 +0,0 @@
1echo ${PWD}
test/standalone/cmakedefine/expected_sigil.h deleted-4
...@@ -1,4 +0,0 @@
1#define AT @
2#define ATAT @@
3#define ATATAT @@@
4#define ATATATAT @@@@
test/standalone/cmakedefine/expected_stack.h deleted-3
...@@ -1,3 +0,0 @@
1#define NEST_UNDERSCORE_PROXY NEST_UNDERSCORE_PROXY
2
3#define NEST_UNDERSCORE_PROXY NEST_UNDERSCORE_PROXY
test/standalone/cmakedefine/expected_wrapper.h deleted-30
...@@ -1,30 +0,0 @@
1// becomes TEXT
2#define TEXT
3#define TEXT
4
5// becomes `at`TEXT`at`
6#define @TEXT@
7#define @TEXT@
8
9// becomes TRAP
10#define TRAP
11
12// becomes `dollar sign`{STRING}
13#define ${STRING}
14#define ${STRING}
15
16// becomes `dollar sign`{STRING}
17#define ${STRING}
18#define ${STRING}
19
20// becomes `dollar sign`{TEXT}
21#define ${TEXT}
22#define ${TEXT}
23
24// becomes `at`STRING`at`
25#define @STRING@
26#define @STRING@
27
28#define \@STRING_VAR\@
29#define \${STRING}
30#define $\{STRING_VAR}
test/standalone/cmakedefine/pwd.sh.in deleted-1
...@@ -1 +0,0 @@
1echo @DIR@
test/standalone/cmakedefine/sigil.h.in deleted-4
...@@ -1,4 +0,0 @@
1#define AT @
2#define ATAT @@
3#define ATATAT @@@
4#define ATATATAT @@@@
test/standalone/cmakedefine/stack.h.in deleted-3
...@@ -1,3 +0,0 @@
1#define NEST_UNDERSCORE_PROXY ${NEST${UNDERSCORE}PROXY}
2
3#define NEST_UNDERSCORE_PROXY ${NEST${${NEST_UNDERSCORE${UNDERSCORE}PROXY}}PROXY}
test/standalone/cmakedefine/wrapper.h.in deleted-30
...@@ -1,30 +0,0 @@
1// becomes TEXT
2#define @STRING@
3#define ${STRING}
4
5// becomes `at`TEXT`at`
6#define @${STRING}@
7#define @@STRING@@
8
9// becomes TRAP
10#define ${@STRING@}
11
12// becomes `dollar sign`{STRING}
13#define $@STRING_CURLY@
14#define $${STRING_CURLY}
15
16// becomes `dollar sign`{STRING}
17#define @STRING_VAR@
18#define ${STRING_VAR}
19
20// becomes `dollar sign`{TEXT}
21#define ${DOLLAR}{${STRING}}
22#define @DOLLAR@{${STRING}}
23
24// becomes `at`STRING`at`
25#define ${STRING_AT}
26#define @STRING_AT@
27
28#define \@STRING_VAR\@
29#define \${STRING_VAR}
30#define $\{STRING_VAR}
test/standalone/config_header/autoconf_at/autoconf_at.h created+63
...@@ -0,0 +1,63 @@
1/* This file was generated by ConfigHeader using the Zig Build System. */
2/* Some Comment */
3int foo();
4// empty strings are preserved
5
6// line with misc content is preserved
7#define KEPT_VALUE no substitution
8
9// empty @ sigils are preserved
10#define AT_SIGIL_1 @
11#define AT_SIGIL_2 @@
12#define AT_SIGIL_3 @@@
13#define AT_SIGIL_4 @@@@
14
15// simple substitution
16#define SIMPLE_UNDEFINED
17#define SIMPLE_DEFINED
18#define SIMPLE_BOOL_TRUE 1
19#define SIMPLE_BOOL_FALSE 0
20#define SIMPLE_INTEGER 42
21#define SIMPLE_STRING text
22
23// double packed substitution
24#define DOUBLE_PACKED texttext
25
26// triple packed substitution
27#define TRIPLE_PACKED text42text
28
29// double separated substitution
30#define DOUBLE_SEPARATED 42.42
31
32// triple separated substitution
33#define TRIPLE_SEPARATED 42.1.42
34
35// misc prefix is preserved
36#define MISC_PREFIX false is 0
37
38// misc suffix is preserved
39#define MISC_SUFFIX 1 is true
40
41// surrounding content is preserved
42#define SURROUNDING what is 6*7? 42!
43
44// incomplete key is preserved
45#define INCOMPLETE_KEY @undefined
46
47// @-vars resolved only when they wrap valid characters, otherwise considered literals
48#define DOUBLE_WRAPPED @text@
49
50// expanded variables are considered strings after expansion
51#define EXPANDED_STRING @string@
52
53// variable name with underscores
54#define UNDERSCORED_VAR value
55
56// backslash before at-sigil does not prevent resolution
57#define BACKSLASH_AT \text
58
59// value that is an at-sign itself
60#define AT_SIGN_VALUE @
61
62// incomplete key mid-line is preserved, trailing content kept
63#define INCOMPLETE_MID @incomplete trailing content
test/standalone/config_header/autoconf_at/autoconf_at.h.in created+62
...@@ -0,0 +1,62 @@
1/* Some Comment */
2int foo();
3// empty strings are preserved
4
5// line with misc content is preserved
6#define KEPT_VALUE no substitution
7
8// empty @ sigils are preserved
9#define AT_SIGIL_1 @
10#define AT_SIGIL_2 @@
11#define AT_SIGIL_3 @@@
12#define AT_SIGIL_4 @@@@
13
14// simple substitution
15#define SIMPLE_UNDEFINED @undefined@
16#define SIMPLE_DEFINED @defined@
17#define SIMPLE_BOOL_TRUE @boolean_true@
18#define SIMPLE_BOOL_FALSE @boolean_false@
19#define SIMPLE_INTEGER @integer@
20#define SIMPLE_STRING @string@
21
22// double packed substitution
23#define DOUBLE_PACKED @string@@string@
24
25// triple packed substitution
26#define TRIPLE_PACKED @string@@integer@@string@
27
28// double separated substitution
29#define DOUBLE_SEPARATED @integer@.@integer@
30
31// triple separated substitution
32#define TRIPLE_SEPARATED @integer@.@boolean_true@.@integer@
33
34// misc prefix is preserved
35#define MISC_PREFIX false is @boolean_false@
36
37// misc suffix is preserved
38#define MISC_SUFFIX @boolean_true@ is true
39
40// surrounding content is preserved
41#define SURROUNDING what is 6*7? @integer@!
42
43// incomplete key is preserved
44#define INCOMPLETE_KEY @undefined
45
46// @-vars resolved only when they wrap valid characters, otherwise considered literals
47#define DOUBLE_WRAPPED @@string@@
48
49// expanded variables are considered strings after expansion
50#define EXPANDED_STRING @string_at@
51
52// variable name with underscores
53#define UNDERSCORED_VAR @underscored_var@
54
55// backslash before at-sigil does not prevent resolution
56#define BACKSLASH_AT \@string@
57
58// value that is an at-sign itself
59#define AT_SIGN_VALUE @at_sign@
60
61// incomplete key mid-line is preserved, trailing content kept
62#define INCOMPLETE_MID @incomplete trailing content
test/standalone/config_header/autoconf_undef/config.h created+32
...@@ -0,0 +1,32 @@
1/* This file was generated by ConfigHeader using the Zig Build System. */
2/* Some Comment */
3
4int foo();
5
6/* #undef SOME_NO */
7#define SOME_TRUE 1
8#define SOME_FALSE 0
9#define SOME_ZERO 0
10#define SOME_ONE 1
11#define SOME_TEN 10
12#define SOME_ENUM foo
13#define SOME_ENUM_LITERAL test
14#define SOME_STRING "test"
15
16// Used twice
17#define SOME_TRUE 1
18
19/* #undef PREFIX_SPACE */
20/* #undef PREFIX_TAB */
21/* #undef POSTFIX_SPACE */
22/* #undef POSTFIX_TAB */
23
24// #undef with underscored variable name
25#define SOME_UNDERSCORED 1
26
27// #undef with extra tokens after variable name (ignored)
28#define SOME_ONE 1
29
30// non-#undef # lines pass through unchanged
31#define KEPT_DEFINE value
32#include <kept.h>
test/standalone/config_header/autoconf_undef/config.h.in created+31
...@@ -0,0 +1,31 @@
1/* Some Comment */
2
3int foo();
4
5#undef SOME_NO
6#undef SOME_TRUE
7#undef SOME_FALSE
8#undef SOME_ZERO
9#undef SOME_ONE
10#undef SOME_TEN
11#undef SOME_ENUM
12#undef SOME_ENUM_LITERAL
13#undef SOME_STRING
14
15// Used twice
16#undef SOME_TRUE
17
18#undef PREFIX_SPACE
19#undef PREFIX_TAB
20#undef POSTFIX_SPACE
21#undef POSTFIX_TAB
22
23// #undef with underscored variable name
24#undef SOME_UNDERSCORED
25
26// #undef with extra tokens after variable name (ignored)
27#undef SOME_ONE extra ignored tokens
28
29// non-#undef # lines pass through unchanged
30#define KEPT_DEFINE value
31#include <kept.h>
test/standalone/config_header/blank/config.h created+13
...@@ -0,0 +1,13 @@
1/* This file was generated by ConfigHeader using the Zig Build System. */
2#ifndef CONFIG_H
3#define CONFIG_H
4/* #undef UNDEFINED */
5#define DEFINED
6#define TRUE 1
7#define FALSE 0
8#define ZERO 0
9#define ONE 1
10#define TEN 10
11#define IDENT identifier
12#define STRING "test"
13#endif /* CONFIG_H */
test/standalone/config_header/build.zig+155-4
...@@ -1,8 +1,11 @@...@@ -1,8 +1,11 @@
1const std = @import("std");1const std = @import("std");
22
3pub fn build(b: *std.Build) void {3pub fn build(b: *std.Build) void {
4 const test_step = b.step("test", "Test it");
5 b.default_step = test_step;
6
4 const config_header = b.addConfigHeader(7 const config_header = b.addConfigHeader(
5 .{ .style = .{ .autoconf_undef = b.path("config.h.in") } },8 .{ .style = .{ .autoconf_undef = b.path("autoconf_undef/config.h.in") } },
6 .{9 .{
7 .SOME_NO = null,10 .SOME_NO = null,
8 .SOME_TRUE = true,11 .SOME_TRUE = true,
...@@ -13,16 +16,164 @@ pub fn build(b: *std.Build) void {...@@ -13,16 +16,164 @@ pub fn build(b: *std.Build) void {
13 .SOME_ENUM = @as(enum { foo, bar }, .foo),16 .SOME_ENUM = @as(enum { foo, bar }, .foo),
14 .SOME_ENUM_LITERAL = .@"test",17 .SOME_ENUM_LITERAL = .@"test",
15 .SOME_STRING = "test",18 .SOME_STRING = "test",
16
17 .PREFIX_SPACE = null,19 .PREFIX_SPACE = null,
18 .PREFIX_TAB = null,20 .PREFIX_TAB = null,
19 .POSTFIX_SPACE = null,21 .POSTFIX_SPACE = null,
20 .POSTFIX_TAB = null,22 .POSTFIX_TAB = null,
23 .SOME_UNDERSCORED = true,
21 },24 },
22 );25 );
26 const check_config_header = b.addCheckFile(config_header.getOutputFile(), .{
27 .expected_exact = @embedFile("autoconf_undef/config.h"),
28 });
29 test_step.dependOn(&check_config_header.step);
2330
24 const check_config_header = b.addCheckFile(config_header.getOutputFile(), .{ .expected_exact = @embedFile("config.h") });31 const config_header_autoconf_at = b.addConfigHeader(
32 .{ .style = .{ .autoconf_at = b.path("autoconf_at/autoconf_at.h.in") } },
33 .{
34 .undefined = null,
35 .defined = {},
36 .boolean_true = true,
37 .boolean_false = false,
38 .integer = 42,
39 .string = "text",
40 .string_at = "@string@",
41 .underscored_var = "value",
42 .at_sign = "@",
43 },
44 );
45 const check_config_header_autoconf_at = b.addCheckFile(config_header_autoconf_at.getOutputFile(), .{
46 .expected_exact = @embedFile("autoconf_at/autoconf_at.h"),
47 });
48 test_step.dependOn(&check_config_header_autoconf_at.step);
2549
26 const test_step = b.step("test", "Test it");50 const config_header_blank = b.addConfigHeader(
51 .{
52 .style = .blank,
53 .include_path = "config.h",
54 },
55 .{
56 .UNDEFINED = null,
57 .DEFINED = {},
58 .TRUE = true,
59 .FALSE = false,
60 .ZERO = 0,
61 .ONE = 1,
62 .TEN = 10,
63 .IDENT = @as(enum { identifier }, .identifier),
64 .STRING = "test",
65 },
66 );
67 const check_config_header_blank = b.addCheckFile(config_header_blank.getOutputFile(), .{
68 .expected_exact = @embedFile("blank/config.h"),
69 });
70 test_step.dependOn(&check_config_header_blank.step);
71
72 const config_header_nasm = b.addConfigHeader(
73 .{
74 .style = .nasm,
75 .include_path = "config.asm",
76 },
77 .{
78 .UNDEFINED = null,
79 .DEFINED = {},
80 .TRUE = true,
81 .FALSE = false,
82 .ZERO = 0,
83 .ONE = 1,
84 .TEN = 10,
85 .IDENT = @as(enum { identifier }, .identifier),
86 .STRING = "test",
87 },
88 );
89 const check_config_header_nasm = b.addCheckFile(config_header_nasm.getOutputFile(), .{
90 .expected_exact = @embedFile("nasm/config.asm"),
91 });
92 test_step.dependOn(&check_config_header_nasm.step);
93
94 addCmakeChecks(b, test_step);
95}
96
97fn addCmakeChecks(b: *std.Build, test_step: *std.Build.Step) void {
98 const config_header = b.addConfigHeader(
99 .{ .style = .{ .cmake = b.path("cmake/config.h.in") } },
100 .{
101 .NOVAL = null,
102 .TRUEVAL = true,
103 .FALSEVAL = false,
104 .ZEROVAL = 0,
105 .ONEVAL = 1,
106 .TENVAL = 10,
107 .STRINGVAL = "test",
108 .BOOLNOVAL = {},
109 .BOOLTRUEVAL = true,
110 .BOOLFALSEVAL = false,
111 .BOOLZEROVAL = 0,
112 .BOOLONEVAL = 1,
113 .BOOLTENVAL = 10,
114 .BOOLSTRINGVAL = "test",
115 },
116 );
117 const check_config_header = b.addCheckFile(config_header.getOutputFile(), .{
118 .expected_exact = @embedFile("cmake/config.h"),
119 });
27 test_step.dependOn(&check_config_header.step);120 test_step.dependOn(&check_config_header.step);
121
122 const pwd_sh = b.addConfigHeader(
123 .{ .style = .{ .cmake = b.path("cmake/pwd.sh.in") } },
124 .{ .DIR = "${PWD}" },
125 );
126 const check_pwd_sh = b.addCheckFile(pwd_sh.getOutputFile(), .{
127 .expected_exact = @embedFile("cmake/pwd.sh"),
128 });
129 test_step.dependOn(&check_pwd_sh.step);
130
131 const config_header_edge_cases = b.addConfigHeader(
132 .{ .style = .{ .cmake = b.path("cmake/edge_cases.h.in") } },
133 .{
134 .DOLLAR = "$",
135 .UNDERSCORE = "_",
136 .STRING = "text",
137 .STRING_PROXY = "STRING",
138 .STRING_AT = "@STRING@",
139 .STRING_CURLY = "{STRING}",
140 .STRING_VAR = "${STRING}",
141 .NEST_UNDERSCORE_PROXY = "UNDERSCORE",
142 .NEST_PROXY = "NEST_UNDERSCORE_PROXY",
143 },
144 );
145 const check_config_header_edge_cases = b.addCheckFile(config_header_edge_cases.getOutputFile(), .{
146 .expected_exact = @embedFile("cmake/edge_cases.h"),
147 });
148 test_step.dependOn(&check_config_header_edge_cases.step);
149
150 const config_header_cmakedefine_edge_cases = b.addConfigHeader(
151 .{
152 .style = .{ .cmake = b.path("cmake/cmakedefine_edge_cases.h.in") },
153 .include_path = "cmakedefine_edge_cases_renamed.h",
154 },
155 .{
156 .MULTI_WORD = true,
157 .MULTI_WORD_FALSE = false,
158 .NO_VALUE = true,
159 .NO_VALUE_FALSE = false,
160 .WITH_UNDERSCORE_TRUE = true,
161 .WITH_UNDERSCORE_FALSE = false,
162 ._LEADING = true,
163 .TRAILING_ = true,
164 ._UNDER_01 = true,
165 .UNDER_01_ = true,
166 .SUBST_VAL = true,
167 .SUBST_VAL_FALSE = false,
168 .STRING = "text",
169 .VAR_NAME = "ACTUAL_VAR",
170 .ACTUAL_VAR = true,
171 .AT_SIGN = "@",
172 .DOLLAR_SIGN = "$",
173 },
174 );
175 const check_config_header_cmakedefine_edge_cases = b.addCheckFile(config_header_cmakedefine_edge_cases.getOutputFile(), .{
176 .expected_exact = @embedFile("cmake/cmakedefine_edge_cases.h"),
177 });
178 test_step.dependOn(&check_config_header_cmakedefine_edge_cases.step);
28}179}
test/standalone/config_header/cmake/cmakedefine_edge_cases.h created+42
...@@ -0,0 +1,42 @@
1/* This file was generated by ConfigHeader using the Zig Build System. */
2// cmakedefine with multi-word string value (truthy)
3#define MULTI_WORD "hello world"
4
5// cmakedefine with multi-word string value (falsy)
6/* #undef MULTI_WORD_FALSE */
7
8// cmakedefine with no replacement value (truthy)
9#define NO_VALUE
10
11// cmakedefine with no replacement value (falsy)
12/* #undef NO_VALUE_FALSE */
13
14// cmakedefine01 with underscored variable names (truthy)
15#define WITH_UNDERSCORE_TRUE 1
16
17// cmakedefine01 with underscored variable names (falsy)
18#define WITH_UNDERSCORE_FALSE 0
19
20// cmakedefine with leading/trailing underscores (truthy)
21#define _LEADING 1
22#define TRAILING_ 1
23
24// cmakedefine01 with leading/trailing underscores (truthy)
25#define _UNDER_01 1
26#define UNDER_01_ 1
27
28// cmakedefine with @ substitution in the replacement value (truthy)
29#define SUBST_VAL text
30
31// cmakedefine with @ substitution in the replacement value (falsy)
32/* #undef SUBST_VAL_FALSE */
33
34// cmakedefine with @ substitution as the variable name
35#define ACTUAL_VAR custom_val
36
37// cmakedefine with dollar-curly substitution as the variable name
38#define ACTUAL_VAR custom_val
39
40// @ and $ as literal config values
41@
42$
test/standalone/config_header/cmake/cmakedefine_edge_cases.h.in created+41
...@@ -0,0 +1,41 @@
1// cmakedefine with multi-word string value (truthy)
2#cmakedefine MULTI_WORD "hello world"
3
4// cmakedefine with multi-word string value (falsy)
5#cmakedefine MULTI_WORD_FALSE "hello world"
6
7// cmakedefine with no replacement value (truthy)
8#cmakedefine NO_VALUE
9
10// cmakedefine with no replacement value (falsy)
11#cmakedefine NO_VALUE_FALSE
12
13// cmakedefine01 with underscored variable names (truthy)
14#cmakedefine01 WITH_UNDERSCORE_TRUE
15
16// cmakedefine01 with underscored variable names (falsy)
17#cmakedefine01 WITH_UNDERSCORE_FALSE
18
19// cmakedefine with leading/trailing underscores (truthy)
20#cmakedefine _LEADING 1
21#cmakedefine TRAILING_ 1
22
23// cmakedefine01 with leading/trailing underscores (truthy)
24#cmakedefine01 _UNDER_01
25#cmakedefine01 UNDER_01_
26
27// cmakedefine with @ substitution in the replacement value (truthy)
28#cmakedefine SUBST_VAL @STRING@
29
30// cmakedefine with @ substitution in the replacement value (falsy)
31#cmakedefine SUBST_VAL_FALSE @STRING@
32
33// cmakedefine with @ substitution as the variable name
34#cmakedefine @VAR_NAME@ custom_val
35
36// cmakedefine with dollar-curly substitution as the variable name
37#cmakedefine ${VAR_NAME} custom_val
38
39// @ and $ as literal config values
40@AT_SIGN@
41${DOLLAR_SIGN}
test/standalone/config_header/cmake/config.h created+144
...@@ -0,0 +1,144 @@
1/* This file was generated by ConfigHeader using the Zig Build System. */
2// cmakedefine — value is null (undefined) → /* #undef */
3/* #undef NOVAL */
4
5// cmakedefine — value is true → #define ... 1
6#define TRUEVAL 1
7
8// cmakedefine — value is false → /* #undef */
9/* #undef FALSEVAL */
10
11// cmakedefine — value is 0 (falsy) → /* #undef */
12/* #undef ZEROVAL */
13
14// cmakedefine — value is 1 (truthy) → #define ... 1
15#define ONEVAL 1
16
17// cmakedefine — value is 10 (truthy) → #define ... 1
18#define TENVAL 1
19
20// cmakedefine — value is non-empty string (truthy) → #define ... 1
21#define STRINGVAL 1
22
23// cmakedefine — leading whitespace preserved in output
24 #define STRINGVAL 1
25 #define STRINGVAL 1
26
27
28// cmakedefine01 — value is {} (defined, no value) → 0
29#define BOOLNOVAL 0
30
31// cmakedefine01 — value is true → 1
32#define BOOLTRUEVAL 1
33
34// cmakedefine01 — value is false → 0
35#define BOOLFALSEVAL 0
36
37// cmakedefine01 — value is 0 (falsy) → 0
38#define BOOLZEROVAL 0
39
40// cmakedefine01 — value is 1 (truthy) → 1
41#define BOOLONEVAL 1
42
43// cmakedefine01 — value is 10 (truthy) → 1
44#define BOOLTENVAL 1
45
46// cmakedefine01 — value is non-empty string (truthy) → 1
47#define BOOLSTRINGVAL 1
48
49
50// @-substitution — value is null → empty string
51//
52
53// @-substitution — null values produce nothing even when packed
54//
55
56// @-substitution — null values produce nothing even when separated
57// .
58
59// @-substitution — value is true → "1"
60// 1
61
62// @-substitution — value is false → "0"
63// 0
64
65// @-substitution — true + false packed → "10"
66// 10
67
68// @-substitution — false + true separated → "0.1"
69// 0.1
70
71// @-substitution — value is 0 → "0"
72// 0
73
74// @-substitution — value is 1 → "1"
75// 1
76
77// @-substitution — value is 10 → "10"
78// 10
79
80// @-substitution — 0 + 1 packed → "01"
81// 01
82
83// @-substitution — 0 + 10 separated → "0.10"
84// 0.10
85
86// @-substitution — value is string "test" → "test"
87// test
88
89// @-substitution — strings packed → "testtest"
90// testtest
91
92// @-substitution — strings separated → "test.test"
93// test.test
94
95// @-substitution — mixed null/string/true/zero → "test10"
96// test10
97
98// dollar-curly substitution — value is null → empty string
99//
100
101// dollar-curly substitution — null values produce nothing even when packed
102//
103
104// dollar-curly substitution — null values produce nothing even when separated
105// .
106
107// dollar-curly substitution — value is true → "1"
108// 1
109
110// dollar-curly substitution — value is false → "0"
111// 0
112
113// dollar-curly substitution — true + false packed → "10"
114// 10
115
116// dollar-curly substitution — false + true separated → "0.1"
117// 0.1
118
119// dollar-curly substitution — value is 0 → "0"
120// 0
121
122// dollar-curly substitution — value is 1 → "1"
123// 1
124
125// dollar-curly substitution — value is 10 → "10"
126// 10
127
128// dollar-curly substitution — 0 + 1 packed → "01"
129// 01
130
131// dollar-curly substitution — 0 + 10 separated → "0.10"
132// 0.10
133
134// dollar-curly substitution — value is string "test" → "test"
135// test
136
137// dollar-curly substitution — strings packed → "testtest"
138// testtest
139
140// dollar-curly substitution — strings separated → "test.test"
141// test.test
142
143// dollar-curly substitution — mixed null/string/true/zero → "test10"
144// test10
test/standalone/config_header/cmake/config.h.in created+143
...@@ -0,0 +1,143 @@
1// cmakedefine — value is null (undefined) → /* #undef */
2#cmakedefine NOVAL unreachable
3
4// cmakedefine — value is true → #define ... 1
5#cmakedefine TRUEVAL 1
6
7// cmakedefine — value is false → /* #undef */
8#cmakedefine FALSEVAL unreachable
9
10// cmakedefine — value is 0 (falsy) → /* #undef */
11#cmakedefine ZEROVAL unreachable
12
13// cmakedefine — value is 1 (truthy) → #define ... 1
14#cmakedefine ONEVAL 1
15
16// cmakedefine — value is 10 (truthy) → #define ... 1
17#cmakedefine TENVAL 1
18
19// cmakedefine — value is non-empty string (truthy) → #define ... 1
20#cmakedefine STRINGVAL 1
21
22// cmakedefine — leading whitespace preserved in output
23 #cmakedefine STRINGVAL 1
24 #cmakedefine STRINGVAL 1
25
26
27// cmakedefine01 — value is {} (defined, no value) → 0
28#cmakedefine01 BOOLNOVAL
29
30// cmakedefine01 — value is true → 1
31#cmakedefine01 BOOLTRUEVAL
32
33// cmakedefine01 — value is false → 0
34#cmakedefine01 BOOLFALSEVAL
35
36// cmakedefine01 — value is 0 (falsy) → 0
37#cmakedefine01 BOOLZEROVAL
38
39// cmakedefine01 — value is 1 (truthy) → 1
40#cmakedefine01 BOOLONEVAL
41
42// cmakedefine01 — value is 10 (truthy) → 1
43#cmakedefine01 BOOLTENVAL
44
45// cmakedefine01 — value is non-empty string (truthy) → 1
46#cmakedefine01 BOOLSTRINGVAL
47
48
49// @-substitution — value is null → empty string
50// @NOVAL@
51
52// @-substitution — null values produce nothing even when packed
53// @NOVAL@@NOVAL@
54
55// @-substitution — null values produce nothing even when separated
56// @NOVAL@.@NOVAL@
57
58// @-substitution — value is true → "1"
59// @TRUEVAL@
60
61// @-substitution — value is false → "0"
62// @FALSEVAL@
63
64// @-substitution — true + false packed → "10"
65// @TRUEVAL@@FALSEVAL@
66
67// @-substitution — false + true separated → "0.1"
68// @FALSEVAL@.@TRUEVAL@
69
70// @-substitution — value is 0 → "0"
71// @ZEROVAL@
72
73// @-substitution — value is 1 → "1"
74// @ONEVAL@
75
76// @-substitution — value is 10 → "10"
77// @TENVAL@
78
79// @-substitution — 0 + 1 packed → "01"
80// @ZEROVAL@@ONEVAL@
81
82// @-substitution — 0 + 10 separated → "0.10"
83// @ZEROVAL@.@TENVAL@
84
85// @-substitution — value is string "test" → "test"
86// @STRINGVAL@
87
88// @-substitution — strings packed → "testtest"
89// @STRINGVAL@@STRINGVAL@
90
91// @-substitution — strings separated → "test.test"
92// @STRINGVAL@.@STRINGVAL@
93
94// @-substitution — mixed null/string/true/zero → "test10"
95// @NOVAL@@STRINGVAL@@TRUEVAL@@ZEROVAL@
96
97// dollar-curly substitution — value is null → empty string
98// ${NOVAL}
99
100// dollar-curly substitution — null values produce nothing even when packed
101// ${NOVAL}${NOVAL}
102
103// dollar-curly substitution — null values produce nothing even when separated
104// ${NOVAL}.${NOVAL}
105
106// dollar-curly substitution — value is true → "1"
107// ${TRUEVAL}
108
109// dollar-curly substitution — value is false → "0"
110// ${FALSEVAL}
111
112// dollar-curly substitution — true + false packed → "10"
113// ${TRUEVAL}${FALSEVAL}
114
115// dollar-curly substitution — false + true separated → "0.1"
116// ${FALSEVAL}.${TRUEVAL}
117
118// dollar-curly substitution — value is 0 → "0"
119// ${ZEROVAL}
120
121// dollar-curly substitution — value is 1 → "1"
122// ${ONEVAL}
123
124// dollar-curly substitution — value is 10 → "10"
125// ${TENVAL}
126
127// dollar-curly substitution — 0 + 1 packed → "01"
128// ${ZEROVAL}${ONEVAL}
129
130// dollar-curly substitution — 0 + 10 separated → "0.10"
131// ${ZEROVAL}.${TENVAL}
132
133// dollar-curly substitution — value is string "test" → "test"
134// ${STRINGVAL}
135
136// dollar-curly substitution — strings packed → "testtest"
137// ${STRINGVAL}${STRINGVAL}
138
139// dollar-curly substitution — strings separated → "test.test"
140// ${STRINGVAL}.${STRINGVAL}
141
142// dollar-curly substitution — mixed null/string/true/zero → "test10"
143// ${NOVAL}${STRINGVAL}${TRUEVAL}${ZEROVAL}
test/standalone/config_header/cmake/edge_cases.h created+43
...@@ -0,0 +1,43 @@
1/* This file was generated by ConfigHeader using the Zig Build System. */
2// empty lines are preserved
3
4// double-wrapped at-sigils work like single-wrapped
5@text@
6@text@
7
8// at-var lookup happens inside dollar-curly before dollar-curly lookup
9text
10
11// expanded variables are treated as strings and can be re-substituted
12@STRING@
13@STRING@
14${STRING}
15${STRING}
16${STRING}
17${STRING}
18${text}
19${text}
20${text}
21
22// nested dollar-curly expansion from the inside out
23STRING
24STRING
25
26// nested dollar-curly — only completed brace blocks are expanded
27NEST_UNDERSCORE_PROXY
28NEST_UNDERSCORE_PROXY
29
30// backslash is invalid in at-var names — preserved as literal
31\@STRING\@
32
33// backslash does not affect dollar-curly expansion
34\text
35
36// backslash before opening brace breaks dollar-curly identification
37$\{STRING}
38
39// bare at-sigils pass through unchanged with no variable map
40#define AT @
41#define ATAT @@
42#define ATATAT @@@
43#define ATATATAT @@@@
test/standalone/config_header/cmake/edge_cases.h.in created+42
...@@ -0,0 +1,42 @@
1// empty lines are preserved
2
3// double-wrapped at-sigils work like single-wrapped
4@@STRING@@
5@${STRING}@
6
7// at-var lookup happens inside dollar-curly before dollar-curly lookup
8${@STRING_PROXY@}
9
10// expanded variables are treated as strings and can be re-substituted
11@STRING_AT@
12${STRING_AT}
13$@STRING_CURLY@
14$${STRING_CURLY}
15${STRING_VAR}
16@STRING_VAR@
17${DOLLAR}{${STRING}}
18@DOLLAR@{${STRING}}
19@DOLLAR@{@STRING@}
20
21// nested dollar-curly expansion from the inside out
22${STRING${UNDERSCORE}PROXY}
23${STRING@UNDERSCORE@PROXY}
24
25// nested dollar-curly — only completed brace blocks are expanded
26${NEST${UNDERSCORE}PROXY}
27${NEST${${NEST_UNDERSCORE${UNDERSCORE}PROXY}}PROXY}
28
29// backslash is invalid in at-var names — preserved as literal
30\@STRING\@
31
32// backslash does not affect dollar-curly expansion
33\${STRING}
34
35// backslash before opening brace breaks dollar-curly identification
36$\{STRING}
37
38// bare at-sigils pass through unchanged with no variable map
39#define AT @
40#define ATAT @@
41#define ATATAT @@@
42#define ATATATAT @@@@
test/standalone/config_header/cmake/pwd.sh created+2
...@@ -0,0 +1,2 @@
1/* This file was generated by ConfigHeader using the Zig Build System. */
2echo ${PWD}
test/standalone/config_header/cmake/pwd.sh.in created+1
...@@ -0,0 +1 @@
1echo @DIR@
test/standalone/config_header/config.h deleted-23
...@@ -1,23 +0,0 @@
1/* This file was generated by ConfigHeader using the Zig Build System. */
2/* Some Comment */
3
4int foo();
5
6/* #undef SOME_NO */
7#define SOME_TRUE 1
8#define SOME_FALSE 0
9#define SOME_ZERO 0
10#define SOME_ONE 1
11#define SOME_TEN 10
12#define SOME_ENUM foo
13#define SOME_ENUM_LITERAL test
14#define SOME_STRING "test"
15
16// Used twice
17#define SOME_TRUE 1
18
19/* #undef PREFIX_SPACE */
20/* #undef PREFIX_TAB */
21/* #undef POSTFIX_SPACE */
22/* #undef POSTFIX_TAB */
23
test/standalone/config_header/config.h.in deleted-21
...@@ -1,21 +0,0 @@
1/* Some Comment */
2
3int foo();
4
5#undef SOME_NO
6#undef SOME_TRUE
7#undef SOME_FALSE
8#undef SOME_ZERO
9#undef SOME_ONE
10#undef SOME_TEN
11#undef SOME_ENUM
12#undef SOME_ENUM_LITERAL
13#undef SOME_STRING
14
15// Used twice
16#undef SOME_TRUE
17
18#undef PREFIX_SPACE
19#undef PREFIX_TAB
20#undef POSTFIX_SPACE
21#undef POSTFIX_TAB
test/standalone/config_header/nasm/config.asm created+10
...@@ -0,0 +1,10 @@
1; This file was generated by ConfigHeader using the Zig Build System.
2; %undef UNDEFINED
3%define DEFINED
4%define TRUE 1
5%define FALSE 0
6%define ZERO 0
7%define ONE 1
8%define TEN 10
9%define IDENT identifier
10%define STRING "test"