]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/6l/obj.c
cwfs: fix listen filedescriptor leaks
[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                         snprint(name, sizeof name, "/%s/lib/lib%s.a", thestring, file+2);
400                 else
401                         snprint(name, sizeof name, "/usr/%clib/lib%s.a", thechar, file+2);
402                 file = name;
403         }
404         if(debug['v'])
405                 Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file);
406         Bflush(&bso);
407         f = open(file, 0);
408         if(f < 0) {
409                 diag("cannot open file: %s", file);
410                 errorexit();
411         }
412         l = read(f, magbuf, SARMAG);
413         if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){
414                 /* load it as a regular file */
415                 l = seek(f, 0L, 2);
416                 seek(f, 0L, 0);
417                 ldobj(f, l, file);
418                 close(f);
419                 return;
420         }
421
422         l = read(f, &arhdr, SAR_HDR);
423         if(l != SAR_HDR) {
424                 diag("%s: short read on archive file symbol header", file);
425                 goto out;
426         }
427         if(strncmp(arhdr.name, symname, strlen(symname))) {
428                 diag("%s: first entry not symbol header", file);
429                 goto out;
430         }
431
432         esym = SARMAG + SAR_HDR + atolwhex(arhdr.size);
433         off = SARMAG + SAR_HDR;
434
435         /*
436          * just bang the whole symbol file into memory
437          */
438         seek(f, off, 0);
439         cnt = esym - off;
440         start = malloc(cnt + 10);
441         cnt = read(f, start, cnt);
442         if(cnt <= 0){
443                 close(f);
444                 return;
445         }
446         stop = &start[cnt];
447         memset(stop, 0, 10);
448
449         work = 1;
450         while(work) {
451                 if(debug['v'])
452                         Bprint(&bso, "%5.2f library pass: %s\n", cputime(), file);
453                 Bflush(&bso);
454                 work = 0;
455                 for(e = start; e < stop; e = strchr(e+5, 0) + 1) {
456                         s = lookup(e+5, 0);
457                         if(s->type != SXREF)
458                                 continue;
459                         snprint(pname, sizeof pname, "%s(%s)", file, s->name);
460                         if(debug['v'])
461                                 Bprint(&bso, "%5.2f library: %s\n", cputime(), pname);
462                         Bflush(&bso);
463                         l = e[1] & 0xff;
464                         l |= (e[2] & 0xff) << 8;
465                         l |= (e[3] & 0xff) << 16;
466                         l |= (e[4] & 0xff) << 24;
467                         seek(f, l, 0);
468                         l = read(f, &arhdr, SAR_HDR);
469                         if(l != SAR_HDR)
470                                 goto bad;
471                         if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag)))
472                                 goto bad;
473                         l = atolwhex(arhdr.size);
474                         ldobj(f, l, pname);
475                         if(s->type == SXREF) {
476                                 diag("%s: failed to load: %s", file, s->name);
477                                 errorexit();
478                         }
479                         work = 1;
480                         xrefresolv = 1;
481                 }
482         }
483         return;
484
485 bad:
486         diag("%s: bad or out of date archive", file);
487 out:
488         close(f);
489 }
490
491 int
492 zaddr(uchar *p, Adr *a, Sym *h[])
493 {
494         int c, t, i;
495         long l;
496         Sym *s;
497         Auto *u;
498
499         t = p[0];
500         c = 1;
501         if(t & T_INDEX) {
502                 a->index = p[c];
503                 a->scale = p[c+1];
504                 c += 2;
505         } else {
506                 a->index = D_NONE;
507                 a->scale = 0;
508         }
509         a->offset = 0;
510         if(t & T_OFFSET) {
511                 /*
512                  * Hack until Charles fixes the compiler.
513                 a->offset = (long)(p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24));
514                  */
515                 l = p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24);
516                 a->offset = l;
517                 c += 4;
518                 if(t & T_64) {
519                         l = p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24);
520                         a->offset = ((vlong)l<<32) | (a->offset & 0xFFFFFFFFUL);
521                         c += 4;
522                 }
523         }
524         a->sym = S;
525         if(t & T_SYM) {
526                 a->sym = h[p[c]];
527                 c++;
528         }
529         a->type = D_NONE;
530         if(t & T_FCONST) {
531                 a->ieee.l = p[c] | (p[c+1]<<8) | (p[c+2]<<16) | (p[c+3]<<24);
532                 a->ieee.h = p[c+4] | (p[c+5]<<8) | (p[c+6]<<16) | (p[c+7]<<24);
533                 c += 8;
534                 a->type = D_FCONST;
535         } else
536         if(t & T_SCONST) {
537                 for(i=0; i<NSNAME; i++)
538                         a->scon[i] = p[c+i];
539                 c += NSNAME;
540                 a->type = D_SCONST;
541         }
542         if(t & T_TYPE) {
543                 a->type = p[c];
544                 c++;
545         }
546         s = a->sym;
547         if(s == S)
548                 return c;
549
550         t = a->type;
551         if(t != D_AUTO && t != D_PARAM)
552                 return c;
553         l = a->offset;
554         for(u=curauto; u; u=u->link) {
555                 if(u->asym == s)
556                 if(u->type == t) {
557                         if(u->aoffset > l)
558                                 u->aoffset = l;
559                         return c;
560                 }
561         }
562
563         while(nhunk < sizeof(Auto))
564                 gethunk();
565         u = (Auto*)hunk;
566         nhunk -= sizeof(Auto);
567         hunk += sizeof(Auto);
568
569         u->link = curauto;
570         curauto = u;
571         u->asym = s;
572         u->aoffset = l;
573         u->type = t;
574         return c;
575 }
576
577 void
578 addlib(char *obj)
579 {
580         char name[1024], comp[256], *p;
581         int i;
582
583         if(histfrogp <= 0)
584                 return;
585
586         if(histfrog[0]->name[1] == '/') {
587                 name[0] = 0;
588                 i = 1;
589         } else
590         if(histfrog[0]->name[1] == '.') {
591                 snprint(name, sizeof name, ".");
592                 i = 0;
593         } else {
594                 if(debug['9'])
595                         snprint(name, sizeof name, "/%s/lib", thestring);
596                 else
597                         snprint(name, sizeof name, "/usr/%clib", thechar);
598                 i = 0;
599         }
600
601         for(; i<histfrogp; i++) {
602                 snprint(comp, sizeof comp, histfrog[i]->name+1);
603                 for(;;) {
604                         p = strstr(comp, "$O");
605                         if(p == 0)
606                                 break;
607                         memmove(p+1, p+2, strlen(p+2)+1);
608                         p[0] = thechar;
609                 }
610                 for(;;) {
611                         p = strstr(comp, "$M");
612                         if(p == 0)
613                                 break;
614                         if(strlen(comp)+strlen(thestring)-2+1 >= sizeof comp) {
615                                 diag("library component too long");
616                                 return;
617                         }
618                         memmove(p+strlen(thestring), p+2, strlen(p+2)+1);
619                         memmove(p, thestring, strlen(thestring));
620                 }
621                 if(strlen(name) + strlen(comp) + 3 >= sizeof(name)) {
622                         diag("library component too long");
623                         return;
624                 }
625                 strcat(name, "/");
626                 strcat(name, comp);
627         }
628         for(i=0; i<libraryp; i++)
629                 if(strcmp(name, library[i]) == 0)
630                         return;
631         if(libraryp == nelem(library)){
632                 diag("too many autolibs; skipping %s", name);
633                 return;
634         }
635
636         p = malloc(strlen(name) + 1);
637         strcpy(p, name);
638         library[libraryp] = p;
639         p = malloc(strlen(obj) + 1);
640         strcpy(p, obj);
641         libraryobj[libraryp] = p;
642         libraryp++;
643 }
644
645 void
646 addhist(long line, int type)
647 {
648         Auto *u;
649         Sym *s;
650         int i, j, k;
651
652         u = malloc(sizeof(Auto));
653         s = malloc(sizeof(Sym));
654         s->name = malloc(2*(histfrogp+1) + 1);
655
656         u->asym = s;
657         u->type = type;
658         u->aoffset = line;
659         u->link = curhist;
660         curhist = u;
661
662         j = 1;
663         for(i=0; i<histfrogp; i++) {
664                 k = histfrog[i]->value;
665                 s->name[j+0] = k>>8;
666                 s->name[j+1] = k;
667                 j += 2;
668         }
669 }
670
671 void
672 histtoauto(void)
673 {
674         Auto *l;
675
676         while(l = curhist) {
677                 curhist = l->link;
678                 l->link = curauto;
679                 curauto = l;
680         }
681 }
682
683 void
684 collapsefrog(Sym *s)
685 {
686         int i;
687
688         /*
689          * bad encoding of path components only allows
690          * MAXHIST components. if there is an overflow,
691          * first try to collapse xxx/..
692          */
693         for(i=1; i<histfrogp; i++)
694                 if(strcmp(histfrog[i]->name+1, "..") == 0) {
695                         memmove(histfrog+i-1, histfrog+i+1,
696                                 (histfrogp-i-1)*sizeof(histfrog[0]));
697                         histfrogp--;
698                         goto out;
699                 }
700
701         /*
702          * next try to collapse .
703          */
704         for(i=0; i<histfrogp; i++)
705                 if(strcmp(histfrog[i]->name+1, ".") == 0) {
706                         memmove(histfrog+i, histfrog+i+1,
707                                 (histfrogp-i-1)*sizeof(histfrog[0]));
708                         goto out;
709                 }
710
711         /*
712          * last chance, just truncate from front
713          */
714         memmove(histfrog+0, histfrog+1,
715                 (histfrogp-1)*sizeof(histfrog[0]));
716
717 out:
718         histfrog[histfrogp-1] = s;
719 }
720
721 void
722 nopout(Prog *p)
723 {
724         p->as = ANOP;
725         p->from.type = D_NONE;
726         p->to.type = D_NONE;
727 }
728
729 uchar*
730 readsome(int f, uchar *buf, uchar *good, uchar *stop, int max)
731 {
732         int n;
733
734         n = stop - good;
735         memmove(buf, good, stop - good);
736         stop = buf + n;
737         n = MAXIO - n;
738         if(n > max)
739                 n = max;
740         n = read(f, stop, n);
741         if(n <= 0)
742                 return 0;
743         return stop + n;
744 }
745
746 void
747 ldobj(int f, long c, char *pn)
748 {
749         vlong ipc;
750         Prog *p, *t;
751         uchar *bloc, *bsize, *stop;
752         int v, o, r, skip, mode;
753         Sym *h[NSYM], *s, *di;
754         ulong sig;
755         static int files;
756         static char **filen;
757         char **nfilen;
758
759         if((files&15) == 0){
760                 nfilen = malloc((files+16)*sizeof(char*));
761                 memmove(nfilen, filen, files*sizeof(char*));
762                 free(filen);
763                 filen = nfilen;
764         }
765         filen[files++] = strdup(pn);
766
767         bsize = buf.xbuf;
768         bloc = buf.xbuf;
769         di = S;
770
771 newloop:
772         memset(h, 0, sizeof(h));
773         version++;
774         histfrogp = 0;
775         ipc = pc;
776         skip = 0;
777         mode = 64;
778
779 loop:
780         if(c <= 0)
781                 goto eof;
782         r = bsize - bloc;
783         if(r < 100 && r < c) {          /* enough for largest prog */
784                 bsize = readsome(f, buf.xbuf, bloc, bsize, c);
785                 if(bsize == 0)
786                         goto eof;
787                 bloc = buf.xbuf;
788                 goto loop;
789         }
790         o = bloc[0] | (bloc[1] << 8);
791         if(o <= AXXX || o >= ALAST) {
792                 if(o < 0)
793                         goto eof;
794                 diag("%s: opcode out of range %d", pn, o);
795                 print(" probably not a .6 file\n");
796                 errorexit();
797         }
798
799         if(o == ANAME || o == ASIGNAME) {
800                 sig = 0;
801                 if(o == ASIGNAME) {
802                         sig = bloc[2] | (bloc[3]<<8) | (bloc[4]<<16) | (bloc[5]<<24);
803                         bloc += 4;
804                         c -= 4;
805                 }
806                 stop = memchr(&bloc[4], 0, bsize-&bloc[4]);
807                 if(stop == 0){
808                         bsize = readsome(f, buf.xbuf, bloc, bsize, c);
809                         if(bsize == 0)
810                                 goto eof;
811                         bloc = buf.xbuf;
812                         stop = memchr(&bloc[4], 0, bsize-&bloc[4]);
813                         if(stop == 0){
814                                 fprint(2, "%s: name too long\n", pn);
815                                 errorexit();
816                         }
817                 }
818                 v = bloc[2];    /* type */
819                 o = bloc[3];    /* sym */
820                 bloc += 4;
821                 c -= 4;
822
823                 r = 0;
824                 if(v == D_STATIC)
825                         r = version;
826                 s = lookup((char*)bloc, r);
827                 c -= &stop[1] - bloc;
828                 bloc = stop + 1;
829
830                 if(debug['S'] && r == 0)
831                         sig = 1729;
832                 if(sig != 0){
833                         if(s->sig != 0 && s->sig != sig)
834                                 diag("incompatible type signatures %lux(%s) and %lux(%s) for %s", s->sig, filen[s->file], sig, pn, s->name);
835                         s->sig = sig;
836                         s->file = files-1;
837                 }
838
839                 if(debug['W'])
840                         print(" ANAME   %s\n", s->name);
841                 h[o] = s;
842                 if((v == D_EXTERN || v == D_STATIC) && s->type == 0)
843                         s->type = SXREF;
844                 if(v == D_FILE) {
845                         if(s->type != SFILE) {
846                                 histgen++;
847                                 s->type = SFILE;
848                                 s->value = histgen;
849                         }
850                         if(histfrogp < MAXHIST) {
851                                 histfrog[histfrogp] = s;
852                                 histfrogp++;
853                         } else
854                                 collapsefrog(s);
855                 }
856                 goto loop;
857         }
858
859         while(nhunk < sizeof(Prog))
860                 gethunk();
861         p = (Prog*)hunk;
862         nhunk -= sizeof(Prog);
863         hunk += sizeof(Prog);
864
865         p->as = o;
866         p->line = bloc[2] | (bloc[3] << 8) | (bloc[4] << 16) | (bloc[5] << 24);
867         p->back = 2;
868         p->mode = mode;
869         r = zaddr(bloc+6, &p->from, h) + 6;
870         r += zaddr(bloc+r, &p->to, h);
871         bloc += r;
872         c -= r;
873
874         if(debug['W'])
875                 print("%P\n", p);
876
877         switch(p->as) {
878         case AHISTORY:
879                 if(p->to.offset == -1) {
880                         addlib(pn);
881                         histfrogp = 0;
882                         goto loop;
883                 }
884                 addhist(p->line, D_FILE);               /* 'z' */
885                 if(p->to.offset)
886                         addhist(p->to.offset, D_FILE1); /* 'Z' */
887                 histfrogp = 0;
888                 goto loop;
889
890         case AEND:
891                 histtoauto();
892                 if(curtext != P)
893                         curtext->to.autom = curauto;
894                 curauto = 0;
895                 curtext = P;
896                 if(c)
897                         goto newloop;
898                 return;
899
900         case AGLOBL:
901                 s = p->from.sym;
902                 if(p->from.scale & DUPOK)
903                         s->dupok = 1;
904                 if(s->type == 0 || s->type == SXREF) {
905                         s->type = SBSS;
906                         s->value = 0;
907                 }
908
909                 if(s->type != SBSS) {
910                         diag("%s: redefinition: %s in %s",
911                                 pn, s->name, TNAME);
912                         s->type = SBSS;
913                         s->value = 0;
914                 }
915                 if(p->to.offset > s->value)
916                         s->value = p->to.offset;
917                 goto loop;
918
919         case ADYNT:
920                 if(p->to.sym == S) {
921                         diag("DYNT without a sym\n%P", p);
922                         break;
923                 }
924                 di = p->to.sym;
925                 p->from.scale = 4;
926                 if(di->type == SXREF) {
927                         if(debug['z'])
928                                 Bprint(&bso, "%P set to %d\n", p, dtype);
929                         di->type = SCONST;
930                         di->value = dtype;
931                         dtype += 4;
932                 }
933                 if(p->from.sym == S)
934                         break;
935
936                 p->from.offset = di->value;
937                 p->from.sym->type = SDATA;
938                 if(curtext == P) {
939                         diag("DYNT not in text: %P", p);
940                         break;
941                 }
942                 p->to.sym = curtext->from.sym;
943                 p->to.type = D_ADDR;
944                 p->to.index = D_EXTERN;
945                 goto data;
946
947         case AINIT:
948                 if(p->from.sym == S) {
949                         diag("INIT without a sym\n%P", p);
950                         break;
951                 }
952                 if(di == S) {
953                         diag("INIT without previous DYNT\n%P", p);
954                         break;
955                 }
956                 p->from.offset = di->value;
957                 p->from.sym->type = SDATA;
958                 goto data;
959
960         case ADATA:
961         data:
962                 if(edatap == P)
963                         datap = p;
964                 else
965                         edatap->link = p;
966                 edatap = p;
967                 p->link = P;
968                 goto loop;
969
970         case AGOK:
971                 diag("%s: GOK opcode in %s", pn, TNAME);
972                 pc++;
973                 goto loop;
974
975         case ATEXT:
976                 if(curtext != P) {
977                         histtoauto();
978                         curtext->to.autom = curauto;
979                         curauto = 0;
980                 }
981                 skip = 0;
982                 curtext = p;
983                 s = p->from.sym;
984                 if(s == S) {
985                         diag("%s: no TEXT symbol: %P", pn, p);
986                         errorexit();
987                 }
988                 if(s->type != 0 && s->type != SXREF) {
989                         if(p->from.scale & DUPOK) {
990                                 skip = 1;
991                                 goto casdef;
992                         }
993                         diag("%s: redefinition: %s\n%P", pn, s->name, p);
994                 }
995                 s->type = STEXT;
996                 s->value = pc;
997                 lastp->link = p;
998                 lastp = p;
999                 p->pc = pc;
1000                 pc++;
1001                 if(textp == P) {
1002                         textp = p;
1003                         etextp = p;
1004                         goto loop;
1005                 }
1006                 etextp->pcond = p;
1007                 etextp = p;
1008                 goto loop;
1009
1010         case AMODE:
1011                 if(p->from.type == D_CONST || p->from.type == D_INDIR+D_NONE){
1012                         switch((int)p->from.offset){
1013                         case 16: case 32: case 64:
1014                                 mode = p->from.offset;
1015                                 break;
1016                         }
1017                 }
1018                 goto loop;
1019
1020         case AFMOVF:
1021         case AFADDF:
1022         case AFSUBF:
1023         case AFSUBRF:
1024         case AFMULF:
1025         case AFDIVF:
1026         case AFDIVRF:
1027         case AFCOMF:
1028         case AFCOMFP:
1029         case AMOVSS:
1030         case AADDSS:
1031         case ASUBSS:
1032         case AMULSS:
1033         case ADIVSS:
1034         case ACOMISS:
1035         case AUCOMISS:
1036                 if(skip)
1037                         goto casdef;
1038                 if(p->from.type == D_FCONST) {
1039                         /* size sb 9 max */
1040                         snprint(literal, sizeof literal, "$%lux", ieeedtof(&p->from.ieee));
1041                         s = lookup(literal, 0);
1042                         if(s->type == 0) {
1043                                 s->type = SBSS;
1044                                 s->value = 4;
1045                                 t = prg();
1046                                 t->as = ADATA;
1047                                 t->line = p->line;
1048                                 t->from.type = D_EXTERN;
1049                                 t->from.sym = s;
1050                                 t->from.scale = 4;
1051                                 t->to = p->from;
1052                                 if(edatap == P)
1053                                         datap = t;
1054                                 else
1055                                         edatap->link = t;
1056                                 edatap = t;
1057                                 t->link = P;
1058                         }
1059                         p->from.type = D_EXTERN;
1060                         p->from.sym = s;
1061                         p->from.offset = 0;
1062                 }
1063                 goto casdef;
1064
1065         case AFMOVD:
1066         case AFADDD:
1067         case AFSUBD:
1068         case AFSUBRD:
1069         case AFMULD:
1070         case AFDIVD:
1071         case AFDIVRD:
1072         case AFCOMD:
1073         case AFCOMDP:
1074         case AMOVSD:
1075         case AADDSD:
1076         case ASUBSD:
1077         case AMULSD:
1078         case ADIVSD:
1079         case ACOMISD:
1080         case AUCOMISD:
1081                 if(skip)
1082                         goto casdef;
1083                 if(p->from.type == D_FCONST) {
1084                         /* size sb 18 max */
1085                         snprint(literal, sizeof literal, "$%lux.%lux",
1086                                 p->from.ieee.l, p->from.ieee.h);
1087                         s = lookup(literal, 0);
1088                         if(s->type == 0) {
1089                                 s->type = SBSS;
1090                                 s->value = 8;
1091                                 t = prg();
1092                                 t->as = ADATA;
1093                                 t->line = p->line;
1094                                 t->from.type = D_EXTERN;
1095                                 t->from.sym = s;
1096                                 t->from.scale = 8;
1097                                 t->to = p->from;
1098                                 if(edatap == P)
1099                                         datap = t;
1100                                 else
1101                                         edatap->link = t;
1102                                 edatap = t;
1103                                 t->link = P;
1104                         }
1105                         p->from.type = D_EXTERN;
1106                         p->from.sym = s;
1107                         p->from.offset = 0;
1108                 }
1109                 goto casdef;
1110
1111         casdef:
1112         default:
1113                 if(skip)
1114                         nopout(p);
1115
1116                 if(p->to.type == D_BRANCH)
1117                         p->to.offset += ipc;
1118                 lastp->link = p;
1119                 lastp = p;
1120                 p->pc = pc;
1121                 pc++;
1122                 goto loop;
1123         }
1124         goto loop;
1125
1126 eof:
1127         diag("truncated object file: %s", pn);
1128 }
1129
1130 Sym*
1131 lookup(char *symb, int v)
1132 {
1133         Sym *s;
1134         char *p;
1135         long h;
1136         int l, c;
1137
1138         h = v;
1139         for(p=symb; c = *p; p++)
1140                 h = h+h+h + c;
1141         l = (p - symb) + 1;
1142         if(h < 0)
1143                 h = ~h;
1144         h %= NHASH;
1145         for(s = hash[h]; s != S; s = s->link)
1146                 if(s->version == v)
1147                 if(memcmp(s->name, symb, l) == 0)
1148                         return s;
1149
1150         while(nhunk < sizeof(Sym))
1151                 gethunk();
1152         s = (Sym*)hunk;
1153         nhunk -= sizeof(Sym);
1154         hunk += sizeof(Sym);
1155
1156         s->name = malloc(l + 1);
1157         memmove(s->name, symb, l);
1158
1159         s->link = hash[h];
1160         s->type = 0;
1161         s->version = v;
1162         s->value = 0;
1163         s->sig = 0;
1164         s->dupok = 0;
1165         hash[h] = s;
1166         nsymbol++;
1167         return s;
1168 }
1169
1170 Prog*
1171 prg(void)
1172 {
1173         Prog *p;
1174
1175         while(nhunk < sizeof(Prog))
1176                 gethunk();
1177         p = (Prog*)hunk;
1178         nhunk -= sizeof(Prog);
1179         hunk += sizeof(Prog);
1180
1181         *p = zprg;
1182         return p;
1183 }
1184
1185 Prog*
1186 copyp(Prog *q)
1187 {
1188         Prog *p;
1189
1190         p = prg();
1191         *p = *q;
1192         return p;
1193 }
1194
1195 Prog*
1196 appendp(Prog *q)
1197 {
1198         Prog *p;
1199
1200         p = prg();
1201         p->link = q->link;
1202         q->link = p;
1203         p->line = q->line;
1204         p->mode = q->mode;
1205         return p;
1206 }
1207
1208 void
1209 gethunk(void)
1210 {
1211         char *h;
1212         long nh;
1213
1214         nh = NHUNK;
1215         if(thunk >= 5L*NHUNK) {
1216                 nh = 5L*NHUNK;
1217                 if(thunk >= 25L*NHUNK)
1218                         nh = 25L*NHUNK;
1219         }
1220         h = mysbrk(nh);
1221         if(h == (char*)-1) {
1222                 diag("out of memory");
1223                 errorexit();
1224         }
1225         hunk = h;
1226         nhunk = nh;
1227         thunk += nh;
1228 }
1229
1230 void
1231 doprof1(void)
1232 {
1233         Sym *s;
1234         long n;
1235         Prog *p, *q;
1236
1237         if(debug['v'])
1238                 Bprint(&bso, "%5.2f profile 1\n", cputime());
1239         Bflush(&bso);
1240         s = lookup("__mcount", 0);
1241         n = 1;
1242         for(p = firstp->link; p != P; p = p->link) {
1243                 if(p->as == ATEXT) {
1244                         q = prg();
1245                         q->line = p->line;
1246                         q->link = datap;
1247                         datap = q;
1248                         q->as = ADATA;
1249                         q->from.type = D_EXTERN;
1250                         q->from.offset = n*4;
1251                         q->from.sym = s;
1252                         q->from.scale = 4;
1253                         q->to = p->from;
1254                         q->to.type = D_CONST;
1255
1256                         q = prg();
1257                         q->line = p->line;
1258                         q->pc = p->pc;
1259                         q->link = p->link;
1260                         p->link = q;
1261                         p = q;
1262                         p->as = AADDL;
1263                         p->from.type = D_CONST;
1264                         p->from.offset = 1;
1265                         p->to.type = D_EXTERN;
1266                         p->to.sym = s;
1267                         p->to.offset = n*4 + 4;
1268
1269                         n += 2;
1270                         continue;
1271                 }
1272         }
1273         q = prg();
1274         q->line = 0;
1275         q->link = datap;
1276         datap = q;
1277
1278         q->as = ADATA;
1279         q->from.type = D_EXTERN;
1280         q->from.sym = s;
1281         q->from.scale = 4;
1282         q->to.type = D_CONST;
1283         q->to.offset = n;
1284
1285         s->type = SBSS;
1286         s->value = n*4;
1287 }
1288
1289 void
1290 doprof2(void)
1291 {
1292         Sym *s2, *s4;
1293         Prog *p, *q, *q2, *ps2, *ps4;
1294
1295         if(debug['v'])
1296                 Bprint(&bso, "%5.2f profile 2\n", cputime());
1297         Bflush(&bso);
1298
1299         if(debug['e']){
1300                 s2 = lookup("_tracein", 0);
1301                 s4 = lookup("_traceout", 0);
1302         }else{
1303                 s2 = lookup("_profin", 0);
1304                 s4 = lookup("_profout", 0);
1305         }
1306         if(s2->type != STEXT || s4->type != STEXT) {
1307                 if(debug['e'])
1308                         diag("_tracein/_traceout not defined %d %d", s2->type, s4->type);
1309                 else
1310                         diag("_profin/_profout not defined");
1311                 return;
1312         }
1313
1314         ps2 = P;
1315         ps4 = P;
1316         for(p = firstp; p != P; p = p->link) {
1317                 if(p->as == ATEXT) {
1318                         if(p->from.sym == s2) {
1319                                 p->from.scale = 1;
1320                                 ps2 = p;
1321                         }
1322                         if(p->from.sym == s4) {
1323                                 p->from.scale = 1;
1324                                 ps4 = p;
1325                         }
1326                 }
1327         }
1328         for(p = firstp; p != P; p = p->link) {
1329                 if(p->as == ATEXT) {
1330                         curtext = p;
1331
1332                         if(p->from.scale & NOPROF) {    /* dont profile */
1333                                 for(;;) {
1334                                         q = p->link;
1335                                         if(q == P)
1336                                                 break;
1337                                         if(q->as == ATEXT)
1338                                                 break;
1339                                         p = q;
1340                                 }
1341                                 continue;
1342                         }
1343
1344                         /*
1345                          * JMPL profin
1346                          */
1347                         q = prg();
1348                         q->line = p->line;
1349                         q->pc = p->pc;
1350                         q->link = p->link;
1351                         if(debug['e']){         /* embedded tracing */
1352                                 q2 = prg();
1353                                 p->link = q2;
1354                                 q2->link = q;
1355
1356                                 q2->line = p->line;
1357                                 q2->pc = p->pc;
1358
1359                                 q2->as = AJMP;
1360                                 q2->to.type = D_BRANCH;
1361                                 q2->to.sym = p->to.sym;
1362                                 q2->pcond = q->link;
1363                         }else
1364                                 p->link = q;
1365                         p = q;
1366                         p->as = ACALL;
1367                         p->to.type = D_BRANCH;
1368                         p->pcond = ps2;
1369                         p->to.sym = s2;
1370
1371                         continue;
1372                 }
1373                 if(p->as == ARET) {
1374                         /*
1375                          * RET (default)
1376                          */
1377                         if(debug['e']){         /* embedded tracing */
1378                                 q = prg();
1379                                 q->line = p->line;
1380                                 q->pc = p->pc;
1381                                 q->link = p->link;
1382                                 p->link = q;
1383                                 p = q;
1384                         }
1385                         /*
1386                          * RET
1387                          */
1388                         q = prg();
1389                         q->as = ARET;
1390                         q->from = p->from;
1391                         q->to = p->to;
1392                         q->link = p->link;
1393                         p->link = q;
1394
1395                         /*
1396                          * JAL  profout
1397                          */
1398                         p->as = ACALL;
1399                         p->from = zprg.from;
1400                         p->to = zprg.to;
1401                         p->to.type = D_BRANCH;
1402                         p->pcond = ps4;
1403                         p->to.sym = s4;
1404
1405                         p = q;
1406
1407                         continue;
1408                 }
1409         }
1410 }
1411
1412 void
1413 nuxiinit(void)
1414 {
1415         int i, c;
1416
1417         for(i=0; i<4; i++) {
1418                 c = find1(0x04030201L, i+1);
1419                 if(i < 2)
1420                         inuxi2[i] = c;
1421                 if(i < 1)
1422                         inuxi1[i] = c;
1423                 inuxi4[i] = c;
1424                 fnuxi4[i] = c;
1425                 fnuxi8[i] = c;
1426                 fnuxi8[i+4] = c+4;
1427         }
1428
1429         for(i=0; i<8; i++)
1430                 inuxi8[i] = find1v(0x0807060504030201LL, i+1);
1431
1432         if(debug['v']) {
1433                 Bprint(&bso, "inuxi = ");
1434                 for(i=0; i<1; i++)
1435                         Bprint(&bso, "%d", inuxi1[i]);
1436                 Bprint(&bso, " ");
1437                 for(i=0; i<2; i++)
1438                         Bprint(&bso, "%d", inuxi2[i]);
1439                 Bprint(&bso, " ");
1440                 for(i=0; i<4; i++)
1441                         Bprint(&bso, "%d", inuxi4[i]);
1442                 Bprint(&bso, " ");
1443                 for(i=0; i<8; i++)
1444                         Bprint(&bso, "%d", inuxi8[i]);
1445                 Bprint(&bso, "\nfnuxi = ");
1446                 for(i=0; i<4; i++)
1447                         Bprint(&bso, "%d", fnuxi4[i]);
1448                 Bprint(&bso, " ");
1449                 for(i=0; i<8; i++)
1450                         Bprint(&bso, "%d", fnuxi8[i]);
1451                 Bprint(&bso, "\n");
1452         }
1453         Bflush(&bso);
1454 }
1455
1456 int
1457 find1(long l, int c)
1458 {
1459         char *p;
1460         int i;
1461
1462         p = (char*)&l;
1463         for(i=0; i<4; i++)
1464                 if(*p++ == c)
1465                         return i;
1466         return 0;
1467 }
1468
1469 int
1470 find1v(vlong l, int c)
1471 {
1472         char *p;
1473         int i;
1474
1475         p = (char*)&l;
1476         for(i=0; i<8; i++)
1477                 if(*p++ == c)
1478                         return i;
1479         return 0;
1480 }
1481
1482 int
1483 find2(long l, int c)
1484 {
1485         short *p;
1486         int i;
1487
1488         p = (short*)&l;
1489         for(i=0; i<4; i+=2) {
1490                 if(((*p >> 8) & 0xff) == c)
1491                         return i;
1492                 if((*p++ & 0xff) == c)
1493                         return i+1;
1494         }
1495         return 0;
1496 }
1497
1498 long
1499 ieeedtof(Ieee *e)
1500 {
1501         int exp;
1502         long v;
1503
1504         if(e->h == 0)
1505                 return 0;
1506         exp = (e->h>>20) & ((1L<<11)-1L);
1507         exp -= (1L<<10) - 2L;
1508         v = (e->h & 0xfffffL) << 3;
1509         v |= (e->l >> 29) & 0x7L;
1510         if((e->l >> 28) & 1) {
1511                 v++;
1512                 if(v & 0x800000L) {
1513                         v = (v & 0x7fffffL) >> 1;
1514                         exp++;
1515                 }
1516         }
1517         if(exp <= -126 || exp >= 130)
1518                 diag("double fp to single fp overflow");
1519         v |= ((exp + 126) & 0xffL) << 23;
1520         v |= e->h & 0x80000000L;
1521         return v;
1522 }
1523
1524 double
1525 ieeedtod(Ieee *ieeep)
1526 {
1527         Ieee e;
1528         double fr;
1529         int exp;
1530
1531         if(ieeep->h & (1L<<31)) {
1532                 e.h = ieeep->h & ~(1L<<31);
1533                 e.l = ieeep->l;
1534                 return -ieeedtod(&e);
1535         }
1536         if(ieeep->l == 0 && ieeep->h == 0)
1537                 return 0;
1538         fr = ieeep->l & ((1L<<16)-1L);
1539         fr /= 1L<<16;
1540         fr += (ieeep->l>>16) & ((1L<<16)-1L);
1541         fr /= 1L<<16;
1542         fr += (ieeep->h & (1L<<20)-1L) | (1L<<20);
1543         fr /= 1L<<21;
1544         exp = (ieeep->h>>20) & ((1L<<11)-1L);
1545         exp -= (1L<<10) - 2L;
1546         return ldexp(fr, exp);
1547 }
1548
1549 void
1550 undefsym(Sym *s)
1551 {
1552         int n;
1553
1554         n = imports;
1555         if(s->value != 0)
1556                 diag("value != 0 on SXREF");
1557         if(n >= 1<<Rindex)
1558                 diag("import index %d out of range", n);
1559         s->value = n<<Roffset;
1560         s->type = SUNDEF;
1561         imports++;
1562 }
1563
1564 void
1565 zerosig(char *sp)
1566 {
1567         Sym *s;
1568
1569         s = lookup(sp, 0);
1570         s->sig = 0;
1571 }
1572
1573 void
1574 readundefs(char *f, int t)
1575 {
1576         int i, n;
1577         Sym *s;
1578         Biobuf *b;
1579         char *l, buf[256], *fields[64];
1580
1581         if(f == nil)
1582                 return;
1583         b = Bopen(f, OREAD);
1584         if(b == nil){
1585                 diag("could not open %s: %r", f);
1586                 errorexit();
1587         }
1588         while((l = Brdline(b, '\n')) != nil){
1589                 n = Blinelen(b);
1590                 if(n >= sizeof(buf)){
1591                         diag("%s: line too long", f);
1592                         errorexit();
1593                 }
1594                 memmove(buf, l, n);
1595                 buf[n-1] = '\0';
1596                 n = getfields(buf, fields, nelem(fields), 1, " \t\r\n");
1597                 if(n == nelem(fields)){
1598                         diag("%s: bad format", f);
1599                         errorexit();
1600                 }
1601                 for(i = 0; i < n; i++){
1602                         s = lookup(fields[i], 0);
1603                         s->type = SXREF;
1604                         s->subtype = t;
1605                         if(t == SIMPORT)
1606                                 nimports++;
1607                         else
1608                                 nexports++;
1609                 }
1610         }
1611         Bterm(b);
1612 }