summaryrefslogtreecommitdiff
path: root/src/eval.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval.zig')
-rw-r--r--src/eval.zig259
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;