xref: /plan9-contrib/sys/src/cmd/venti/srv/arenas.c (revision 588d0145e19f8596f2f4442d05dd8a9eda147983)
1368c31abSDavid du Colombier #include "stdinc.h"
2368c31abSDavid du Colombier #include "dat.h"
3368c31abSDavid du Colombier #include "fns.h"
4368c31abSDavid du Colombier 
5368c31abSDavid du Colombier typedef struct AHash	AHash;
6368c31abSDavid du Colombier 
7368c31abSDavid du Colombier /*
8368c31abSDavid du Colombier  * hash table for finding arena's based on their names.
9368c31abSDavid du Colombier  */
10368c31abSDavid du Colombier struct AHash
11368c31abSDavid du Colombier {
12368c31abSDavid du Colombier 	AHash	*next;
13368c31abSDavid du Colombier 	Arena	*arena;
14368c31abSDavid du Colombier };
15368c31abSDavid du Colombier 
16368c31abSDavid du Colombier enum
17368c31abSDavid du Colombier {
18*588d0145SDavid du Colombier 	AHashSize	= 512,
19*588d0145SDavid du Colombier 	Emergency	= 0,		/* flag: performing emergency surgery */
20368c31abSDavid du Colombier };
21368c31abSDavid du Colombier 
22368c31abSDavid du Colombier static AHash	*ahash[AHashSize];
23368c31abSDavid du Colombier 
24368c31abSDavid du Colombier static u32int
hashstr(char * s)25368c31abSDavid du Colombier hashstr(char *s)
26368c31abSDavid du Colombier {
27368c31abSDavid du Colombier 	u32int h;
28368c31abSDavid du Colombier 	int c;
29368c31abSDavid du Colombier 
30368c31abSDavid du Colombier 	h = 0;
31368c31abSDavid du Colombier 	for(; c = *s; s++){
32368c31abSDavid du Colombier 		c ^= c << 6;
33368c31abSDavid du Colombier 		h += (c << 11) ^ (c >> 1);
34368c31abSDavid du Colombier 		c = *s;
35368c31abSDavid du Colombier 		h ^= (c << 14) + (c << 7) + (c << 4) + c;
36368c31abSDavid du Colombier 	}
37368c31abSDavid du Colombier 	return h;
38368c31abSDavid du Colombier }
39368c31abSDavid du Colombier 
40368c31abSDavid du Colombier int
addarena(Arena * arena)41368c31abSDavid du Colombier addarena(Arena *arena)
42368c31abSDavid du Colombier {
43368c31abSDavid du Colombier 	AHash *a;
44368c31abSDavid du Colombier 	u32int h;
45368c31abSDavid du Colombier 
46368c31abSDavid du Colombier 	h = hashstr(arena->name) & (AHashSize - 1);
47368c31abSDavid du Colombier 	a = MK(AHash);
48368c31abSDavid du Colombier 	if(a == nil)
49368c31abSDavid du Colombier 		return -1;
50368c31abSDavid du Colombier 	a->arena = arena;
51368c31abSDavid du Colombier 	a->next = ahash[h];
52368c31abSDavid du Colombier 	ahash[h] = a;
53368c31abSDavid du Colombier 	return 0;
54368c31abSDavid du Colombier }
55368c31abSDavid du Colombier 
56368c31abSDavid du Colombier Arena*
findarena(char * name)57368c31abSDavid du Colombier findarena(char *name)
58368c31abSDavid du Colombier {
59368c31abSDavid du Colombier 	AHash *a;
60368c31abSDavid du Colombier 	u32int h;
61368c31abSDavid du Colombier 
62368c31abSDavid du Colombier 	h = hashstr(name) & (AHashSize - 1);
63368c31abSDavid du Colombier 	for(a = ahash[h]; a != nil; a = a->next)
64368c31abSDavid du Colombier 		if(strcmp(a->arena->name, name) == 0)
65368c31abSDavid du Colombier 			return a->arena;
66368c31abSDavid du Colombier 	return nil;
67368c31abSDavid du Colombier }
68368c31abSDavid du Colombier 
69368c31abSDavid du Colombier int
delarena(Arena * arena)70368c31abSDavid du Colombier delarena(Arena *arena)
71368c31abSDavid du Colombier {
72368c31abSDavid du Colombier 	AHash *a, *last;
73368c31abSDavid du Colombier 	u32int h;
74368c31abSDavid du Colombier 
75368c31abSDavid du Colombier 	h = hashstr(arena->name) & (AHashSize - 1);
76368c31abSDavid du Colombier 	last = nil;
77368c31abSDavid du Colombier 	for(a = ahash[h]; a != nil; a = a->next){
78368c31abSDavid du Colombier 		if(a->arena == arena){
79368c31abSDavid du Colombier 			if(last != nil)
80368c31abSDavid du Colombier 				last->next = a->next;
81368c31abSDavid du Colombier 			else
82368c31abSDavid du Colombier 				ahash[h] = a->next;
83368c31abSDavid du Colombier 			free(a);
84368c31abSDavid du Colombier 			return 0;
85368c31abSDavid du Colombier 		}
86368c31abSDavid du Colombier 		last = a;
87368c31abSDavid du Colombier 	}
88368c31abSDavid du Colombier 	return -1;
89368c31abSDavid du Colombier }
90368c31abSDavid du Colombier 
91368c31abSDavid du Colombier ArenaPart*
initarenapart(Part * part)92368c31abSDavid du Colombier initarenapart(Part *part)
93368c31abSDavid du Colombier {
94368c31abSDavid du Colombier 	AMapN amn;
95368c31abSDavid du Colombier 	ArenaPart *ap;
96368c31abSDavid du Colombier 	ZBlock *b;
97368c31abSDavid du Colombier 	u32int i;
98368c31abSDavid du Colombier 	int ok;
99368c31abSDavid du Colombier 
100368c31abSDavid du Colombier 	b = alloczblock(HeadSize, 0, 0);
101368c31abSDavid du Colombier 	if(b == nil || readpart(part, PartBlank, b->data, HeadSize) < 0){
102368c31abSDavid du Colombier 		seterr(EAdmin, "can't read arena partition header: %r");
103368c31abSDavid du Colombier 		return nil;
104368c31abSDavid du Colombier 	}
105368c31abSDavid du Colombier 
106368c31abSDavid du Colombier 	ap = MKZ(ArenaPart);
107368c31abSDavid du Colombier 	if(ap == nil){
108368c31abSDavid du Colombier 		freezblock(b);
109368c31abSDavid du Colombier 		return nil;
110368c31abSDavid du Colombier 	}
111368c31abSDavid du Colombier 	ap->part = part;
112368c31abSDavid du Colombier 	ok = unpackarenapart(ap, b->data);
113368c31abSDavid du Colombier 	freezblock(b);
114368c31abSDavid du Colombier 	if(ok < 0){
115368c31abSDavid du Colombier 		freearenapart(ap, 0);
116368c31abSDavid du Colombier 		return nil;
117368c31abSDavid du Colombier 	}
118368c31abSDavid du Colombier 
119368c31abSDavid du Colombier 	ap->tabbase = (PartBlank + HeadSize + ap->blocksize - 1) & ~(ap->blocksize - 1);
120368c31abSDavid du Colombier 	if(ap->version != ArenaPartVersion){
121368c31abSDavid du Colombier 		seterr(ECorrupt, "unknown arena partition version %d", ap->version);
122368c31abSDavid du Colombier 		freearenapart(ap, 0);
123368c31abSDavid du Colombier 		return nil;
124368c31abSDavid du Colombier 	}
125368c31abSDavid du Colombier 	if(ap->blocksize & (ap->blocksize - 1)){
126368c31abSDavid du Colombier 		seterr(ECorrupt, "illegal non-power-of-2 block size %d\n", ap->blocksize);
127368c31abSDavid du Colombier 		freearenapart(ap, 0);
128368c31abSDavid du Colombier 		return nil;
129368c31abSDavid du Colombier 	}
130368c31abSDavid du Colombier 	if(ap->tabbase >= ap->arenabase){
131368c31abSDavid du Colombier 		seterr(ECorrupt, "arena partition table overlaps with arena storage");
132368c31abSDavid du Colombier 		freearenapart(ap, 0);
133368c31abSDavid du Colombier 		return nil;
134368c31abSDavid du Colombier 	}
135368c31abSDavid du Colombier 	ap->tabsize = ap->arenabase - ap->tabbase;
136368c31abSDavid du Colombier 	partblocksize(part, ap->blocksize);
137368c31abSDavid du Colombier 	ap->size = ap->part->size & ~(u64int)(ap->blocksize - 1);
138368c31abSDavid du Colombier 
139368c31abSDavid du Colombier 	if(readarenamap(&amn, part, ap->tabbase, ap->tabsize) < 0){
140368c31abSDavid du Colombier 		freearenapart(ap, 0);
141368c31abSDavid du Colombier 		return nil;
142368c31abSDavid du Colombier 	}
143368c31abSDavid du Colombier 	ap->narenas = amn.n;
144368c31abSDavid du Colombier 	ap->map = amn.map;
145368c31abSDavid du Colombier 	if(okamap(ap->map, ap->narenas, ap->arenabase, ap->size, "arena table") < 0){
146*588d0145SDavid du Colombier 		if(!Emergency){
147368c31abSDavid du Colombier 			freearenapart(ap, 0);
148368c31abSDavid du Colombier 			return nil;
149368c31abSDavid du Colombier 		}
150*588d0145SDavid du Colombier 		/* else keep on, for emergency use */
151*588d0145SDavid du Colombier 	}
152368c31abSDavid du Colombier 
153368c31abSDavid du Colombier 	ap->arenas = MKNZ(Arena*, ap->narenas);
154368c31abSDavid du Colombier 	for(i = 0; i < ap->narenas; i++){
155b8a11165SDavid du Colombier 		debugarena = i;
156368c31abSDavid du Colombier 		ap->arenas[i] = initarena(part, ap->map[i].start, ap->map[i].stop - ap->map[i].start, ap->blocksize);
157368c31abSDavid du Colombier 		if(ap->arenas[i] == nil){
158368c31abSDavid du Colombier 			seterr(ECorrupt, "%s: %r", ap->map[i].name);
159*588d0145SDavid du Colombier 			if(!Emergency){
160368c31abSDavid du Colombier 				freearenapart(ap, 1);
161368c31abSDavid du Colombier 				return nil;
162*588d0145SDavid du Colombier 			}else{
163*588d0145SDavid du Colombier 				/* keep on, for emergency use */
164*588d0145SDavid du Colombier 				ap->narenas = i;
165*588d0145SDavid du Colombier 				break;
166*588d0145SDavid du Colombier 			}
167368c31abSDavid du Colombier 		}
168368c31abSDavid du Colombier 		if(namecmp(ap->map[i].name, ap->arenas[i]->name) != 0){
169368c31abSDavid du Colombier 			seterr(ECorrupt, "arena name mismatches with expected name: %s vs. %s",
170368c31abSDavid du Colombier 				ap->map[i].name, ap->arenas[i]->name);
171368c31abSDavid du Colombier 			freearenapart(ap, 1);
172368c31abSDavid du Colombier 			return nil;
173368c31abSDavid du Colombier 		}
174368c31abSDavid du Colombier 		if(findarena(ap->arenas[i]->name)){
175368c31abSDavid du Colombier 			seterr(ECorrupt, "duplicate arena name %s in %s",
176368c31abSDavid du Colombier 				ap->map[i].name, ap->part->name);
177368c31abSDavid du Colombier 			freearenapart(ap, 1);
178368c31abSDavid du Colombier 			return nil;
179368c31abSDavid du Colombier 		}
180368c31abSDavid du Colombier 	}
181368c31abSDavid du Colombier 
182b8a11165SDavid du Colombier 	for(i = 0; i < ap->narenas; i++) {
183b8a11165SDavid du Colombier 		debugarena = i;
184368c31abSDavid du Colombier 		addarena(ap->arenas[i]);
185b8a11165SDavid du Colombier 	}
186b8a11165SDavid du Colombier 	debugarena = -1;
187368c31abSDavid du Colombier 
188368c31abSDavid du Colombier 	return ap;
189368c31abSDavid du Colombier }
190368c31abSDavid du Colombier 
191368c31abSDavid du Colombier ArenaPart*
newarenapart(Part * part,u32int blocksize,u32int tabsize)192368c31abSDavid du Colombier newarenapart(Part *part, u32int blocksize, u32int tabsize)
193368c31abSDavid du Colombier {
194368c31abSDavid du Colombier 	ArenaPart *ap;
195368c31abSDavid du Colombier 
196368c31abSDavid du Colombier 	if(blocksize & (blocksize - 1)){
197368c31abSDavid du Colombier 		seterr(ECorrupt, "illegal non-power-of-2 block size %d\n", blocksize);
198368c31abSDavid du Colombier 		return nil;
199368c31abSDavid du Colombier 	}
200368c31abSDavid du Colombier 	ap = MKZ(ArenaPart);
201368c31abSDavid du Colombier 	if(ap == nil)
202368c31abSDavid du Colombier 		return nil;
203368c31abSDavid du Colombier 
204368c31abSDavid du Colombier 	ap->version = ArenaPartVersion;
205368c31abSDavid du Colombier 	ap->part = part;
206368c31abSDavid du Colombier 	ap->blocksize = blocksize;
207368c31abSDavid du Colombier 	partblocksize(part, blocksize);
208368c31abSDavid du Colombier 	ap->size = part->size & ~(u64int)(blocksize - 1);
209368c31abSDavid du Colombier 	ap->tabbase = (PartBlank + HeadSize + blocksize - 1) & ~(blocksize - 1);
210368c31abSDavid du Colombier 	ap->arenabase = (ap->tabbase + tabsize + blocksize - 1) & ~(blocksize - 1);
211368c31abSDavid du Colombier 	ap->tabsize = ap->arenabase - ap->tabbase;
212368c31abSDavid du Colombier 	ap->narenas = 0;
213368c31abSDavid du Colombier 
214368c31abSDavid du Colombier 	if(wbarenapart(ap) < 0){
215368c31abSDavid du Colombier 		freearenapart(ap, 0);
216368c31abSDavid du Colombier 		return nil;
217368c31abSDavid du Colombier 	}
218368c31abSDavid du Colombier 
219368c31abSDavid du Colombier 	return ap;
220368c31abSDavid du Colombier }
221368c31abSDavid du Colombier 
222368c31abSDavid du Colombier int
wbarenapart(ArenaPart * ap)223368c31abSDavid du Colombier wbarenapart(ArenaPart *ap)
224368c31abSDavid du Colombier {
225368c31abSDavid du Colombier 	ZBlock *b;
226368c31abSDavid du Colombier 
227368c31abSDavid du Colombier 	if(okamap(ap->map, ap->narenas, ap->arenabase, ap->size, "arena table") < 0)
228368c31abSDavid du Colombier 		return -1;
229368c31abSDavid du Colombier 	b = alloczblock(HeadSize, 1, 0);
230368c31abSDavid du Colombier 	if(b == nil)
231368c31abSDavid du Colombier /* ZZZ set error message? */
232368c31abSDavid du Colombier 		return -1;
233368c31abSDavid du Colombier 
234368c31abSDavid du Colombier 	if(packarenapart(ap, b->data) < 0){
235368c31abSDavid du Colombier 		seterr(ECorrupt, "can't make arena partition header: %r");
236368c31abSDavid du Colombier 		freezblock(b);
237368c31abSDavid du Colombier 		return -1;
238368c31abSDavid du Colombier 	}
239368c31abSDavid du Colombier 	if(writepart(ap->part, PartBlank, b->data, HeadSize) < 0 ||
240368c31abSDavid du Colombier 	   flushpart(ap->part) < 0){
241368c31abSDavid du Colombier 		seterr(EAdmin, "can't write arena partition header: %r");
242368c31abSDavid du Colombier 		freezblock(b);
243368c31abSDavid du Colombier 		return -1;
244368c31abSDavid du Colombier 	}
245368c31abSDavid du Colombier 	freezblock(b);
246368c31abSDavid du Colombier 
247368c31abSDavid du Colombier 	return wbarenamap(ap->map, ap->narenas, ap->part, ap->tabbase, ap->tabsize);
248368c31abSDavid du Colombier }
249368c31abSDavid du Colombier 
250368c31abSDavid du Colombier void
freearenapart(ArenaPart * ap,int freearenas)251368c31abSDavid du Colombier freearenapart(ArenaPart *ap, int freearenas)
252368c31abSDavid du Colombier {
253368c31abSDavid du Colombier 	int i;
254368c31abSDavid du Colombier 
255368c31abSDavid du Colombier 	if(ap == nil)
256368c31abSDavid du Colombier 		return;
257368c31abSDavid du Colombier 	if(freearenas){
258368c31abSDavid du Colombier 		for(i = 0; i < ap->narenas; i++){
259368c31abSDavid du Colombier 			if(ap->arenas[i] == nil)
260368c31abSDavid du Colombier 				continue;
261368c31abSDavid du Colombier 			delarena(ap->arenas[i]);
262368c31abSDavid du Colombier 			freearena(ap->arenas[i]);
263368c31abSDavid du Colombier 		}
264368c31abSDavid du Colombier 	}
265368c31abSDavid du Colombier 	free(ap->map);
266368c31abSDavid du Colombier 	free(ap->arenas);
267368c31abSDavid du Colombier 	free(ap);
268368c31abSDavid du Colombier }
269368c31abSDavid du Colombier 
270368c31abSDavid du Colombier int
okamap(AMap * am,int n,u64int start,u64int stop,char * what)271368c31abSDavid du Colombier okamap(AMap *am, int n, u64int start, u64int stop, char *what)
272368c31abSDavid du Colombier {
273368c31abSDavid du Colombier 	u64int last;
274368c31abSDavid du Colombier 	u32int i;
275368c31abSDavid du Colombier 
276368c31abSDavid du Colombier 	last = start;
277368c31abSDavid du Colombier 	for(i = 0; i < n; i++){
278368c31abSDavid du Colombier 		if(am[i].start < last){
279368c31abSDavid du Colombier 			if(i == 0)
280368c31abSDavid du Colombier 				seterr(ECorrupt, "invalid start address in %s", what);
281368c31abSDavid du Colombier 			else
282368c31abSDavid du Colombier 				seterr(ECorrupt, "overlapping ranges in %s", what);
283368c31abSDavid du Colombier 			return -1;
284368c31abSDavid du Colombier 		}
285368c31abSDavid du Colombier 		if(am[i].stop < am[i].start){
286368c31abSDavid du Colombier 			seterr(ECorrupt, "invalid range in %s", what);
287368c31abSDavid du Colombier 			return -1;
288368c31abSDavid du Colombier 		}
289368c31abSDavid du Colombier 		last = am[i].stop;
290368c31abSDavid du Colombier 	}
291368c31abSDavid du Colombier 	if(last > stop){
292368c31abSDavid du Colombier 		seterr(ECorrupt, "invalid ending address in %s", what);
293368c31abSDavid du Colombier 		return -1;
294368c31abSDavid du Colombier 	}
295368c31abSDavid du Colombier 	return 0;
296368c31abSDavid du Colombier }
297368c31abSDavid du Colombier 
298368c31abSDavid du Colombier int
maparenas(AMap * am,Arena ** arenas,int n,char * what)299368c31abSDavid du Colombier maparenas(AMap *am, Arena **arenas, int n, char *what)
300368c31abSDavid du Colombier {
301368c31abSDavid du Colombier 	u32int i;
302368c31abSDavid du Colombier 
303368c31abSDavid du Colombier 	for(i = 0; i < n; i++){
304368c31abSDavid du Colombier 		arenas[i] = findarena(am[i].name);
305368c31abSDavid du Colombier 		if(arenas[i] == nil){
306368c31abSDavid du Colombier 			seterr(EAdmin, "can't find arena '%s' for '%s'\n", am[i].name, what);
307368c31abSDavid du Colombier 			return -1;
308368c31abSDavid du Colombier 		}
309368c31abSDavid du Colombier 	}
310368c31abSDavid du Colombier 	return 0;
311368c31abSDavid du Colombier }
312368c31abSDavid du Colombier 
313368c31abSDavid du Colombier int
readarenamap(AMapN * amn,Part * part,u64int base,u32int size)314368c31abSDavid du Colombier readarenamap(AMapN *amn, Part *part, u64int base, u32int size)
315368c31abSDavid du Colombier {
316368c31abSDavid du Colombier 	IFile f;
317368c31abSDavid du Colombier 	u32int ok;
318368c31abSDavid du Colombier 
319368c31abSDavid du Colombier 	if(partifile(&f, part, base, size) < 0)
320368c31abSDavid du Colombier 		return -1;
321368c31abSDavid du Colombier 	ok = parseamap(&f, amn);
322368c31abSDavid du Colombier 	freeifile(&f);
323368c31abSDavid du Colombier 	return ok;
324368c31abSDavid du Colombier }
325368c31abSDavid du Colombier 
326368c31abSDavid du Colombier int
wbarenamap(AMap * am,int n,Part * part,u64int base,u64int size)327368c31abSDavid du Colombier wbarenamap(AMap *am, int n, Part *part, u64int base, u64int size)
328368c31abSDavid du Colombier {
329368c31abSDavid du Colombier 	Fmt f;
330368c31abSDavid du Colombier 	ZBlock *b;
331368c31abSDavid du Colombier 
332368c31abSDavid du Colombier 	b = alloczblock(size, 1, part->blocksize);
333368c31abSDavid du Colombier 	if(b == nil)
334368c31abSDavid du Colombier 		return -1;
335368c31abSDavid du Colombier 
336368c31abSDavid du Colombier 	fmtzbinit(&f, b);
337368c31abSDavid du Colombier 
338368c31abSDavid du Colombier 	if(outputamap(&f, am, n) < 0){
339368c31abSDavid du Colombier 		seterr(ECorrupt, "arena set size too small");
340368c31abSDavid du Colombier 		freezblock(b);
341368c31abSDavid du Colombier 		return -1;
342368c31abSDavid du Colombier 	}
343368c31abSDavid du Colombier 	if(writepart(part, base, b->data, size) < 0 || flushpart(part) < 0){
344368c31abSDavid du Colombier 		seterr(EAdmin, "can't write arena set: %r");
345368c31abSDavid du Colombier 		freezblock(b);
346368c31abSDavid du Colombier 		return -1;
347368c31abSDavid du Colombier 	}
348368c31abSDavid du Colombier 	freezblock(b);
349368c31abSDavid du Colombier 	return 0;
350368c31abSDavid du Colombier }
351368c31abSDavid du Colombier 
352368c31abSDavid du Colombier /*
353368c31abSDavid du Colombier  * amap: n '\n' amapelem * n
354368c31abSDavid du Colombier  * n: u32int
355368c31abSDavid du Colombier  * amapelem: name '\t' astart '\t' astop '\n'
356368c31abSDavid du Colombier  * astart, astop: u64int
357368c31abSDavid du Colombier  */
358368c31abSDavid du Colombier int
parseamap(IFile * f,AMapN * amn)359368c31abSDavid du Colombier parseamap(IFile *f, AMapN *amn)
360368c31abSDavid du Colombier {
361368c31abSDavid du Colombier 	AMap *am;
362368c31abSDavid du Colombier 	u64int v64;
363368c31abSDavid du Colombier 	u32int v;
364368c31abSDavid du Colombier 	char *s, *t, *flds[4];
365368c31abSDavid du Colombier 	int i, n;
366368c31abSDavid du Colombier 
367368c31abSDavid du Colombier 	/*
368368c31abSDavid du Colombier 	 * arenas
369368c31abSDavid du Colombier 	 */
370368c31abSDavid du Colombier 	if(ifileu32int(f, &v) < 0){
371368c31abSDavid du Colombier 		seterr(ECorrupt, "syntax error: bad number of elements in %s", f->name);
372368c31abSDavid du Colombier 		return -1;
373368c31abSDavid du Colombier 	}
374368c31abSDavid du Colombier 	n = v;
375368c31abSDavid du Colombier 	if(n > MaxAMap){
37668860d28SDavid du Colombier 		seterr(ECorrupt, "illegal number of elements %d in %s",
37768860d28SDavid du Colombier 			n, f->name);
378368c31abSDavid du Colombier 		return -1;
379368c31abSDavid du Colombier 	}
380368c31abSDavid du Colombier 	am = MKNZ(AMap, n);
381368c31abSDavid du Colombier 	if(am == nil){
382368c31abSDavid du Colombier 		fprint(2, "out of memory\n");
383368c31abSDavid du Colombier 		return -1;
384368c31abSDavid du Colombier 	}
385368c31abSDavid du Colombier 	for(i = 0; i < n; i++){
386368c31abSDavid du Colombier 		s = ifileline(f);
387368c31abSDavid du Colombier 		if(s)
388368c31abSDavid du Colombier 			t = estrdup(s);
389368c31abSDavid du Colombier 		else
390368c31abSDavid du Colombier 			t = nil;
391368c31abSDavid du Colombier 		if(s == nil || getfields(s, flds, 4, 0, "\t") != 3){
392368c31abSDavid du Colombier 			fprint(2, "early eof after %d of %d, %s:#%d: %s\n", i, n, f->name, f->pos, t);
393368c31abSDavid du Colombier 			free(t);
394368c31abSDavid du Colombier 			return -1;
395368c31abSDavid du Colombier 		}
396368c31abSDavid du Colombier 		free(t);
397368c31abSDavid du Colombier 		if(nameok(flds[0]) < 0)
398368c31abSDavid du Colombier 			return -1;
399368c31abSDavid du Colombier 		namecp(am[i].name, flds[0]);
400368c31abSDavid du Colombier 		if(stru64int(flds[1], &v64) < 0){
401368c31abSDavid du Colombier 			seterr(ECorrupt, "syntax error: bad arena base address in %s", f->name);
402368c31abSDavid du Colombier 			free(am);
403368c31abSDavid du Colombier 			return -1;
404368c31abSDavid du Colombier 		}
405368c31abSDavid du Colombier 		am[i].start = v64;
406368c31abSDavid du Colombier 		if(stru64int(flds[2], &v64) < 0){
407368c31abSDavid du Colombier 			seterr(ECorrupt, "syntax error: bad arena size in %s", f->name);
408368c31abSDavid du Colombier 			free(am);
409368c31abSDavid du Colombier 			return -1;
410368c31abSDavid du Colombier 		}
411368c31abSDavid du Colombier 		am[i].stop = v64;
412368c31abSDavid du Colombier 	}
413368c31abSDavid du Colombier 
414368c31abSDavid du Colombier 	amn->map = am;
415368c31abSDavid du Colombier 	amn->n = n;
416368c31abSDavid du Colombier 	return 0;
417368c31abSDavid du Colombier }
418368c31abSDavid du Colombier 
419368c31abSDavid du Colombier int
outputamap(Fmt * f,AMap * am,int n)420368c31abSDavid du Colombier outputamap(Fmt *f, AMap *am, int n)
421368c31abSDavid du Colombier {
422368c31abSDavid du Colombier 	int i;
423368c31abSDavid du Colombier 
424368c31abSDavid du Colombier 	if(fmtprint(f, "%ud\n", n) < 0)
425368c31abSDavid du Colombier 		return -1;
426368c31abSDavid du Colombier 	for(i = 0; i < n; i++)
427368c31abSDavid du Colombier 		if(fmtprint(f, "%s\t%llud\t%llud\n", am[i].name, am[i].start, am[i].stop) < 0)
428368c31abSDavid du Colombier 			return -1;
429368c31abSDavid du Colombier 	return 0;
430368c31abSDavid du Colombier }
431