Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#define	EXTERN
2
#include	"l.h"
3
#include	<ar.h>
4
 
5
#ifndef	DEFAULT
6
#define	DEFAULT	'9'
7
#endif
8
 
9
char	*noname		= "<none>";
10
char	symname[]	= SYMDEF;
11
char	thechar		= '8';
12
char	*thestring 	= "386";
13
 
14
char**	libdir;
15
int	nlibdir	= 0;
16
static	int	maxlibdir = 0;
17
 
18
/*
19
 *	-H0 -T0x40004C -D0x10000000	is garbage unix
20
 *	-H1 -T0xd0 -R4			is unix coff
21
 *	-H2 -T4128 -R4096		is plan9 format
22
 *	-H3 -Tx -Rx			is MS-DOS .COM
23
 *	-H4 -Tx -Rx			is fake MS-DOS .EXE
24
 *	-H5 -T0x80100020 -R4096		is ELF
25
 */
26
 
27
void
28
usage(void)
29
{
30
	diag("usage: %s [-options] objects", argv0);
31
	errorexit();
32
}
33
 
34
static int
35
isobjfile(char *f)
36
{
37
	int n, v;
38
	Biobuf *b;
39
	char buf1[5], buf2[SARMAG];
40
 
41
	b = Bopen(f, OREAD);
42
	if(b == nil)
43
		return 0;
44
	n = Bread(b, buf1, 5);
45
	if(n == 5 && (buf1[2] == 1 && buf1[3] == '<' || buf1[3] == 1 && buf1[4] == '<'))
46
		v = 1;	/* good enough for our purposes */
47
	else{
48
		Bseek(b, 0, 0);
49
		n = Bread(b, buf2, SARMAG);
50
		v = n == SARMAG && strncmp(buf2, ARMAG, SARMAG) == 0;
51
	}
52
	Bterm(b);
53
	return v;
54
}
55
 
