diff options
Diffstat (limited to 'appl/cmd/mash/mash.b')
| -rw-r--r-- | appl/cmd/mash/mash.b | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/appl/cmd/mash/mash.b b/appl/cmd/mash/mash.b new file mode 100644 index 00000000..4e2f2ded --- /dev/null +++ b/appl/cmd/mash/mash.b @@ -0,0 +1,154 @@ +implement Mash; + +# +# mash - Inferno make/shell +# +# Bruce Ellis - 1Q 98 +# + +include "mash.m"; +include "mashparse.m"; + +# +# mash consists of three modules plus library modules and loadable builtins. +# +# This module, Mash, loads the other two (Mashparse and Mashlib), loads +# the builtin "builtins", initializes things and calls the parser. +# +# It has two entry points. One is the traditional init() function and the other, +# tkinit, is an interface to WmMash that allows the "tk" builtin to cooperate +# with the command window. +# + +Mash: module +{ + tkinit: fn(ctxt: ref Draw->Context, top: ref Tk->Toplevel, args: list of string); + init: fn(ctxt: ref Draw->Context, args: list of string); +}; + +Iobuf: import Bufio; + +sys: Sys; +lib: Mashlib; +parse: Mashparse; + +Env, Stab: import lib; + +cmd: string; + +# +# Check for /dev/console. +# +isconsole(fd: ref Sys->FD): int +{ + (ok1, d1) := sys->fstat(fd); + (ok2, d2) := sys->stat(lib->CONSOLE); + if (ok1 < 0 || ok2 < 0) + return 0; + return d1.dtype == d2.dtype && d1.qid.path == d2.qid.path; +} + +usage(e: ref Env) +{ + sys->fprint(e.stderr, "usage: mash [-denx] [-c command] [src [args]]\n"); + lib->exits("usage"); +} + +flags(e: ref Env, l: list of string): list of string +{ + while (l != nil && len hd l && (s := hd l)[0] == '-') { + l = tl l; + if (s == "--") + break; + n := len s; + for (i := 1; i < n; i++) { + case s[i] { + 'c' => + if (++i < n) { + if (l != nil) + usage(e); + cmd = s[i:]; + } else { + if (len l != 1) + usage(e); + cmd = hd l; + } + return nil; + 'd' => + e.flags |= lib->EDumping; + 'e' => + e.flags |= lib->ERaise; + 'n' => + e.flags |= lib->ENoxeq; + 'x' => + e.flags |= lib->EEcho; + * => + usage(e); + } + } + } + return l; +} + +tkinit(ctxt: ref Draw->Context, top: ref Tk->Toplevel, args: list of string) +{ + fd: ref Sys->FD; + sys = load Sys Sys->PATH; + stderr := sys->fildes(2); + lib = load Mashlib Mashlib->PATH; + if (lib == nil) { + sys->fprint(stderr, "could not load %s: %r\n", Mashlib->PATH); + exit; + } + parse = load Mashparse Mashparse->PATH; + if (parse == nil) { + sys->fprint(stderr, "could not load %s: %r\n", Mashparse->PATH); + exit; + } + e := Env.new(); + e.stderr = stderr; + stderr = nil; + lib->initmash(ctxt, top, sys, e, lib, parse); + parse->init(lib); + boot := args == nil; + if (!boot) + args = flags(e, tl args); + e.doload(lib->LIB + lib->BUILTINS); + lib->prompt = "mash% "; + lib->contin = "\t"; + if (cmd == nil && args == nil && !boot) { + e.global.assign(lib->MASHINIT, "true" :: nil); + fd = sys->open(lib->PROFILE, Sys->OREAD); + if (fd != nil) { + e.fopen(fd, lib->PROFILE); + parse->parse(e); + fd = nil; + } + } + e.global.assign(lib->MASHINIT, nil); + if (cmd == nil) { + if (args != nil) { + s := hd args; + args = tl args; + fd = sys->open(s, Sys->OREAD); + if (fd == nil) + e.couldnot("open", s); + e.fopen(fd, s); + e.global.assign(lib->ARGS, args); + } + if (fd == nil) { + fd = sys->fildes(0); + if (isconsole(fd)) + e.interactive(fd); + e.fopen(fd, "<stdin>"); + fd = nil; + } + } else + e.sopen(cmd); + parse->parse(e); +} + +init(ctxt: ref Draw->Context, args: list of string) +{ + tkinit(ctxt, nil, args); +} |
