summaryrefslogtreecommitdiff
path: root/appl/cmd/install/ckproto.b
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
commit37da2899f40661e3e9631e497da8dc59b971cbd0 (patch)
treecbc6d4680e347d906f5fa7fca73214418741df72 /appl/cmd/install/ckproto.b
parent54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff)
20060303a
Diffstat (limited to 'appl/cmd/install/ckproto.b')
-rw-r--r--appl/cmd/install/ckproto.b267
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);
+}