#include "l.h" #include char *noname = ""; char symname[] = SYMDEF; char** libdir; int nlibdir = 0; static int maxlibdir = 0; int isobjfile(char *f) { int n, v; Biobuf *b; char buf1[5], buf2[SARMAG]; b = Bopen(f, OREAD); if(b == nil) return 0; n = Bread(b, buf1, 5); if(n == 5 && (buf1[2] == 1 && buf1[3] == '<' || buf1[3] == 1 && buf1[4] == '<')) v = 1; /* good enough for our purposes */ else{ Bseek(b, 0, 0); n = Bread(b, buf2, SARMAG); v = n == SARMAG && strncmp(buf2, ARMAG, SARMAG) == 0; } Bterm(b); return v; } void loadlib(void) { int i; long h; Sym *s; loop: xrefresolv = 0; for(i=0; ilink) if(s->type == SXREF) goto loop; } void objfile(char *file) { long off, esym, cnt, l; int f, work; Sym *s; char magbuf[SARMAG]; char name[LIBNAMELEN], pname[LIBNAMELEN]; struct ar_hdr arhdr; char *e, *start, *stop; if(debug['v']) Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file); Bflush(&bso); if(file[0] == '-' && file[1] == 'l') { snprint(pname, sizeof(pname), "lib%s.a", file+2); e = findlib(pname); if(e == nil) { diag("cannot find library: %s", file); errorexit(); } snprint(name, sizeof(name), "%s/%s", e, pname); file = name; } f = open(file, 0); if(f < 0) { diag("cannot open %s: %r", file); errorexit(); } l = read(f, magbuf, SARMAG); if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){ /* load it as a regular file */ l = seek(f, 0L, 2); seek(f, 0L, 0); ldobj(f, l, file); close(f); return; } if(debug['v']) Bprint(&bso, "%5.2f ldlib: %s\n", cputime(), file); l = read(f, &arhdr, SAR_HDR); if(l != SAR_HDR) { diag("%s: short read on archive file symbol header", file); goto out; } if(strncmp(arhdr.name, symname, strlen(symname))) { diag("%s: first entry not symbol header", file); goto out; } esym = SARMAG + SAR_HDR + atolwhex(arhdr.size); off = SARMAG + SAR_HDR; /* * just bang the whole symbol file into memory */ seek(f, off, 0); cnt = esym - off; start = malloc(cnt + 10); cnt = read(f, start, cnt); if(cnt <= 0){ close(f); return; } stop = &start[cnt]; memset(stop, 0, 10); work = 1; while(work){ if(debug['v']) Bprint(&bso, "%5.2f library pass: %s\n", cputime(), file); Bflush(&bso); work = 0; for(e = start; e < stop; e = strchr(e+5, 0) + 1) { s = lookup(e+5, 0); if(s->type != SXREF) continue; sprint(pname, "%s(%s)", file, s->name); if(debug['v']) Bprint(&bso, "%5.2f library: %s\n", cputime(), pname); Bflush(&bso); l = e[1] & 0xff; l |= (e[2] & 0xff) << 8; l |= (e[3] & 0xff) << 16; l |= (e[4] & 0xff) << 24; seek(f, l, 0); l = read(f, &arhdr, SAR_HDR); if(l != SAR_HDR) goto bad; if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag))) goto bad; l = atolwhex(arhdr.size); ldobj(f, l, pname); if(s->type == SXREF) { diag("%s: failed to load: %s", file, s->name); errorexit(); } work = 1; xrefresolv = 1; } } return; bad: diag("%s: bad or out of date archive", file); out: close(f); } void addlibpath(char *arg) { char **p; if(nlibdir >= maxlibdir) { if(maxlibdir == 0) maxlibdir = 8; else maxlibdir *= 2; p = malloc(maxlibdir*sizeof(*p)); if(p == nil) { diag("out of memory"); errorexit(); } memmove(p, libdir, nlibdir*sizeof(*p)); free(libdir); libdir = p; } libdir[nlibdir++] = strdup(arg); } char* findlib(char *file) { int i; char name[LIBNAMELEN]; for(i = 0; i < nlibdir; i++) { snprint(name, sizeof(name), "%s/%s", libdir[i], file); if(fileexists(name)) return libdir[i]; } return nil; } void addlibroot(void) { char *a; char name[LIBNAMELEN]; a = getenv("ccroot"); if(a != nil && *a != '\0') { if(!fileexists(a)) { diag("nonexistent $ccroot: %s", a); errorexit(); } }else a = ""; snprint(name, sizeof(name), "%s/%s/lib", a, thestring); addlibpath(name); } void addlib(char *obj) { char fn1[LIBNAMELEN], fn2[LIBNAMELEN], comp[LIBNAMELEN], *p, *name; int i, search; if(histfrogp <= 0) return; name = fn1; search = 0; if(histfrog[0]->name[1] == '/') { sprint(name, ""); i = 1; } else if(histfrog[0]->name[1] == '.') { sprint(name, "."); i = 0; } else { sprint(name, ""); i = 0; search = 1; } for(; iname+1); for(;;) { p = strstr(comp, "$O"); if(p == 0) break; memmove(p+1, p+2, strlen(p+2)+1); p[0] = thechar; } for(;;) { p = strstr(comp, "$M"); if(p == 0) break; if(strlen(comp)+strlen(thestring)-2+1 >= sizeof comp) { diag("library component too long"); return; } memmove(p+strlen(thestring), p+2, strlen(p+2)+1); memmove(p, thestring, strlen(thestring)); } if(strlen(fn1) + strlen(comp) + 3 >= sizeof(fn1)) { diag("library component too long"); return; } if(i > 0 || !search) strcat(fn1, "/"); strcat(fn1, comp); } cleanname(name); if(search){ p = findlib(name); if(p != nil){ snprint(fn2, sizeof(fn2), "%s/%s", p, name); name = fn2; } } for(i=0; iname = malloc(2*(histfrogp+1) + 1); u->asym = s; u->type = type; u->aoffset = line; u->link = curhist; curhist = u; j = 1; for(i=0; ivalue; s->name[j+0] = k>>8; s->name[j+1] = k; j += 2; } } void histtoauto(void) { Auto *l; while((l = curhist) != nil) { curhist = l->link; l->link = curauto; curauto = l; } } void collapsefrog(Sym *s) { int i; /* * bad encoding of path components only allows * MAXHIST components. if there is an overflow, * first try to collapse xxx/.. */ for(i=1; iname+1, "..") == 0) { memmove(histfrog+i-1, histfrog+i+1, (histfrogp-i-1)*sizeof(histfrog[0])); histfrogp--; goto out; } /* * next try to collapse . */ for(i=0; iname+1, ".") == 0) { memmove(histfrog+i, histfrog+i+1, (histfrogp-i-1)*sizeof(histfrog[0])); goto out; } /* * last chance, just truncate from front */ memmove(histfrog+0, histfrog+1, (histfrogp-1)*sizeof(histfrog[0])); out: histfrog[histfrogp-1] = s; } uchar* readsome(int f, uchar *buf, uchar *good, uchar *stop, int max) { int n; n = stop - good; memmove(buf, good, stop - good); stop = buf + n; n = MAXIO - n; if(n > max) n = max; n = read(f, stop, n); if(n <= 0) return 0; return stop + n; } Sym* lookup(char *symb, int v) { Sym *s; char *p; long h; int c, l; h = v; for(p=symb; c = *p; p++) h = h+h+h + c; l = (p - symb) + 1; if(h < 0) h = ~h; h %= NHASH; for(s = hash[h]; s != S; s = s->link) if(s->version == v) if(memcmp(s->name, symb, l) == 0) return s; s = halloc(sizeof(Sym)); s->name = malloc(l + 1); memmove(s->name, symb, l); s->link = hash[h]; s->type = 0; s->version = v; s->value = 0; s->sig = 0; hash[h] = s; return s; } int find1(long l, int c) { char *p; int i; p = (char*)&l; for(i=0; i<4; i++) if(*p++ == c) return i; return 0; } long ieeedtof(Ieee *ieeep) { int exp; long v; if(ieeep->h == 0) return 0; exp = (ieeep->h>>20) & ((1L<<11)-1L); exp -= (1L<<10) - 2L; v = (ieeep->h & 0xfffffL) << 3; v |= (ieeep->l >> 29) & 0x7L; if((ieeep->l >> 28) & 1) { v++; if(v & 0x800000L) { v = (v & 0x7fffffL) >> 1; exp++; } } if(exp <= -126 || exp >= 130) diag("double fp to single fp overflow"); v |= ((exp + 126) & 0xffL) << 23; v |= ieeep->h & 0x80000000L; return v; } double ieeedtod(Ieee *ieeep) { Ieee e; double fr; int exp; if(ieeep->h & (1L<<31)) { e.h = ieeep->h & ~(1L<<31); e.l = ieeep->l; return -ieeedtod(&e); } if(ieeep->l == 0 && ieeep->h == 0) return 0; fr = ieeep->l & ((1L<<16)-1L); fr /= 1L<<16; fr += (ieeep->l>>16) & ((1L<<16)-1L); fr /= 1L<<16; fr += (ieeep->h & (1L<<20)-1L) | (1L<<20); fr /= 1L<<21; exp = (ieeep->h>>20) & ((1L<<11)-1L); exp -= (1L<<10) - 2L; return ldexp(fr, exp); }