From 0f788c3fd76b25c1c6355756d62398d1e4236ccd Mon Sep 17 00:00:00 2001 From: Aqua-sama Date: Mon, 25 May 2020 19:17:01 +0300 Subject: Add dump subcommand --- src/dump.zig | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.zig | 53 ++++++++--------------------- 2 files changed, 123 insertions(+), 39 deletions(-) create mode 100644 src/dump.zig diff --git a/src/dump.zig b/src/dump.zig new file mode 100644 index 0000000..a41b2be --- /dev/null +++ b/src/dump.zig @@ -0,0 +1,109 @@ +const std = @import("std"); +const adler32 = std.hash.Adler32; +const openFlags = std.fs.File.OpenFlags{ + .read = true, + .write = false, + .lock = std.fs.File.Lock.None, +}; +const output_flags = std.fs.File.CreateFlags{ + .read = false, + .truncate = true, + .exclusive = false, + .lock = std.fs.File.Lock.None, +}; + +fn help(args: [][]u8) u8 { + std.debug.warn( + \\Usage: {} {} [-h] [-o OUTPUT] input ... + \\ + \\Optional arguments: + \\ -h, --help show this help message and exit + \\ -o, --output OUTPUT output header file (by default, stdout) + \\ + \\Positional arguments: + \\ input one or more input files + \\ + , .{ args[0], args[1] }); + return if (args.len < 3) 255 else 0; +} + +pub fn cmd(args: [][]u8) u8 { + if (args.len < 3) { + return help(args); + } + + const State = enum { + Start, + OptionOutput, + }; + + var output_file: ?std.fs.File = null; + defer if (output_file != null) output_file.?.close(); + + var input_index: ?usize = null; + var state: State = State.Start; + + parse_args: for (args[2..args.len]) |c, i| { + switch (state) { + State.Start => { + switch (adler32.hash(c)) { + adler32.hash("-h"), adler32.hash("--help") => return help(args), + adler32.hash("-o"), adler32.hash("--output") => state = State.OptionOutput, + else => { + if (input_index == null) { + input_index = i; + break :parse_args; + } + }, + } + }, + State.OptionOutput => { + output_file = switch (std.fs.path.isAbsolute(c)) { + true => std.fs.createFileAbsolute(c, output_flags) catch return 128, + false => std.fs.cwd().createFile(c, output_flags) catch return 128, + }; + state = State.Start; + }, + } + } + + var output = (output_file orelse std.io.getStdOut()).outStream(); + + if (input_index == null) + return help(args); + + for (args[2 + input_index.? .. args.len]) |path| { + output.print("// {}\n", .{path}) catch return 1; + hexdump(output, path, path) catch std.debug.warn("// Could not read file '{}'\n", .{path}); + } + + return 0; +} + +fn hexdump(out: std.fs.File.OutStream, path: []const u8, name: []const u8) !void { + var file = switch (std.fs.path.isAbsolute(path)) { + true => try std.fs.openFileAbsolute(path, openFlags), + false => try std.fs.cwd().openFile(path, openFlags), + }; + defer file.close(); + + var buffer: [16]u8 = undefined; + var r: u64 = undefined; + var l: u64 = 0; + + try out.print("constexpr uint8_t {}_data[] = {{\n", .{name}); + while (true) { + r = file.read(&buffer) catch break; + if (r <= 0) + break; + + l += r; + try out.print(" ", .{}); + for (buffer[0..r]) |c| { + try out.print("0x{x:2}, ", .{c}); + } + try out.print("\n", .{}); + } + try out.print("}};\n", .{}); + try out.print("constexpr size_t {}_len = {};\n\n", .{ name, l }); +} diff --git a/src/main.zig b/src/main.zig index 1b8f702..c45cbed 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,43 +1,19 @@ const std = @import("std"); +const dump = @import("dump.zig"); const adler32 = std.hash.Adler32; -const openFlags = std.fs.File.OpenFlags{ - .read = true, - .write = false, - .lock = std.fs.File.Lock.None, -}; - -fn dump(args: [][]u8) u8 { - if (args.len < 3) { - std.debug.warn("Usage: {} [subcommand] [options]\n", .{args[0]}); - return 255; - } - - var file = std.fs.openFileAbsolute(args[2], openFlags) catch { - std.debug.warn("Cannot open file {}\n", .{args[2]}); - return 255; - }; - defer file.close(); - - var buffer: [16]u8 = undefined; - var r: u64 = undefined; - while (true) { - r = file.read(&buffer) catch { - break; - }; - if (r <= 0) - break; - - for (buffer[0..r]) |c| { - std.debug.warn("0x{x:2} ", .{c}); - } - std.debug.warn(" -- {}\n", .{r}); - } - - return 0; -} fn help(args: [][]u8) u8 { - std.debug.warn("Usage: {} [subcommand] [options]\n", .{args[0]}); + std.debug.warn( + \\Usage: {} [subcommand] [options] + \\ + \\Resource Compiler for C++ + \\ + \\Subcommands: + \\ dump [options] inputs hexdump the input files + \\ + \\For a full list of subcommand options, use [subcommand] --help + \\ + , .{args[0]}); return if (args.len < 2) 255 else 0; } @@ -45,15 +21,14 @@ pub fn main() anyerror!u8 { var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer arena.deinit(); - std.debug.warn("All your codebase are belong to us.\n\n", .{}); - const args = try std.process.argsAlloc(&arena.allocator); if (args.len < 2) { return help(args); } return switch (adler32.hash(args[1])) { - adler32.hash("dump") => dump(args), + adler32.hash("dump") => dump.cmd(args), + adler32.hash("-h"), adler32.hash("--help") => help(args), else => help(args), }; } -- cgit v1.2.1