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