summaryrefslogtreecommitdiff
path: root/appl/cmd/install/proto2list.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/cmd/install/proto2list.b')
-rw-r--r--appl/cmd/install/proto2list.b209
1 files changed, 209 insertions, 0 deletions
diff --git a/appl/cmd/install/proto2list.b b/appl/cmd/install/proto2list.b
new file mode 100644
index 00000000..b5997c15
--- /dev/null
+++ b/appl/cmd/install/proto2list.b
@@ -0,0 +1,209 @@
+#
+# Copyright © 2001 Vita Nuova (Holdings) Limited. All rights reserved.
+#
+
+implement Proto2list;
+
+# make a version list suitable for SDS from a series of proto files
+
+include "sys.m";
+ sys : Sys;
+include "draw.m";
+include "bufio.m";
+ bufio : Bufio;
+ Iobuf : import bufio;
+include "crc.m";
+ crcm : Crc;
+include "proto.m";
+ proto : Proto;
+include "protocaller.m";
+ protocaller : Protocaller;
+
+WARN, ERROR, FATAL : import Protocaller;
+
+Proto2list: module
+{
+ init : fn(ctxt: ref Draw->Context, argv: list of string);
+ protofile: fn(new : string, old : string, d : ref Sys->Dir);
+ protoerr: fn(lev : int, line : int, err : string);
+};
+
+stderr: ref Sys->FD;
+protof: string;
+
+Element: type (string, string);
+
+List: adt{
+ as: array of Element;
+ n: int;
+ init: fn(l: self ref List);
+ add: fn(l: self ref List, e: Element);
+ end: fn(l: self ref List): array of Element;
+};
+
+flist: ref List;
+
+List.init(l: self ref List)
+{
+ l.as = array[1024] of Element;
+ l.n = 0;
+}
+
+List.add(l: self ref List, e: Element)
+{
+ if(l.n == len l.as)
+ l.as = (array[2*l.n] of Element)[0:] = l.as;
+ l.as[l.n++] = e;
+}
+
+List.end(l: self ref List): array of Element
+{
+ return l.as[0: l.n];
+}
+
+usage()
+{
+ sys->fprint(stderr, "Usage: proto2list protofile ...\n");
+ exit;
+}
+
+init(nil: ref Draw->Context, argv: list of string)
+{
+ sys = load Sys Sys->PATH;
+ bufio = load Bufio Bufio->PATH;
+ crcm = load Crc Crc->PATH;
+ proto = load Proto Proto->PATH;
+ protocaller = load Protocaller "$self";
+ stderr = sys->fildes(2);
+ root := "/";
+ flist = ref List;
+ flist.init();
+ for(argv = tl argv; argv != nil; argv = tl argv){
+ protof = hd argv;
+ proto->rdproto(hd argv, root, protocaller);
+ }
+ fs := flist.end();
+ sort(fs);
+ fs = uniq(fs);
+ out(fs);
+}
+
+protofile(new : string, old : string, nil : ref Sys->Dir)
+{
+ if(new == old)
+ new = "-";
+ flist.add((old, new));
+}
+
+out(fs: array of Element)
+{
+ nf := len fs;
+ for(i := 0; i < nf; i++){
+ (f, g) := fs[i];
+ (ok, d) := sys->stat(f);
+ if (ok < 0) {
+ sys->fprint(stderr, "cannot open %s\n", f);
+ continue;
+ }
+ if (d.mode & Sys->DMDIR)
+ d.length = big 0;
+ sys->print("%s %s %d %d %d %d %d\n", f, g, int d.length, d.mode, d.mtime, crc(f, d), 0);
+ }
+}
+
+protoerr(lev : int, line : int, err : string)
+{
+ s := "line " + string line + " : " + err;
+ case lev {
+ WARN => warn(s);
+ ERROR => error(s);
+ FATAL => fatal(s);
+ }
+}
+
+crc(f : string, d: Sys->Dir) : int
+{
+ crcs := crcm->init(0, int 16rffffffff);
+ if (d.mode & Sys->DMDIR)
+ return 0;
+ fd := sys->open(f, Sys->OREAD);
+ if (fd == nil) {
+ sys->fprint(stderr, "cannot open %s\n", f);
+ return 0;
+ }
+ crc := 0;
+ buf := array[Sys->ATOMICIO] of byte;
+ for (;;) {
+ nr := sys->read(fd, buf, len buf);
+ if (nr < 0) {
+ sys->fprint(stderr, "bad read on %s : %r\n", f);
+ return 0;
+ }
+ if (nr <= 0)
+ break;
+ crc = crcm->crc(crcs, buf, nr);
+ }
+ crcm->reset(crcs);
+ return crc;
+}
+
+sort(a: array of Element)
+{
+ mergesort(a, array[len a] of Element);
+}
+
+mergesort(a, b: array of Element)
+{
+ r := len a;
+ if (r > 1) {
+ m := (r-1)/2 + 1;
+ mergesort(a[0:m], b[0:m]);
+ mergesort(a[m:], b[m:]);
+ b[0:] = a;
+ for ((i, j, k) := (0, m, 0); i < m && j < r; k++) {
+ if (b[i].t0 > b[j].t0)
+ a[k] = b[j++];
+ else
+ a[k] = b[i++];
+ }
+ if (i < m)
+ a[k:] = b[i:m];
+ else if (j < r)
+ a[k:] = b[j:r];
+ }
+}
+
+
+uniq(a: array of Element): array of Element
+{
+ m := n := len a;
+ for(i := 0; i < n-1; ){
+ if(a[i].t0 == a[i+1].t0){
+ if(a[i].t1 != a[i+1].t1)
+ warn(sys->sprint("duplicate %s(%s %s)", a[i].t0, a[i].t1, a[i+1].t1));
+ a[i+1:] = a[i+2: n--];
+ }
+ else
+ i++;
+ }
+ if(n == m)
+ return a;
+ return a[0: n];
+}
+
+error(s: string)
+{
+ sys->fprint(stderr, "%s: %s\n", protof, s);
+ exit;
+}
+
+fatal(s: string)
+{
+ sys->fprint(stderr, "fatal: %s\n", s);
+ exit;
+}
+
+warn(s: string)
+{
+ sys->fprint(stderr, "%s: %s\n", protof, s);
+}