56
void
57
main(int argc, char *argv[])
58
{
59
	int i, c;
60
	char *a;
61
	char name[LIBNAMELEN];
62
 
63
	Binit(&bso, 1, OWRITE);
64
	cout = -1;
65
	listinit();
66
	memset(debug, 0, sizeof(debug));
67
	nerrors = 0;
68
	outfile = "8.out";
69
	HEADTYPE = -1;
70
	INITTEXT = -1;
71
	INITTEXTP = -1;
72
	INITDAT = -1;
73
	INITRND = -1;
74
	INITENTRY = 0;
75
	ARGBEGIN {
76
	default:
77
		c = ARGC();
78
		if(c >= 0 && c < sizeof(debug))
79
			debug[c]++;
80
		break;
81
	case 'o': /* output to (next arg) */
82
		outfile = ARGF();
83
		break;
84
	case 'E':
85
		a = ARGF();
86
		if(a)
87
			INITENTRY = a;
88
		break;
89
	case 'H':
90
		a = ARGF();
91
		if(a)
92
			HEADTYPE = atolwhex(a);
93
		break;
94
	case 'L':
95
		addlibpath(EARGF(usage()));
96
		break;
97
	case 'T':
98
		a = ARGF();
99
		if(a)
100
			INITTEXT = atolwhex(a);
101
		break;
102
	case 'P':
103
		a = ARGF();
104
		if(a)
105
			INITTEXTP = atolwhex(a);
106
		break;
107
	case 'D':
108
		a = ARGF();
109
		if(a)
110
			INITDAT = atolwhex(a);
111
		break;
112
	case 'R':
113
		a = ARGF();
114
		if(a)
115
			INITRND = atolwhex(a);
116
		break;
117
	case 'x':	/* produce export table */
118
		doexp = 1;
119
		if(argv[1] != nil && argv[1][0] != '-' && !isobjfile(argv[1])){
120
			a = ARGF();
121
			if(strcmp(a, "*") == 0)
122
				allexport = 1;
123
			else
124
				readundefs(a, SEXPORT);
125
		}
126
		break;
127
	case 'u':	/* produce dynamically loadable module */
128
		dlm = 1;
129
		debug['l']++;
130
		if(argv[1] != nil && argv[1][0] != '-' && !isobjfile(argv[1]))
131
			readundefs(ARGF(), SIMPORT);
132
		break;
133
	} ARGEND
134
	USED(argc);
135
	if(*argv == 0)
136
		usage();
137
	if(!debug['9'] && !debug['U'] && !debug['B'])
138
		debug[DEFAULT] = 1;
139
	a = getenv("ccroot");
140
	if(a != nil && *a != '\0') {
141
		if(!fileexists(a)) {
142
			diag("nonexistent $ccroot: %s", a);
143
			errorexit();
144
		}
145
	}else
146
		a = "";
147
	snprint(name, sizeof(name), "%s/%s/lib", a, thestring);
148
	addlibpath(name);
149
	if(HEADTYPE == -1) {
150
		if(debug['U'])
151
			HEADTYPE = 1;
152
		if(debug['B'])
153
			HEADTYPE = 2;
154
		if(debug['9'])
155
			HEADTYPE = 2;
156
	}
157
	switch(HEADTYPE) {
158
	default:
159
		diag("unknown -H option");
160
		errorexit();
161
 
162
	case 0:	/* this is garbage */
163
		HEADR = 20L+56L;
164
		if(INITTEXT == -1)
165
			INITTEXT = 0x40004CL;
166
		if(INITDAT == -1)
167
			INITDAT = 0x10000000L;
168
		if(INITRND == -1)
169
			INITRND = 0;
170
		break;
171
	case 1:	/* is unix coff */
172
		HEADR = 0xd0L;
173
		if(INITTEXT == -1)
174
			INITTEXT = 0xd0;
175
		if(INITDAT == -1)
176
			INITDAT = 0x400000;
177
		if(INITRND == -1)
178
			INITRND = 0;
179
		break;
180
	case 2:	/* plan 9 */
181
		HEADR = 32L;
182
		if(INITTEXT == -1)
183
			INITTEXT = 4096+32;
184
		if(INITDAT == -1)
185
			INITDAT = 0;
186
		if(INITRND == -1)
187
			INITRND = 4096;
188
		break;
189
	case 3:	/* MS-DOS .COM */
190
		HEADR = 0;
191
		if(INITTEXT == -1)
192
			INITTEXT = 0x0100;
193
		if(INITDAT == -1)
194
			INITDAT = 0;
195
		if(INITRND == -1)
196
			INITRND = 4;
197
		break;
198
	case 4:	/* fake MS-DOS .EXE */
199
		HEADR = 0x200;
200
		if(INITTEXT == -1)
201
			INITTEXT = 0x0100;
202
		if(INITDAT == -1)
203
			INITDAT = 0;
204
		if(INITRND == -1)
205
			INITRND = 4;
206
		HEADR += (INITTEXT & 0xFFFF);
207
		if(debug['v'])
208
			Bprint(&bso, "HEADR = 0x%ld\n", HEADR);
209
		break;
210
	case 5:	/* elf executable */
211
		HEADR = rnd(Ehdr32sz+3*Phdr32sz, 16);
212
		if(INITTEXT == -1)
213
			INITTEXT = 0x80100020L;
214
		if(INITDAT == -1)
215
			INITDAT = 0;
216
		if(INITRND == -1)
217
			INITRND = 4096;
218
		break;
219
	}
220
	if (INITTEXTP == -1)
221
		INITTEXTP = INITTEXT;
222
	if(INITDAT != 0 && INITRND != 0)
223
		print("warning: -D0x%lux is ignored because of -R0x%lux\n",
224
			INITDAT, INITRND);
225
	if(debug['v'])
226
		Bprint(&bso, "HEADER = -H0x%ld -T0x%lux -D0x%lux -R0x%lux\n",
227
			HEADTYPE, INITTEXT, INITDAT, INITRND);
228
	Bflush(&bso);
229
	for(i=1; optab[i].as; i++)
230
		if(i != optab[i].as) {
231
			diag("phase error in optab: %d", i);
232
			errorexit();
233
		}
234
 
235
	for(i=0; i<Ymax; i++)
236
		ycover[i*Ymax + i] = 1;
237
 
238
	ycover[Yi0*Ymax + Yi8] = 1;
239
	ycover[Yi1*Ymax + Yi8] = 1;
240
 
241
	ycover[Yi0*Ymax + Yi32] = 1;
242
	ycover[Yi1*Ymax + Yi32] = 1;
243
	ycover[Yi8*Ymax + Yi32] = 1;
244
 
245
	ycover[Yal*Ymax + Yrb] = 1;
246
	ycover[Ycl*Ymax + Yrb] = 1;
247
	ycover[Yax*Ymax + Yrb] = 1;
248
	ycover[Ycx*Ymax + Yrb] = 1;
249
	ycover[Yrx*Ymax + Yrb] = 1;
250
 
251
	ycover[Yax*Ymax + Yrx] = 1;
252
	ycover[Ycx*Ymax + Yrx] = 1;
253
 
254
	ycover[Yax*Ymax + Yrl] = 1;
255
	ycover[Ycx*Ymax + Yrl] = 1;
256
	ycover[Yrx*Ymax + Yrl] = 1;
257
 
258
	ycover[Yf0*Ymax + Yrf] = 1;
259
 
260
	ycover[Yal*Ymax + Ymb] = 1;
261
	ycover[Ycl*Ymax + Ymb] = 1;
262
	ycover[Yax*Ymax + Ymb] = 1;
263
	ycover[Ycx*Ymax + Ymb] = 1;
264
	ycover[Yrx*Ymax + Ymb] = 1;
265
	ycover[Yrb*Ymax + Ymb] = 1;
266
	ycover[Ym*Ymax + Ymb] = 1;
267
 
268
	ycover[Yax*Ymax + Yml] = 1;
269
	ycover[Ycx*Ymax + Yml] = 1;
270
	ycover[Yrx*Ymax + Yml] = 1;
271
	ycover[Yrl*Ymax + Yml] = 1;
272
	ycover[Ym*Ymax + Yml] = 1;
273
 
274
	for(i=0; i<D_NONE; i++) {
275
		reg[i] = -1;
276
		if(i >= D_AL && i <= D_BH)
277
			reg[i] = (i-D_AL) & 7;
278
		if(i >= D_AX && i <= D_DI)
279
			reg[i] = (i-D_AX) & 7;
280
		if(i >= D_F0 && i <= D_F0+7)
281
			reg[i] = (i-D_F0) & 7;
282
	}
283
 
284
	zprg.link = P;
285
	zprg.pcond = P;
286
	zprg.back = 2;
287
	zprg.as = AGOK;
288
	zprg.from.type = D_NONE;
289
	zprg.from.index = D_NONE;
290
	zprg.from.scale = 1;
291
	zprg.to = zprg.from;
292
 
293
	pcstr = "%.6lux ";
294
	nuxiinit();
295
	histgen = 0;
296
	textp = P;
297
	datap = P;
298
	edatap = P;
299
	pc = 0;
300
	dtype = 4;
301
	cout = create(outfile, 1, 0775);
302
	if(cout < 0) {
303
		diag("cannot create %s: %r", outfile);
304
		errorexit();
305
	}
306
	version = 0;
307
	cbp = buf.cbuf;
308
	cbc = sizeof(buf.cbuf);
309
	firstp = prg();
310
	lastp = firstp;
311
 
312
	if(INITENTRY == 0) {
313
		INITENTRY = "_main";
314
		if(debug['p'])
315
			INITENTRY = "_mainp";
316
		if(!debug['l'])
317
			lookup(INITENTRY, 0)->type = SXREF;
318
	} else if(!(*INITENTRY >= '0' && *INITENTRY <= '9'))
319
		lookup(INITENTRY, 0)->type = SXREF;
320
 
321
	while(*argv)
322
		objfile(*argv++);
323
	if(!debug['l'])
324
		loadlib();
325
	firstp = firstp->link;
326
	if(firstp == P)
327
		errorexit();
328
	if(doexp || dlm){
329
		EXPTAB = "_exporttab";
330
		zerosig(EXPTAB);
331
		zerosig("etext");
332
		zerosig("edata");
333
		zerosig("end");
334
		if(dlm){
335
			import();
336
			HEADTYPE = 2;
337
			INITTEXT = INITDAT = 0;
338
			INITRND = 8;
339
			INITENTRY = EXPTAB;
340
		}
341
		export();
342
	}
343
	patch();
344
	follow();
345
	dodata();
346
	dostkoff();
347
	if(debug['p'])
348
		if(debug['1'])
349
			doprof1();
350
		else
351
			doprof2();
352
	span();
353
	doinit();
354
	asmb();
355
	undef();
356
	if(debug['v']) {
357
		Bprint(&bso, "%5.2f cpu time\n", cputime());
358
		Bprint(&bso, "%ld symbols\n", nsymbol);
359
		Bprint(&bso, "%ld memory used\n", thunk);
360
		Bprint(&bso, "%d sizeof adr\n", sizeof(Adr));
361
		Bprint(&bso, "%d sizeof prog\n", sizeof(Prog));
362
	}
363
	Bflush(&bso);
364
 
365
	errorexit();
366
}
367
 
