| ... | @@ -4,22 +4,35 @@ const std = @import("std"); | ... | @@ -4,22 +4,35 @@ const std = @import("std"); |
| 4 | const Io = std.Io; | 4 | const Io = std.Io; |
| 5 | const Configuration = std.Build.Configuration; | 5 | const Configuration = std.Build.Configuration; |
| 6 | const Writer = std.Io.Writer; | 6 | const Writer = std.Io.Writer; |
| | 7 | const Path = std.Build.Cache.Path; |
| | 8 | const Allocator = std.mem.Allocator; |
| 7 | | 9 | |
| 8 | const Step = @import("../Step.zig"); | 10 | const Step = @import("../Step.zig"); |
| 9 | const Maker = @import("../../Maker.zig"); | 11 | const Maker = @import("../../Maker.zig"); |
| 10 | | 12 | |
| | 13 | const header_text = "This file was generated by ConfigHeader using the Zig Build System."; |
| | 14 | const c_generated_line = "/* " ++ header_text ++ " */\n"; |
| | 15 | const asm_generated_line = "; " ++ header_text ++ "\n"; |
| | 16 | |
| 11 | pub fn make( | 17 | pub fn make( |
| 12 | config_header: *ConfigHeader, | 18 | config_header: *ConfigHeader, |
| 13 | step_index: Configuration.Step.Index, | 19 | step_index: Configuration.Step.Index, |
| 14 | maker: *Maker, | 20 | maker: *Maker, |
| 15 | progress_node: std.Progress.Node, | 21 | progress_node: std.Progress.Node, |
| 16 | ) Step.ExtendedMakeError!void { | 22 | ) Step.ExtendedMakeError!void { |
| | 23 | _ = config_header; |
| | 24 | _ = progress_node; |
| 17 | const graph = maker.graph; | 25 | const graph = maker.graph; |
| 18 | const arena = maker.graph.arena; // TODO don't leak into process arena | 26 | const gpa = maker.gpa; |
| 19 | const step = maker.stepByIndex(step_index); | 27 | const step = maker.stepByIndex(step_index); |
| 20 | const io = graph.io; | 28 | const io = graph.io; |
| | 29 | const arena = graph.arena; // TODO don't leak into the process arena |
| | 30 | const conf = &maker.scanned_config.configuration; |
| | 31 | const conf_step = step_index.ptr(conf); |
| | 32 | const conf_ch = conf_step.extended.get(conf.extra).config_header; |
| | 33 | const cache_root = graph.local_cache_root; |
| 21 | | 34 | |
| 22 | if (config_header.style.getPath()) |lp| | 35 | if (conf_ch.style.getPath()) |lp| |
| 23 | try step.singleUnchangingWatchInput(maker, arena, lp); | 36 | try step.singleUnchangingWatchInput(maker, arena, lp); |
| 24 | | 37 | |
| 25 | var man = graph.cache.obtain(); | 38 | var man = graph.cache.obtain(); |
| ... | @@ -29,45 +42,51 @@ pub fn make( | ... | @@ -29,45 +42,51 @@ pub fn make( |
| 29 | // random bytes when ConfigHeader implementation is modified in a | 42 | // random bytes when ConfigHeader implementation is modified in a |
| 30 | // non-backwards-compatible way. | 43 | // non-backwards-compatible way. |
| 31 | man.hash.add(@as(u32, 0xdef08d23)); | 44 | man.hash.add(@as(u32, 0xdef08d23)); |
| 32 | man.hash.addBytes(config_header.include_path); | 45 | man.hash.addBytes(conf_ch.include_path); |
| 33 | man.hash.addOptionalBytes(config_header.include_guard_override); | 46 | man.hash.addOptionalBytes(conf_ch.include_guard_override); |
| 34 | | 47 | |
| 35 | var aw: Writer.Allocating = .init(arena); | 48 | var aw: Writer.Allocating = .init(arena); |
| 36 | defer aw.deinit(); | 49 | defer aw.deinit(); |
| 37 | const bw = &aw.writer; | | |
| 38 | | 50 | |
| 39 | const header_text = "This file was generated by ConfigHeader using the Zig Build System."; | 51 | switch (conf_ch.flags.style) { |
| 40 | const c_generated_line = "/* " ++ header_text ++ " */\n"; | 52 | .autoconf_undef => { |
| 41 | const asm_generated_line = "; " ++ header_text ++ "\n"; | 53 | const src_path = try maker.resolveLazyPathIndex(arena, conf_ch.template_file.value.?, step_index); |
| 42 | | 54 | const contents = Io.Dir.cwd().readFileAlloc(io, src_path, arena, .limited(conf_ch.max_bytes)) catch |err| |
| 43 | switch (config_header.style) { | | |
| 44 | .autoconf_undef, .autoconf_at => |file_source| { | | |
| 45 | try bw.writeAll(c_generated_line); | | |
| 46 | const src_path = file_source.getPath2(b, step); | | |
| 47 | const contents = Io.Dir.cwd().readFileAlloc(io, src_path, arena, .limited(config_header.max_bytes)) catch |err| { | | |
| 48 | return step.fail("unable to read autoconf input file {s}: {t}", .{ src_path, err }); | 55 | return step.fail("unable to read autoconf input file {s}: {t}", .{ src_path, err }); |
| | 56 | renderAutoConfUndef(step, contents, &aw.writer, &conf_ch.values, src_path) catch |err| switch (err) { |
| | 57 | error.WriteFailed => return error.OutOfMemory, |
| | 58 | else => |e| return e, |
| | 59 | }; |
| | 60 | }, |
| | 61 | .autoconf_at => { |
| | 62 | const src_path = try maker.resolveLazyPathIndex(arena, conf_ch.template_file.value.?, step_index); |
| | 63 | const contents = Io.Dir.cwd().readFileAlloc(io, src_path, arena, .limited(conf_ch.max_bytes)) catch |err| |
| | 64 | return step.fail("unable to read autoconf input file {s}: {t}", .{ src_path, err }); |
| | 65 | renderAutoconfAt(step, contents, &aw, &conf_ch.values, src_path) catch |err| switch (err) { |
| | 66 | error.WriteFailed => return error.OutOfMemory, |
| | 67 | else => |e| return e, |
| 49 | }; | 68 | }; |
| 50 | switch (config_header.style) { | | |
| 51 | .autoconf_undef => try render_autoconf_undef(step, contents, bw, &config_header.values, src_path), | | |
| 52 | .autoconf_at => try render_autoconf_at(step, contents, &aw, &config_header.values, src_path), | | |
| 53 | else => unreachable, | | |
| 54 | } | | |
| 55 | }, | 69 | }, |
| 56 | .cmake => |file_source| { | 70 | .cmake => { |
| 57 | try bw.writeAll(c_generated_line); | 71 | const src_path = try maker.resolveLazyPathIndex(arena, conf_ch.template_file.value.?, step_index); |
| 58 | const src_path = file_source.getPath2(b, step); | 72 | const contents = Io.Dir.cwd().readFileAlloc(io, src_path, arena, .limited(conf_ch.max_bytes)) catch |err| |
| 59 | const contents = Io.Dir.cwd().readFileAlloc(io, src_path, arena, .limited(config_header.max_bytes)) catch |err| { | | |
| 60 | return step.fail("unable to read cmake input file {s}: {t}", .{ src_path, err }); | 73 | return step.fail("unable to read cmake input file {s}: {t}", .{ src_path, err }); |
| | 74 | renderCmake(step, contents, &aw.writer, conf_ch.values, src_path) catch |err| switch (err) { |
| | 75 | error.WriteFailed => return error.OutOfMemory, |
| | 76 | else => |e| return e, |
| 61 | }; | 77 | }; |
| 62 | try render_cmake(step, contents, bw, config_header.values, src_path); | | |
| 63 | }, | 78 | }, |
| 64 | .blank => { | 79 | .blank => { |
| 65 | try bw.writeAll(c_generated_line); | 80 | renderBlank(gpa, &aw.writer, conf_ch.values, conf_ch.include_path, conf_ch.include_guard_override) catch |err| switch (err) { |
| 66 | try render_blank(gpa, bw, config_header.values, config_header.include_path, config_header.include_guard_override); | 81 | error.WriteFailed => return error.OutOfMemory, |
| | 82 | else => |e| return e, |
| | 83 | }; |
| 67 | }, | 84 | }, |
| 68 | .nasm => { | 85 | .nasm => { |
| 69 | try bw.writeAll(asm_generated_line); | 86 | renderNasm(&aw.writer, conf_ch.values) catch |err| switch (err) { |
| 70 | try render_nasm(bw, config_header.values); | 87 | error.WriteFailed => return error.OutOfMemory, |
| | 88 | else => |e| return e, |
| | 89 | }; |
| 71 | }, | 90 | }, |
| 72 | } | 91 | } |
| 73 | | 92 | |
| ... | @@ -76,7 +95,10 @@ pub fn make( | ... | @@ -76,7 +95,10 @@ pub fn make( |
| 76 | | 95 | |
| 77 | if (try step.cacheHit(&man)) { | 96 | if (try step.cacheHit(&man)) { |
| 78 | const digest = man.final(); | 97 | const digest = man.final(); |
| 79 | config_header.generated_dir.path = try b.cache_root.join(arena, &.{ "o", &digest }); | 98 | maker.generatedPath().* = .{ |
| | 99 | .root_dir = cache_root, |
| | 100 | .sub_path = try Io.Dir.path.join(arena, &.{ "o", &digest }), |
| | 101 | }; |
| 80 | return; | 102 | return; |
| 81 | } | 103 | } |
| 82 | | 104 | |
| ... | @@ -87,35 +109,38 @@ pub fn make( | ... | @@ -87,35 +109,38 @@ pub fn make( |
| 87 | // output_path is libavutil/avconfig.h | 109 | // output_path is libavutil/avconfig.h |
| 88 | // We want to open directory zig-cache/o/HASH/libavutil/ | 110 | // We want to open directory zig-cache/o/HASH/libavutil/ |
| 89 | // but keep output_dir as zig-cache/o/HASH for -I include | 111 | // but keep output_dir as zig-cache/o/HASH for -I include |
| 90 | const sub_path = b.pathJoin(&.{ "o", &digest, config_header.include_path }); | 112 | const out_path: Path = .{ |
| 91 | const sub_path_dirname = std.fs.path.dirname(sub_path).?; | 113 | .root_dir = cache_root, |
| 92 | | 114 | .sub_path = try Io.Dir.path.join(arena, &.{ "o", &digest, conf_ch.include_path.slice(conf) }), |
| 93 | b.cache_root.handle.createDirPath(io, sub_path_dirname) catch |err| { | | |
| 94 | return step.fail("unable to make path '{f}{s}': {s}", .{ | | |
| 95 | b.cache_root, sub_path_dirname, @errorName(err), | | |
| 96 | }); | | |
| 97 | }; | 115 | }; |
| | 116 | const out_path_dirname = out_path.dirname().?; |
| | 117 | |
| | 118 | out_path_dirname.root_dir.handle.createDirPath(io, out_path_dirname.sub_path) catch |err| |
| | 119 | return step.fail("unable to make path {f}: {t}", .{ out_path_dirname, err }); |
| 98 | | 120 | |
| 99 | b.cache_root.handle.writeFile(io, .{ .sub_path = sub_path, .data = output }) catch |err| { | 121 | out_path.root_dir.handle.writeFile(io, .{ .sub_path = out_path.sub_path, .data = output }) catch |err| |
| 100 | return step.fail("unable to write file '{f}{s}': {s}", .{ | 122 | return step.fail("unable to write file {f}: {t}", .{ out_path, err }); |
| 101 | b.cache_root, sub_path, @errorName(err), | 123 | |
| 102 | }); | 124 | maker.generatedPath().* = .{ |
| | 125 | .root_dir = cache_root, |
| | 126 | .sub_path = try Io.Dir.path.join(arena, &.{ "o", &digest }), |
| 103 | }; | 127 | }; |
| 104 | | 128 | |
| 105 | config_header.generated_dir.path = try b.cache_root.join(arena, &.{ "o", &digest }); | 129 | try step.writeManifest(maker, &man); |
| 106 | try man.writeManifest(); | | |
| 107 | } | 130 | } |
| 108 | | 131 | |
| 109 | fn render_autoconf_undef( | 132 | fn renderAutoConfUndef( |
| 110 | step: *Step, | 133 | step: *Step, |
| 111 | contents: []const u8, | 134 | contents: []const u8, |
| 112 | bw: *Writer, | 135 | w: *Writer, |
| 113 | values: *const std.array_hash_map.String(Value), | 136 | values: *const std.array_hash_map.String(Value), |
| 114 | src_path: []const u8, | 137 | src_path: []const u8, |
| 115 | ) !void { | 138 | ) !void { |
| 116 | const build = step.owner; | 139 | const build = step.owner; |
| 117 | const allocator = build.allocator; | 140 | const allocator = build.allocator; |
| 118 | | 141 | |
| | 142 | try w.writeAll(c_generated_line); |
| | 143 | |
| 119 | var is_used: std.bit_set.Dynamic = try .initEmpty(allocator, values.count()); | 144 | var is_used: std.bit_set.Dynamic = try .initEmpty(allocator, values.count()); |
| 120 | defer is_used.deinit(allocator); | 145 | defer is_used.deinit(allocator); |
| 121 | | 146 | |
| ... | @@ -124,15 +149,15 @@ fn render_autoconf_undef( | ... | @@ -124,15 +149,15 @@ fn render_autoconf_undef( |
| 124 | var line_it = std.mem.splitScalar(u8, contents, '\n'); | 149 | var line_it = std.mem.splitScalar(u8, contents, '\n'); |
| 125 | while (line_it.next()) |line| : (line_index += 1) { | 150 | while (line_it.next()) |line| : (line_index += 1) { |
| 126 | if (!std.mem.startsWith(u8, line, "#")) { | 151 | if (!std.mem.startsWith(u8, line, "#")) { |
| 127 | try bw.writeAll(line); | 152 | try w.writeAll(line); |
| 128 | try bw.writeByte('\n'); | 153 | try w.writeByte('\n'); |
| 129 | continue; | 154 | continue; |
| 130 | } | 155 | } |
| 131 | var it = std.mem.tokenizeAny(u8, line[1..], " \t\r"); | 156 | var it = std.mem.tokenizeAny(u8, line[1..], " \t\r"); |
| 132 | const undef = it.next().?; | 157 | const undef = it.next().?; |
| 133 | if (!std.mem.eql(u8, undef, "undef")) { | 158 | if (!std.mem.eql(u8, undef, "undef")) { |
| 134 | try bw.writeAll(line); | 159 | try w.writeAll(line); |
| 135 | try bw.writeByte('\n'); | 160 | try w.writeByte('\n'); |
| 136 | continue; | 161 | continue; |
| 137 | } | 162 | } |
| 138 | const name = it.next().?; | 163 | const name = it.next().?; |
| ... | @@ -144,7 +169,7 @@ fn render_autoconf_undef( | ... | @@ -144,7 +169,7 @@ fn render_autoconf_undef( |
| 144 | continue; | 169 | continue; |
| 145 | }; | 170 | }; |
| 146 | is_used.set(index); | 171 | is_used.set(index); |
| 147 | try renderValueC(bw, name, values.values()[index]); | 172 | try renderValueC(w, name, values.values()[index]); |
| 148 | } | 173 | } |
| 149 | | 174 | |
| 150 | var unused_value_it = is_used.iterator(.{ .kind = .unset }); | 175 | var unused_value_it = is_used.iterator(.{ .kind = .unset }); |
| ... | @@ -158,7 +183,7 @@ fn render_autoconf_undef( | ... | @@ -158,7 +183,7 @@ fn render_autoconf_undef( |
| 158 | } | 183 | } |
| 159 | } | 184 | } |
| 160 | | 185 | |
| 161 | fn render_autoconf_at( | 186 | fn renderAutoconfAt( |
| 162 | step: *Step, | 187 | step: *Step, |
| 163 | contents: []const u8, | 188 | contents: []const u8, |
| 164 | aw: *Writer.Allocating, | 189 | aw: *Writer.Allocating, |
| ... | @@ -167,7 +192,9 @@ fn render_autoconf_at( | ... | @@ -167,7 +192,9 @@ fn render_autoconf_at( |
| 167 | ) !void { | 192 | ) !void { |
| 168 | const build = step.owner; | 193 | const build = step.owner; |
| 169 | const allocator = build.allocator; | 194 | const allocator = build.allocator; |
| 170 | const bw = &aw.writer; | 195 | const w = &aw.writer; |
| | 196 | |
| | 197 | try w.writeAll(c_generated_line); |
| 171 | | 198 | |
| 172 | const used = allocator.alloc(bool, values.count()) catch @panic("OOM"); | 199 | const used = allocator.alloc(bool, values.count()) catch @panic("OOM"); |
| 173 | for (used) |*u| u.* = false; | 200 | for (used) |*u| u.* = false; |
| ... | @@ -180,7 +207,7 @@ fn render_autoconf_at( | ... | @@ -180,7 +207,7 @@ fn render_autoconf_at( |
| 180 | const last_line = line_it.index == line_it.buffer.len; | 207 | const last_line = line_it.index == line_it.buffer.len; |
| 181 | | 208 | |
| 182 | const old_len = aw.written().len; | 209 | const old_len = aw.written().len; |
| 183 | expand_variables_autoconf_at(bw, line, values, used) catch |err| switch (err) { | 210 | expandVariablesAutoconfAt(w, line, values, used) catch |err| switch (err) { |
| 184 | error.MissingValue => { | 211 | error.MissingValue => { |
| 185 | const name = aw.written()[old_len..]; | 212 | const name = aw.written()[old_len..]; |
| 186 | defer aw.shrinkRetainingCapacity(old_len); | 213 | defer aw.shrinkRetainingCapacity(old_len); |
| ... | @@ -198,7 +225,7 @@ fn render_autoconf_at( | ... | @@ -198,7 +225,7 @@ fn render_autoconf_at( |
| 198 | continue; | 225 | continue; |
| 199 | }, | 226 | }, |
| 200 | }; | 227 | }; |
| 201 | if (!last_line) try bw.writeByte('\n'); | 228 | if (!last_line) try w.writeByte('\n'); |
| 202 | } | 229 | } |
| 203 | | 230 | |
| 204 | for (values.entries.slice().items(.key), used) |name, u| { | 231 | for (values.entries.slice().items(.key), used) |name, u| { |
| ... | @@ -211,16 +238,18 @@ fn render_autoconf_at( | ... | @@ -211,16 +238,18 @@ fn render_autoconf_at( |
| 211 | if (any_errors) return error.MakeFailed; | 238 | if (any_errors) return error.MakeFailed; |
| 212 | } | 239 | } |
| 213 | | 240 | |
| 214 | fn render_cmake( | 241 | fn renderCmake( |
| 215 | step: *Step, | 242 | step: *Step, |
| 216 | contents: []const u8, | 243 | contents: []const u8, |
| 217 | bw: *Writer, | 244 | w: *Writer, |
| 218 | values: std.array_hash_map.String(Value), | 245 | values: std.array_hash_map.String(Value), |
| 219 | src_path: []const u8, | 246 | src_path: []const u8, |
| 220 | ) !void { | 247 | ) !void { |
| 221 | const build = step.owner; | 248 | const build = step.owner; |
| 222 | const allocator = build.allocator; | 249 | const allocator = build.allocator; |
| 223 | | 250 | |
| | 251 | try w.writeAll(c_generated_line); |
| | 252 | |
| 224 | var values_copy = try values.clone(allocator); | 253 | var values_copy = try values.clone(allocator); |
| 225 | defer values_copy.deinit(allocator); | 254 | defer values_copy.deinit(allocator); |
| 226 | | 255 | |
| ... | @@ -230,7 +259,7 @@ fn render_cmake( | ... | @@ -230,7 +259,7 @@ fn render_cmake( |
| 230 | while (line_it.next()) |raw_line| : (line_index += 1) { | 259 | while (line_it.next()) |raw_line| : (line_index += 1) { |
| 231 | const last_line = line_it.index == line_it.buffer.len; | 260 | const last_line = line_it.index == line_it.buffer.len; |
| 232 | | 261 | |
| 233 | const line = expand_variables_cmake(allocator, raw_line, values) catch |err| switch (err) { | 262 | const line = expandVariablesCmake(allocator, raw_line, values) catch |err| switch (err) { |
| 234 | error.InvalidCharacter => { | 263 | error.InvalidCharacter => { |
| 235 | try step.addError("{s}:{d}: error: invalid character in a variable name", .{ | 264 | try step.addError("{s}:{d}: error: invalid character in a variable name", .{ |
| 236 | src_path, line_index + 1, | 265 | src_path, line_index + 1, |
| ... | @@ -249,16 +278,16 @@ fn render_cmake( | ... | @@ -249,16 +278,16 @@ fn render_cmake( |
| 249 | defer allocator.free(line); | 278 | defer allocator.free(line); |
| 250 | | 279 | |
| 251 | const line_start = std.mem.findNone(u8, line, " \t\r") orelse { | 280 | const line_start = std.mem.findNone(u8, line, " \t\r") orelse { |
| 252 | try bw.writeAll(line); | 281 | try w.writeAll(line); |
| 253 | if (!last_line) try bw.writeByte('\n'); | 282 | if (!last_line) try w.writeByte('\n'); |
| 254 | continue; | 283 | continue; |
| 255 | }; | 284 | }; |
| 256 | const whitespace_prefix = line[0..line_start]; | 285 | const whitespace_prefix = line[0..line_start]; |
| 257 | const trimmed_line = line[line_start..]; | 286 | const trimmed_line = line[line_start..]; |
| 258 | | 287 | |
| 259 | if (!std.mem.startsWith(u8, trimmed_line, "#")) { | 288 | if (!std.mem.startsWith(u8, trimmed_line, "#")) { |
| 260 | try bw.writeAll(line); | 289 | try w.writeAll(line); |
| 261 | if (!last_line) try bw.writeByte('\n'); | 290 | if (!last_line) try w.writeByte('\n'); |
| 262 | continue; | 291 | continue; |
| 263 | } | 292 | } |
| 264 | | 293 | |
| ... | @@ -267,8 +296,8 @@ fn render_cmake( | ... | @@ -267,8 +296,8 @@ fn render_cmake( |
| 267 | if (!std.mem.eql(u8, cmakedefine, "cmakedefine") and | 296 | if (!std.mem.eql(u8, cmakedefine, "cmakedefine") and |
| 268 | !std.mem.eql(u8, cmakedefine, "cmakedefine01")) | 297 | !std.mem.eql(u8, cmakedefine, "cmakedefine01")) |
| 269 | { | 298 | { |
| 270 | try bw.writeAll(line); | 299 | try w.writeAll(line); |
| 271 | if (!last_line) try bw.writeByte('\n'); | 300 | if (!last_line) try w.writeByte('\n'); |
| 272 | continue; | 301 | continue; |
| 273 | } | 302 | } |
| 274 | | 303 | |
| ... | @@ -339,8 +368,8 @@ fn render_cmake( | ... | @@ -339,8 +368,8 @@ fn render_cmake( |
| 339 | value = Value{ .ident = it.rest() }; | 368 | value = Value{ .ident = it.rest() }; |
| 340 | } | 369 | } |
| 341 | | 370 | |
| 342 | try bw.writeAll(whitespace_prefix); | 371 | try w.writeAll(whitespace_prefix); |
| 343 | try renderValueC(bw, name, value); | 372 | try renderValueC(w, name, value); |
| 344 | } | 373 | } |
| 345 | | 374 | |
| 346 | if (any_errors) { | 375 | if (any_errors) { |
| ... | @@ -348,13 +377,15 @@ fn render_cmake( | ... | @@ -348,13 +377,15 @@ fn render_cmake( |
| 348 | } | 377 | } |
| 349 | } | 378 | } |
| 350 | | 379 | |
| 351 | fn render_blank( | 380 | fn renderBlank( |
| 352 | gpa: std.mem.Allocator, | 381 | gpa: std.mem.Allocator, |
| 353 | bw: *Writer, | 382 | w: *Writer, |
| 354 | defines: std.array_hash_map.String(Value), | 383 | defines: std.array_hash_map.String(Value), |
| 355 | include_path: []const u8, | 384 | include_path: []const u8, |
| 356 | include_guard_override: ?[]const u8, | 385 | include_guard_override: ?[]const u8, |
| 357 | ) !void { | 386 | ) !void { |
| | 387 | try w.writeAll(c_generated_line); |
| | 388 | |
| 358 | const include_guard_name = include_guard_override orelse blk: { | 389 | const include_guard_name = include_guard_override orelse blk: { |
| 359 | const name = try gpa.dupe(u8, include_path); | 390 | const name = try gpa.dupe(u8, include_path); |
| 360 | for (name) |*byte| { | 391 | for (name) |*byte| { |
| ... | @@ -368,51 +399,52 @@ fn render_blank( | ... | @@ -368,51 +399,52 @@ fn render_blank( |
| 368 | }; | 399 | }; |
| 369 | defer if (include_guard_override == null) gpa.free(include_guard_name); | 400 | defer if (include_guard_override == null) gpa.free(include_guard_name); |
| 370 | | 401 | |
| 371 | try bw.print( | 402 | try w.print( |
| 372 | \\#ifndef {[0]s} | 403 | \\#ifndef {[0]s} |
| 373 | \\#define {[0]s} | 404 | \\#define {[0]s} |
| 374 | \\ | 405 | \\ |
| 375 | , .{include_guard_name}); | 406 | , .{include_guard_name}); |
| 376 | | 407 | |
| 377 | const values = defines.values(); | 408 | const values = defines.values(); |
| 378 | for (defines.keys(), 0..) |name, i| try renderValueC(bw, name, values[i]); | 409 | for (defines.keys(), 0..) |name, i| try renderValueC(w, name, values[i]); |
| 379 | | 410 | |
| 380 | try bw.print( | 411 | try w.print( |
| 381 | \\#endif /* {s} */ | 412 | \\#endif /* {s} */ |
| 382 | \\ | 413 | \\ |
| 383 | , .{include_guard_name}); | 414 | , .{include_guard_name}); |
| 384 | } | 415 | } |
| 385 | | 416 | |
| 386 | fn render_nasm(bw: *Writer, defines: std.array_hash_map.String(Value)) !void { | 417 | fn renderNasm(w: *Writer, defines: std.array_hash_map.String(Value)) !void { |
| 387 | for (defines.keys(), defines.values()) |name, value| try renderValueNasm(bw, name, value); | 418 | try w.writeAll(asm_generated_line); |
| | 419 | for (defines.keys(), defines.values()) |name, value| try renderValueNasm(w, name, value); |
| 388 | } | 420 | } |
| 389 | | 421 | |
| 390 | fn renderValueC(bw: *Writer, name: []const u8, value: Value) !void { | 422 | fn renderValueC(w: *Writer, name: []const u8, value: Value) !void { |
| 391 | switch (value) { | 423 | switch (value) { |
| 392 | .undef => try bw.print("/* #undef {s} */\n", .{name}), | 424 | .undef => try w.print("/* #undef {s} */\n", .{name}), |
| 393 | .defined => try bw.print("#define {s}\n", .{name}), | 425 | .defined => try w.print("#define {s}\n", .{name}), |
| 394 | .boolean => |b| try bw.print("#define {s} {c}\n", .{ name, @as(u8, '0') + @intFromBool(b) }), | 426 | .boolean => |b| try w.print("#define {s} {c}\n", .{ name, @as(u8, '0') + @intFromBool(b) }), |
| 395 | .int => |i| try bw.print("#define {s} {d}\n", .{ name, i }), | 427 | .int => |i| try w.print("#define {s} {d}\n", .{ name, i }), |
| 396 | .ident => |ident| try bw.print("#define {s} {s}\n", .{ name, ident }), | 428 | .ident => |ident| try w.print("#define {s} {s}\n", .{ name, ident }), |
| 397 | // TODO: use C-specific escaping instead of zig string literals | 429 | // TODO: use C-specific escaping instead of zig string literals |
| 398 | .string => |string| try bw.print("#define {s} \"{f}\"\n", .{ name, std.zig.fmtString(string) }), | 430 | .string => |string| try w.print("#define {s} \"{f}\"\n", .{ name, std.zig.fmtString(string) }), |
| 399 | } | 431 | } |
| 400 | } | 432 | } |
| 401 | | 433 | |
| 402 | fn renderValueNasm(bw: *Writer, name: []const u8, value: Value) !void { | 434 | fn renderValueNasm(w: *Writer, name: []const u8, value: Value) !void { |
| 403 | switch (value) { | 435 | switch (value) { |
| 404 | .undef => try bw.print("; %undef {s}\n", .{name}), | 436 | .undef => try w.print("; %undef {s}\n", .{name}), |
| 405 | .defined => try bw.print("%define {s}\n", .{name}), | 437 | .defined => try w.print("%define {s}\n", .{name}), |
| 406 | .boolean => |b| try bw.print("%define {s} {c}\n", .{ name, @as(u8, '0') + @intFromBool(b) }), | 438 | .boolean => |b| try w.print("%define {s} {c}\n", .{ name, @as(u8, '0') + @intFromBool(b) }), |
| 407 | .int => |i| try bw.print("%define {s} {d}\n", .{ name, i }), | 439 | .int => |i| try w.print("%define {s} {d}\n", .{ name, i }), |
| 408 | .ident => |ident| try bw.print("%define {s} {s}\n", .{ name, ident }), | 440 | .ident => |ident| try w.print("%define {s} {s}\n", .{ name, ident }), |
| 409 | // TODO: use nasm-specific escaping instead of zig string literals | 441 | // TODO: use nasm-specific escaping instead of zig string literals |
| 410 | .string => |string| try bw.print("%define {s} \"{f}\"\n", .{ name, std.zig.fmtString(string) }), | 442 | .string => |string| try w.print("%define {s} \"{f}\"\n", .{ name, std.zig.fmtString(string) }), |
| 411 | } | 443 | } |
| 412 | } | 444 | } |
| 413 | | 445 | |
| 414 | fn expand_variables_autoconf_at( | 446 | fn expandVariablesAutoconfAt( |
| 415 | bw: *Writer, | 447 | w: *Writer, |
| 416 | contents: []const u8, | 448 | contents: []const u8, |
| 417 | values: *const std.array_hash_map.String(Value), | 449 | values: *const std.array_hash_map.String(Value), |
| 418 | used: []bool, | 450 | used: []bool, |
| ... | @@ -437,17 +469,17 @@ fn expand_variables_autoconf_at( | ... | @@ -437,17 +469,17 @@ fn expand_variables_autoconf_at( |
| 437 | const key = contents[curr + 1 .. close_pos]; | 469 | const key = contents[curr + 1 .. close_pos]; |
| 438 | const index = values.getIndex(key) orelse { | 470 | const index = values.getIndex(key) orelse { |
| 439 | // Report the missing key to the caller. | 471 | // Report the missing key to the caller. |
| 440 | try bw.writeAll(key); | 472 | try w.writeAll(key); |
| 441 | return error.MissingValue; | 473 | return error.MissingValue; |
| 442 | }; | 474 | }; |
| 443 | const value = values.entries.slice().items(.value)[index]; | 475 | const value = values.entries.slice().items(.value)[index]; |
| 444 | used[index] = true; | 476 | used[index] = true; |
| 445 | try bw.writeAll(contents[source_offset..curr]); | 477 | try w.writeAll(contents[source_offset..curr]); |
| 446 | switch (value) { | 478 | switch (value) { |
| 447 | .undef, .defined => {}, | 479 | .undef, .defined => {}, |
| 448 | .boolean => |b| try bw.writeByte(@as(u8, '0') + @intFromBool(b)), | 480 | .boolean => |b| try w.writeByte(@as(u8, '0') + @intFromBool(b)), |
| 449 | .int => |i| try bw.print("{d}", .{i}), | 481 | .int => |i| try w.print("{d}", .{i}), |
| 450 | .ident, .string => |s| try bw.writeAll(s), | 482 | .ident, .string => |s| try w.writeAll(s), |
| 451 | } | 483 | } |
| 452 | | 484 | |
| 453 | curr = close_pos; | 485 | curr = close_pos; |
| ... | @@ -455,10 +487,10 @@ fn expand_variables_autoconf_at( | ... | @@ -455,10 +487,10 @@ fn expand_variables_autoconf_at( |
| 455 | } | 487 | } |
| 456 | } | 488 | } |
| 457 | | 489 | |
| 458 | try bw.writeAll(contents[source_offset..]); | 490 | try w.writeAll(contents[source_offset..]); |
| 459 | } | 491 | } |
| 460 | | 492 | |
| 461 | fn expand_variables_cmake( | 493 | fn expandVariablesCmake( |
| 462 | allocator: Allocator, | 494 | allocator: Allocator, |
| 463 | contents: []const u8, | 495 | contents: []const u8, |
| 464 | values: std.array_hash_map.String(Value), | 496 | values: std.array_hash_map.String(Value), |
| ... | @@ -602,7 +634,7 @@ fn testReplaceVariablesAutoconfAt( | ... | @@ -602,7 +634,7 @@ fn testReplaceVariablesAutoconfAt( |
| 602 | for (used) |*u| u.* = false; | 634 | for (used) |*u| u.* = false; |
| 603 | defer allocator.free(used); | 635 | defer allocator.free(used); |
| 604 | | 636 | |
| 605 | try expand_variables_autoconf_at(&aw.writer, contents, values, used); | 637 | try expandVariablesAutoconfAt(&aw.writer, contents, values, used); |
| 606 | | 638 | |
| 607 | for (used) |u| if (!u) return error.UnusedValue; | 639 | for (used) |u| if (!u) return error.UnusedValue; |
| 608 | try std.testing.expectEqualStrings(expected, aw.written()); | 640 | try std.testing.expectEqualStrings(expected, aw.written()); |
| ... | @@ -614,13 +646,13 @@ fn testReplaceVariablesCMake( | ... | @@ -614,13 +646,13 @@ fn testReplaceVariablesCMake( |
| 614 | expected: []const u8, | 646 | expected: []const u8, |
| 615 | values: std.array_hash_map.String(Value), | 647 | values: std.array_hash_map.String(Value), |
| 616 | ) !void { | 648 | ) !void { |
| 617 | const actual = try expand_variables_cmake(allocator, contents, values); | 649 | const actual = try expandVariablesCmake(allocator, contents, values); |
| 618 | defer allocator.free(actual); | 650 | defer allocator.free(actual); |
| 619 | | 651 | |
| 620 | try std.testing.expectEqualStrings(expected, actual); | 652 | try std.testing.expectEqualStrings(expected, actual); |
| 621 | } | 653 | } |
| 622 | | 654 | |
| 623 | test "expand_variables_autoconf_at simple cases" { | 655 | test "expandVariablesAutoconfAt simple cases" { |
| 624 | const allocator = std.testing.allocator; | 656 | const allocator = std.testing.allocator; |
| 625 | var values: std.array_hash_map.String(Value) = .init(allocator); | 657 | var values: std.array_hash_map.String(Value) = .init(allocator); |
| 626 | defer values.deinit(); | 658 | defer values.deinit(); |
| ... | @@ -716,7 +748,7 @@ test "expand_variables_autoconf_at simple cases" { | ... | @@ -716,7 +748,7 @@ test "expand_variables_autoconf_at simple cases" { |
| 716 | values.clearRetainingCapacity(); | 748 | values.clearRetainingCapacity(); |
| 717 | } | 749 | } |
| 718 | | 750 | |
| 719 | test "expand_variables_autoconf_at edge cases" { | 751 | test "expandVariablesAutoconfAt edge cases" { |
| 720 | const allocator = std.testing.allocator; | 752 | const allocator = std.testing.allocator; |
| 721 | var values: std.array_hash_map.String(Value) = .init(allocator); | 753 | var values: std.array_hash_map.String(Value) = .init(allocator); |
| 722 | defer values.deinit(); | 754 | defer values.deinit(); |
| ... | @@ -732,7 +764,7 @@ test "expand_variables_autoconf_at edge cases" { | ... | @@ -732,7 +764,7 @@ test "expand_variables_autoconf_at edge cases" { |
| 732 | values.clearRetainingCapacity(); | 764 | values.clearRetainingCapacity(); |
| 733 | } | 765 | } |
| 734 | | 766 | |
| 735 | test "expand_variables_cmake simple cases" { | 767 | test "expandVariablesCmake simple cases" { |
| 736 | const allocator = std.testing.allocator; | 768 | const allocator = std.testing.allocator; |
| 737 | var values: std.array_hash_map.String(Value) = .init(allocator); | 769 | var values: std.array_hash_map.String(Value) = .init(allocator); |
| 738 | defer values.deinit(); | 770 | defer values.deinit(); |
| ... | @@ -820,7 +852,7 @@ test "expand_variables_cmake simple cases" { | ... | @@ -820,7 +852,7 @@ test "expand_variables_cmake simple cases" { |
| 820 | try std.testing.expectError(error.MissingValue, testReplaceVariablesCMake(allocator, "${bad}", "", values)); | 852 | try std.testing.expectError(error.MissingValue, testReplaceVariablesCMake(allocator, "${bad}", "", values)); |
| 821 | } | 853 | } |
| 822 | | 854 | |
| 823 | test "expand_variables_cmake edge cases" { | 855 | test "expandVariablesCmake edge cases" { |
| 824 | const allocator = std.testing.allocator; | 856 | const allocator = std.testing.allocator; |
| 825 | var values: std.array_hash_map.String(Value) = .init(allocator); | 857 | var values: std.array_hash_map.String(Value) = .init(allocator); |
| 826 | defer values.deinit(); | 858 | defer values.deinit(); |
| ... | @@ -881,7 +913,7 @@ test "expand_variables_cmake edge cases" { | ... | @@ -881,7 +913,7 @@ test "expand_variables_cmake edge cases" { |
| 881 | try std.testing.expectError(error.InvalidCharacter, testReplaceVariablesCMake(allocator, "${str@ing}", "", values)); | 913 | try std.testing.expectError(error.InvalidCharacter, testReplaceVariablesCMake(allocator, "${str@ing}", "", values)); |
| 882 | } | 914 | } |
| 883 | | 915 | |
| 884 | test "expand_variables_cmake escaped characters" { | 916 | test "expandVariablesCmake escaped characters" { |
| 885 | const allocator = std.testing.allocator; | 917 | const allocator = std.testing.allocator; |
| 886 | var values: std.array_hash_map.String(Value) = .init(allocator); | 918 | var values: std.array_hash_map.String(Value) = .init(allocator); |
| 887 | defer values.deinit(); | 919 | defer values.deinit(); |