From 422cd2502ce2c4ff73f1979fdad2907d900e510d Mon Sep 17 00:00:00 2001 From: Luna Date: Thu, 8 Aug 2019 20:13:49 -0300 Subject: [PATCH 1/3] lang: add basic argument validation --- src/lang.zig | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/src/lang.zig b/src/lang.zig index cf5b1e6..7b6ec82 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -6,6 +6,7 @@ pub const ParseError = error{ NoCommandGiven, UnknownCommand, ArgRequired, + FloatParseFail, }; pub const CommandType = enum { @@ -232,6 +233,40 @@ pub const Lang = struct { return null; } + fn expectSingle(self: *Lang, args: ArgList) !void { + if (args.len != 1) { + std.debug.warn("expected 1 argument, found {}\n", args.len); + return error.ArgRequired; + } + } + + fn expectFloat(self: *Lang, count: usize, args: ArgList) !void { + var i: usize = 0; + + if (args.len != count) { + std.debug.warn("expected {} arguments, found {}\n", count, args.len); + return error.ArgRequired; + } + + while (i < count) : (i += 1) { + var arg = args.at(i); + + _ = std.fmt.parseFloat(f32, arg) catch |err| { + std.debug.warn("failed to parse f32: {}\n", err); + return error.FloatParseFail; + }; + } + } + + fn validateCommand(self: *Lang, cmd: *Command) !void { + switch (cmd.command) { + .Quicksave, .Noop => {}, + .Load, .RunQS => try self.expectSingle(cmd.args), + .Amp => try self.expectFloat(3, cmd.args), + else => std.debug.warn("WARN unchecked command {}\n", cmd.command), + } + } + pub fn parse(self: *Lang, data: []const u8) !CommandList { var splitted_it = std.mem.separate(data, ";"); try self.fillKeywords(); @@ -261,14 +296,17 @@ pub const Lang = struct { } var args = ArgList.init(self.allocator); - while (tok_it.next()) |arg| { try args.append(arg); } // construct final Command based on command var cmd_ptr = try self.allocator.create(Command); + errdefer self.allocator.destroy(cmd_ptr); + cmd_ptr.* = Command{ .command = ctype, .args = args }; + try self.validateCommand(cmd_ptr); + try cmds.append(cmd_ptr); } From ab2e8884b83f33d185c2cb15c8d718348bd2c6c1 Mon Sep 17 00:00:00 2001 From: Luna Date: Thu, 8 Aug 2019 20:24:25 -0300 Subject: [PATCH 2/3] lang: add arg checks for the other commands --- src/lang.zig | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/lang.zig b/src/lang.zig index 7b6ec82..882cac9 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -233,13 +233,17 @@ pub const Lang = struct { return null; } - fn expectSingle(self: *Lang, args: ArgList) !void { - if (args.len != 1) { - std.debug.warn("expected 1 argument, found {}\n", args.len); + fn expectAny(self: *Lang, count: usize, args: ArgList) !void { + if (args.len != count) { + std.debug.warn("expected {} arguments, found {}\n", count, args.len); return error.ArgRequired; } } + fn expectSingle(self: *Lang, args: ArgList) !void { + return try self.expectAny(1, args); + } + fn expectFloat(self: *Lang, count: usize, args: ArgList) !void { var i: usize = 0; @@ -263,6 +267,21 @@ pub const Lang = struct { .Quicksave, .Noop => {}, .Load, .RunQS => try self.expectSingle(cmd.args), .Amp => try self.expectFloat(3, cmd.args), + .RFlanger => try self.expectFloat(4, cmd.args), + .Eq => try self.expectFloat(5, cmd.args), + .Phaser => try self.expectFloat(6, cmd.args), + .Mbeq => try self.expectFloat(15, cmd.args), + .Chorus => try self.expectFloat(8, cmd.args), + .PitchScaler => try self.expectFloat(3, cmd.args), + .Reverb => try self.expectFloat(12, cmd.args), + .Highpass => try self.expectFloat(5, cmd.args), + .Delay => try self.expectFloat(12, cmd.args), + .Vinyl => try self.expectFloat(7, cmd.args), + .RevDelay => try self.expectFloat(5, cmd.args), + .Noise => try self.expectFloat(4, cmd.args), + .WildNoise => try self.expectFloat(4, cmd.args), + .Write => try self.expectFloat(3, cmd.args), + .Rotate => try self.expectAny(2, cmd.args), else => std.debug.warn("WARN unchecked command {}\n", cmd.command), } } From 90bc830a9a46186e19504164072c3bdac140f550 Mon Sep 17 00:00:00 2001 From: Luna Date: Thu, 8 Aug 2019 20:27:24 -0300 Subject: [PATCH 3/3] lang: show line where error happened --- src/image.zig | 2 +- src/lang.zig | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/image.zig b/src/image.zig index e031c5a..17a545d 100644 --- a/src/image.zig +++ b/src/image.zig @@ -193,7 +193,7 @@ pub const Image = struct { sseek(out_file, start); while (i <= end) : (i += buf.len) { - std.debug.warn("i={}, buf.len={}, end={}\n", i, buf.len, end); + std.debug.warn("\t\ti={}, buf.len={}, end={}\n", i, buf.len, end); sseek(self.sndfile, i); sseek(out_file, i); diff --git a/src/lang.zig b/src/lang.zig index 882cac9..79d38d0 100644 --- a/src/lang.zig +++ b/src/lang.zig @@ -7,6 +7,7 @@ pub const ParseError = error{ UnknownCommand, ArgRequired, FloatParseFail, + ParseFail, }; pub const CommandType = enum { @@ -290,6 +291,7 @@ pub const Lang = struct { var splitted_it = std.mem.separate(data, ";"); try self.fillKeywords(); var cmds = CommandList.init(self.allocator); + var idx: usize = 0; while (splitted_it.next()) |stmt_orig| { var stmt = std.mem.trimRight(u8, stmt_orig, "\n"); @@ -324,9 +326,13 @@ pub const Lang = struct { errdefer self.allocator.destroy(cmd_ptr); cmd_ptr.* = Command{ .command = ctype, .args = args }; - try self.validateCommand(cmd_ptr); + self.validateCommand(cmd_ptr) catch |err| { + std.debug.warn("error at line {}: {}\n", idx, err); + return ParseError.ParseFail; + }; try cmds.append(cmd_ptr); + idx += 1; } return cmds;