summaryrefslogtreecommitdiff
path: root/src/eval.zig
blob: 17486aaf83fb701d26445abd634452a205da4e07 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
const std = @import("std");
const print = std.debug.print;
const ArrayList = std.ArrayList;
const Allocator = std.mem.Allocator;
const Thread = std.Thread;
const Mutex = std.Thread.Mutex;

const c = @cImport({
    @cInclude("errno.h");
    @cInclude("stdio.h");
    if (@import("builtin").os.tag != .windows) {
        @cInclude("sys/statvfs.h");
    }
});

const cmd = @import("cmd.zig");
const Command = cmd.Command;
const BuiltinCommand = cmd.BuiltinCommand;

const syntax = @import("syntax.zig");
const FileSpec = syntax.FileSpec;
const RedirectType = syntax.RedirectType;
const Redirect = syntax.Redirect;

const cmdTypes = @import("cmd/lib/types.zig");
pub const CommandStatus = cmdTypes.CommandStatus;
const OutputCapture = cmdTypes.OutputCapture;
const InputSource = cmdTypes.InputSource;
const CommandContext = cmdTypes.CommandContext;

const STDOUT_BUFFER_SIZE: usize = 1024;
const STDERR_BUFFER_SIZE: usize = 1024;

pub fn executeCommand(command: Command, allocator: Allocator) !CommandStatus {
    return executeCommandWithOutput(command, allocator, null, null);
}

pub fn executeCommandWithOutput(command: Command, allocator: Allocator, output_capture: ?*OutputCapture, input_source: ?*InputSource) !CommandStatus {
    const ctx = CommandContext.init(allocator, output_capture, input_source, executeCommandWithOutput);

    switch (command) {
        .Empty => return CommandStatus{ .Code = 0 },

        .Builtin => |builtin_cmd| {
            switch (builtin_cmd) {
                .EchoText => |echo_text| {
                    return echo_text.eval(ctx);
                },
                .Cls => |cls| {
                    return cls.eval(ctx);
                },
                .Exit => {
                    return CommandStatus.ExitShell;
                },
                .EchoPlain => |echo_plain| {
                    return echo_plain.eval(ctx);
                },
                .EchoOn => |echo_on| {
                    return echo_on.eval(ctx);
                },
                .EchoOff => |echo_off| {
                    return echo_off.eval(ctx);
                },
                .Ver => |ver| {
                    return ver.eval(ctx);
                },
                .Date => |date| {
                    return date.eval(ctx);
                },
                .Time => |time| {
                    return time.eval(ctx);
                },
                .Dir => |dir| {
                    return dir.eval(ctx);
                },
                .Type => |type_cmd| {
                    return type_cmd.eval(ctx);
                },
                .Sort => |sort| {
                    return sort.eval(ctx);
                },
                .Chdir => |chdir| {
                    return chdir.eval(ctx);
                },
                .Copy => |copy| {
                    return copy.eval(ctx);
                },
                .Remove => |remove| {
                    return remove.eval(ctx);
                },
                .Mkdir => |mkdir| {
                    return mkdir.eval(ctx);
                },
                .Rmdir => |rmdir| {
                    return rmdir.eval(ctx);
                },
                .Rename => |rename| {
                    return rename.eval(ctx);
                },
                .Move => |move| {
                    return move.eval(ctx);
                },
                .PathGet => |path_get| {
                    return path_get.eval(ctx);
                },
                .PathSet => |path_set| {
                    return path_set.eval(ctx);
                },
                else => {
                    const error_msg = try std.fmt.allocPrint(ctx.allocator, "Command not implemented: {any}\n", .{builtin_cmd});
                    defer ctx.allocator.free(error_msg);
                    if (ctx.output_capture) |capture| {
                        try capture.write(error_msg);
                    } else {
                        print("{s}", .{error_msg});
                    }
                    return CommandStatus{ .Code = 1 };
                },
            }
        },

        .External => |external| {
            return external.eval(ctx);
        },

        .Redirect => |redirect| {
            return redirect.eval(ctx);
        },

        .Pipe => |pipe| {
            return pipe.eval(ctx);
        },
    }
}