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