368
void
369
addlibpath(char *arg)
370
{
371
	char **p;
372
 
373
	if(nlibdir >= maxlibdir) {
374
		if(maxlibdir == 0)
375
			maxlibdir = 8;
376
		else
377
			maxlibdir *= 2;
378
		p = malloc(maxlibdir*sizeof(*p));
379
		if(p == nil) {
380
			diag("out of memory");
381
			errorexit();
382
		}
383
		memmove(p, libdir, nlibdir*sizeof(*p));
384
		free(libdir);
385
		libdir = p;
386
	}
387
	libdir[nlibdir++] = strdup(arg);
388
}
389
 
390
char*
391
findlib(char *file)
392
{
393
	int i;
394
	char name[LIBNAMELEN];
395
 
396
	for(i = 0; i < nlibdir; i++) {
397
		snprint(name, sizeof(name), "%s/%s", libdir[i], file);
398
		if(fileexists(name))
399
			return libdir[i];
400
	}
401
	return nil;
402
}
403
 
404
void
405
loadlib(void)
406
{
407
	int i;
408
	long h;
409
	Sym *s;
410
 
411
loop:
412
	xrefresolv = 0;
413
	for(i=0; i<libraryp; i++) {
414
		if(debug['v'])
415
			Bprint(&bso, "%5.2f autolib: %s (from %s)\n", cputime(), library[i], libraryobj[i]);
416
		objfile(library[i]);
417
	}
418
	if(xrefresolv)
419
	for(h=0; h<nelem(hash); h++)
420
	for(s = hash[h]; s != S; s = s->link)
421
		if(s->type == SXREF)
422
			goto loop;
423
}
424
 
425
void
426
errorexit(void)
427
{
428
 
429
	if(nerrors) {
430
		if(cout >= 0)
431
			remove(outfile);
432
		exits("error");
433
	}
434
	exits(0);
435
}
436
 
437
void
438
objfile(char *file)
439
{
440
	long off, esym, cnt, l;
441
	int f, work;
442
	Sym *s;
443
	char magbuf[SARMAG];
444
	char name[LIBNAMELEN], pname[LIBNAMELEN];
445
	struct ar_hdr arhdr;
446
	char *e, *start, *stop;
447
 
448
	if(debug['v'])
449
		Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file);
450
	Bflush(&bso);
451
	if(file[0] == '-' && file[1] == 'l') {
452
		snprint(pname, sizeof(pname), "lib%s.a", file+2);
453
		e = findlib(pname);
454
		if(e == nil) {
455
			diag("cannot find library: %s", file);
456
			errorexit();
457
		}
458
		snprint(name, sizeof(name), "%s/%s", e, pname);
459
		file = name;
460
	}
461
	f = open(file, 0);
462
	if(f < 0) {
463
		diag("cannot open %s: %r", file);
464
		errorexit();
465
	}
466
	l = read(f, magbuf, SARMAG);
467
	if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){
468
		/* load it as a regular file */
469
		l = seek(f, 0L, 2);
470
		seek(f, 0L, 0);
471
		ldobj(f, l, file);
472
		close(f);
473
		return;
474
	}
475
 
476
	l = read(f, &arhdr, SAR_HDR);
477
	if(l != SAR_HDR) {
478
		diag("%s: short read on archive file symbol header", file);
479
		goto out;
480
	}
481
	if(strncmp(arhdr.name, symname, strlen(symname))) {
482
		diag("%s: first entry not symbol header", file);
483
		goto out;
484
	}
485
 
486
	esym = SARMAG + SAR_HDR + atolwhex(arhdr.size);
487
	off = SARMAG + SAR_HDR;
488
 
489
	/*
490
	 * just bang the whole symbol file into memory
491
	 */
492
	seek(f, off, 0);
493
	cnt = esym - off;
494
	start = malloc(cnt + 10);
495
	cnt = read(f, start, cnt);
496
	if(cnt <= 0){
497
		close(f);
498
		return;
499
	}
500
	stop = &start[cnt];
501
	memset(stop, 0, 10);
502
 
503
	work = 1;
504
	while(work) {
505
		if(debug['v'])
506
			Bprint(&bso, "%5.2f library pass: %s\n", cputime(), file);
507
		Bflush(&bso);
508
		work = 0;
509
		for(e = start; e < stop; e = strchr(e+5, 0) + 1) {
510
			s = lookup(e+5, 0);
511
			if(s->type != SXREF)
512
				continue;
513
			sprint(pname, "%s(%s)", file, s->name);
514
			if(debug['v'])
515
				Bprint(&bso, "%5.2f library: %s\n", cputime(), pname);
516
			Bflush(&bso);
517
			l = e[1] & 0xff;
518
			l |= (e[2] & 0xff) << 8;
519
			l |= (e[3] & 0xff) << 16;
520
			l |= (e[4] & 0xff) << 24;
521
			seek(f, l, 0);
522
			/* need readn to read the dumps (at least) */
523
			l = readn(f, &arhdr, SAR_HDR);
524
			if(l != SAR_HDR)
525
				goto bad;
526
			if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag)))
527
				goto bad;
528
			l = atolwhex(arhdr.size);
529
			ldobj(f, l, pname);
530
			if(s->type == SXREF) {
531
				diag("%s: failed to load: %s", file, s->name);
532
				errorexit();
533
			}
534
			work = 1;
535
			xrefresolv = 1;
536
		}
537
	}
538
	return;
539
 
540
bad:
541
	diag("%s: bad or out of date archive", file);
542
out:
543
	close(f);
544
}
545
 
546
int
547
zaddr(uchar *p, Adr *a, Sym *h[])
548
{
549
	int c, t, i;
550
	int l;
551
	Sym *s;
552
	Auto *u;
553
 
554
	t = p[0];
555
 
556
	c = 1;
557
	if(t & T_INDEX) {
558
		a->index = p[c];
559
		a->scale = p[c+1];
560
		c += 2;
561
	} else {
562
		a->index = D_NONE;
563
		a->scale = 0;
564
	}
565
	a->offset = 0;
566
	if(t & T_OFFSET) {
567
		a->offset = p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24);
568
		c += 4;
569
	}
570
	a->sym = S;
571
	if(t & T_SYM) {
572
		a->sym = h[p[c]];
573
		c++;
574
	}
575
	a->type = D_NONE;
