home *** CD-ROM | disk | FTP | other *** search
- /*
- * link editor
- */
-
- #include <signal.h>
- #include "sys/types.h"
- #include "sys/stat.h"
-
- /* Layout of a.out file :
- *
- * header of 8 words magic number 405, 407, 410, 411
- * text size )
- * data size ) in bytes but even
- * bss size )
- * symbol table size
- * entry point
- * {unused}
- * flag set if no relocation
- *
- *
- * header: 0
- * text: 16
- * data: 16+textsize
- * relocation: 16+textsize+datasize
- * symbol table: 16+2*(textsize+datasize) or 16+textsize+datasize
- *
- */
- #define TRUE 1
- #define FALSE 0
-
-
- #define ARCMAGIC 0177545
- #define OMAGIC 0405
- #define FMAGIC 0407
- #define NMAGIC 0410
- #define IMAGIC 0411
-
- #define EXTERN 040
- #define UNDEF 00
- #define ABS 01
- #define TEXT 02
- #define DATA 03
- #define BSS 04
- #define COMM 05 /* internal use only */
-
- #define RABS 00
- #define RTEXT 02
- #define RDATA 04
- #define RBSS 06
- #define REXT 010
-
- #define NOVLY 16
- #define RELFLG 01
- #define NROUT 256
- #define NSYM 1103
- #define NSYMPR 1000
-
- char premeof[] = "Premature EOF";
- char goodnm[] = "__.SYMDEF";
-
- /* table of contents stuff */
- #define TABSZ 700
- struct tab
- { char cname[8];
- long cloc;
- } tab[TABSZ];
- int tnum;
-
-
- /* overlay management */
- int vindex;
- struct overlay {
- int argsav;
- int symsav;
- struct liblist *libsav;
- char *vname;
- int ctsav, cdsav, cbsav;
- int offt, offd, offb, offs;
- } vnodes[NOVLY];
-
- /* input management */
- struct page {
- int nuser;
- int bno;
- int nibuf;
- int buff[256];
- } page[2];
-
- struct {
- int nuser;
- int bno;
- } fpage;
-
- struct stream {
- int *ptr;
- int bno;
- int nibuf;
- int size;
- struct page *pno;
- };
-
- struct stream text;
- struct stream reloc;
-
- struct {
- char aname[14];
- long atime;
- char auid, agid;
- int amode;
- long asize;
- } archdr;
-
- struct {
- int fmagic;
- int tsize;
- int dsize;
- int bsize;
- int ssize;
- int entry;
- int pad;
- int relflg;
- } filhdr;
-
-
- /* one entry for each archive member referenced;
- * set in first pass; needs restoring for overlays
- */
- struct liblist {
- long loc;
- };
-
- struct liblist liblist[NROUT];
- struct liblist *libp = liblist;
-
-
- /* symbol management */
- struct symbol {
- char sname[8];
- char stype;
- char spare;
- int svalue;
- };
-
- struct local {
- int locindex; /* index to symbol in file */
- struct symbol *locsymbol; /* ptr to symbol table */
- };
-
- struct symbol cursym; /* current symbol */
- struct symbol symtab[NSYM]; /* actual symbols */
- struct symbol **symhash[NSYM]; /* ptr to hash table entry */
- struct symbol *lastsym; /* last symbol entered */
- int symindex; /* next available symbol table entry */
- struct symbol *hshtab[NSYM+2]; /* hash table for symbols */
- struct local local[NSYMPR];
-
- /* internal symbols */
- struct symbol *p_etext;
- struct symbol *p_edata;
- struct symbol *p_end;
- struct symbol *entrypt;
-
- int trace;
- /* flags */
- int xflag; /* discard local symbols */
- int Xflag; /* discard locals starting with 'L' */
- int Sflag; /* discard all except locals and globals*/
- int rflag; /* preserve relocation bits, don't define common */
- int arflag; /* original copy of rflag */
- int sflag; /* discard all symbols */
- int nflag; /* pure procedure */
- int Oflag; /* set magic # to 0405 (overlay) */
- int dflag; /* define common even with rflag */
- int iflag; /* I/D space separated */
- int vflag; /* overlays used */
-
- int ofilfnd;
- char *ofilename = "l.out";
- int infil;
- char *filname;
-
- /* cumulative sizes set in pass 1 */
- int tsize;
- int dsize;
- int bsize;
- int ssize;
-
- /* symbol relocation; both passes */
- int ctrel;
- int cdrel;
- int cbrel;
-
- int errlev;
- int delarg = 4;
- char tfname[] = "/tmp/ldaXXXXX";
-
-
- /* output management */
- struct buf {
- int fildes;
- int nleft;
- int *xnext;
- int iobuf[256];
- };
- struct buf toutb;
- struct buf doutb;
- struct buf troutb;
- struct buf droutb;
- struct buf soutb;
-
- struct symbol **lookup();
- struct symbol **slookup();
- struct symbol *lookloc();
-
- delexit()
- {
- unlink("l.out");
- if (delarg==0)
- chmod(ofilename, 0777 & ~umask(0));
- exit(delarg);
- }
-
- main(argc, argv)
- char **argv;
- {
- register int c, i;
- int num;
- register char *ap, **p;
- int found;
- int vscan;
- char save;
-
- if (signal(SIGINT, SIG_IGN) != SIG_IGN)
- signal(SIGINT, delexit);
- if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
- signal(SIGTERM, delexit);
- if (argc == 1)
- exit(4);
- p = argv+1;
-
- /* scan files once to find symdefs */
- for (c=1; c<argc; c++) {
- if (trace) printf("%s:\n", *p);
- filname = 0;
- ap = *p++;
-
- if (*ap == '-') {
- for (i=1; ap[i]; i++) {
- switch (ap[i]) {
- case 'o':
- if (++c >= argc)
- error(2, "Bad output file");
- ofilename = *p++;
- ofilfnd++;
- continue;
-
- case 'u':
- case 'e':
- if (++c >= argc)
- error(2, "Bad 'use' or 'entry'");
- enter(slookup(*p++));
- if (ap[i]=='e')
- entrypt = lastsym;
- continue;
-
- case 'v':
- if (++c >= argc)
- error(2, "-v: arg missing");
- vflag=TRUE;
- vscan = vindex;
- found=FALSE;
- while (--vscan>=0 && found==FALSE)
- found = eq(vnodes[vscan].vname, *p);
- if (found) {
- endload(c, argv);
- restore(vscan);
- } else
- record(c, *p);
- p++;
- continue;
-
- case 'D':
- if (++c >= argc)
- error(2, "-D: arg missing");
- num = atoi(*p++);
- if (dsize>num)
- error(2, "-D: too small");
- dsize = num;
- continue;
-
- case 'l':
- save = ap[--i];
- ap[i]='-';
- load1arg(&ap[i]);
- ap[i]=save;
- break;
-
- case 'x':
- xflag++;
- continue;
-
- case 'X':
- Xflag++;
- continue;
-
- case 'S':
- Sflag++;
- continue;
-
- case 'r':
- rflag++;
- arflag++;
- continue;
-
- case 's':
- sflag++;
- xflag++;
- continue;
-
- case 'n':
- nflag++;
- continue;
-
- case 'd':
- dflag++;
- continue;
-
- case 'i':
- iflag++;
- continue;
-
- case 'O':
- Oflag++;
- continue;
-
- case 't':
- trace++;
- continue;
-
- default:
- error(2, "bad flag");
- } /*endsw*/
- break;
- } /*endfor*/
- } else
- load1arg(ap);
- }
- endload(argc, argv);
- }
-
- /* used after pass 1 */
- int nsym;
- int torigin;
- int dorigin;
- int borigin;
-
- endload(argc, argv)
- int argc;
- char **argv;
- {
- register int c, i;
- int dnum;
- register char *ap, **p;
- filname = 0;
- middle();
- setupout();
- p = argv+1;
- libp = liblist;
- for (c=1; c<argc; c++) {
- ap = *p++;
- if (trace) printf("%s:\n", ap);
- if (*ap == '-') {
- for (i=1; ap[i]; i++) {
- switch (ap[i]) {
- case 'D':
- for (dnum = atoi(*p); dorigin<dnum; dorigin += 2) {
- putw(0, &doutb);
- if (rflag)
- putw(0, &droutb);
- }
- case 'u':
- case 'e':
- case 'o':
- case 'v':
- ++c;
- ++p;
-
- default:
- continue;
-
- case 'l':
- ap[--i]='-';
- load2arg(&ap[i]);
- break;
- } /*endsw*/
- break;
- } /*endfor*/
- } else
- load2arg(ap);
- }
- finishout();
- }
-
- record(c, nam)
- int c;
- char *nam;
- {
- register struct overlay *v;
-
- v = &vnodes[vindex++];
- v->argsav = c;
- v->symsav = symindex;
- v->libsav = libp;
- v->vname = nam;
- v->offt = tsize;
- v->offd = dsize;
- v->offb = bsize;
- v->offs = ssize;
- v->ctsav = ctrel;
- v->cdsav = cdrel;
- v->cbsav = cbrel;
- }
-
- restore(vscan)
- int vscan;
- {
- register struct overlay *v;
- register int saved;
-
- v = &vnodes[vscan];
- vindex = vscan+1;
- libp = v->libsav;
- ctrel = v->ctsav;
- cdrel = v->cdsav;
- cbrel = v->cbsav;
- tsize = v->offt;
- dsize = v->offd;
- bsize = v->offb;
- ssize = v->offs;
- saved = v->symsav;
- while (symindex>saved)
- *symhash[--symindex]=0;
- }
-
- /* scan file to find defined symbols */
- load1arg(acp)
- char *acp;
- {
- register char *cp;
- long nloc;
-
- cp = acp;
- switch ( getfile(cp)) {
- case 0:
- load1(0, 0L);
- break;
-
- /* regular archive */
- case 1:
- nloc = 1;
- while ( step(nloc))
- nloc += (archdr.asize + sizeof(archdr) + 1) >> 1;
- break;
-
- /* table of contents */
- case 2:
- tnum = archdr.asize / sizeof(struct tab);
- if (tnum >= TABSZ) {
- error(2, "fast load buffer too small");
- }
- lseek(infil, (long)(sizeof(filhdr.fmagic)+sizeof(archdr)), 0);
- read(infil, (char *)tab, tnum * sizeof(struct tab));
- while (ldrand());
- libp->loc = -1;
- libp++;
- break;
- /* out of date table of contents */
- case 3:
- error(0, "out of date (warning)");
- for(nloc = 1+((archdr.asize+sizeof(archdr)+1) >> 1); step(nloc);
- nloc += (archdr.asize + sizeof(archdr) + 1) >> 1);
- break;
- }
- close(infil);
- }
-
- step(nloc)
- long nloc;
- {
- dseek(&text, nloc, sizeof archdr);
- if (text.size <= 0) {
- libp->loc = -1;
- libp++;
- return(0);
- }
- mget((int *)&archdr, sizeof archdr);
- if (load1(1, nloc + (sizeof archdr) / 2)) {
- libp->loc = nloc;
- libp++;
- }
- return(1);
- }
-
- ldrand()
- {
- int i;
- struct symbol *sp, **pp;
- struct liblist *oldp = libp;
- for(i = 0; i<tnum; i++) {
- if ((pp = slookup(tab[i].cname)) == 0)
- continue;
- sp = *pp;
- if (sp->stype != EXTERN+UNDEF)
- continue;
- step(tab[i].cloc >> 1);
- }
- return(oldp != libp);
- }
-
- add(a,b,s)
- int a, b;
- char *s;
- {
- long r;
-
- r = (long)(unsigned)a + (unsigned)b;
- if (r >= 0200000)
- error(1,s);
- return(r);
- }
-
-
- /* single file or archive member */
- load1(libflg, loc)
- long loc;
- {
- register struct symbol *sp;
- int savindex;
- int ndef, nloc, type, mtype;
-
- readhdr(loc);
- ctrel = tsize;
- cdrel += dsize;
- cbrel += bsize;
- ndef = 0;
- nloc = sizeof cursym;
- savindex = symindex;
- if ((filhdr.relflg&RELFLG)==1) {
- error(1, "No relocation bits");
- return(0);
- }
- loc += (sizeof filhdr)/2 + filhdr.tsize + filhdr.dsize;
- dseek(&text, loc, filhdr.ssize);
- while (text.size > 0) {
- mget((int *)&cursym, sizeof cursym);
- type = cursym.stype;
- if (Sflag) {
- mtype = type&037;
- if (mtype==1 || mtype>4) {
- continue;
- }
- }
- if ((type&EXTERN)==0) {
- if (Xflag==0 || cursym.sname[0]!='L')
- nloc += sizeof cursym;
- continue;
- }
- symreloc();
- if (enter(lookup()))
- continue;
- if ((sp = lastsym)->stype != EXTERN+UNDEF)
- continue;
- if (cursym.stype == EXTERN+UNDEF) {
- if (cursym.svalue > sp->svalue)
- sp->svalue = cursym.svalue;
- continue;
- }
- if (sp->svalue != 0 && cursym.stype == EXTERN+TEXT)
- continue;
- ndef++;
- sp->stype = cursym.stype;
- sp->svalue = cursym.svalue;
- }
- if (libflg==0 || ndef) {
- tsize = add(tsize,filhdr.tsize,"text overflow");
- dsize = add(dsize,filhdr.dsize,"data overflow");
- bsize = add(bsize,filhdr.bsize,"bss overflow");
- ssize = add(ssize,nloc,"symbol table overflow");
- return(1);
- }
- /*
- * No symbols defined by this library member.
- * Rip out the hash table entries and reset the symbol table.
- */
- while (symindex>savindex)
- *symhash[--symindex]=0;
- return(0);
- }
-
- middle()
- {
- register struct symbol *sp, *symp;
- register t, csize;
- int nund, corigin;
-
- torigin=0;
- dorigin=0;
- borigin=0;
-
- p_etext = *slookup("_etext");
- p_edata = *slookup("_edata");
- p_end = *slookup("_end");
- /*
- * If there are any undefined symbols, save the relocation bits.
- */
- symp = &symtab[symindex];
- if (rflag==0) {
- for (sp = symtab; sp<symp; sp++)
- if (sp->stype==EXTERN+UNDEF && sp->svalue==0
- && sp!=p_end && sp!=p_edata && sp!=p_etext) {
- rflag++;
- dflag = 0;
- break;
- }
- }
- if (rflag)
- nflag = sflag = iflag = Oflag = 0;
- /*
- * Assign common locations.
- */
- csize = 0;
- if (dflag || rflag==0) {
- ldrsym(p_etext, tsize, EXTERN+TEXT);
- ldrsym(p_edata, dsize, EXTERN+DATA);
- ldrsym(p_end, bsize, EXTERN+BSS);
- for (sp = symtab; sp<symp; sp++)
- if (sp->stype==EXTERN+UNDEF && (t = sp->svalue)!=0) {
- t = (t+1) & ~01;
- sp->svalue = csize;
- sp->stype = EXTERN+COMM;
- csize = add(csize, t, "bss overflow");
- }
- }
- /*
- * Now set symbols to their final value
- */
- if (nflag || iflag)
- tsize = (tsize + 077) & ~077;
- dorigin = tsize;
- if (nflag)
- dorigin = (tsize+017777) & ~017777;
- if (iflag)
- dorigin = 0;
- corigin = dorigin + dsize;
- borigin = corigin + csize;
- nund = 0;
- for (sp = symtab; sp<symp; sp++) switch (sp->stype) {
- case EXTERN+UNDEF:
- errlev |= 01;
- if (arflag==0 && sp->svalue==0) {
- if (nund==0)
- printf("Undefined:\n");
- nund++;
- printf("%.8s\n", sp->sname);
- }
- continue;
-
- case EXTERN+ABS:
- default:
- continue;
-
- case EXTERN+TEXT:
- sp->svalue += torigin;
- continue;
-
- case EXTERN+DATA:
- sp->svalue += dorigin;
- continue;
-
- case EXTERN+BSS:
- sp->svalue += borigin;
- continue;
-
- case EXTERN+COMM:
- sp->stype = EXTERN+BSS;
- sp->svalue += corigin;
- continue;
- }
- if (sflag || xflag)
- ssize = 0;
- bsize = add(bsize, csize, "bss overflow");
- nsym = ssize / (sizeof cursym);
- }
-
- ldrsym(asp, val, type)
- struct symbol *asp;
- {
- register struct symbol *sp;
-
- if ((sp = asp) == 0)
- return;
- if (sp->stype != EXTERN+UNDEF || sp->svalue) {
- printf("%.8s: ", sp->sname);
- error(1, "Multiply defined");
- return;
- }
- sp->stype = type;
- sp->svalue = val;
- }
-
- setupout()
- {
- tcreat(&toutb, 0);
- mktemp(tfname);
- tcreat(&doutb, 1);
- if (sflag==0 || xflag==0)
- tcreat(&soutb, 1);
- if (rflag) {
- tcreat(&troutb, 1);
- tcreat(&droutb, 1);
- }
- filhdr.fmagic = (Oflag ? OMAGIC :( iflag ? IMAGIC : ( nflag ? NMAGIC : FMAGIC )));
- filhdr.tsize = tsize;
- filhdr.dsize = dsize;
- filhdr.bsize = bsize;
- filhdr.ssize = sflag? 0: (ssize + (sizeof cursym)*symindex);
- if (entrypt) {
- if (entrypt->stype!=EXTERN+TEXT)
- error(1, "Entry point not in text");
- else
- filhdr.entry = entrypt->svalue | 01;
- } else
- filhdr.entry=0;
- filhdr.pad = 0;
- filhdr.relflg = (rflag==0);
- mput(&toutb, (int *)&filhdr, sizeof filhdr);
- }
-
- tcreat(buf, tempflg)
- struct buf *buf;
- {
- register int ufd;
- char *nam;
- nam = (tempflg ? tfname : ofilename);
- if ((ufd = creat(nam, 0666)) < 0)
- error(2, tempflg?"cannot create temp":"cannot create output");
- close(ufd);
- buf->fildes = open(nam, 2);
- if (tempflg)
- unlink(tfname);
- buf->nleft = sizeof(buf->iobuf)/sizeof(int);
- buf->xnext = buf->iobuf;
- }
-
- load2arg(acp)
- char *acp;
- {
- register char *cp;
- register struct liblist *lp;
-
- cp = acp;
- if (getfile(cp) == 0) {
- while (*cp)
- cp++;
- while (cp >= acp && *--cp != '/');
- mkfsym(++cp);
- load2(0L);
- } else { /* scan archive members referenced */
- for (lp = libp; lp->loc != -1; lp++) {
- dseek(&text, lp->loc, sizeof archdr);
- mget((int *)&archdr, sizeof archdr);
- mkfsym(archdr.aname);
- load2(lp->loc + (sizeof archdr) / 2);
- }
- libp = ++lp;
- }
- close(infil);
- }
-
- load2(loc)
- long loc;
- {
- register struct symbol *sp;
- register struct local *lp;
- register int symno;
- int type, mtype;
-
- readhdr(loc);
- ctrel = torigin;
- cdrel += dorigin;
- cbrel += borigin;
- /*
- * Reread the symbol table, recording the numbering
- * of symbols for fixing external references.
- */
- lp = local;
- symno = -1;
- loc += (sizeof filhdr)/2;
- dseek(&text, loc + filhdr.tsize + filhdr.dsize, filhdr.ssize);
- while (text.size > 0) {
- symno++;
- mget((int *)&cursym, sizeof cursym);
- symreloc();
- type = cursym.stype;
- if (Sflag) {
- mtype = type&037;
- if (mtype==1 || mtype>4) continue;
- }
- if ((type&EXTERN) == 0) {
- if (!sflag&&!xflag&&(!Xflag||cursym.sname[0]!='L'))
- mput(&soutb, (int *)&cursym, sizeof cursym);
- continue;
- }
- if ((sp = *lookup()) == 0)
- error(2, "internal error: symbol not found");
- if (cursym.stype == EXTERN+UNDEF) {
- if (lp >= &local[NSYMPR])
- error(2, "Local symbol overflow");
- lp->locindex = symno;
- lp++->locsymbol = sp;
- continue;
- }
- if (cursym.stype!=sp->stype || cursym.svalue!=sp->svalue) {
- printf("%.8s: ", cursym.sname);
- error(1, "Multiply defined");
- }
- }
- dseek(&text, loc, filhdr.tsize);
- dseek(&reloc, loc + half(filhdr.tsize + filhdr.dsize), filhdr.tsize);
- load2td(lp, ctrel, &toutb, &troutb);
- dseek(&text, loc+half(filhdr.tsize), filhdr.dsize);
- dseek(&reloc, loc+filhdr.tsize+half(filhdr.dsize), filhdr.dsize);
- load2td(lp, cdrel, &doutb, &droutb);
- torigin += filhdr.tsize;
- dorigin += filhdr.dsize;
- borigin += filhdr.bsize;
- }
-
- load2td(lp, creloc, b1, b2)
- struct local *lp;
- struct buf *b1, *b2;
- {
- register r, t;
- register struct symbol *sp;
-
- for (;;) {
- /*
- * The pickup code is copied from "get" for speed.
- */
-
- /* next text or data word */
- if (--text.size <= 0) {
- if (text.size < 0)
- break;
- text.size++;
- t = get(&text);
- } else if (--text.nibuf < 0) {
- text.nibuf++;
- text.size++;
- t = get(&text);
- } else
- t = *text.ptr++;
-
- /* next relocation word */
- if (--reloc.size <= 0) {
- if (reloc.size < 0)
- error(2, "Relocation error");
- reloc.size++;
- r = get(&reloc);
- } else if (--reloc.nibuf < 0) {
- reloc.nibuf++;
- reloc.size++;
- r = get(&reloc);
- } else
- r = *reloc.ptr++;
-
- switch (r&016) {
-
- case RTEXT:
- t += ctrel;
- break;
-
- case RDATA:
- t += cdrel;
- break;
-
- case RBSS:
- t += cbrel;
- break;
-
- case REXT:
- sp = lookloc(lp, r);
- if (sp->stype==EXTERN+UNDEF) {
- r = (r&01) + ((nsym+(sp-symtab))<<4) + REXT;
- break;
- }
- t += sp->svalue;
- r = (r&01) + ((sp->stype-(EXTERN+ABS))<<1);
- break;
- }
- if (r&01)
- t -= creloc;
- putw(t, b1);
- if (rflag)
- putw(r, b2);
- }
- }
-
- finishout()
- {
- register n, *p;
-
- if (nflag||iflag) {
- n = torigin;
- while (n&077) {
- n += 2;
- putw(0, &toutb);
- if (rflag)
- putw(0, &troutb);
- }
- }
- copy(&doutb);
- if (rflag) {
- copy(&troutb);
- copy(&droutb);
- }
- if (sflag==0) {
- if (xflag==0)
- copy(&soutb);
- for (p = (int *)symtab; p < (int *)&symtab[symindex];)
- putw(*p++, &toutb);
- }
- flush(&toutb);
- close(toutb.fildes);
- if (!ofilfnd) {
- unlink("a.out");
- link("l.out", "a.out");
- ofilename = "a.out";
- }
- delarg = errlev;
- delexit();
- }
-
- copy(buf)
- struct buf *buf;
- {
- register f, *p, n;
-
- flush(buf);
- lseek(f = buf->fildes, (long)0, 0);
- while ((n = read(f, (char *)doutb.iobuf, sizeof(doutb.iobuf))) > 1) {
- n >>= 1;
- p = (int *)doutb.iobuf;
- do
- putw(*p++, &toutb);
- while (--n);
- }
- close(f);
- }
-
- mkfsym(s)
- char *s;
- {
-
- if (sflag || xflag)
- return;
- cp8c(s, cursym.sname);
- cursym.stype = 037;
- cursym.svalue = torigin;
- mput(&soutb, (int *)&cursym, sizeof cursym);
- }
-
- mget(aloc, an)
- int *aloc;
- {
- register *loc, n;
- register *p;
-
- n = an;
- n >>= 1;
- loc = aloc;
- if ((text.nibuf -= n) >= 0) {
- if ((text.size -= n) > 0) {
- p = text.ptr;
- do
- *loc++ = *p++;
- while (--n);
- text.ptr = p;
- return;
- } else
- text.size += n;
- }
- text.nibuf += n;
- do {
- *loc++ = get(&text);
- }
- while (--n);
- }
-
- mput(buf, aloc, an)
- struct buf *buf;
- int *aloc;
- {
- register *loc;
- register n;
-
- loc = aloc;
- n = an>>1;
- do {
- putw(*loc++, buf);
- }
- while (--n);
- }
-
- dseek(asp, aloc, s)
- long aloc;
- struct stream *asp;
- {
- register struct stream *sp;
- register struct page *p;
- /* register */ long b, o;
- int n;
-
- b = aloc >> 8;
- o = aloc & 0377;
- sp = asp;
- --sp->pno->nuser;
- if ((p = &page[0])->bno!=b && (p = &page[1])->bno!=b)
- if (p->nuser==0 || (p = &page[0])->nuser==0) {
- if (page[0].nuser==0 && page[1].nuser==0)
- if (page[0].bno < page[1].bno)
- p = &page[0];
- p->bno = b;
- lseek(infil, (aloc & ~0377L) << 1, 0);
- if ((n = read(infil, (char *)p->buff, 512)>>1) < 0)
- n = 0;
- p->nibuf = n;
- } else
- error(2, "No pages");
- ++p->nuser;
- sp->bno = b;
- sp->pno = p;
- sp->ptr = p->buff + o;
- if (s != -1)
- sp->size = half(s);
- if ((sp->nibuf = p->nibuf-o) <= 0)
- sp->size = 0;
- }
-
- half(i)
- {
- return((i>>1)&077777);
- }
-
- get(asp)
- struct stream *asp;
- {
- register struct stream *sp;
-
- sp = asp;
- if (--sp->nibuf < 0) {
- dseek(sp, (long)(sp->bno + 1) << 8, -1);
- --sp->nibuf;
- }
- if (--sp->size <= 0) {
- if (sp->size < 0)
- error(2, premeof);
- ++fpage.nuser;
- --sp->pno->nuser;
- sp->pno = (struct page *)&fpage;
- }
- return(*sp->ptr++);
- }
-
- getfile(acp)
- char *acp;
- {
- register char *cp;
- register int c;
- struct stat x;
-
- cp = acp;
- infil = -1;
- archdr.aname[0] = '\0';
- filname = cp;
- if (cp[0]=='-' && cp[1]=='l') {
- if(cp[2] == '\0')
- cp = "-la";
- filname = "/usr/lib/libxxxxxxxxxxxxxxx";
- for(c=0; cp[c+2]; c++)
- filname[c+12] = cp[c+2];
- filname[c+12] = '.';
- filname[c+13] = 'a';
- filname[c+14] = '\0';
- if ((infil = open(filname+4, 0)) >= 0) {
- filname += 4;
- }
- }
- if (infil == -1 && (infil = open(filname, 0)) < 0)
- error(2, "cannot open");
- page[0].bno = page[1].bno = -1;
- page[0].nuser = page[1].nuser = 0;
- text.pno = reloc.pno = (struct page *)&fpage;
- fpage.nuser = 2;
- dseek(&text, 0L, 2);
- if (text.size <= 0)
- error(2, premeof);
- if(get(&text) != ARCMAGIC)
- return(0); /* regualr file */
- dseek(&text, 1L, sizeof archdr); /* word addressing */
- if(text.size <= 0)
- return(1); /* regular archive */
- mget((int *)&archdr, sizeof archdr);
- if(strncmp(archdr.aname, goodnm, 14) != 0)
- return(1); /* regular archive */
- else {
- fstat(infil, &x);
- if(x.st_mtime > archdr.atime)
- {
- return(3);
- }
- else return(2);
- }
- }
-
- struct symbol **lookup()
- {
- int i;
- int clash;
- register struct symbol **hp;
- register char *cp, *cp1;
-
- i = 0;
- for (cp = cursym.sname; cp < &cursym.sname[8];)
- i = (i<<1) + *cp++;
- for (hp = &hshtab[(i&077777)%NSYM+2]; *hp!=0;) {
- cp1 = (*hp)->sname;
- clash=FALSE;
- for (cp = cursym.sname; cp < &cursym.sname[8];)
- if (*cp++ != *cp1++) {
- clash=TRUE;
- break;
- }
- if (clash) {
- if (++hp >= &hshtab[NSYM+2])
- hp = hshtab;
- } else
- break;
- }
- return(hp);
- }
-
- struct symbol **slookup(s)
- char *s;
- {
- cp8c(s, cursym.sname);
- cursym.stype = EXTERN+UNDEF;
- cursym.svalue = 0;
- return(lookup());
- }
-
- enter(hp)
- struct symbol **hp;
- {
- register struct symbol *sp;
-
- if (*hp==0) {
- if (symindex>=NSYM)
- error(2, "Symbol table overflow");
- symhash[symindex] = hp;
- *hp = lastsym = sp = &symtab[symindex++];
- cp8c(cursym.sname, sp->sname);
- sp->stype = cursym.stype;
- sp->svalue = cursym.svalue;
- return(1);
- } else {
- lastsym = *hp;
- return(0);
- }
- }
-
- symreloc()
- {
- switch (cursym.stype) {
-
- case TEXT:
- case EXTERN+TEXT:
- cursym.svalue += ctrel;
- return;
-
- case DATA:
- case EXTERN+DATA:
- cursym.svalue += cdrel;
- return;
-
- case BSS:
- case EXTERN+BSS:
- cursym.svalue += cbrel;
- return;
-
- case EXTERN+UNDEF:
- return;
- }
- if (cursym.stype&EXTERN)
- cursym.stype = EXTERN+ABS;
- }
-
- error(n, s)
- char *s;
- {
- if (errlev==0)
- printf("ld:");
- if (filname) {
- printf("%s", filname);
- if (archdr.aname[0])
- printf("(%.14s)", archdr.aname);
- printf(": ");
- }
- printf("%s\n", s);
- if (n > 1)
- delexit();
- errlev = n;
- }
-
- struct symbol *
- lookloc(alp, r)
- struct local *alp;
- {
- register struct local *clp, *lp;
- register sn;
-
- lp = alp;
- sn = (r>>4) & 07777;
- for (clp = local; clp<lp; clp++)
- if (clp->locindex == sn)
- return(clp->locsymbol);
- error(2, "Local symbol botch");
- }
-
- readhdr(loc)
- long loc;
- {
- register st, sd;
-
- dseek(&text, loc, sizeof filhdr);
- mget((int *)&filhdr, sizeof filhdr);
- if (filhdr.fmagic != FMAGIC)
- error(2, "Bad format");
- st = (filhdr.tsize+01) & ~01;
- filhdr.tsize = st;
- cdrel = -st;
- sd = (filhdr.dsize+01) & ~01;
- cbrel = - (st+sd);
- filhdr.bsize = (filhdr.bsize+01) & ~01;
- }
-
- cp8c(from, to)
- char *from, *to;
- {
- register char *f, *t, *te;
-
- f = from;
- t = to;
- te = t+8;
- while ((*t++ = *f++) && t<te);
- while (t<te)
- *t++ = 0;
- }
-
- eq(s1, s2)
- char *s1;
- char *s2;
- {
- while (*s1==*s2++)
- if ((*s1++)==0)
- return(TRUE);
- return(FALSE);
- }
-
- putw(w, b)
- register struct buf *b;
- {
- *(b->xnext)++ = w;
- if (--b->nleft <= 0)
- flush(b);
- }
-
- flush(b)
- register struct buf *b;
- {
- register n;
-
- if ((n = (char *)b->xnext - (char *)b->iobuf) > 0)
- if (write(b->fildes, (char *)b->iobuf, n) != n)
- error(2, "output error");
- b->xnext = b->iobuf;
- b->nleft = sizeof(b->iobuf)/sizeof(int);
- }
-