| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const ConfigHeader = @This(); | 2 | const ConfigHeader = @This(); |
| 3 | const Step = std.Build.Step; | 3 | const Step = std.Build.Step; |
| | 4 | const Allocator = std.mem.Allocator; |
| 4 | | 5 | |
| 5 | pub const Style = union(enum) { | 6 | pub const Style = union(enum) { |
| 6 | /// The configure format supported by autotools. It uses `#undef foo` to | 7 | /// The configure format supported by autotools. It uses `#undef foo` to |
| ... | @@ -292,18 +293,27 @@ fn render_cmake( | ... | @@ -292,18 +293,27 @@ fn render_cmake( |
| 292 | values: std.StringArrayHashMap(Value), | 293 | values: std.StringArrayHashMap(Value), |
| 293 | src_path: []const u8, | 294 | src_path: []const u8, |
| 294 | ) !void { | 295 | ) !void { |
| | 296 | var build = step.owner; |
| | 297 | var allocator = build.allocator; |
| | 298 | |
| 295 | var values_copy = try values.clone(); | 299 | var values_copy = try values.clone(); |
| 296 | defer values_copy.deinit(); | 300 | defer values_copy.deinit(); |
| 297 | | 301 | |
| 298 | var any_errors = false; | 302 | var any_errors = false; |
| 299 | var line_index: u32 = 0; | 303 | var line_index: u32 = 0; |
| 300 | var line_it = std.mem.splitScalar(u8, contents, '\n'); | 304 | var line_it = std.mem.splitScalar(u8, contents, '\n'); |
| 301 | while (line_it.next()) |line| : (line_index += 1) { | 305 | while (line_it.next()) |raw_line| : (line_index += 1) { |
| 302 | // if we reached the end of the buffer there is nothing worth doing anymore | 306 | // if we reached the end of the buffer there is nothing worth doing anymore |
| 303 | if (line_it.index == line_it.buffer.len) { | 307 | if (line_it.index == line_it.buffer.len) { |
| 304 | continue; | 308 | continue; |
| 305 | } | 309 | } |
| 306 | | 310 | |
| | 311 | const first_pass = replace_variables(allocator, raw_line, values, "@", "@") catch @panic("Failed to substitute"); |
| | 312 | const line = replace_variables(allocator, first_pass, values, "${", "}") catch @panic("Failed to substitute"); |
| | 313 | |
| | 314 | allocator.free(first_pass); |
| | 315 | defer allocator.free(line); |
| | 316 | |
| 307 | if (!std.mem.startsWith(u8, line, "#")) { | 317 | if (!std.mem.startsWith(u8, line, "#")) { |
| 308 | try output.appendSlice(line); | 318 | try output.appendSlice(line); |
| 309 | try output.appendSlice("\n"); | 319 | try output.appendSlice("\n"); |
| ... | @@ -491,3 +501,65 @@ fn renderValueNasm(output: *std.ArrayList(u8), name: []const u8, value: Value) ! | ... | @@ -491,3 +501,65 @@ fn renderValueNasm(output: *std.ArrayList(u8), name: []const u8, value: Value) ! |
| 491 | }, | 501 | }, |
| 492 | } | 502 | } |
| 493 | } | 503 | } |
| | 504 | |
| | 505 | fn replace_variables( |
| | 506 | allocator: Allocator, |
| | 507 | contents: []const u8, |
| | 508 | values: std.StringArrayHashMap(Value), |
| | 509 | prefix: []const u8, |
| | 510 | suffix: []const u8, |
| | 511 | ) ![]const u8 { |
| | 512 | var content_buf = allocator.dupe(u8, contents) catch @panic("OOM"); |
| | 513 | |
| | 514 | var last_index: usize = 0; |
| | 515 | while (std.mem.indexOfPos(u8, content_buf, last_index, prefix)) |prefix_index| { |
| | 516 | const start_index = prefix_index + prefix.len; |
| | 517 | if (std.mem.indexOfPos(u8, content_buf, start_index, suffix)) |suffix_index| { |
| | 518 | const end_index = suffix_index + suffix.len; |
| | 519 | |
| | 520 | const beginline = content_buf[0..prefix_index]; |
| | 521 | const endline = content_buf[end_index..]; |
| | 522 | const key = content_buf[start_index..suffix_index]; |
| | 523 | const value = values.get(key) orelse .undef; |
| | 524 | |
| | 525 | switch (value) { |
| | 526 | .boolean => |b| { |
| | 527 | const buf = try std.fmt.allocPrint(allocator, "{s}{}{s}", .{ beginline, @intFromBool(b), endline }); |
| | 528 | last_index = start_index + 1; |
| | 529 | |
| | 530 | allocator.free(content_buf); |
| | 531 | content_buf = buf; |
| | 532 | }, |
| | 533 | .int => |i| { |
| | 534 | const buf = try std.fmt.allocPrint(allocator, "{s}{}{s}", .{ beginline, i, endline }); |
| | 535 | const isNegative = i < 0; |
| | 536 | const digits = (if (0 < i) std.math.log10(std.math.absCast(i)) else 0) + 1; |
| | 537 | last_index = start_index + @intFromBool(isNegative) + digits + 1; |
| | 538 | |
| | 539 | allocator.free(content_buf); |
| | 540 | content_buf = buf; |
| | 541 | }, |
| | 542 | .string => |string| { |
| | 543 | const buf = try std.fmt.allocPrint(allocator, "{s}{s}{s}", .{ beginline, string, endline }); |
| | 544 | last_index = start_index + string.len + 1; |
| | 545 | |
| | 546 | allocator.free(content_buf); |
| | 547 | content_buf = buf; |
| | 548 | }, |
| | 549 | |
| | 550 | else => { |
| | 551 | const buf = try std.fmt.allocPrint(allocator, "{s}{s}", .{ beginline, endline }); |
| | 552 | last_index = start_index + 1; |
| | 553 | |
| | 554 | allocator.free(content_buf); |
| | 555 | content_buf = buf; |
| | 556 | }, |
| | 557 | } |
| | 558 | continue; |
| | 559 | } |
| | 560 | |
| | 561 | last_index = start_index + 1; |
| | 562 | } |
| | 563 | |
| | 564 | return content_buf; |
| | 565 | } |