srctree

Gregory Mullen parent 885af3a0 b81d2824 552e5bd5
Merge branch 'steampunkengine/set'

src/builtins/set.zig added: 147, removed: 23, total 124
@@ -14,7 +14,7 @@ pub const Set = @This();
pub const Opts = enum(u8) {
Export = 'a',
BgJob = 'b',
NoColbber = 'C',
NoClobber = 'C',
ErrExit = 'e',
PathExpan = 'f',
HashAll = 'h',
@@ -64,21 +64,54 @@ const OptState = union(OOptions) {
vi: ?bool,
xtrace: ?bool,
};
const KnOptions = std.ArrayList(OptState);
 
pub const KnOptions = struct {
allexport: ?bool,
errexit: ?bool,
ignoreeof: ?bool,
monitor: ?bool,
noclobber: ?bool,
noglob: ?bool,
noexec: ?bool,
nolog: ?bool,
notify: ?bool,
nounset: ?bool,
verbose: ?bool,
vi: ?bool,
xtrace: ?bool,
 
pub fn init() KnOptions {
return KnOptions {
.allexport = false,
.errexit = false,
.ignoreeof = false,
.monitor = false,
.noclobber = false,
.noglob = false,
.noexec = false,
.nolog = false,
.notify = false,
.nounset = false,
.verbose = false,
.vi = false,
.xtrace = false,
};
}
};
 
var known_options: KnOptions = undefined;
 
pub fn init(a: std.mem.Allocator) void {
known_options = KnOptions.init(a);
pub fn init() void {
known_options = KnOptions.init();
hsh.addState(State{
.name = "set",
.ctx = &.{},
.ctx = &known_options,
.api = &.{ .save = save },
}) catch unreachable;
}
 
pub fn raze() void {
known_options.clearAndFree();
return nop();
}
 
fn save(_: *HSH, _: *anyopaque) ?[][]const u8 {
@@ -92,7 +125,7 @@ fn enable(h: *HSH, o: Opts) !void {
switch (o) {
.Export => return nop(),
.BgJob => return nop(),
.NoColbber => return nop(),
.NoClobber => known_options.noclobber = true,
.ErrExit => return nop(),
.PathExpan => return nop(),
.HashAll => return nop(),
@@ -108,7 +141,7 @@ fn disable(h: *HSH, o: Opts) !void {
switch (o) {
.Export => return nop(),
.BgJob => return nop(),
.NoColbber => return nop(),
.NoClobber => known_options.noclobber = false,
.ErrExit => return nop(),
.PathExpan => return nop(),
.HashAll => return nop(),
@@ -152,6 +185,10 @@ fn dump(h: *HSH) Err!u8 {
return 0;
}
 
pub fn get_noclobber() bool {
return known_options.noclobber;
}
 
pub fn set(h: *HSH, titr: *ParsedIterator) Err!u8 {
if (!std.mem.eql(u8, titr.first().cannon(), "set")) return Err.InvalidCommand;
 
@@ -186,4 +223,4 @@ pub fn set(h: *HSH, titr: *ParsedIterator) Err!u8 {
return dump(h);
}
return 0;
}
}
No newline at end of file
 
src/exec.zig added: 147, removed: 23, total 124
@@ -15,12 +15,15 @@ const ParsedIterator = parse.ParsedIterator;
const log = @import("log");
const mem = std.mem;
const fd_t = std.os.fd_t;
const fs = @import("fs.zig");
const bi = @import("builtins.zig");
const signal = @import("signals.zig");
const logic_ = @import("logic.zig");
const Variables = @import("variables.zig");
 
const fs = @import("fs.zig");
const noclobberError = fs.Error.Noclobber;
const clobberMode = fs.clobberMode;
 
const STDIN_FILENO = std.os.STDIN_FILENO;
const STDOUT_FILENO = std.os.STDOUT_FILENO;
const STDERR_FILENO = std.os.STDERR_FILENO;
@@ -263,13 +266,20 @@ fn mkCallableStack(a: Allocator, itr: *TokenIterator) Error![]CallableStack {
for (eslice) |maybeio| {
if (maybeio.kind == .io) {
switch (maybeio.kind.io) {
.Out, .Append => {
if (fs.openFile(maybeio.cannon(), true)) |file| {
io.out = file.handle;
if (maybeio.kind.io == .Append) {
file.seekFromEnd(0) catch return Error.StdIOError;
.Out => {
const f = fs.openStdoutFile(maybeio.cannon(), true, clobberMode.maybeClobber) catch |err| {
switch (err) {
noclobberError => log.err("Noclobber is enabled.\n", .{}),
else => log.err("Failed to open file {s}\n", .{maybeio.cannon()}),
}
}
return Error.StdIOError;
};
io.out = f.handle;
},
.Append => {
const f = fs.openStdoutFile(maybeio.cannon(), true, clobberMode.append) catch return Error.StdIOError;
io.out = f.handle;
f.seekFromEnd(0) catch return Error.StdIOError;
},
.In, .HDoc => {
if (prev_stdout) |out| {
 
src/fs.zig added: 147, removed: 23, total 124
@@ -4,8 +4,12 @@ const mem = @import("mem.zig");
const Allocator = mem.Allocator;
const log = @import("log");
const INotify = @import("inotify.zig");
const hsh = @import("hsh.zig");
const HSH = @import("hsh.zig").HSH;
const rand = @import("random.zig");
const set = @import("builtins/set.zig");
const KnOptions = set.KnOptions;
const PathAlreadyExists = std.fs.File.OpenError.PathAlreadyExists;
 
pub const fs = @This();
 
@@ -66,9 +70,16 @@ pub const Error = error{
System,
Missing,
Perm,
Noclobber,
Other,
};
 
pub const clobberMode = enum {
append, // Append to file, so noclobber option is irrelevent,
maybeClobber, // Check noclobber option before writing.
forceClobber, // Ignore noclobber option.
};
 
pub fn init(a: mem.Allocator, env: std.process.EnvMap) !fs {
var paths = std.ArrayList([]const u8).init(a);
if (env.get("PATH")) |penv| {
@@ -311,6 +322,52 @@ pub fn findPath(
return Error.Missing;
}
 
pub fn openStdoutFile(name: []const u8, comptime create: bool, clobber: clobberMode) !std.fs.File {
switch (clobber) {
.append, .forceClobber => {
if (openFile(name, create)) |file| {
return file;
}
},
.maybeClobber => {
// Check for noclobber
if (hsh.getState("set")) |ctx| {
const opts: *KnOptions = @ptrCast(ctx);
if (opts.noclobber) |noclobber| {
// noclobber enabled
if (noclobber) {
// Check for existing file
if (std.fs.cwd().openFile(name, .{ .mode = .read_only })) |file| {
file.close();
return Error.Noclobber;
} else |err| {
switch (err) {
std.fs.File.OpenError.FileNotFound => {
if (openFile(name, true)) |file| {
return file;
}
},
else => return err,
}
}
return Error.Noclobber;
}
// noclobber disabled
else {
if (openFile(name, create)) |file| {
return file;
}
}
}
} else |_| {
log.err("set state not found.\n", .{});
return Error.Noclobber;
}
},
}
return Error.Noclobber;
}
 
pub const CoreFiles = enum {
rc,
history,
 
src/hsh.zig added: 147, removed: 23, total 124
@@ -72,7 +72,7 @@ fn initBuiltins(h: *HSH) !void {
savestates = ArrayList(State).init(h.alloc);
bi.Export.init(h.alloc);
bi.Aliases.init(h.alloc);
bi.Set.init(h.alloc);
bi.Set.init();
}
 
fn razeBuiltins(h: *HSH) void {
@@ -157,6 +157,15 @@ pub fn addState(s: State) E!void {
try savestates.append(s);
}
 
pub fn getState(name: []const u8) !*anyopaque {
for (savestates.items) |*s| {
if (std.mem.eql(u8, name, s.getName())) {
return s.getCtx();
}
}
return E.Other;
}
 
fn writeLine(f: std.fs.File, line: []const u8) !usize {
const size = try f.write(line);
return size;
 
src/main.zig added: 147, removed: 23, total 124
@@ -162,6 +162,9 @@ pub fn main() !void {
try Draw.drawAfter(&hsh.draw, tree);
try Draw.render(&hsh.draw);
},
error.StdIOError => {
log.err("StdIoError\n", .{});
},
else => {
log.err("Exec error {}\n", .{err});
unreachable;
 
src/state.zig added: 147, removed: 23, total 124
@@ -18,3 +18,11 @@ pub const API = struct {
pub fn save(self: *State, h: *HSH) ?[][]const u8 {
return self.api.save(h, self.ctx);
}
 
pub fn getName(self: *State) []const u8 {
return self.name;
}
 
pub fn getCtx(self: *State) *anyopaque {
return self.ctx;
}