576
	if(t & T_FCONST) {
577
		a->ieee.l = p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24);
578
		a->ieee.h = p[c+4] | (p[c+5]<<8) | (p[c+6]<<16) | (p[c+7]<<24);
579
		c += 8;
580
		a->type = D_FCONST;
581
	} else
582
	if(t & T_SCONST) {
583
		for(i=0; i<NSNAME; i++)
584
			a->scon[i] = p[c+i];
585
		c += NSNAME;
586
		a->type = D_SCONST;
587
	}
588
	if(t & T_TYPE) {
589
		a->type = p[c];
590
		c++;
591
	}
592
	s = a->sym;
593
	if(s == S)
594
		return c;
595
 
596
	t = a->type;
597
	if(t != D_AUTO && t != D_PARAM)
598
		return c;
599
	l = a->offset;
600
	for(u=curauto; u; u=u->link) {
601
		if(u->asym == s)
602
		if(u->type == t) {
603
			if(u->aoffset > l)
604
				u->aoffset = l;
605
			return c;
606
		}
607
	}
608
 
609
	while(nhunk < sizeof(Auto))
610
		gethunk();
611
	u = (Auto*)hunk;
612
	nhunk -= sizeof(Auto);
613
	hunk += sizeof(Auto);
614
 
615
	u->link = curauto;
616
	curauto = u;
617
	u->asym = s;
618
	u->aoffset = l;
619
	u->type = t;
620
	return c;
621
}
622
 
623
void
624
addlib(char *obj)
625
{
626
	char fn1[LIBNAMELEN], fn2[LIBNAMELEN], comp[LIBNAMELEN], *p, *name;
627
	int i, search;
628
 
629
	if(histfrogp <= 0)
630
		return;
631
 
632
	name = fn1;
633
	search = 0;
634
	if(histfrog[0]->name[1] == '/') {
635
		sprint(name, "");
636
		i = 1;
637
	} else if(histfrog[0]->name[1] == '.') {
638
		sprint(name, ".");
639
		i = 0;
640
	} else {
641
		sprint(name, "");
642
		i = 0;
643
		search = 1;
644
	}
645
 
646
	for(; i<histfrogp; i++) {
647
		snprint(comp, sizeof comp, histfrog[i]->name+1);
648
		for(;;) {
649
			p = strstr(comp, "$O");
650
			if(p == 0)
651
				break;
652
			memmove(p+1, p+2, strlen(p+2)+1);
653
			p[0] = thechar;
654
		}
655
		for(;;) {
656
			p = strstr(comp, "$M");
657
			if(p == 0)
658
				break;
659
			if(strlen(comp)+strlen(thestring)-2+1 >= sizeof comp) {
660
				diag("library component too long");
661
				return;
662
			}
663
			memmove(p+strlen(thestring), p+2, strlen(p+2)+1);
664
			memmove(p, thestring, strlen(thestring));
665
		}
666
		if(strlen(fn1) + strlen(comp) + 3 >= sizeof(fn1)) {
667
			diag("library component too long");
668
			return;
669
		}
670
		if(i > 0 || !search)
671
			strcat(fn1, "/");
672
		strcat(fn1, comp);
673
	}
674
 
675
	cleanname(name);
676
 
677
	if(search){
678
		p = findlib(name);
679
		if(p != nil){
680
			snprint(fn2, sizeof(fn2), "%s/%s", p, name);
681
			name = fn2;
682
		}
683
	}
684
 
685
	for(i=0; i<libraryp; i++)
686
		if(strcmp(name, library[i]) == 0)
687
			return;
688
	if(libraryp == nelem(library)){
689
		diag("too many autolibs; skipping %s", name);
690
		return;
691
	}
692
 
693
	p = malloc(strlen(name) + 1);
694
	strcpy(p, name);
695
	library[libraryp] = p;
696
	p = malloc(strlen(obj) + 1);
697
	strcpy(p, obj);
698
	libraryobj[libraryp] = p;
699
	libraryp++;
700
}
701
 
702
void
703
addhist(long line, int type)
704
{
705
	Auto *u;
706
	Sym *s;
707
	int i, j, k;
708
 
709
	u = malloc(sizeof(Auto));
710
	s = malloc(sizeof(Sym));
711
	s->name = malloc(2*(histfrogp+1) + 1);
712
 
713
	u->asym = s;
714
	u->type = type;
715
	u->aoffset = line;
716
	u->link = curhist;
717
	curhist = u;
718
 
719
	j = 1;
720
	for(i=0; i<histfrogp; i++) {
721
		k = histfrog[i]->value;
722
		s->name[j+0] = k>>8;
723
		s->name[j+1] = k;
724
		j += 2;
725
	}
726
}
727
 
728
void
729
histtoauto(void)
730
{
731
	Auto *l;
732
 
733
	while(l = curhist) {
734
		curhist = l->link;
735
		l->link = curauto;
736
		curauto = l;
737
	}
738
}
739
 
740
void
741
collapsefrog(Sym *s)
742
{
743
	int i;
744
 
745
	/*
746
	 * bad encoding of path components only allows
747
	 * MAXHIST components. if there is an overflow,
748
	 * first try to collapse xxx/..
749
	 */
750
	for(i=1; i<histfrogp; i++)
751
		if(strcmp(histfrog[i]->name+1, "..") == 0) {
752
			memmove(histfrog+i-1, histfrog+i+1,
753
				(histfrogp-i-1)*sizeof(histfrog[0]));
754
			histfrogp--;
755
			goto out;
756
		}
757
 
758
	/*
759
	 * next try to collapse .
760
	 */
761
	for(i=0; i<histfrogp; i++)
762
		if(strcmp(histfrog[i]->name+1, ".") == 0) {
763
			memmove(histfrog+i, histfrog+i+1,
764
				(histfrogp-i-1)*sizeof(histfrog[0]));
765
			goto out;
766
		}
767
 
768
	/*
769
	 * last chance, just truncate from front
770
	 */
771
	memmove(histfrog+0, histfrog+1,
772
		(histfrogp-1)*sizeof(histfrog[0]));
773
 
774
out:
775
	histfrog[histfrogp-1] = s;
776
}
777
 
778
void
779
nopout(Prog *p)
780
{
781
	p->as = ANOP;
782
	p->from.type = D_NONE;
783
	p->to.type = D_NONE;
784
}
785
 
