authorgravatar for sentrycraft123@gmail.comJan200101 <sentrycraft123@gmail.com> 2023-06-21 21:50:55+02:00
committergravatar for sentrycraft123@gmail.comJan200101 <sentrycraft123@gmail.com> 2023-06-21 21:51:07+02:00
log1864ba2cccea8452c319bf2cb9787ecb41d44a34
treeee1db767578097c069923e035db24e71f7b7ea42
parent5177068c885cb2377bc6058c81418318b9cfdb9c
signaturelock-open Commit is signed but in an unrecognized format.

std.Build: implement variable substitution


1 files changed, 73 insertions(+), 1 deletions(-)

lib/std/Build/Step/ConfigHeader.zig+73-1
......@@ -1,6 +1,7 @@
11const std = @import("std");
22const ConfigHeader = @This();
33const Step = std.Build.Step;
4const Allocator = std.mem.Allocator;
45
56pub const Style = union(enum) {
67 /// The configure format supported by autotools. It uses `#undef foo` to
......@@ -292,18 +293,27 @@ fn render_cmake(
292293 values: std.StringArrayHashMap(Value),
293294 src_path: []const u8,
294295) !void {
296 var build = step.owner;
297 var allocator = build.allocator;
298
295299 var values_copy = try values.clone();
296300 defer values_copy.deinit();
297301
298302 var any_errors = false;
299303 var line_index: u32 = 0;
300304 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) {
302306 // if we reached the end of the buffer there is nothing worth doing anymore
303307 if (line_it.index == line_it.buffer.len) {
304308 continue;
305309 }
306310
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
307317 if (!std.mem.startsWith(u8, line, "#")) {
308318 try output.appendSlice(line);
309319 try output.appendSlice("\n");
......@@ -491,3 +501,65 @@ fn renderValueNasm(output: *std.ArrayList(u8), name: []const u8, value: Value) !
491501 },
492502 }
493503}
504
505fn 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}