xref: /inferno-os/appl/cmd/install/proto2list.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1#
2# Copyright © 2001 Vita Nuova (Holdings) Limited.  All rights reserved.
3#
4
5implement Proto2list;
6
7# make a version list suitable for SDS from a series of proto files
8
9include "sys.m";
10	sys : Sys;
11include "draw.m";
12include "bufio.m";
13	bufio : Bufio;
14	Iobuf : import bufio;
15include "crc.m";
16	crcm : Crc;
17include "proto.m";
18	proto : Proto;
19include "protocaller.m";
20	protocaller : Protocaller;
21
22WARN, ERROR, FATAL : import Protocaller;
23
24Proto2list: module
25{
26	init : fn(ctxt: ref Draw->Context, argv: list of string);
27	protofile: fn(new : string, old : string, d : ref Sys->Dir);
28	protoerr: fn(lev : int, line : int, err : string);
29};
30
31stderr: ref Sys->FD;
32protof: string;
33
34Element: type (string, string);
35
36List: adt{
37	as: array of Element;
38	n: int;
39	init: fn(l: self ref List);
40	add: fn(l: self ref List, e: Element);
41	end: fn(l: self ref List): array of Element;
42};
43
44flist: ref List;
45
46List.init(l: self ref List)
47{
48	l.as = array[1024] of Element;
49	l.n = 0;
50}
51
52List.add(l: self ref List, e: Element)
53{
54	if(l.n == len l.as)
55		l.as = (array[2*l.n] of Element)[0:] = l.as;
56	l.as[l.n++] = e;
57}
58
59List.end(l: self ref List): array of Element
60{
61	return l.as[0: l.n];
62}
63
64usage()
65{
66	sys->fprint(stderr, "Usage: proto2list protofile ...\n");
67	exit;
68}
69
70init(nil: ref Draw->Context, argv: list of string)
71{
72	sys = load Sys Sys->PATH;
73	bufio = load Bufio Bufio->PATH;
74	crcm = load Crc Crc->PATH;
75	proto = load Proto Proto->PATH;
76	protocaller = load Protocaller "$self";
77	stderr = sys->fildes(2);
78	root := "/";
79	flist = ref List;
80	flist.init();
81	for(argv = tl argv; argv != nil; argv = tl argv){
82		protof = hd argv;
83		proto->rdproto(hd argv, root, protocaller);
84	}
85	fs := flist.end();
86	sort(fs);
87	fs = uniq(fs);
88	out(fs);
89}
90
91protofile(new : string, old : string, nil : ref Sys->Dir)
92{
93	if(new == old)
94		new = "-";
95	flist.add((old, new));
96}
97
98out(fs: array of Element)
99{
100	nf := len fs;
101	for(i := 0; i < nf; i++){
102		(f, g) := fs[i];
103		(ok, d) := sys->stat(f);
104		if (ok < 0) {
105			sys->fprint(stderr, "cannot open %s\n", f);
106			continue;
107		}
108		if (d.mode & Sys->DMDIR)
109			d.length = big 0;
110		sys->print("%s	%s	%d	%d	%d	%d	%d\n", f, g, int d.length, d.mode, d.mtime, crc(f, d), 0);
111	}
112}
113
114protoerr(lev : int, line : int, err : string)
115{
116	s := "line " + string line + " : " + err;
117	case lev {
118		WARN => warn(s);
119		ERROR => error(s);
120		FATAL => fatal(s);
121	}
122}
123
124crc(f : string, d: Sys->Dir) : int
125{
126	crcs := crcm->init(0, int 16rffffffff);
127	if (d.mode & Sys->DMDIR)
128		return 0;
129	fd := sys->open(f, Sys->OREAD);
130	if (fd == nil) {
131		sys->fprint(stderr, "cannot open %s\n", f);
132		return 0;
133	}
134	crc := 0;
135	buf := array[Sys->ATOMICIO] of byte;
136	for (;;) {
137		nr := sys->read(fd, buf, len buf);
138		if (nr < 0) {
139			sys->fprint(stderr, "bad read on %s : %r\n", f);
140			return 0;
141		}
142		if (nr <= 0)
143			break;
144		crc = crcm->crc(crcs, buf, nr);
145	}
146	crcm->reset(crcs);
147	return crc;
148}
149
150sort(a: array of Element)
151{
152	mergesort(a, array[len a] of Element);
153}
154
155mergesort(a, b: array of Element)
156{
157	r := len a;
158	if (r > 1) {
159		m := (r-1)/2 + 1;
160		mergesort(a[0:m], b[0:m]);
161		mergesort(a[m:], b[m:]);
162		b[0:] = a;
163		for ((i, j, k) := (0, m, 0); i < m && j < r; k++) {
164			if (b[i].t0 > b[j].t0)
165				a[k] = b[j++];
166			else
167				a[k] = b[i++];
168		}
169		if (i < m)
170			a[k:] = b[i:m];
171		else if (j < r)
172			a[k:] = b[j:r];
173	}
174}
175
176
177uniq(a: array of Element): array of Element
178{
179	m := n := len a;
180	for(i := 0; i < n-1; ){
181		if(a[i].t0 == a[i+1].t0){
182			if(a[i].t1 != a[i+1].t1)
183				warn(sys->sprint("duplicate %s(%s %s)", a[i].t0, a[i].t1, a[i+1].t1));
184			a[i+1:] = a[i+2: n--];
185		}
186		else
187			i++;
188	}
189	if(n == m)
190		return a;
191	return a[0: n];
192}
193
194error(s: string)
195{
196	sys->fprint(stderr, "%s: %s\n", protof, s);
197	exit;
198}
199
200fatal(s: string)
201{
202	sys->fprint(stderr, "fatal: %s\n", s);
203	exit;
204}
205
206warn(s: string)
207{
208	sys->fprint(stderr, "%s: %s\n", protof, s);
209}
210