const std = @import("std"); const Allocator = std.mem.Allocator; const ArrayList = std.ArrayList; const syntax = @import("syntax.zig"); const FileSpec = syntax.FileSpec; const Redirect = syntax.Redirect; const Copy = @import("cmd/copy.zig").Copy; const Chdir = @import("cmd/chdir.zig").Chdir; const Remove = @import("cmd/remove.zig").Remove; const Mkdir = @import("cmd/mkdir.zig").Mkdir; const Rmdir = @import("cmd/rmdir.zig").Rmdir; const Rename = @import("cmd/rename.zig").Rename; const PathGet = @import("cmd/path.zig").PathGet; const PathSet = @import("cmd/path.zig").PathSet; const Dir = @import("cmd/dir.zig").Dir; const Type = @import("cmd/type.zig").Type; const EchoOff = @import("cmd/echo.zig").EchoOff; const EchoOn = @import("cmd/echo.zig").EchoOn; const EchoPlain = @import("cmd/echo.zig").EchoPlain; const EchoText = @import("cmd/echo.zig").EchoText; const Cls = @import("cmd/cls.zig").Cls; const Ver = @import("cmd/ver.zig").Ver; const Date = @import("cmd/date.zig").Date; const Time = @import("cmd/time.zig").Time; const Sort = @import("cmd/sort.zig").Sort; const Move = @import("cmd/move.zig").Move; const Help = @import("cmd/help.zig").Help; const External = @import("cmd/external.zig").External; const RedirectCommand = @import("cmd/redirect.zig").RedirectCommand; const PipeCommand = @import("cmd/pipe.zig").PipeCommand; pub const BuiltinCommand = union(enum) { // File-oriented Copy: Copy, Deltree: struct { path: []const u8, }, Dir: Dir, Fc, Find, Mkdir: Mkdir, Move: Move, Remove: Remove, Rename: Rename, Replace, Rmdir: Rmdir, Sort: Sort, Tree: struct { path: []const u8, }, Type: Type, Xcopy: struct { from: FileSpec, to: FileSpec, recursive: bool, }, // Shell-oriented Append, Chdir: Chdir, EchoOff: EchoOff, EchoOn: EchoOn, EchoPlain: EchoPlain, EchoText: EchoText, Exit, PathGet: PathGet, PathSet: PathSet, PromptGet, PromptSet: struct { message: []const u8, }, Set: struct { name: []const u8, value: []const u8, }, Setver, Ver: Ver, // Utilities Date: Date, Time: Time, // Screen-oriented Cls: Cls, More, // Dummies Verify, Fastopen, Smartdrv, Sizer, // For later Assign, Attrib, Chkdsk, Doskey, Dosshell, Edit, Fasthelp, Help: Help, Join, Mem, Power, Subst, Truename, // For much later, if ever Break, Chcp, Ctty, Defrag, Diskcopy, Emm386, Fdisk, Format, Interlnk, Keyb, Label, Mode, Msav, Msbackup, Mscdex, Msd, Print_: void, // 'print' is reserved in Zig Qbasic, Restore, Scandisk, Share, Sys, Undelete, Unformat, Vol, Vsafe, // Scripting Call, Choice, Echo, For, Goto, If, Pause, Prompt, Rem: struct { message: []const u8, }, Shift, }; pub const Command = union(enum) { Pipe: PipeCommand, Redirect: RedirectCommand, External: External, Builtin: BuiltinCommand, Empty, pub fn deinit(self: *Command, allocator: Allocator) void { switch (self.*) { .Pipe => |*pipe| { pipe.left.deinit(allocator); pipe.right.deinit(allocator); allocator.destroy(pipe.left); allocator.destroy(pipe.right); }, .Redirect => |*redirect| { redirect.command.deinit(allocator); allocator.destroy(redirect.command); for (redirect.redirects.items) |redir| { switch (redir.target) { .Path => |path| allocator.free(path), else => {}, } } redirect.redirects.deinit(allocator); }, .External => |*external| { allocator.free(external.program); for (external.args.items) |arg| { allocator.free(arg); } external.args.deinit(allocator); }, .Builtin => |builtin| { switch (builtin) { .Dir => |dir| allocator.free(dir.path), .Chdir => |chdir| allocator.free(chdir.path), .EchoText => |echo| allocator.free(echo.message), .Type => |type_cmd| { switch (type_cmd.file) { .Path => |path| allocator.free(path), else => {}, } }, .Copy => |copy| { switch (copy.from) { .Path => |path| allocator.free(path), else => {}, } switch (copy.to) { .Path => |path| allocator.free(path), else => {}, } }, .Remove => |remove| allocator.free(remove.path), .Mkdir => |mkdir| allocator.free(mkdir.path), .Deltree => |deltree| allocator.free(deltree.path), .Tree => |tree| allocator.free(tree.path), .Rmdir => |rmdir| allocator.free(rmdir.path), .PathSet => |pathset| allocator.free(pathset.value), .PromptSet => |promptset| allocator.free(promptset.message), .Set => |set| { allocator.free(set.name); allocator.free(set.value); }, .Rem => |rem| allocator.free(rem.message), .Help => |help| { if (help.command) |cmd| { allocator.free(cmd); } }, .Rename => |rename| { switch (rename.from) { .Path => |path| allocator.free(path), else => {}, } switch (rename.to) { .Path => |path| allocator.free(path), else => {}, } }, .Xcopy => |xcopy| { switch (xcopy.from) { .Path => |path| allocator.free(path), else => {}, } switch (xcopy.to) { .Path => |path| allocator.free(path), else => {}, } }, else => {}, } }, else => {}, } } };