diff options
Diffstat (limited to 'appl/cmd/install/proto2list.b')
| -rw-r--r-- | appl/cmd/install/proto2list.b | 209 |
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); +} |
