| ... | @@ -11,8 +11,10 @@ const Step = @import("../Step.zig"); | ... | @@ -11,8 +11,10 @@ const Step = @import("../Step.zig"); |
| 11 | const Maker = @import("../../Maker.zig"); | 11 | const Maker = @import("../../Maker.zig"); |
| 12 | | 12 | |
| 13 | const header_text = "This file was generated by ConfigHeader using the Zig Build System."; | 13 | const header_text = "This file was generated by ConfigHeader using the Zig Build System."; |
| 14 | const c_generated_line = "/* " ++ header_text ++ " */\n"; | 14 | const c_generated_line = "/* " ++ header_text ++ " */"; |
| 15 | const asm_generated_line = "; " ++ header_text ++ "\n"; | 15 | const asm_generated_line = "; " ++ header_text; |
| | 16 | |
| | 17 | const os_newline = if (@import("builtin").os.tag == .windows) "\r\n" else "\n"; |
| 16 | | 18 | |
| 17 | /// Table value is whether the value is used. | 19 | /// Table value is whether the value is used. |
| 18 | const ValueMap = std.array_hash_map.String(bool); | 20 | const ValueMap = std.array_hash_map.String(bool); |
| ... | @@ -160,6 +162,15 @@ fn ensureAllValuesUsed( | ... | @@ -160,6 +162,15 @@ fn ensureAllValuesUsed( |
| 160 | if (any_errors) return error.MakeFailed; | 162 | if (any_errors) return error.MakeFailed; |
| 161 | } | 163 | } |
| 162 | | 164 | |
| | 165 | fn 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 | |
| 163 | fn renderAutoConfUndef( | 174 | fn renderAutoConfUndef( |
| 164 | maker: *Maker, | 175 | maker: *Maker, |
| 165 | step: *Step, | 176 | step: *Step, |
| ... | @@ -170,25 +181,28 @@ fn renderAutoConfUndef( | ... | @@ -170,25 +181,28 @@ fn renderAutoConfUndef( |
| 170 | src_path: Path, | 181 | src_path: Path, |
| 171 | ) !void { | 182 | ) !void { |
| 172 | const conf = &maker.scanned_config.configuration; | 183 | const conf = &maker.scanned_config.configuration; |
| | 184 | const newline = detectNewline(contents); |
| 173 | | 185 | |
| 174 | try w.writeAll(c_generated_line); | 186 | try w.writeAll(c_generated_line); |
| | 187 | try w.writeAll(newline); |
| 175 | | 188 | |
| 176 | var any_errors = false; | 189 | var any_errors = false; |
| 177 | var line_index: u32 = 0; | 190 | var line_index: u32 = 0; |
| 178 | var line_it = std.mem.splitScalar(u8, contents, '\n'); | 191 | 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) { |
| 180 | const last_line = line_it.index == line_it.buffer.len; | 193 | const last_line = line_it.index == line_it.buffer.len; |
| | 194 | const line = std.mem.trimEnd(u8, raw_line, "\r"); |
| 181 | | 195 | |
| 182 | if (!std.mem.startsWith(u8, line, "#")) { | 196 | if (!std.mem.startsWith(u8, line, "#")) { |
| 183 | try w.writeAll(line); | 197 | try w.writeAll(line); |
| 184 | if (!last_line) try w.writeByte('\n'); | 198 | if (!last_line) try w.writeAll(newline); |
| 185 | continue; | 199 | continue; |
| 186 | } | 200 | } |
| 187 | var it = std.mem.tokenizeAny(u8, line[1..], " \t\r"); | 201 | var it = std.mem.tokenizeAny(u8, line[1..], " \t\r"); |
| 188 | const undef = it.next().?; | 202 | const undef = it.next().?; |
| 189 | if (!std.mem.eql(u8, undef, "undef")) { | 203 | if (!std.mem.eql(u8, undef, "undef")) { |
| 190 | try w.writeAll(line); | 204 | try w.writeAll(line); |
| 191 | if (!last_line) try w.writeByte('\n'); | 205 | if (!last_line) try w.writeAll(newline); |
| 192 | continue; | 206 | continue; |
| 193 | } | 207 | } |
| 194 | const name = it.next().?; | 208 | const name = it.next().?; |
| ... | @@ -200,7 +214,7 @@ fn renderAutoConfUndef( | ... | @@ -200,7 +214,7 @@ fn renderAutoConfUndef( |
| 200 | continue; | 214 | continue; |
| 201 | }; | 215 | }; |
| 202 | value_map.values()[index] = true; // Set to used. | 216 | 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); |
| 204 | } | 218 | } |
| 205 | | 219 | |
| 206 | try ensureAllValuesUsed(maker, step, value_map, src_path); | 220 | try ensureAllValuesUsed(maker, step, value_map, src_path); |
| ... | @@ -218,14 +232,17 @@ fn renderAutoconfAt( | ... | @@ -218,14 +232,17 @@ fn renderAutoconfAt( |
| 218 | ) !void { | 232 | ) !void { |
| 219 | const w = &aw.writer; | 233 | const w = &aw.writer; |
| 220 | const conf = &maker.scanned_config.configuration; | 234 | const conf = &maker.scanned_config.configuration; |
| | 235 | const newline = detectNewline(contents); |
| 221 | | 236 | |
| 222 | try w.writeAll(c_generated_line); | 237 | try w.writeAll(c_generated_line); |
| | 238 | try w.writeAll(newline); |
| 223 | | 239 | |
| 224 | var any_errors = false; | 240 | var any_errors = false; |
| 225 | var line_index: u32 = 0; | 241 | var line_index: u32 = 0; |
| 226 | var line_it = std.mem.splitScalar(u8, contents, '\n'); | 242 | 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) { |
| 228 | const last_line = line_it.index == line_it.buffer.len; | 244 | const last_line = line_it.index == line_it.buffer.len; |
| | 245 | const line = std.mem.trimEnd(u8, raw_line, "\r"); |
| 229 | | 246 | |
| 230 | const old_len = aw.written().len; | 247 | const old_len = aw.written().len; |
| 231 | expandVariablesAutoconfAt(w, line, conf, value_pairs, value_map) catch |err| switch (err) { | 248 | expandVariablesAutoconfAt(w, line, conf, value_pairs, value_map) catch |err| switch (err) { |
| ... | @@ -246,7 +263,7 @@ fn renderAutoconfAt( | ... | @@ -246,7 +263,7 @@ fn renderAutoconfAt( |
| 246 | continue; | 263 | continue; |
| 247 | }, | 264 | }, |
| 248 | }; | 265 | }; |
| 249 | if (!last_line) try w.writeByte('\n'); | 266 | if (!last_line) try w.writeAll(newline); |
| 250 | } | 267 | } |
| 251 | | 268 | |
| 252 | try ensureAllValuesUsed(maker, step, value_map, src_path); | 269 | try ensureAllValuesUsed(maker, step, value_map, src_path); |
| ... | @@ -264,16 +281,19 @@ fn renderCmake( | ... | @@ -264,16 +281,19 @@ fn renderCmake( |
| 264 | src_path: Path, | 281 | src_path: Path, |
| 265 | ) !void { | 282 | ) !void { |
| 266 | const conf = &maker.scanned_config.configuration; | 283 | const conf = &maker.scanned_config.configuration; |
| | 284 | const newline = detectNewline(contents); |
| 267 | | 285 | |
| 268 | try w.writeAll(c_generated_line); | 286 | try w.writeAll(c_generated_line); |
| | 287 | try w.writeAll(newline); |
| 269 | | 288 | |
| 270 | var any_errors = false; | 289 | var any_errors = false; |
| 271 | var line_index: u32 = 0; | 290 | var line_index: u32 = 0; |
| 272 | var line_it = std.mem.splitScalar(u8, contents, '\n'); | 291 | var line_it = std.mem.splitScalar(u8, contents, '\n'); |
| 273 | while (line_it.next()) |raw_line| : (line_index += 1) { | 292 | while (line_it.next()) |raw_line| : (line_index += 1) { |
| 274 | const last_line = line_it.index == line_it.buffer.len; | 293 | const last_line = line_it.index == line_it.buffer.len; |
| | 294 | const stripped_line = std.mem.trimEnd(u8, raw_line, "\r"); |
| 275 | | 295 | |
| 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) { |
| 277 | error.InvalidCharacter => { | 297 | error.InvalidCharacter => { |
| 278 | try step.addError(maker, "{f}:{d}: invalid character in a variable name", .{ | 298 | try step.addError(maker, "{f}:{d}: invalid character in a variable name", .{ |
| 279 | src_path, line_index + 1, | 299 | src_path, line_index + 1, |
| ... | @@ -292,7 +312,7 @@ fn renderCmake( | ... | @@ -292,7 +312,7 @@ fn renderCmake( |
| 292 | | 312 | |
| 293 | const line_start = std.mem.findNone(u8, line, " \t\r") orelse { | 313 | const line_start = std.mem.findNone(u8, line, " \t\r") orelse { |
| 294 | try w.writeAll(line); | 314 | try w.writeAll(line); |
| 295 | if (!last_line) try w.writeByte('\n'); | 315 | if (!last_line) try w.writeAll(newline); |
| 296 | continue; | 316 | continue; |
| 297 | }; | 317 | }; |
| 298 | const whitespace_prefix = line[0..line_start]; | 318 | const whitespace_prefix = line[0..line_start]; |
| ... | @@ -300,7 +320,7 @@ fn renderCmake( | ... | @@ -300,7 +320,7 @@ fn renderCmake( |
| 300 | | 320 | |
| 301 | if (!std.mem.startsWith(u8, trimmed_line, "#")) { | 321 | if (!std.mem.startsWith(u8, trimmed_line, "#")) { |
| 302 | try w.writeAll(line); | 322 | try w.writeAll(line); |
| 303 | if (!last_line) try w.writeByte('\n'); | 323 | if (!last_line) try w.writeAll(newline); |
| 304 | continue; | 324 | continue; |
| 305 | } | 325 | } |
| 306 | | 326 | |
| ... | @@ -313,7 +333,7 @@ fn renderCmake( | ... | @@ -313,7 +333,7 @@ fn renderCmake( |
| 313 | false | 333 | false |
| 314 | else { | 334 | else { |
| 315 | try w.writeAll(line); | 335 | try w.writeAll(line); |
| 316 | if (!last_line) try w.writeByte('\n'); | 336 | if (!last_line) try w.writeAll(newline); |
| 317 | continue; | 337 | continue; |
| 318 | }; | 338 | }; |
| 319 | | 339 | |
| ... | @@ -337,7 +357,7 @@ fn renderCmake( | ... | @@ -337,7 +357,7 @@ fn renderCmake( |
| 337 | try w.writeAll(whitespace_prefix); | 357 | try w.writeAll(whitespace_prefix); |
| 338 | | 358 | |
| 339 | if (booldefine) { | 359 | if (booldefine) { |
| 340 | try renderValueCBool(w, name, switch (value.unpack(conf)) { | 360 | try renderValueCBool(w, newline, name, switch (value.unpack(conf)) { |
| 341 | .undef, .defined => false, | 361 | .undef, .defined => false, |
| 342 | .bool => |b| b, | 362 | .bool => |b| b, |
| 343 | inline .u64, .i64 => |i| i != 0, | 363 | inline .u64, .i64 => |i| i != 0, |
| ... | @@ -345,9 +365,9 @@ fn renderCmake( | ... | @@ -345,9 +365,9 @@ fn renderCmake( |
| 345 | .ident => false, | 365 | .ident => false, |
| 346 | }); | 366 | }); |
| 347 | } else if (value != .undef) { | 367 | } else if (value != .undef) { |
| 348 | try renderValueCIdent(w, name, it.rest()); | 368 | try renderValueCIdent(w, newline, name, it.rest()); |
| 349 | } else { | 369 | } else { |
| 350 | try renderValueC(conf, w, name, value); | 370 | try renderValueC(conf, w, newline, name, value); |
| 351 | } | 371 | } |
| 352 | } | 372 | } |
| 353 | | 373 | |
| ... | @@ -364,6 +384,7 @@ fn renderBlank( | ... | @@ -364,6 +384,7 @@ fn renderBlank( |
| 364 | include_guard_override: ?[]const u8, | 384 | include_guard_override: ?[]const u8, |
| 365 | ) !void { | 385 | ) !void { |
| 366 | try w.writeAll(c_generated_line); | 386 | try w.writeAll(c_generated_line); |
| | 387 | try w.writeAll(os_newline); |
| 367 | | 388 | |
| 368 | const include_guard_fmt: IncludeGuardFmt = .{ | 389 | const include_guard_fmt: IncludeGuardFmt = .{ |
| 369 | .include_path = include_path, | 390 | .include_path = include_path, |
| ... | @@ -376,7 +397,7 @@ fn renderBlank( | ... | @@ -376,7 +397,7 @@ fn renderBlank( |
| 376 | \\ | 397 | \\ |
| 377 | , .{include_guard_fmt}); | 398 | , .{include_guard_fmt}); |
| 378 | | 399 | |
| 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); |
| 380 | | 401 | |
| 381 | try w.print( | 402 | try w.print( |
| 382 | \\#endif /* {f} */ | 403 | \\#endif /* {f} */ |
| ... | @@ -405,41 +426,42 @@ fn renderNasm( | ... | @@ -405,41 +426,42 @@ fn renderNasm( |
| 405 | value_map: *const ValueMap, | 426 | value_map: *const ValueMap, |
| 406 | ) !void { | 427 | ) !void { |
| 407 | try w.writeAll(asm_generated_line); | 428 | 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); |
| 409 | } | 431 | } |
| 410 | | 432 | |
| 411 | fn renderValueC(conf: *const Configuration, w: *Writer, name: []const u8, value: Value.Index) !void { | 433 | fn renderValueC(conf: *const Configuration, w: *Writer, newline: []const u8, name: []const u8, value: Value.Index) !void { |
| 412 | switch (value.unpack(conf)) { | 434 | switch (value.unpack(conf)) { |
| 413 | .undef => try w.print("/* #undef {s} */\n", .{name}), | 435 | .undef => try w.print("/* #undef {s} */{s}", .{ name, newline }), |
| 414 | .defined => try w.print("#define {s}\n", .{name}), | 436 | .defined => try w.print("#define {s}{s}", .{ name, newline }), |
| 415 | .bool => |b| return renderValueCBool(w, name, b), | 437 | .bool => |b| return renderValueCBool(w, newline, name, b), |
| 416 | inline .u64, .i64 => |i| try w.print("#define {s} {d}\n", .{ name, i }), | 438 | inline .u64, .i64 => |i| try w.print("#define {s} {d}{s}", .{ name, i, newline }), |
| 417 | .ident => |ident| return renderValueCIdent(w, name, ident), | 439 | .ident => |ident| return renderValueCIdent(w, newline, name, ident), |
| 418 | .string => |string| try w.print("#define {s} \"{f}\"\n", .{ name, std.zig.fmtString(string) }), | 440 | .string => |string| try w.print("#define {s} \"{f}\"{s}", .{ name, std.zig.fmtString(string), newline }), |
| 419 | } | 441 | } |
| 420 | } | 442 | } |
| 421 | | 443 | |
| 422 | fn renderValueCIdent(w: *Writer, name: []const u8, ident: []const u8) Writer.Error!void { | 444 | fn renderValueCIdent(w: *Writer, newline: []const u8, name: []const u8, ident: []const u8) Writer.Error!void { |
| 423 | try w.print("#define {s}", .{name}); | 445 | try w.print("#define {s}", .{name}); |
| 424 | if (ident.len > 0) { | 446 | if (ident.len > 0) { |
| 425 | try w.writeByte(' '); | 447 | try w.writeByte(' '); |
| 426 | try w.writeAll(ident); | 448 | try w.writeAll(ident); |
| 427 | } | 449 | } |
| 428 | return w.writeByte('\n'); | 450 | return w.writeAll(newline); |
| 429 | } | 451 | } |
| 430 | | 452 | |
| 431 | fn renderValueCBool(w: *Writer, name: []const u8, b: bool) Writer.Error!void { | 453 | fn renderValueCBool(w: *Writer, newline: []const u8, name: []const u8, b: bool) Writer.Error!void { |
| 432 | return w.print("#define {s} {c}\n", .{ name, @as(u8, '0') + @intFromBool(b) }); | 454 | return w.print("#define {s} {c}{s}", .{ name, @as(u8, '0') + @intFromBool(b), newline }); |
| 433 | } | 455 | } |
| 434 | | 456 | |
| 435 | fn renderValueNasm(conf: *const Configuration, w: *Writer, name: []const u8, value: Value.Index) !void { | 457 | fn renderValueNasm(conf: *const Configuration, w: *Writer, newline: []const u8, name: []const u8, value: Value.Index) !void { |
| 436 | switch (value.unpack(conf)) { | 458 | switch (value.unpack(conf)) { |
| 437 | .undef => try w.print("; %undef {s}\n", .{name}), | 459 | .undef => try w.print("; %undef {s}{s}", .{ name, newline }), |
| 438 | .defined => try w.print("%define {s}\n", .{name}), | 460 | .defined => try w.print("%define {s}{s}", .{ name, newline }), |
| 439 | .bool => |b| try w.print("%define {s} {c}\n", .{ name, @as(u8, '0') + @intFromBool(b) }), | 461 | .bool => |b| try w.print("%define {s} {c}{s}", .{ name, @as(u8, '0') + @intFromBool(b), newline }), |
| 440 | inline .u64, .i64 => |i| try w.print("%define {s} {d}\n", .{ name, i }), | 462 | inline .u64, .i64 => |i| try w.print("%define {s} {d}{s}", .{ name, i, newline }), |
| 441 | .ident => |ident| try w.print("%define {s} {s}\n", .{ name, ident }), | 463 | .ident => |ident| try w.print("%define {s} {s}{s}", .{ name, ident, newline }), |
| 442 | .string => |string| try w.print("%define {s} \"{f}\"\n", .{ name, std.zig.fmtString(string) }), | 464 | .string => |string| try w.print("%define {s} \"{f}\"{s}", .{ name, std.zig.fmtString(string), newline }), |
| 443 | } | 465 | } |
| 444 | } | 466 | } |
| 445 | | 467 | |