diff options
Diffstat (limited to 'src/eval.zig')
-rw-r--r-- | src/eval.zig | 259 |
1 files changed, 10 insertions, 249 deletions
diff --git a/src/eval.zig b/src/eval.zig index 0fe0fde..dcf34f4 100644 --- a/src/eval.zig +++ b/src/eval.zig @@ -13,9 +13,11 @@ const c = @cImport({ } }); +const cmd = @import("cmd.zig"); +const Command = cmd.Command; +const BuiltinCommand = cmd.BuiltinCommand; + const syntax = @import("syntax.zig"); -const Command = syntax.Command; -const BuiltinCommand = syntax.BuiltinCommand; const FileSpec = syntax.FileSpec; const RedirectType = syntax.RedirectType; const Redirect = syntax.Redirect; @@ -24,69 +26,14 @@ const paths = @import("paths.zig"); const formatDosPath = paths.formatDosPath; const convertTo83 = paths.convertTo83; +const cmdTypes = @import("cmd/types.zig"); +pub const CommandStatus = cmdTypes.CommandStatus; +const OutputCapture = cmdTypes.OutputCapture; +const InputSource = cmdTypes.InputSource; + const STDOUT_BUFFER_SIZE: usize = 1024; const STDERR_BUFFER_SIZE: usize = 1024; -pub const CommandStatus = union(enum) { - Code: u16, - ExitShell, -}; - -const OutputCapture = struct { - buffer: ArrayList(u8), - - pub fn init(allocator: Allocator) OutputCapture { - return OutputCapture{ - .buffer = ArrayList(u8).init(allocator), - }; - } - - pub fn deinit(self: *OutputCapture) void { - self.buffer.deinit(); - } - - pub fn write(self: *OutputCapture, data: []const u8) !void { - try self.buffer.appendSlice(data); - } - - pub fn getContents(self: *const OutputCapture) []const u8 { - return self.buffer.items; - } -}; - -const InputSource = struct { - data: []const u8, - position: usize, - - pub fn init(data: []const u8) InputSource { - return InputSource{ - .data = data, - .position = 0, - }; - } - - pub fn readLine(self: *InputSource, allocator: Allocator) !?[]const u8 { - if (self.position >= self.data.len) { - return null; // EOF - } - - var line_end = self.position; - while (line_end < self.data.len and self.data[line_end] != '\n') { - line_end += 1; - } - - const line = self.data[self.position..line_end]; - self.position = if (line_end < self.data.len) line_end + 1 else self.data.len; - - // Remove trailing \r if present (DOS line endings) - if (line.len > 0 and line[line.len - 1] == '\r') { - return try allocator.dupe(u8, line[0 .. line.len - 1]); - } else { - return try allocator.dupe(u8, line); - } - } -}; - fn formatDosDateTime(allocator: Allocator, timestamp_secs: i64) ![]const u8 { const epoch_seconds = @as(u64, @intCast(@max(timestamp_secs, 0))); const epoch_day = @divFloor(epoch_seconds, std.time.s_per_day); @@ -544,193 +491,7 @@ fn executeCommandWithOutput(command: Command, allocator: Allocator, output_captu } }, .Copy => |copy| { - // Handle source file - const source_path = switch (copy.from) { - .Con => { - // COPY CON <file> - copy from console to file - const dest_path = switch (copy.to) { - .Con => { - const error_msg = "Cannot copy from CON to CON\n"; - if (output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } - return CommandStatus{ .Code = 1 }; - }, - .Lpt1, .Lpt2, .Lpt3, .Prn => { - const error_msg = "Cannot copy to device\n"; - if (output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } - return CommandStatus{ .Code = 1 }; - }, - .Path => |path| path, - }; - - // Create the destination file - const dest_file = std.fs.cwd().createFile(dest_path, .{}) catch |err| { - const error_msg = switch (err) { - error.AccessDenied => "Access denied\n", - error.PathAlreadyExists => "File already exists - use different name\n", - else => "Cannot create file\n", - }; - if (output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } - return CommandStatus{ .Code = 1 }; - }; - defer dest_file.close(); - - // Read from stdin and write to file until EOF (Ctrl+Z on DOS) - const stdin = std.io.getStdIn().reader(); - var line_count: u32 = 0; - - // Skip output redirection since we're doing interactive input - if (output_capture == null) { - // In interactive mode, show no prompt (DOS behavior) - } - - while (true) { - if (stdin.readUntilDelimiterOrEofAlloc(allocator, '\n', 4096)) |maybe_line| { - if (maybe_line) |line| { - defer allocator.free(line); - - // Check for Ctrl+Z (EOF marker) - if (line.len == 1 and line[0] == 26) { // ASCII 26 = Ctrl+Z - break; - } - - // Remove trailing \r if present (Windows line endings) - const clean_line = if (line.len > 0 and line[line.len - 1] == '\r') - line[0 .. line.len - 1] - else - line; - - // Write line to file with DOS line ending - try dest_file.writeAll(clean_line); - try dest_file.writeAll("\r\n"); - line_count += 1; - } else { - // EOF reached - break; - } - } else |_| { - // Error reading input - break; - } - } - - const msg = try std.fmt.allocPrint(allocator, " 1 File(s) copied\n", .{}); - defer allocator.free(msg); - if (output_capture) |capture| { - try capture.write(msg); - } else { - print("{s}", .{msg}); - } - return CommandStatus{ .Code = 0 }; - }, - .Lpt1, .Lpt2, .Lpt3, .Prn => { - const error_msg = "Cannot copy from device\n"; - if (output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } - return CommandStatus{ .Code = 1 }; - }, - .Path => |path| path, - }; - - // Handle destination - const dest_path = switch (copy.to) { - .Con => { - // Copy to console (display file contents) - const source_file = std.fs.cwd().openFile(source_path, .{}) catch |err| { - const error_msg = switch (err) { - error.FileNotFound => "File not found\n", - error.AccessDenied => "Access denied\n", - else => "Cannot access source file\n", - }; - if (output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } - return CommandStatus{ .Code = 1 }; - }; - defer source_file.close(); - - // Read and display file contents - var buffer: [4096]u8 = undefined; - while (true) { - const bytes_read = source_file.readAll(&buffer) catch { - const error_msg = "Error reading file\n"; - if (output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } - return CommandStatus{ .Code = 1 }; - }; - if (bytes_read == 0) break; - - if (output_capture) |capture| { - try capture.write(buffer[0..bytes_read]); - } else { - print("{s}", .{buffer[0..bytes_read]}); - } - - if (bytes_read < buffer.len) break; - } - - const msg = " 1 File(s) copied\n"; - if (output_capture) |capture| { - try capture.write(msg); - } else { - print("{s}", .{msg}); - } - return CommandStatus{ .Code = 0 }; - }, - .Lpt1, .Lpt2, .Lpt3, .Prn => { - const error_msg = "Cannot copy to device\n"; - if (output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } - return CommandStatus{ .Code = 1 }; - }, - .Path => |path| path, - }; - - // Regular file-to-file copy - std.fs.cwd().copyFile(source_path, std.fs.cwd(), dest_path, .{}) catch |err| { - const error_msg = switch (err) { - error.FileNotFound => "File not found\n", - error.AccessDenied => "Access denied\n", - error.PathAlreadyExists => "File already exists\n", - else => "Cannot copy file\n", - }; - if (output_capture) |capture| { - try capture.write(error_msg); - } else { - print("{s}", .{error_msg}); - } - return CommandStatus{ .Code = 1 }; - }; - - const msg = " 1 File(s) copied\n"; - if (output_capture) |capture| { - try capture.write(msg); - } else { - print("{s}", .{msg}); - } - return CommandStatus{ .Code = 0 }; + return copy.eval(allocator, output_capture, input_source); }, .Remove => |remove| { const file_path = remove.path; |