Skip to content
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.zig-cache/
zig-out/
zig-pkg/
.vscode/
.dim-out/
8 changes: 4 additions & 4 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
.fingerprint = 0x9947018c924eecb2,
.dependencies = .{
.zfat = .{
.url = "git+https://github.com/ZigEmbeddedGroup/zfat.git#0571b0d8c8cc4fcb037a1d5e7ea5666cb2f83ddf",
.hash = "zfat-0.15.0-SNNK9RRqcgCLQ5mjXghbB6mokzcHORsGnY7GtbfOt2k3",
.url = "git+https://github.com/khitiara/zfat?ref=0.15#4ce2a6a95d4410573dcc1c159085f554465aea04",
.hash = "zfat-0.15.0-SNNK9QCZcgBdWwpwf_lzSuKP12w2HZQnIQwT4qn8TfZi",
},
.args = .{
.url = "git+https://github.com/ikskuh/zig-args.git#8ae26b44a884ff20dca98ee84c098e8f8e94902f",
.hash = "args-0.0.0-CiLiqojRAACGzDRO7A9dw7kWSchNk29caJZkXuMCb0Cn",
.url = "git+https://github.com/khitiara/zig-args#4085c9be55dfd2eeb6893694510a2ce97e89f9fe",
.hash = "args-0.0.0-CiLiqiLSAAArS0NVwnYLAarU-u1csj8zAkg5-q4pa1n8",
},
},
.paths = .{
Expand Down
50 changes: 29 additions & 21 deletions src/BuildInterface.zig
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,20 @@ pub fn createDisk(dimmer: Interface, size: u64, content: Content) std.Build.Lazy

const write_files = b.addWriteFiles();

const script_source, const variables = renderContent(write_files, b.allocator, content);
const script_source, const variables = renderContent(write_files, b.allocator, content, dimmer.builder.graph.io);

const script_file = write_files.add("image.dis", script_source);

const compile_script = b.addRunArtifact(dimmer.dimmer_exe);

compile_script.setCwd(script_file.dirname());

_ = compile_script.addPrefixedDepFileOutputArg("--deps-file=", "image.d");

compile_script.addArg(b.fmt("--size={d}", .{size}));

compile_script.addPrefixedFileArg("--script=", script_file);
compile_script.addPrefixedDirectoryArg("--script-root=", .{ .cwd_relative = "." });
// compile_script.addPrefixedDirectoryArg("--script-root=", .{ .cwd_relative = "." });

const result_file = compile_script.addPrefixedOutputFileArg("--output=", "disk.img");

Expand Down Expand Up @@ -67,6 +69,7 @@ fn renderContent(
wfs: *std.Build.Step.WriteFile,
allocator: std.mem.Allocator,
content: Content,
io: std.Io,
) struct { []const u8, ContentWriter.VariableMap } {
var code: std.Io.Writer.Allocating = .init(allocator);
defer code.deinit();
Expand All @@ -79,7 +82,7 @@ fn renderContent(
.vars = &variables,
};

cw.render(content) catch @panic("out of memory");
cw.render(content, io) catch @panic("out of memory");

const source = std.mem.trim(
u8,
Expand Down Expand Up @@ -107,7 +110,7 @@ const ContentWriter = struct {
code: *std.Io.Writer,
vars: *VariableMap,

fn render(cw: ContentWriter, content: Content) !void {
fn render(cw: ContentWriter, content: Content, io: std.Io) !void {
// Always insert some padding before and after:
try cw.code.writeAll(" ");
errdefer cw.code.writeAll(" ") catch {};
Expand All @@ -122,15 +125,15 @@ const ContentWriter = struct {
},

.paste_file => |data| {
try cw.code.print("paste-file {f}", .{cw.fmtLazyPath(data, .file)});
try cw.code.print("paste-file {f}", .{cw.fmtLazyPath(data, .file, io)});
},

.mbr_part_table => |data| {
try cw.code.writeAll("mbr-part\n");

if (data.bootloader) |loader| {
try cw.code.writeAll(" bootloader ");
try cw.render(loader.*);
try cw.render(loader.*, io);
try cw.code.writeAll("\n");
}

Expand All @@ -151,7 +154,7 @@ const ContentWriter = struct {
try cw.code.print(" size {d}\n", .{size});
}
try cw.code.writeAll(" contains");
try cw.render(part.data);
try cw.render(part.data, io);
try cw.code.writeAll("\n");
try cw.code.writeAll(" endpart\n");
} else {
Expand Down Expand Up @@ -183,14 +186,17 @@ const ContentWriter = struct {
if (part.name) |name| {
try cw.code.print(" name \"{f}\"\n", .{std.zig.fmtString(name)});
}
if (part.part_guid) |pg| {
try cw.code.print(" guid \"{s}\"", .{&pg});
}
if (part.offset) |offset| {
try cw.code.print(" offset {d}\n", .{offset});
}
if (part.size) |size| {
try cw.code.print(" size {d}\n", .{size});
}
try cw.code.writeAll(" contains");
try cw.render(part.data);
try cw.render(part.data, io);
try cw.code.writeAll("\n");
try cw.code.writeAll(" endpart\n");
}
Expand All @@ -208,14 +214,14 @@ const ContentWriter = struct {
});
}

try cw.renderFileSystemTree(data.tree);
try cw.renderFileSystemTree(data.tree, io);

try cw.code.writeAll("endfat\n");
},
}
}

fn renderFileSystemTree(cw: ContentWriter, fs: FileSystem) !void {
fn renderFileSystemTree(cw: ContentWriter, fs: FileSystem, io: std.Io) !void {
for (fs.items) |item| {
switch (item) {
.empty_dir => |dir| try cw.code.print("mkdir {f}\n", .{
Expand All @@ -224,16 +230,16 @@ const ContentWriter = struct {

.copy_dir => |copy| try cw.code.print("copy-dir {f} {f}\n", .{
fmtPath(copy.destination),
cw.fmtLazyPath(copy.source, .directory),
cw.fmtLazyPath(copy.source, .directory, io),
}),

.copy_file => |copy| try cw.code.print("copy-file {f} {f}\n", .{
fmtPath(copy.destination),
cw.fmtLazyPath(copy.source, .file),
cw.fmtLazyPath(copy.source, .file, io),
}),

.include_script => |script| try cw.code.print("!include {f}\n", .{
cw.fmtLazyPath(script, .file),
cw.fmtLazyPath(script, .file, io),
}),
}
}
Expand Down Expand Up @@ -280,7 +286,7 @@ const ContentWriter = struct {
}
};
const LazyPathFormatter = std.fmt.Alt(
struct { ContentWriter, std.Build.LazyPath, UsageHint },
struct { ContentWriter, std.Build.LazyPath, UsageHint, std.Io },
formatLazyPath,
);
const UsageHint = enum { file, directory };
Expand All @@ -289,19 +295,20 @@ const ContentWriter = struct {
cw: ContentWriter,
path: std.Build.LazyPath,
hint: UsageHint,
io: std.Io,
) LazyPathFormatter {
return .{ .data = .{ cw, path, hint } };
return .{ .data = .{ cw, path, hint, io } };
}

fn fmtPath(path: []const u8) PathFormatter {
return .{ .path = path };
}

fn formatLazyPath(
data: struct { ContentWriter, std.Build.LazyPath, UsageHint },
data: struct { ContentWriter, std.Build.LazyPath, UsageHint, std.Io },
writer: *std.Io.Writer,
) std.Io.Writer.Error!void {
const cw, const path, const hint = data;
const cw, const path, const hint, const io = data;

switch (path) {
.cwd_relative,
Expand All @@ -314,12 +321,12 @@ const ContentWriter = struct {
const rel_path = path.getPath2(cw.wfs.step.owner, &cw.wfs.step);

const full_path = if (!std.fs.path.isAbsolute(rel_path))
std.fs.cwd().realpathAlloc(cw.wfs.step.owner.allocator, rel_path) catch @panic("oom")
std.Io.Dir.cwd().realPathFileAlloc(io, rel_path, cw.wfs.step.owner.allocator) catch @panic("oom")
else
rel_path;

if (!std.fs.path.isAbsolute(full_path)) {
const cwd = std.fs.cwd().realpathAlloc(cw.wfs.step.owner.allocator, ".") catch @panic("oom");
const cwd = std.Io.Dir.cwd().realPathFileAlloc(io, ".", cw.wfs.step.owner.allocator) catch @panic("oom");
std.debug.print("non-absolute path detected for {t}: cwd=\"{f}\" path=\"{f}\"\n", .{
path,
std.zig.fmtString(cwd),
Expand Down Expand Up @@ -414,6 +421,7 @@ pub const GptPartTable = struct {
guid: [36]u8,
},
name: ?[]const u8 = null,
part_guid: ?[36]u8 = null,
size: ?u64 = null,
offset: ?u64 = null,
data: Content,
Expand All @@ -439,12 +447,12 @@ pub const FatFs = struct {

pub const FileSystemBuilder = struct {
b: *std.Build,
list: std.ArrayListUnmanaged(FileSystem.Item),
list: std.ArrayList(FileSystem.Item),

pub fn init(b: *std.Build) FileSystemBuilder {
return FileSystemBuilder{
.b = b,
.list = .{},
.list = .empty,
};
}

Expand Down
59 changes: 31 additions & 28 deletions src/Parser.zig
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,19 @@ pub const Error = Tokenizer.Error || error{
UnknownDirective,
OutOfMemory,
InvalidEscapeSequence,
Canceled,
};

pub const IO = struct {
fetch_file_fn: *const fn (io: *const IO, std.mem.Allocator, path: []const u8) error{ FileNotFound, IoError, OutOfMemory, InvalidPath }![]const u8,
resolve_variable_fn: *const fn (io: *const IO, name: []const u8) error{UnknownVariable}![]const u8,
fetch_file_fn: *const fn (stdio: std.Io, io: *const IO, std.mem.Allocator, path: []const u8) error{ FileNotFound, IoError, OutOfMemory, InvalidPath, Canceled }![]const u8,
resolve_variable_fn: *const fn (stdio: std.Io, io: *const IO, name: []const u8) error{UnknownVariable}![]const u8,

pub fn fetch_file(io: *const IO, allocator: std.mem.Allocator, path: []const u8) error{ FileNotFound, IoError, OutOfMemory, InvalidPath }![]const u8 {
return io.fetch_file_fn(io, allocator, path);
pub fn fetch_file(io: *const IO, stdio: std.Io, allocator: std.mem.Allocator, path: []const u8) error{ FileNotFound, IoError, OutOfMemory, InvalidPath, Canceled }![]const u8 {
return io.fetch_file_fn(stdio,io, allocator, path);
}

pub fn resolve_variable(io: *const IO, name: []const u8) error{UnknownVariable}![]const u8 {
return io.resolve_variable_fn(io, name);
pub fn resolve_variable(io: *const IO, stdio: std.Io, name: []const u8) error{UnknownVariable}![]const u8 {
return io.resolve_variable_fn(stdio,io, name);
}
};

Expand Down Expand Up @@ -84,10 +85,10 @@ pub fn push_source(parser: *Parser, options: struct {
};
}

pub fn push_file(parser: *Parser, include_path: []const u8) !void {
pub fn push_file(parser: *Parser, stdio: std.Io, include_path: []const u8) !void {
const abs_include_path = try parser.get_include_path(parser.arena.allocator(), include_path);

const file_contents = try parser.io.fetch_file(parser.arena.allocator(), abs_include_path);
const file_contents = try parser.io.fetch_file(stdio , parser.arena.allocator(), abs_include_path);

const index = parser.file_stack.len;
parser.file_stack.len += 1;
Expand Down Expand Up @@ -120,14 +121,14 @@ pub fn get_include_path(parser: Parser, allocator: std.mem.Allocator, rel_includ
return abs_include_path;
}

pub fn next(parser: *Parser) (Error || error{UnexpectedEndOfFile})![]const u8 {
return if (try parser.next_or_eof()) |word|
pub fn next(parser: *Parser, stdio: std.Io) (Error || error{UnexpectedEndOfFile})![]const u8 {
return if (try parser.next_or_eof(stdio)) |word|
word
else
error.UnexpectedEndOfFile;
}

pub fn next_or_eof(parser: *Parser) Error!?[]const u8 {
pub fn next_or_eof(parser: *Parser, stdio: std.Io) Error!?[]const u8 {
fetch_loop: while (parser.file_stack.len > 0) {
const top = &parser.file_stack[parser.file_stack.len - 1];

Expand All @@ -141,7 +142,7 @@ pub fn next_or_eof(parser: *Parser) Error!?[]const u8 {
switch (token.type) {
.whitespace, .comment => unreachable,

.word, .variable, .string => return try parser.resolve_value(
.word, .variable, .string => return try parser.resolve_value(stdio,
token.type,
top.tokenizer.get_text(token),
),
Expand All @@ -152,14 +153,14 @@ pub fn next_or_eof(parser: *Parser) Error!?[]const u8 {
if (std.mem.eql(u8, directive, "!include")) {
if (try fetch_token(&top.tokenizer)) |path_token| {
const rel_include_path = switch (path_token.type) {
.word, .variable, .string => try parser.resolve_value(
.word, .variable, .string => try parser.resolve_value(stdio,
path_token.type,
top.tokenizer.get_text(path_token),
),
.comment, .directive, .whitespace => return error.BadDirective,
};

try parser.push_file(rel_include_path);
try parser.push_file(stdio, rel_include_path);
} else {
return error.ExpectedIncludePath;
}
Expand Down Expand Up @@ -189,11 +190,11 @@ fn fetch_token(tok: *Tokenizer) Tokenizer.Error!?Token {
}
}

fn resolve_value(parser: *Parser, token_type: TokenType, text: []const u8) ![]const u8 {
fn resolve_value(parser: *Parser, stdio: std.Io, token_type: TokenType, text: []const u8) ![]const u8 {
return switch (token_type) {
.word => text,

.variable => try parser.io.resolve_variable(
.variable => try parser.io.resolve_variable(stdio,
text[1..],
),

Expand All @@ -208,10 +209,12 @@ fn resolve_value(parser: *Parser, token_type: TokenType, text: []const u8) ![]co
if (!has_includes)
return content_slice;

var unescaped: std.array_list.Managed(u8) = .init(parser.arena.allocator());
defer unescaped.deinit();
const allocator = parser.arena.allocator();

try unescaped.ensureTotalCapacityPrecise(content_slice.len);
var unescaped = std.ArrayList(u8).empty;
defer unescaped.deinit(allocator);

try unescaped.ensureTotalCapacityPrecise(allocator, content_slice.len);

{
var i: usize = 0;
Expand All @@ -220,7 +223,7 @@ fn resolve_value(parser: *Parser, token_type: TokenType, text: []const u8) ![]co
i += 1;

if (c != '\\') {
try unescaped.append(c);
try unescaped.append(allocator, c);
continue;
}

Expand All @@ -233,20 +236,20 @@ fn resolve_value(parser: *Parser, token_type: TokenType, text: []const u8) ![]co
errdefer std.log.err("invalid escape sequence: \\{s}", .{[_]u8{esc_code}});

switch (esc_code) {
'r' => try unescaped.append('\r'),
'n' => try unescaped.append('\n'),
't' => try unescaped.append('\t'),
'\\' => try unescaped.append('\\'),
'\"' => try unescaped.append('\"'),
'\'' => try unescaped.append('\''),
'e' => try unescaped.append('\x1B'),
'r' => try unescaped.append(allocator, '\r'),
'n' => try unescaped.append(allocator, '\n'),
't' => try unescaped.append(allocator, '\t'),
'\\' => try unescaped.append(allocator, '\\'),
'\"' => try unescaped.append(allocator, '\"'),
'\'' => try unescaped.append(allocator, '\''),
'e' => try unescaped.append(allocator, '\x1B'),

else => return error.InvalidEscapeSequence,
}
}
}

return try unescaped.toOwnedSlice();
return try unescaped.toOwnedSlice(allocator);
},

.comment, .directive, .whitespace => unreachable,
Expand Down
6 changes: 4 additions & 2 deletions src/components/EmptyData.zig
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@ const dim = @import("../dim.zig");

const EmptyData = @This();

pub fn parse(ctx: dim.Context) !dim.Content {
pub fn parse(ctx: dim.Context, stdio: std.Io) !dim.Content {
_ = ctx;
_ = stdio;
return .create_handle(undefined, .create(@This(), .{
.render_fn = render,
}));
}

fn render(self: *EmptyData, stream: *dim.BinaryStream) dim.Content.RenderError!void {
fn render(self: *EmptyData, io: std.Io, stream: *dim.BinaryStream) dim.Content.RenderError!void {
_ = self;
_ = stream;
_ = io;
}
Loading
Loading