authorgravatar for michaldrozd@protonmail.chfardragon <michaldrozd@protonmail.ch> 2026-06-04 19:26:32+00:00
committergravatar for michaldrozd@protonmail.chfardragon <michaldrozd@protonmail.ch> 2026-06-05 14:59:18+02:00
loga6fded0810cdc9998101cc56804b1dc7274f9671
treed63bae70829ce72dc1ccf3cbf29173e4f0ed242c
parent6043fbb2b7f263c0bab308f46f4ef393fec4a678

Make ConfigHeader newline aware


1 files changed, 57 insertions(+), 35 deletions(-)

lib/compiler/Maker/Step/ConfigHeader.zig+57-35
......@@ -11,8 +11,10 @@ const Step = @import("../Step.zig");
1111const Maker = @import("../../Maker.zig");
1212
1313const header_text = "This file was generated by ConfigHeader using the Zig Build System.";
14const c_generated_line = "/* " ++ header_text ++ " */\n";
15const asm_generated_line = "; " ++ header_text ++ "\n";
14const c_generated_line = "/* " ++ header_text ++ " */";
15const asm_generated_line = "; " ++ header_text;
16
17const os_newline = if (@import("builtin").os.tag == .windows) "\r\n" else "\n";
1618
1719/// Table value is whether the value is used.
1820const ValueMap = std.array_hash_map.String(bool);
......@@ -160,6 +162,15 @@ fn ensureAllValuesUsed(
160162 if (any_errors) return error.MakeFailed;
161163}
162164
165fn detectNewline(contents: []const u8) []const u8 {
166 return if (std.mem.endsWith(u8, contents, "\r\n"))
167 "\r\n"
168 else if (std.mem.endsWith(u8, contents, "\n"))
169 "\n"
170 else
171 os_newline;
172}
173
163174fn renderAutoConfUndef(
164175 maker: *Maker,
165176 step: *Step,
......@@ -170,25 +181,28 @@ fn renderAutoConfUndef(
170181 src_path: Path,
171182) !void {
172183 const conf = &maker.scanned_config.configuration;
184 const newline = detectNewline(contents);
173185
174186 try w.writeAll(c_generated_line);
187 try w.writeAll(newline);
175188
176189 var any_errors = false;
177190 var line_index: u32 = 0;
178191 var line_it = std.mem.splitScalar(u8, contents, '\n');
179 while (line_it.next()) |line| : (line_index += 1) {
192 while (line_it.next()) |raw_line| : (line_index += 1) {
180193 const last_line = line_it.index == line_it.buffer.len;
194 const line = std.mem.trimEnd(u8, raw_line, "\r");
181195
182196 if (!std.mem.startsWith(u8, line, "#")) {
183197 try w.writeAll(line);
184 if (!last_line) try w.writeByte('\n');
198 if (!last_line) try w.writeAll(newline);
185199 continue;
186200 }
187201 var it = std.mem.tokenizeAny(u8, line[1..], " \t\r");
188202 const undef = it.next().?;
189203 if (!std.mem.eql(u8, undef, "undef")) {
190204 try w.writeAll(line);
191 if (!last_line) try w.writeByte('\n');
205 if (!last_line) try w.writeAll(newline);
192206 continue;
193207 }
194208 const name = it.next().?;
......@@ -200,7 +214,7 @@ fn renderAutoConfUndef(
200214 continue;
201215 };
202216 value_map.values()[index] = true; // Set to used.
203 try renderValueC(conf, w, name, value_pairs[index].index);
217 try renderValueC(conf, w, newline, name, value_pairs[index].index);
204218 }
205219
206220 try ensureAllValuesUsed(maker, step, value_map, src_path);
......@@ -218,14 +232,17 @@ fn renderAutoconfAt(
218232) !void {
219233 const w = &aw.writer;
220234 const conf = &maker.scanned_config.configuration;
235 const newline = detectNewline(contents);
221236
222237 try w.writeAll(c_generated_line);
238 try w.writeAll(newline);
223239
224240 var any_errors = false;
225241 var line_index: u32 = 0;
226242 var line_it = std.mem.splitScalar(u8, contents, '\n');
227 while (line_it.next()) |line| : (line_index += 1) {
243 while (line_it.next()) |raw_line| : (line_index += 1) {
228244 const last_line = line_it.index == line_it.buffer.len;
245 const line = std.mem.trimEnd(u8, raw_line, "\r");
229246
230247 const old_len = aw.written().len;
231248 expandVariablesAutoconfAt(w, line, conf, value_pairs, value_map) catch |err| switch (err) {
......@@ -246,7 +263,7 @@ fn renderAutoconfAt(
246263 continue;
247264 },
248265 };
249 if (!last_line) try w.writeByte('\n');
266 if (!last_line) try w.writeAll(newline);
250267 }
251268
252269 try ensureAllValuesUsed(maker, step, value_map, src_path);
......@@ -264,16 +281,19 @@ fn renderCmake(
264281 src_path: Path,
265282) !void {
266283 const conf = &maker.scanned_config.configuration;
284 const newline = detectNewline(contents);
267285
268286 try w.writeAll(c_generated_line);
287 try w.writeAll(newline);
269288
270289 var any_errors = false;
271290 var line_index: u32 = 0;
272291 var line_it = std.mem.splitScalar(u8, contents, '\n');
273292 while (line_it.next()) |raw_line| : (line_index += 1) {
274293 const last_line = line_it.index == line_it.buffer.len;
294 const stripped_line = std.mem.trimEnd(u8, raw_line, "\r");
275295
276 const line = expandVariablesCmake(arena, raw_line, conf, value_pairs, value_map) catch |err| switch (err) {
296 const line = expandVariablesCmake(arena, stripped_line, conf, value_pairs, value_map) catch |err| switch (err) {
277297 error.InvalidCharacter => {
278298 try step.addError(maker, "{f}:{d}: invalid character in a variable name", .{
279299 src_path, line_index + 1,
......@@ -292,7 +312,7 @@ fn renderCmake(
292312
293313 const line_start = std.mem.findNone(u8, line, " \t\r") orelse {
294314 try w.writeAll(line);
295 if (!last_line) try w.writeByte('\n');
315 if (!last_line) try w.writeAll(newline);
296316 continue;
297317 };
298318 const whitespace_prefix = line[0..line_start];
......@@ -300,7 +320,7 @@ fn renderCmake(
300320
301321 if (!std.mem.startsWith(u8, trimmed_line, "#")) {
302322 try w.writeAll(line);
303 if (!last_line) try w.writeByte('\n');
323 if (!last_line) try w.writeAll(newline);
304324 continue;
305325 }
306326
......@@ -313,7 +333,7 @@ fn renderCmake(
313333 false
314334 else {
315335 try w.writeAll(line);
316 if (!last_line) try w.writeByte('\n');
336 if (!last_line) try w.writeAll(newline);
317337 continue;
318338 };
319339
......@@ -337,7 +357,7 @@ fn renderCmake(
337357 try w.writeAll(whitespace_prefix);
338358
339359 if (booldefine) {
340 try renderValueCBool(w, name, switch (value.unpack(conf)) {
360 try renderValueCBool(w, newline, name, switch (value.unpack(conf)) {
341361 .undef, .defined => false,
342362 .bool => |b| b,
343363 inline .u64, .i64 => |i| i != 0,
......@@ -345,9 +365,9 @@ fn renderCmake(
345365 .ident => false,
346366 });
347367 } else if (value != .undef) {
348 try renderValueCIdent(w, name, it.rest());
368 try renderValueCIdent(w, newline, name, it.rest());
349369 } else {
350 try renderValueC(conf, w, name, value);
370 try renderValueC(conf, w, newline, name, value);
351371 }
352372 }
353373
......@@ -364,6 +384,7 @@ fn renderBlank(
364384 include_guard_override: ?[]const u8,
365385) !void {
366386 try w.writeAll(c_generated_line);
387 try w.writeAll(os_newline);
367388
368389 const include_guard_fmt: IncludeGuardFmt = .{
369390 .include_path = include_path,
......@@ -376,7 +397,7 @@ fn renderBlank(
376397 \\
377398 , .{include_guard_fmt});
378399
379 for (value_map.keys(), value_pairs) |name, pair| try renderValueC(conf, w, name, pair.index);
400 for (value_map.keys(), value_pairs) |name, pair| try renderValueC(conf, w, os_newline, name, pair.index);
380401
381402 try w.print(
382403 \\#endif /* {f} */
......@@ -405,41 +426,42 @@ fn renderNasm(
405426 value_map: *const ValueMap,
406427) !void {
407428 try w.writeAll(asm_generated_line);
408 for (value_map.keys(), value_pairs) |name, pair| try renderValueNasm(conf, w, name, pair.index);
429 try w.writeAll(os_newline);
430 for (value_map.keys(), value_pairs) |name, pair| try renderValueNasm(conf, w, os_newline, name, pair.index);
409431}
410432
411fn renderValueC(conf: *const Configuration, w: *Writer, name: []const u8, value: Value.Index) !void {
433fn renderValueC(conf: *const Configuration, w: *Writer, newline: []const u8, name: []const u8, value: Value.Index) !void {
412434 switch (value.unpack(conf)) {
413 .undef => try w.print("/* #undef {s} */\n", .{name}),
414 .defined => try w.print("#define {s}\n", .{name}),
415 .bool => |b| return renderValueCBool(w, name, b),
416 inline .u64, .i64 => |i| try w.print("#define {s} {d}\n", .{ name, i }),
417 .ident => |ident| return renderValueCIdent(w, name, ident),
418 .string => |string| try w.print("#define {s} \"{f}\"\n", .{ name, std.zig.fmtString(string) }),
435 .undef => try w.print("/* #undef {s} */{s}", .{ name, newline }),
436 .defined => try w.print("#define {s}{s}", .{ name, newline }),
437 .bool => |b| return renderValueCBool(w, newline, name, b),
438 inline .u64, .i64 => |i| try w.print("#define {s} {d}{s}", .{ name, i, newline }),
439 .ident => |ident| return renderValueCIdent(w, newline, name, ident),
440 .string => |string| try w.print("#define {s} \"{f}\"{s}", .{ name, std.zig.fmtString(string), newline }),
419441 }
420442}
421443
422fn renderValueCIdent(w: *Writer, name: []const u8, ident: []const u8) Writer.Error!void {
444fn renderValueCIdent(w: *Writer, newline: []const u8, name: []const u8, ident: []const u8) Writer.Error!void {
423445 try w.print("#define {s}", .{name});
424446 if (ident.len > 0) {
425447 try w.writeByte(' ');
426448 try w.writeAll(ident);
427449 }
428 return w.writeByte('\n');
450 return w.writeAll(newline);
429451}
430452
431fn renderValueCBool(w: *Writer, name: []const u8, b: bool) Writer.Error!void {
432 return w.print("#define {s} {c}\n", .{ name, @as(u8, '0') + @intFromBool(b) });
453fn renderValueCBool(w: *Writer, newline: []const u8, name: []const u8, b: bool) Writer.Error!void {
454 return w.print("#define {s} {c}{s}", .{ name, @as(u8, '0') + @intFromBool(b), newline });
433455}
434456
435fn renderValueNasm(conf: *const Configuration, w: *Writer, name: []const u8, value: Value.Index) !void {
457fn renderValueNasm(conf: *const Configuration, w: *Writer, newline: []const u8, name: []const u8, value: Value.Index) !void {
436458 switch (value.unpack(conf)) {
437 .undef => try w.print("; %undef {s}\n", .{name}),
438 .defined => try w.print("%define {s}\n", .{name}),
439 .bool => |b| try w.print("%define {s} {c}\n", .{ name, @as(u8, '0') + @intFromBool(b) }),
440 inline .u64, .i64 => |i| try w.print("%define {s} {d}\n", .{ name, i }),
441 .ident => |ident| try w.print("%define {s} {s}\n", .{ name, ident }),
442 .string => |string| try w.print("%define {s} \"{f}\"\n", .{ name, std.zig.fmtString(string) }),
459 .undef => try w.print("; %undef {s}{s}", .{ name, newline }),
460 .defined => try w.print("%define {s}{s}", .{ name, newline }),
461 .bool => |b| try w.print("%define {s} {c}{s}", .{ name, @as(u8, '0') + @intFromBool(b), newline }),
462 inline .u64, .i64 => |i| try w.print("%define {s} {d}{s}", .{ name, i, newline }),
463 .ident => |ident| try w.print("%define {s} {s}{s}", .{ name, ident, newline }),
464 .string => |string| try w.print("%define {s} \"{f}\"{s}", .{ name, std.zig.fmtString(string), newline }),
443465 }
444466}
445467