786
uchar*
787
readsome(int f, uchar *buf, uchar *good, uchar *stop, int max)
788
{
789
	int n;
790
 
791
	n = stop - good;
792
	memmove(buf, good, stop - good);
793
	stop = buf + n;
794
	n = MAXIO - n;
795
	if(n > max)
796
		n = max;
797
	n = read(f, stop, n);
798
	if(n <= 0)
799
		return 0;
800
	return stop + n;
801
}
802
 
803
void
804
ldobj(int f, long c, char *pn)
805
{
806
	long ipc;
807
	Prog *p, *t;
808
	uchar *bloc, *bsize, *stop;
809
	int v, o, r, skip;
810
	Sym *h[NSYM], *s, *di;
811
	ulong sig;
812
	static int files;
813
	static char **filen;
814
	char **nfilen;
815
 
816
	if((files&15) == 0){
817
		nfilen = malloc((files+16)*sizeof(char*));
818
		memmove(nfilen, filen, files*sizeof(char*));
819
		free(filen);
820
		filen = nfilen;
821
	}
822
	filen[files++] = strdup(pn);
823
 
824
	bsize = buf.xbuf;
825
	bloc = buf.xbuf;
826
	di = S;
827
 
828
newloop:
829
	memset(h, 0, sizeof(h));
830
	version++;
831
	histfrogp = 0;
832
	ipc = pc;
833
	skip = 0;
834
 
835
loop:
836
	if(c <= 0)
837
		goto eof;
838
	r = bsize - bloc;
839
	if(r < 100 && r < c) {		/* enough for largest prog */
840
		bsize = readsome(f, buf.xbuf, bloc, bsize, c);
841
		if(bsize == 0)
842
			goto eof;
843
		bloc = buf.xbuf;
844
		goto loop;
845
	}
846
	o = bloc[0] | (bloc[1] << 8);
847
	if(o <= AXXX || o >= ALAST) {
848
		if(o < 0)
849
			goto eof;
850
		diag("%s: opcode out of range %d", pn, o);
851
		print("	probably not a .8 file\n");
852
		errorexit();
853
	}
854
 
855
	if(o == ANAME || o == ASIGNAME) {
856
		sig = 0;
857
		if(o == ASIGNAME) {
858
			sig = bloc[2] | (bloc[3]<<8) | (bloc[4]<<16) | (bloc[5]<<24);
859
			bloc += 4;
860
			c -= 4;
861
		}
862
		stop = memchr(&bloc[4], 0, bsize-&bloc[4]);
863
		if(stop == 0){
864
			bsize = readsome(f, buf.xbuf, bloc, bsize, c);
865
			if(bsize == 0)
866
				goto eof;
867
			bloc = buf.xbuf;
868
			stop = memchr(&bloc[4], 0, bsize-&bloc[4]);
869
			if(stop == 0){
870
				fprint(2, "%s: name too long\n", pn);
871
				errorexit();
872
			}
873
		}
874
		v = bloc[2];	/* type */
875
		o = bloc[3];	/* sym */
876
		bloc += 4;
877
		c -= 4;
878
 
879
		r = 0;
880
		if(v == D_STATIC)
881
			r = version;
882
		s = lookup((char*)bloc, r);
883
		c -= &stop[1] - bloc;
884
		bloc = stop + 1;
885
 
886
		if(debug['S'] && r == 0)
887
			sig = 1729;
888
		if(sig != 0){
889
			if(s->sig != 0 && s->sig != sig)
890
				diag("incompatible type signatures %lux(%s) and %lux(%s) for %s", s->sig, filen[s->file], sig, pn, s->name);
891
			s->sig = sig;
892
			s->file = files-1;
893
		}
894
 
895
		if(debug['W'])
896
			print("	ANAME	%s\n", s->name);
897
		h[o] = s;
898
		if((v == D_EXTERN || v == D_STATIC) && s->type == 0)
899
			s->type = SXREF;
900
		if(v == D_FILE) {
901
			if(s->type != SFILE) {
902
				histgen++;
903
				s->type = SFILE;
904
				s->value = histgen;
905
			}
906
			if(histfrogp < MAXHIST) {
907
				histfrog[histfrogp] = s;
908
				histfrogp++;
909
			} else
910
				collapsefrog(s);
911
		}
912
		goto loop;
913
	}
914
 
915
	while(nhunk < sizeof(Prog))
916
		gethunk();
917
	p = (Prog*)hunk;
918
	nhunk -= sizeof(Prog);
919
	hunk += sizeof(Prog);
920
 
921
	p->as = o;
922
	p->line = bloc[2] | (bloc[3] << 8) | (bloc[4] << 16) | (bloc[5] << 24);
923
	p->back = 2;
924
	r = zaddr(bloc+6, &p->from, h) + 6;
925
	r += zaddr(bloc+r, &p->to, h);
926
	bloc += r;
927
	c -= r;
928
 
929
	if(debug['W'])
930
		print("%P\n", p);
931
 
932
	switch(p->as) {
933
	case AHISTORY:
934
		if(p->to.offset == -1) {
935
			addlib(pn);
936
			histfrogp = 0;
937
			goto loop;
938
		}
939
		addhist(p->line, D_FILE);		/* 'z' */
940
		if(p->to.offset)
941
			addhist(p->to.offset, D_FILE1);	/* 'Z' */
942
		histfrogp = 0;
943
		goto loop;
944
 
945
	case AEND:
946
		histtoauto();
947
		if(curtext != P)
948
			curtext->to.autom = curauto;
949
		curauto = 0;
950
		curtext = P;
951
		if(c)
952
			goto newloop;
953
		return;
954
 
955
	case AGLOBL:
956
		s = p->from.sym;
957
		if(s->type == 0 || s->type == SXREF) {
958
			s->type = SBSS;
959
			s->value = 0;
960
		}
961
		if(s->type != SBSS) {
962
			diag("%s: redefinition: %s in %s",
963
				pn, s->name, TNAME);
964
			s->type = SBSS;
965
			s->value = 0;
966
		}
967
		if(p->to.offset > s->value)
968
			s->value = p->to.offset;
969
		goto loop;
970
 
971
	case ADYNT:
972
		if(p->to.sym == S) {
973
			diag("DYNT without a sym\n%P", p);
974
			break;
975
		}
976
		di = p->to.sym;
977
		p->from.scale = 4;
978
		if(di->type == SXREF) {
979
			if(debug['z'])
980
				Bprint(&bso, "%P set to %d\n", p, dtype);
981
			di->type = SCONST;
982
			di->value = dtype;
983
			dtype += 4;
984
		}
985
		if(p->from.sym == S)
986
			break;
987
 
988
		p->from.offset = di->value;
989
		p->from.sym->type = SDATA;
990
		if(curtext == P) {
991
			diag("DYNT not in text: %P", p);
992
			break;
993
		}
994
		p->to.sym = curtext->from.sym;
995
		p->to.type = D_ADDR;
996
		p->to.index = D_EXTERN;
997
		goto data;
998
 
999
	case AINIT:
1000
		if(p->from.sym == S) {
1001
			diag("INIT without a sym\n%P", p);
1002
			break;
1003
		}
1004
		if(di == S) {
1005
			diag("INIT without previous DYNT\n%P", p);
1006
			break;
1007
		}
1008
		p->from.offset = di->value;
1009
		p->from.sym->type = SDATA;
1010
		goto data;
1011
 
1012
	case ADATA:
1013
	data:
1014
		if(edatap == P)
1015
			datap = p;
1016
		else
1017
			edatap->link = p;
1018
		edatap = p;
1019
		p->link = P;
1020
		goto loop;
1021
 
1022
	case AGOK:
1023
		diag("%s: GOK opcode in %s", pn, TNAME);
1024
		pc++;
1025
		goto loop;
1026
 
1027
	case ATEXT:
1028
		if(curtext != P) {
1029
			histtoauto();
1030
			curtext->to.autom = curauto;
1031
			curauto = 0;
1032
		}
1033
		skip = 0;
1034
		curtext = p;
1035
		s = p->from.sym;
1036
		if(s == S) {
1037
			diag("%s: no TEXT symbol: %P", pn, p);
1038
			errorexit();
1039
		}
1040
		if(s->type != 0 && s->type != SXREF) {
1041
			if(p->from.scale & DUPOK) {
1042
				skip = 1;
1043
				goto casdef;
1044
			}
1045
			diag("%s: redefinition: %s\n%P", pn, s->name, p);
1046
		}
1047
		s->type = STEXT;
1048
		s->value = pc;
1049
		lastp->link = p;
1050
		lastp = p;
1051
		p->pc = pc;
1052
		pc++;
1053
		if(textp == P) {
1054
			textp = p;
1055
			etextp = p;
1056
			goto loop;
1057
		}
1058
		etextp->pcond = p;
1059
		etextp = p;
1060
		goto loop;
1061
 
1062
	case AFMOVF:
1063
	case AFADDF:
1064
	case AFSUBF:
1065
	case AFSUBRF:
1066
	case AFMULF:
1067
	case AFDIVF:
1068
	case AFDIVRF:
1069
	case AFCOMF:
1070
	case AFCOMFP:
1071
		if(skip)
1072
			goto casdef;
1073
		if(p->from.type == D_FCONST) {
1074
			/* size sb 9 max */
1075
			sprint(literal, "$%lux", ieeedtof(&p->from.ieee));
1076
			s = lookup(literal, 0);
1077
			if(s->type == 0) {
1078
				s->type = SBSS;
1079
				s->value = 4;
1080
				t = prg();
1081
				t->as = ADATA;
1082
				t->line = p->line;
1083
				t->from.type = D_EXTERN;
1084
				t->from.sym = s;
1085
				t->from.scale = 4;
1086
				t->to = p->from;
1087
				if(edatap == P)
1088
					datap = t;
1089
				else
1090
					edatap->link = t;
1091
				edatap = t;
1092
				t->link = P;
1093
			}
1094
			p->from.type = D_EXTERN;
1095
			p->from.sym = s;
1096
			p->from.offset = 0;
1097
		}
1098
		goto casdef;
1099
 
1100
	case AFMOVD:
1101
	case AFADDD:
1102
	case AFSUBD:
1103
	case AFSUBRD:
1104
	case AFMULD:
1105
	case AFDIVD:
1106
	case AFDIVRD:
1107
	case AFCOMD:
1108
	case AFCOMDP:
1109
		if(skip)
1110
			goto casdef;
1111
		if(p->from.type == D_FCONST) {
1112
			/* size sb 18 max */
1113
			sprint(literal, "$%lux.%lux",
1114
				p->from.ieee.l, p->from.ieee.h);
1115
			s = lookup(literal, 0);
1116
			if(s->type == 0) {
1117
				s->type = SBSS;
1118
				s->value = 8;
1119
				t = prg();
1120
				t->as = ADATA;
1121
				t->line = p->line;
1122
				t->from.type = D_EXTERN;
1123
				t->from.sym = s;
1124
				t->from.scale = 8;
1125
				t->to = p->from;
1126
				if(edatap == P)
1127
					datap = t;
1128
				else
1129
					edatap->link = t;
1130
				edatap = t;
1131
				t->link = P;
1132
			}
1133
			p->from.type = D_EXTERN;
1134
			p->from.sym = s;
1135
			p->from.offset = 0;
1136
		}
1137
		goto casdef;
1138
 
1139
	casdef:
1140
	default:
1141
		if(skip)
1142
			nopout(p);
1143
 
1144
		if(p->to.type == D_BRANCH)
1145
			p->to.offset += ipc;
1146
		lastp->link = p;
1147
		lastp = p;
1148
		p->pc = pc;
1149
		pc++;
1150
		goto loop;
1151
	}
1152
	goto loop;
1153
 
1154
eof:
1155
	diag("truncated object file: %s", pn);
1156
}
1157
 
