diff options
Diffstat (limited to 'appl/cmd/install/ckproto.b')
| -rw-r--r-- | appl/cmd/install/ckproto.b | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/appl/cmd/install/ckproto.b b/appl/cmd/install/ckproto.b new file mode 100644 index 00000000..1e214f96 --- /dev/null +++ b/appl/cmd/install/ckproto.b @@ -0,0 +1,267 @@ +implement Ckproto; + +include "sys.m"; + sys: Sys; +include "draw.m"; +include "bufio.m"; + bufio: Bufio; + Iobuf: import bufio; +include "arg.m"; + arg: Arg; +include "readdir.m"; + readdir : Readdir; +include "proto.m"; + proto : Proto; +include "protocaller.m"; + protocaller : Protocaller; + +WARN, ERROR, FATAL : import Protocaller; + +Ckproto: module{ + init: fn(nil: ref Draw->Context, nil: list of string); + protofile: fn(new : string, old : string, d : ref Sys->Dir); + protoerr: fn(lev : int, line : int, err : string); +}; + +Dir : adt { + name : string; + proto : string; + parent : cyclic ref Dir; + child : cyclic ref Dir; + sibling : cyclic ref Dir; +}; + +root := "/"; +droot : ref Dir; +protof : string; +stderr : ref Sys->FD; +omitgen := 0; # forget generated files +verbose : int; +ckmode: int; + +init(nil: ref Draw->Context, args: list of string) +{ + sys = load Sys Sys->PATH; + bufio = load Bufio Bufio->PATH; + arg = load Arg Arg->PATH; + readdir = load Readdir Readdir->PATH; + proto = load Proto Proto->PATH; + protocaller = load Protocaller "$self"; + + stderr = sys->fildes(2); + sys->pctl(Sys->NEWPGRP|Sys->FORKNS|Sys->FORKFD, nil); + arg->init(args); + while ((c := arg->opt()) != 0) { + case c { + 'r' => + root = arg->arg(); + if (root == nil) + fatal("missing argument to -r"); + 'o' => + omitgen = 1; + 'v' => + verbose = 1; + 'm' => + ckmode = 1; + * => + fatal("usage: install/ckproto [-o] [-v] [-m] [-r root] protofile ...."); + } + } + droot = ref Dir("/", nil, nil, nil, nil); + droot.parent = droot; + args = arg->argv(); + while (args != nil) { + protof = hd args; + proto->rdproto(hd args, root, protocaller); + args = tl args; + } + if (verbose) + prtree(droot, -1); + ckdir(root, droot); +} + +protofile(new : string, old : string, nil : ref Sys->Dir) +{ + if (verbose) { + if (old == new) + sys->print("%s\n", new); + else + sys->print("%s %s\n", new, old); + } + addfile(droot, old); + if (new != old) + addfile(droot, new); +} + +protoerr(lev : int, line : int, err : string) +{ + s := "line " + string line + " : " + err; + case lev { + WARN => warn(s); + ERROR => error(s); + FATAL => fatal(s); + } +} + +ckdir(d : string, dird : ref Dir) +{ + (dir, n) := readdir->init(d, Readdir->NAME|Readdir->COMPACT); + for (i := 0; i < n; i++) { + dire := lookup(dird, dir[i].name); + if(omitgen && generated(dir[i].name)) + continue; + if (dire == nil){ + sys->print("%s missing\n", mkpath(d, dir[i].name)); + continue; + } + if(ckmode){ + if(dir[i].mode & Sys->DMDIR){ + if((dir[i].mode & 8r775) != 8r775) + sys->print("directory %s not 775 at least\n", mkpath(d, dir[i].name)); + } + else{ + if((dir[i].mode & 8r664) != 8r664) + sys->print("file %s not 664 at least\n", mkpath(d, dir[i].name)); + } + } + if (dir[i].mode & Sys->DMDIR) + ckdir(mkpath(d, dir[i].name), dire); + } +} + +addfile(root : ref Dir, path : string) +{ + elem : string; + + # ckexists(path); + + curd := root; + opath := path; + while (path != nil) { + (elem, path) = split(path); + d := lookup(curd, elem); + if (d == nil) { + d = ref Dir(elem, protof, curd, nil, nil); + if (curd.child == nil) + curd.child = d; + else { + prev, this : ref Dir; + + for (this = curd.child; this != nil; this = this.sibling) { + if (elem < this.name) { + d.sibling = this; + if (prev == nil) + curd.child = d; + else + prev.sibling = d; + break; + } + prev = this; + } + if (this == nil) + prev.sibling = d; + } + } + else if (path == nil && d.proto == protof) + sys->print("%s repeated in proto %s\n", opath, protof); + curd = d; + } +} + +lookup(p : ref Dir, f : string) : ref Dir +{ + if (f == ".") + return p; + if (f == "..") + return p.parent; + for (d := p.child; d != nil; d = d.sibling) { + if (d.name == f) + return d; + if (d.name > f) + return nil; + } + return nil; +} + +prtree(root : ref Dir, indent : int) +{ + if (indent >= 0) + sys->print("%s%s\n", string array[indent] of { * => byte '\t' }, root.name); + for (s := root.child; s != nil; s = s.sibling) + prtree(s, indent+1); +} + +mkpath(prefix, elem: string): string +{ + slash1 := slash2 := 0; + if (len prefix > 0) + slash1 = prefix[len prefix - 1] == '/'; + if (len elem > 0) + slash2 = elem[0] == '/'; + if (slash1 && slash2) + return prefix+elem[1:]; + if (!slash1 && !slash2) + return prefix+"/"+elem; + return prefix+elem; +} + +split(p : string) : (string, string) +{ + if (p == nil) + fatal("nil string in split"); + if (p[0] != '/') + fatal("p0 notg / in split"); + while (p[0] == '/') + p = p[1:]; + i := 0; + while (i < len p && p[i] != '/') + i++; + if (i == len p) + return (p, nil); + else + return (p[0:i], p[i:]); +} + + +gens := array[] of { + "dis", "sbl", "out", "0", "1", "2", "5", "8", "k", "q", "v", "t" +}; + +generated(f : string) : int +{ + for (i := len f -1; i >= 0; i--) + if (f[i] == '.') + break; + if (i < 0) + return 0; + suff := f[i+1:]; + for (i = 0; i < len gens; i++) + if (suff == gens[i]) + return 1; + return 0; +} + +warn(s: string) +{ + sys->print("%s: %s\n", protof, s); +} + +error(s: string) +{ + sys->fprint(stderr, "%s: %s\n", protof, s); + exit;; +} + +fatal(s: string) +{ + sys->fprint(stderr, "fatal: %s\n", s); + exit; +} + +ckexists(path: string) +{ + s := mkpath(root, path); + (ok, nil) := sys->stat(s); + if(ok < 0) + sys->print("%s does not exist\n", s); +} |