1158
Sym*
1159
lookup(char *symb, int v)
1160
{
1161
	Sym *s;
1162
	char *p;
1163
	long h;
1164
	int l, c;
1165
 
1166
	h = v;
1167
	for(p=symb; c = *p; p++)
1168
		h = h+h+h + c;
1169
	l = (p - symb) + 1;
1170
	h &= 0xffffff;
1171
	h %= NHASH;
1172
	for(s = hash[h]; s != S; s = s->link)
1173
		if(s->version == v)
1174
		if(memcmp(s->name, symb, l) == 0)
1175
			return s;
1176
 
1177
	while(nhunk < sizeof(Sym))
1178
		gethunk();
1179
	s = (Sym*)hunk;
1180
	nhunk -= sizeof(Sym);
1181
	hunk += sizeof(Sym);
1182
 
1183
	s->name = malloc(l + 1);
1184
	memmove(s->name, symb, l);
1185
 
1186
	s->link = hash[h];
1187
	s->type = 0;
1188
	s->version = v;
1189
	s->value = 0;
1190
	s->sig = 0;
1191
	hash[h] = s;
1192
	nsymbol++;
1193
	return s;
1194
}
1195
 
1196
Prog*
1197
prg(void)
1198
{
1199
	Prog *p;
1200
 
1201
	while(nhunk < sizeof(Prog))
1202
		gethunk();
1203
	p = (Prog*)hunk;
1204
	nhunk -= sizeof(Prog);
1205
	hunk += sizeof(Prog);
1206
 
1207
	*p = zprg;
1208
	return p;
1209
}
1210
 
1211
Prog*
1212
copyp(Prog *q)
1213
{
1214
	Prog *p;
1215
 
1216
	p = prg();
1217
	*p = *q;
1218
	return p;
1219
}
1220
 
1221
Prog*
1222
appendp(Prog *q)
1223
{
1224
	Prog *p;
1225
 
1226
	p = prg();
1227
	p->link = q->link;
1228
	q->link = p;
1229
	p->line = q->line;
1230
	return p;
1231
}
1232
 
1233
void
1234
gethunk(void)
1235
{
1236
	char *h;
1237
	long nh;
1238
 
1239
	nh = NHUNK;
1240
	if(thunk >= 5L*NHUNK) {
1241
		nh = 5L*NHUNK;
1242
		if(thunk >= 25L*NHUNK)
1243
			nh = 25L*NHUNK;
1244
	}
1245
	h = mysbrk(nh);
1246
	if(h == (char*)-1) {
1247
		diag("out of memory");
1248
		errorexit();
1249
	}
1250
	hunk = h;
1251
	nhunk = nh;
1252
	thunk += nh;
1253
}
1254
 
1255
void
1256
doprof1(void)
1257
{
1258
	Sym *s;
1259
	long n;
1260
	Prog *p, *q;
1261
 
1262
	if(debug['v'])
1263
		Bprint(&bso, "%5.2f profile 1\n", cputime());
1264
	Bflush(&bso);
1265
	s = lookup("__mcount", 0);
1266
	n = 1;
1267
	for(p = firstp->link; p != P; p = p->link) {
1268
		if(p->as == ATEXT) {
1269
			q = prg();
1270
			q->line = p->line;
1271
			q->link = datap;
1272
			datap = q;
1273
			q->as = ADATA;
1274
			q->from.type = D_EXTERN;
1275
			q->from.offset = n*4;
1276
			q->from.sym = s;
1277
			q->from.scale = 4;
1278
			q->to = p->from;
1279
			q->to.type = D_CONST;
1280
 
1281
			q = prg();
1282
			q->line = p->line;
1283
			q->pc = p->pc;
1284
			q->link = p->link;
1285
			p->link = q;
1286
			p = q;
1287
			p->as = AADDL;
1288
			p->from.type = D_CONST;
1289
			p->from.offset = 1;
1290
			p->to.type = D_EXTERN;
1291
			p->to.sym = s;
1292
			p->to.offset = n*4 + 4;
1293
 
1294
			n += 2;
1295
			continue;
1296
		}
1297
	}
1298
	q = prg();
1299
	q->line = 0;
1300
	q->link = datap;
1301
	datap = q;
1302
 
1303
	q->as = ADATA;
1304
	q->from.type = D_EXTERN;
1305
	q->from.sym = s;
1306
	q->from.scale = 4;
1307
	q->to.type = D_CONST;
1308
	q->to.offset = n;
1309
 
1310
	s->type = SBSS;
1311
	s->value = n*4;
1312
}
1313
 
1314
void
1315
doprof2(void)
1316
{
1317
	Sym *s2, *s4;
1318
	Prog *p, *q, *q2, *ps2, *ps4;
1319
 
1320
	if(debug['v'])
1321
		Bprint(&bso, "%5.2f profile 2\n", cputime());
1322
	Bflush(&bso);
1323
 
1324
	if(debug['e']){
1325
		s2 = lookup("_tracein", 0);
1326
		s4 = lookup("_traceout", 0);
1327
	}else{
1328
		s2 = lookup("_profin", 0);
1329
		s4 = lookup("_profout", 0);
1330
	}
1331
	if(s2->type != STEXT || s4->type != STEXT) {
1332
		if(debug['e'])
1333
			diag("_tracein/_traceout not defined %d %d", s2->type, s4->type);
1334
		else
1335
			diag("_profin/_profout not defined");
1336
		return;
1337
	}
1338
 
1339
	ps2 = P;
1340
	ps4 = P;
1341
	for(p = firstp; p != P; p = p->link) {
1342
		if(p->as == ATEXT) {
1343
			if(p->from.sym == s2) {
1344
				p->from.scale = 1;
1345
				ps2 = p;
1346
			}
1347
			if(p->from.sym == s4) {
1348
				p->from.scale = 1;
1349
				ps4 = p;
1350
			}
1351
		}
1352
	}
1353
	for(p = firstp; p != P; p = p->link) {
1354
		if(p->as == ATEXT) {
1355
			curtext = p;
1356
 
1357
			if(p->from.scale & NOPROF) {	/* dont profile */
1358
				for(;;) {
1359
					q = p->link;
1360
					if(q == P)
1361
						break;
1362
					if(q->as == ATEXT)
1363
						break;
1364
					p = q;
1365
				}
1366
				continue;
1367
			}
1368
 
1369
			/*
1370
			 * JMPL	profin
1371
			 */
1372
			q = prg();
1373
			q->line = p->line;
1374
			q->pc = p->pc;
1375
			q->link = p->link;
1376
			if(debug['e']){		/* embedded tracing */
1377
				q2 = prg();
1378
				p->link = q2;
1379
				q2->link = q;
1380
 
1381
				q2->line = p->line;
1382
				q2->pc = p->pc;
1383
 
1384
				q2->as = AJMP;
1385
				q2->to.type = D_BRANCH;
1386
				q2->to.sym = p->to.sym;
1387
				q2->pcond = q->link;
1388
			}else
1389
				p->link = q;
1390
			p = q;
1391
			p->as = ACALL;
1392
			p->to.type = D_BRANCH;
1393
			p->pcond = ps2;
1394
			p->to.sym = s2;
1395
 
1396
			continue;
1397
		}
1398
		if(p->as == ARET) {
1399
			/*
1400
			 * RET (default)
1401
			 */
1402
			if(debug['e']){		/* embedded tracing */
1403
				q = prg();
1404
				q->line = p->line;
1405
				q->pc = p->pc;
1406
				q->link = p->link;
1407
				p->link = q;
1408
				p = q;
1409
			}
1410
			/*
1411
			 * RET
1412
			 */
1413
			q = prg();
1414
			q->as = ARET;
1415
			q->from = p->from;
1416
			q->to = p->to;
1417
			q->link = p->link;
1418
			p->link = q;
1419
 
1420
			/*
1421
			 * JAL	profout
1422
			 */
1423
			p->as = ACALL;
1424
			p->from = zprg.from;
1425
			p->to = zprg.to;
1426
			p->to.type = D_BRANCH;
1427
			p->pcond = ps4;
1428
			p->to.sym = s4;
1429
 
1430
			p = q;
1431
 
1432
			continue;
1433
		}
1434
	}
1435
}
1436
 
1437
void
1438
nuxiinit(void)
1439
{
1440
	int i, c;
1441
 
1442
	for(i=0; i<4; i++) {
1443
		c = find1(0x04030201L, i+1);
1444
		if(i < 2)
1445
			inuxi2[i] = c;
1446
		if(i < 1)
1447
			inuxi1[i] = c;
1448
		inuxi4[i] = c;
1449
		fnuxi4[i] = c;
1450
		fnuxi8[i] = c;
1451
		fnuxi8[i+4] = c+4;
1452
	}
1453
	if(debug['v']) {
1454
		Bprint(&bso, "inuxi = ");
1455
		for(i=0; i<1; i++)
1456
			Bprint(&bso, "%d", inuxi1[i]);
1457
		Bprint(&bso, " ");
1458
		for(i=0; i<2; i++)
1459
			Bprint(&bso, "%d", inuxi2[i]);
1460
		Bprint(&bso, " ");
1461
		for(i=0; i<4; i++)
1462
			Bprint(&bso, "%d", inuxi4[i]);
1463
		Bprint(&bso, "\nfnuxi = ");
1464
		for(i=0; i<4; i++)
1465
			Bprint(&bso, "%d", fnuxi4[i]);
1466
		Bprint(&bso, " ");
1467
		for(i=0; i<8; i++)
1468
			Bprint(&bso, "%d", fnuxi8[i]);
1469
		Bprint(&bso, "\n");
1470
	}
1471
	Bflush(&bso);
1472
}
1473
 
1474
int
1475
find1(long l, int c)
1476
{
1477
	char *p;
1478
	int i;
1479
 
1480
	p = (char*)&l;
1481
	for(i=0; i<4; i++)
1482
		if(*p++ == c)
1483
			return i;
1484
	return 0;
1485
}
1486
 
1487
int
1488
find2(long l, int c)
1489
{
1490
	short *p;
1491
	int i;
1492
 
1493
	p = (short*)&l;
1494
	for(i=0; i<4; i+=2) {
1495
		if(((*p >> 8) & 0xff) == c)
1496
			return i;
1497
		if((*p++ & 0xff) == c)
1498
			return i+1;
1499
	}
1500
	return 0;
1501
}
1502
 
1503
long
1504
ieeedtof(Ieee *e)
1505
{
1506
	int exp;
1507
	long v;
1508
 
1509
	if(e->h == 0)
1510
		return 0;
1511
	exp = (e->h>>20) & ((1L<<11)-1L);
1512
	exp -= (1L<<10) - 2L;
1513
	v = (e->h & 0xfffffL) << 3;
1514
	v |= (e->l >> 29) & 0x7L;
1515
	if((e->l >> 28) & 1) {
1516
		v++;
1517
		if(v & 0x800000L) {
1518
			v = (v & 0x7fffffL) >> 1;
1519
			exp++;
1520
		}
1521
	}
1522
	if(exp <= -126 || exp >= 130)
1523
		diag("double fp to single fp overflow");
1524
	v |= ((exp + 126) & 0xffL) << 23;
1525
	v |= e->h & 0x80000000L;
1526
	return v;
1527
}
1528
 
1529
double
1530
ieeedtod(Ieee *ieeep)
1531
{
1532
	Ieee e;
1533
	double fr;
1534
	int exp;
1535
 
1536
	if(ieeep->h & (1L<<31)) {
1537
		e.h = ieeep->h & ~(1L<<31);
1538
		e.l = ieeep->l;
1539
		return -ieeedtod(&e);
1540
	}
1541
	if(ieeep->l == 0 && ieeep->h == 0)
1542
		return 0;
1543
	fr = ieeep->l & ((1L<<16)-1L);
1544
	fr /= 1L<<16;
1545
	fr += (ieeep->l>>16) & ((1L<<16)-1L);
1546
	fr /= 1L<<16;
1547
	fr += (ieeep->h & (1L<<20)-1L) | (1L<<20);
1548
	fr /= 1L<<21;
1549
	exp = (ieeep->h>>20) & ((1L<<11)-1L);
1550
	exp -= (1L<<10) - 2L;
1551
	return ldexp(fr, exp);
1552
}
1553
 
1554
void
1555
undefsym(Sym *s)
1556
{
1557
	int n;
1558
 
1559
	n = imports;
1560
	if(s->value != 0)
1561
		diag("value != 0 on SXREF");
1562
	if(n >= 1<<Rindex)
1563
		diag("import index %d out of range", n);
1564
	s->value = n<<Roffset;
1565
	s->type = SUNDEF;
1566
	imports++;
1567
}
1568
 
1569
void
1570
zerosig(char *sp)
1571
{
1572
	Sym *s;
1573
 
1574
	s = lookup(sp, 0);
1575
	s->sig = 0;
1576
}
1577
 
1578
void
1579
readundefs(char *f, int t)
1580
{
1581
	int i, n;
1582
	Sym *s;
1583
	Biobuf *b;
1584
	char *l, buf[256], *fields[64];
1585
 
1586
	if(f == nil)
1587
		return;
1588
	b = Bopen(f, OREAD);
1589
	if(b == nil){
1590
		diag("could not open %s: %r", f);
1591
		errorexit();
1592
	}
1593
	while((l = Brdline(b, '\n')) != nil){
1594
		n = Blinelen(b);
1595
		if(n >= sizeof(buf)){
1596
			diag("%s: line too long", f);
1597
			errorexit();
1598
		}
1599
		memmove(buf, l, n);
1600
		buf[n-1] = '\0';
1601
		n = getfields(buf, fields, nelem(fields), 1, " \t\r\n");
1602
		if(n == nelem(fields)){
1603
			diag("%s: bad format", f);
1604
			errorexit();
1605
		}
1606
		for(i = 0; i < n; i++){
1607
			s = lookup(fields[i], 0);
1608
			s->type = SXREF;
1609
			s->subtype = t;
1610
			if(t == SIMPORT)
1611
				nimports++;
1612
			else
1613
				nexports++;
1614
		}
1615
	}
1616
	Bterm(b);
1617
}