BSD 3 development
[unix-history] / usr / src / cmd / ld.c
index 48f52a9..90e8895 100644 (file)
+char LD[] = "@(#)ld.c 1.10 78/12/07 15:34:58"; /* sccs ident */
 /*
 /*
- *  link editor
+ *  link editor for VAX
  */
 
  */
 
-#include <signal.h>
-#include "sys/types.h"
-#include "sys/stat.h"
-
-/*     Layout of a.out file :
+/*     layout of a.out file:
  *
  *
- *     header of 8 words       magic number 405, 407, 410, 411
+ *     header of 8 words       magic number 0410:
+                                       data starts at 1st (PAGSIZ)
+                                       boundary above text
+                               magic number 0407:
+                                       data starts immediately after
+                                       text
  *                             text size       )
  *                             text size       )
- *                             data size       ) in bytes but even
+ *                             data size       ) in bytes
  *                             bss size        )
  *                             symbol table size
  *                             entry point
  *                             bss size        )
  *                             symbol table size
  *                             entry point
- *                             {unused}
- *                             flag set if no relocation
- *
+ *                             size of text relocation info
+ *                             size of data relocation info
  *
  *
+ *  'segment'   origin   comments
  *     header:         0
  *     header:         0
- *     text:           16
- *     data:           16+textsize
- *     relocation:     16+textsize+datasize
- *     symbol table:   16+2*(textsize+datasize) or 16+textsize+datasize
+ *     text:           32       0 padded to multiple of 4 bytes
+ *     data:           32+textsize     0 padded to multiple of 4 bytes
+ *     text relocation:        32+textsize+datasize
+ *     data relocation:        32+textsize+datasize+textrelocationsize
+ *     symbol table:   32+textsize+datasize+textrelocationsize+datarelocationsize
  *
  */
  *
  */
+#include <signal.h>
+#include <stdio.h>
+#include <ar.h>
+#include <a.out.h>
+#include <pagsiz.h>
+
+struct {short hiword; short loword;}; /* stupid fp-11 */
+fixl(p) register long *p;{
+       register short t;
+       t=p->hiword; p->hiword=p->loword; p->loword=t;
+}
+
+writel(p,n,f) long *p; FILE *f; {
+#ifdef vax
+       fwrite(p,sizeof(*p),n,f);
+#else
+       while (n--) {
+               fwrite(&(*p).loword,2,1,f);
+               fwrite(&(*p).hiword,2,1,f);
+               p++;
+       }
+#endif
+}
+
+long htoi(p) register char *p; {/* hex to integer conversion */
+register long n = 0;
+while (*p) {
+       n <<= 4;
+       if              (*p<='9' && *p>='0') n += *p - '0';
+       else if (*p<='f' && *p>='a') n += *p -'a' +10;
+       else if (*p<='F' && *p>='A') n += *p -'A' +10;
+       p++;
+}
+return(n);
+}
+
+typedef        char *STRING;
+typedef        int BOOL;
 #define TRUE   1
 #define FALSE  0
 
 #define TRUE   1
 #define FALSE  0
 
-
-#define        ARCMAGIC 0177545
-#define OMAGIC 0405
-#define        FMAGIC  0407
+#define        OMAGIC  0407
 #define        NMAGIC  0410
 #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
+
+/*
+ * Symbol types
+ */
+#define        UNDEF   0x0
+#define        ABS     0x2
+#define        TEXT    0x4
+#define        DATA    0x6
+#define        BSS     0x8
+#define        DATAO   0xA
+#define        BSSO    0xC
+#define        TEXTO   0xE
+#define        ABSO    0x10
+
+#define        COMM    0x12    /* for internal use only */
+
+#define        EXTERN  0x1
+#define        TYPE    0x1E
+#define STABTYPS 0xE0
+/*
+ * address reference types
+ */
+#define PCREL  1
+#define LEN1   0
+#define LEN2   2
+#define LEN4   4
+
+#define        HW      01
+#define        FW      03
+#define        DW      07
+
+
+#define        TYPMASK 0x1E
+#define        TYMASK  (0x1E)
+#define TMASK  0x1F
+
+#define        RABS    (ABS)
+#define        RTEXT   TEXT
+#define        RDATA   DATA
+#define        RBSS    BSS
+#define        RDATAO  DATAO
+#define        RBSSO   BSSO
+#define        RTEXTO  TEXTO
+#define        RABSO   ABSO
+#define        REXT    (01<<3)
+#define        ROFF    (02<<3)
+#define        REFMASK 0x7
+
+#define NOVLY  1
 #define        RELFLG  01
 #define        NROUT   256
 #define        NSYM    1103
 #define        RELFLG  01
 #define        NROUT   256
 #define        NSYM    1103
-#define        NSYMPR  1000
+#define        NSYMPR  500
 
 char   premeof[] = "Premature EOF";
 
 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;
 
 
+typedef struct {
+       long    loc;
+} LIBLIST;
 
 /* overlay management */
 int    vindex;
 
 /* overlay management */
 int    vindex;
-struct overlay {
+typedef struct {
        int     argsav;
        int     symsav;
        int     argsav;
        int     symsav;
-       struct liblist  *libsav;
-       char    *vname;
-       int     ctsav, cdsav, cbsav;
-       int     offt, offd, offb, offs;
-} vnodes[NOVLY];
+       LIBLIST *libsav;
+       STRING  vname;
+       long    ctsav, cdsav, cbsav;
+       long    offt, offd, offb, offtr, offdr, offs;
+} OVERLAY;
+OVERLAY        vnodes[NOVLY];
 
 /* input management */
 
 /* input management */
-struct page {
-       int     nuser;
+typedef struct {
+       short   *fakeptr;
        int     bno;
        int     nibuf;
        int     bno;
        int     nibuf;
-       int     buff[256];
-} page[2];
+       int     nuser;
+       char    buff[BSIZE];
+} PAGE;
+
+PAGE   page[2];
 
 struct {
 
 struct {
-       int     nuser;
+       short   *fakeptr;
        int     bno;
        int     bno;
+       int     nibuf;
+       int     nuser;
 } fpage;
 
 } fpage;
 
-struct stream {
-       int     *ptr;
+typedef struct {
+       char    *ptr;
        int     bno;
        int     nibuf;
        int     bno;
        int     nibuf;
-       int     size;
-       struct page     *pno;
-};
+       long    size;
+       long    pos;
+       PAGE    *pno;
+} STREAM;
 
 
-struct stream text;
-struct stream reloc;
+STREAM text;
+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;
+struct ar_hdr archdr;
 
 
+struct exec filhdr;
 
 /* one entry for each archive member referenced;
  * set in first pass; needs restoring for overlays
  */
 
 /* 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;
+LIBLIST        liblist[NROUT];
+LIBLIST        *libp = liblist;
 
 
 /* symbol management */
 
 
 /* symbol management */
-struct symbol {
+typedef struct {
        char    sname[8];
        char    stype;
        char    spare;
        char    sname[8];
        char    stype;
        char    spare;
-       int     svalue;
-};
+       short   symhash;        /* index of hash table entry pointing to this symbol */
+       long    svalue;
+} SYMBOL;
 
 
-struct local {
+typedef struct {
        int locindex;           /* index to symbol in file */
        int locindex;           /* index to symbol in file */
-       struct symbol *locsymbol;       /* ptr to symbol table */
-};
+       SYMBOL *locsymbol;      /* ptr to symbol table */
+} LOCAL;
 
 
-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];
+SYMBOL cursym;                 /* current symbol */
+SYMBOL *symtab;                /* actual symbols */
+SYMBOL *lastsym;               /* last symbol entered */
+SYMBOL *nextsym;               /* next available symbol table entry */
+int nsym;                      /* number of symbols allocated in symtab */
+SYMBOL *hshtab[NSYM+2];        /* hash table for symbols */
+LOCAL  *local;
 
 /* internal symbols */
 
 /* internal symbols */
-struct symbol  *p_etext;
-struct symbol  *p_edata;
-struct symbol  *p_end;
-struct symbol  *entrypt;
+SYMBOL *p_data;
+SYMBOL *p_etext;
+SYMBOL *p_edata;
+SYMBOL *p_end;
+SYMBOL *entrypt;
 
 int    trace;
 /* flags */
 
 int    trace;
 /* flags */
@@ -168,55 +222,80 @@ 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    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    nflag = 1;      /* pure procedure */
 int    dflag;          /* define common even with rflag */
 int    iflag;          /* I/D space separated */
 int    dflag;          /* define common even with rflag */
 int    iflag;          /* I/D space separated */
-int    vflag;          /* overlays used */
+BOOL   vflag;          /* overlays used */
+int    zflag;
 
 int    ofilfnd;
 
 int    ofilfnd;
-char   *ofilename = "l.out";
+char   *ofilename      = "l.out";
 int    infil;
 char   *filname;
 
 int    infil;
 char   *filname;
 
+long   textbase;
 /* cumulative sizes set in pass 1 */
 /* cumulative sizes set in pass 1 */
-int    tsize;
-int    dsize;
-int    bsize;
-int    ssize;
+long   tsize;
+long   dsize;
+long   bsize;
+long   trsize;
+long   drsize;
+long   ssize;
 
 /* symbol relocation; both passes */
 
 /* symbol relocation; both passes */
-int    ctrel;
-int    cdrel;
-int    cbrel;
+long   ctrel;
+long   cdrel;
+long   cbrel;
+long   ctorel;
+long   cdorel;
+long   cborel;
 
 int    errlev;
 int    delarg  = 4;
 
 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();
+
+
+FILE   *tout;
+FILE   *dout;
+char   *doutn  = "";
+FILE   *trout;
+char   *troutn = "";
+FILE   *drout;
+char   *droutn = "";
+FILE   *sout;
+char   *soutn  = "";
+
+char   *mktemp();
+char   get();
+char   getb();
+short  gets();
+long   get3();
+long   getl();
+SYMBOL **lookup();
+FILE   *tcreat();
+long   round();
+SYMBOL **slookup();
+SYMBOL *lookloc();
+
+symwrite(sp,n,f) SYMBOL *sp; FILE *f; {
+#ifdef vax
+       fwrite(sp,sizeof(*symtab),n,f);
+#else
+       while (n--) {
+               fwrite(sp,sizeof(*symtab)-sizeof(sp->svalue),1,f);
+               writel(&(sp->svalue),1,f); sp++;
+       }
+#endif
+}
 
 delexit()
 {
        unlink("l.out");
 
 delexit()
 {
        unlink("l.out");
+       unlink(doutn);
+       unlink(troutn);
+       unlink(droutn);
+       unlink(soutn);
        if (delarg==0)
        if (delarg==0)
-               chmod(ofilename, 0777 & ~umask(0));
+               chmod(ofilename, 0777 &umask(0));
        exit(delarg);
 }
 
        exit(delarg);
 }
 
@@ -226,18 +305,17 @@ char **argv;
        register int c, i; 
        int num;
        register char *ap, **p;
        register int c, i; 
        int num;
        register char *ap, **p;
-       int found; 
+       BOOL found; 
        int vscan; 
        char save;
 
        if (signal(SIGINT, SIG_IGN) != SIG_IGN)
                signal(SIGINT, delexit);
        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;
 
        if (argc == 1)
                exit(4);
        p = argv+1;
 
+       nextsym=symtab=sbrk(0); nsym=0;
        /* scan files once to find symdefs */
        for (c=1; c<argc; c++) {
                if (trace) printf("%s:\n", *p);
        /* scan files once to find symdefs */
        for (c=1; c<argc; c++) {
                if (trace) printf("%s:\n", *p);
@@ -249,7 +327,7 @@ char **argv;
                        switch (ap[i]) {
                        case 'o':
                                if (++c >= argc)
                        switch (ap[i]) {
                        case 'o':
                                if (++c >= argc)
-                                       error(2, "Bad output file");
+                                       error(1, "Bad output file");
                                ofilename = *p++;
                                ofilfnd++;
                                continue;
                                ofilename = *p++;
                                ofilfnd++;
                                continue;
@@ -257,7 +335,7 @@ char **argv;
                        case 'u':
                        case 'e':
                                if (++c >= argc)
                        case 'u':
                        case 'e':
                                if (++c >= argc)
-                                       error(2, "Bad 'use' or 'entry'");
+                                       error(1, "Bad 'use' or 'entry'");
                                enter(slookup(*p++));
                                if (ap[i]=='e')
                                        entrypt = lastsym;
                                enter(slookup(*p++));
                                if (ap[i]=='e')
                                        entrypt = lastsym;
@@ -265,7 +343,7 @@ char **argv;
 
                        case 'v':
                                if (++c >= argc)
 
                        case 'v':
                                if (++c >= argc)
-                                       error(2, "-v: arg missing");
+                                       error(1, "-v: arg missing");
                                vflag=TRUE;
                                vscan = vindex; 
                                found=FALSE;
                                vflag=TRUE;
                                vscan = vindex; 
                                found=FALSE;
@@ -281,13 +359,21 @@ char **argv;
 
                        case 'D':
                                if (++c >= argc)
 
                        case 'D':
                                if (++c >= argc)
-                                       error(2, "-D: arg missing");
-                               num = atoi(*p++);
+                                       error(1, "-D: arg missing");
+                               num = htoi(*p++);
                                if (dsize>num)
                                if (dsize>num)
-                                       error(2, "-D: too small");
+                                       error(1, "-D: too small");
                                dsize = num;
                                continue;
 
                                dsize = num;
                                continue;
 
+                       case 'T':
+                               if (++c >= argc)
+                                       error(1, "-T: arg missing");
+                               if (tsize!=0)
+                                       error(1, "-T: too late, some text already loaded");
+                               textbase = htoi(*p++);
+                               continue;
+
                        case 'l':
                                save = ap[--i]; 
                                ap[i]='-';
                        case 'l':
                                save = ap[--i]; 
                                ap[i]='-';
@@ -321,6 +407,10 @@ char **argv;
                                nflag++;
                                continue;
 
                                nflag++;
                                continue;
 
+                       case 'N':
+                               nflag = 0;
+                               continue;
+
                        case 'd':
                                dflag++;
                                continue;
                        case 'd':
                                dflag++;
                                continue;
@@ -329,16 +419,16 @@ char **argv;
                                iflag++;
                                continue;
 
                                iflag++;
                                continue;
 
-                       case 'O':
-                               Oflag++;
-                               continue;
-
                        case 't':
                                trace++;
                                continue;
 
                        case 't':
                                trace++;
                                continue;
 
+                       case 'z':
+                               zflag++;
+                               continue;
+
                        default:
                        default:
-                               error(2, "bad flag");
+                               error(1, "bad flag");
                        } /*endsw*/
                        break;
                        } /*endfor*/
                        } /*endsw*/
                        break;
                        } /*endfor*/
@@ -346,24 +436,28 @@ char **argv;
                        load1arg(ap);
        }
        endload(argc, argv);
                        load1arg(ap);
        }
        endload(argc, argv);
+       exit(0);
 }
 
 /* used after pass 1 */
 }
 
 /* used after pass 1 */
-int    nsym;
-int    torigin;
-int    dorigin;
-int    borigin;
+long   torigin;
+long   dorigin;
+long   borigin;
+long   database;
 
 endload(argc, argv)
 int argc; 
 char **argv;
 {
        register int c, i; 
 
 endload(argc, argv)
 int argc; 
 char **argv;
 {
        register int c, i; 
-       int dnum;
+       long dnum;
        register char *ap, **p;
        register char *ap, **p;
+
+       brk(nextsym);
        filname = 0;
        middle();
        setupout();
        filname = 0;
        middle();
        setupout();
+       if (-1==(local=sbrk(NSYMPR*sizeof(*local)))) error(1,"Memory overflow");
        p = argv+1;
        libp = liblist;
        for (c=1; c<argc; c++) {
        p = argv+1;
        libp = liblist;
        for (c=1; c<argc; c++) {
@@ -373,11 +467,8 @@ char **argv;
                        for (i=1; ap[i]; i++) {
                        switch (ap[i]) {
                        case 'D':
                        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);
-                               }
+                               for (dnum = htoi(*p); dorigin<dnum; dorigin++) putc(0, dout);
+                       case 'T':
                        case 'u':
                        case 'e':
                        case 'o':
                        case 'u':
                        case 'e':
                        case 'o':
@@ -403,18 +494,20 @@ char **argv;
 
 record(c, nam)
 int c; 
 
 record(c, nam)
 int c; 
-char *nam;
+STRING nam;
 {
 {
-       register struct overlay *v;
+       register OVERLAY *v;
 
        v = &vnodes[vindex++];
        v->argsav = c;
 
        v = &vnodes[vindex++];
        v->argsav = c;
-       v->symsav = symindex;
+       v->symsav = nextsym-symtab;
        v->libsav = libp;
        v->vname = nam;
        v->offt = tsize; 
        v->offd = dsize; 
        v->offb = bsize; 
        v->libsav = libp;
        v->vname = nam;
        v->offt = tsize; 
        v->offd = dsize; 
        v->offb = bsize; 
+       v->offtr = trsize;
+       v->offdr = drsize;
        v->offs = ssize;
        v->ctsav = ctrel; 
        v->cdsav = cdrel; 
        v->offs = ssize;
        v->ctsav = ctrel; 
        v->cdsav = cdrel; 
@@ -424,8 +517,8 @@ char *nam;
 restore(vscan)
 int vscan;
 {
 restore(vscan)
 int vscan;
 {
-       register struct overlay *v;
-       register int saved;
+       register OVERLAY *v;
+       register SYMBOL *saved,*sp;
 
        v = &vnodes[vscan];
        vindex = vscan+1;
 
        v = &vnodes[vscan];
        vindex = vscan+1;
@@ -436,133 +529,78 @@ int vscan;
        tsize = v->offt; 
        dsize = v->offd; 
        bsize = v->offb; 
        tsize = v->offt; 
        dsize = v->offd; 
        bsize = v->offb; 
+       trsize = v->offtr;
+       drsize = v->offdr;
        ssize = v->offs;
        ssize = v->offs;
-       saved = v->symsav;
-       while (symindex>saved)
-               *symhash[--symindex]=0;
+       saved = symtab + v->symsav;
+       sp = nextsym;
+       while (sp>saved)
+               hshtab[(--sp)->symhash]=0;
+       nextsym = saved;
 }
 
 /* scan file to find defined symbols */
 }
 
 /* scan file to find defined symbols */
-load1arg(acp)
-char *acp;
+load1arg(cp)
+register char *cp;
 {
 {
-       register char *cp;
-       long nloc;
+       long loc;
 
 
-       cp = acp;
-       switch ( getfile(cp)) {
-       case 0:
+       if (getfile(cp)==0)
                load1(0, 0L);
                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");
+       else {
+               loc = sizeof(int);
+               for (;;) {
+                       dseek(&text, loc, (long)sizeof(archdr));
+                       if (text.size <= 0) {
+                               libp->loc = -1;
+                               if( ++libp >= liblist + NROUT)
+                                       error(1,"liblist overflow");
+                                       /* thanks to Dennis Wasley */
+                               return;
+                       }
+                       mget((short *)&archdr, sizeof archdr, &text);
+                       if (load1(1, loc+sizeof(archdr))) {
+                               libp->loc = loc;
+                               libp++;
+                       }
+#ifndef vax
+                       if (archdr.ar_size.loword==0) fixl(&archdr.ar_size);
+#endif
+                       loc += round(archdr.ar_size, 1) + sizeof(archdr);
                }
                }
-               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);
 }
 
        }
        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;
 {
 /* single file or archive member */
 load1(libflg, loc)
 long loc;
 {
-       register struct symbol *sp;
-       int savindex;
-       int ndef, nloc, type, mtype;
+       register SYMBOL *sp;
+       SYMBOL *savnext;
+       int ndef, nlocal, type;
 
        readhdr(loc);
        ctrel = tsize;
        cdrel += dsize;
        cbrel += bsize;
        ndef = 0;
 
        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);
+       nlocal = sizeof(cursym);
+       savnext = nextsym;
+/*     if (filhdr.a_trsize+filhdr.a_drsize==0) {
+/*             error(0, "No relocation bits");
+/*             return(0);
+/*     }
+*/
+       loc += filhdr.a_text + filhdr.a_data +
+                       filhdr.a_trsize + filhdr.a_drsize + sizeof(filhdr);
+       dseek(&text, loc, filhdr.a_syms);
        while (text.size > 0) {
        while (text.size > 0) {
-               mget((int *)&cursym, sizeof cursym);
+               symget(&cursym, &text);
                type = cursym.stype;
                type = cursym.stype;
-               if (Sflag) {
-                       mtype = type&037;
-                       if (mtype==1 || mtype>4) {
-                               continue;
-                       }
-               }
                if ((type&EXTERN)==0) {
                if ((type&EXTERN)==0) {
-                       if (Xflag==0 || cursym.sname[0]!='L')
-                               nloc += sizeof cursym;
+                       if (Xflag==0 || cursym.sname[0]!='L' || type & STABTYPS)
+                               nlocal += sizeof cursym;
                        continue;
                }
                symreloc();
                        continue;
                }
                symreloc();
@@ -582,82 +620,103 @@ long loc;
                sp->svalue = cursym.svalue;
        }
        if (libflg==0 || ndef) {
                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");
+               tsize += filhdr.a_text;
+               dsize += round(filhdr.a_data, FW);
+               bsize += round(filhdr.a_bss, FW);
+               ssize += nlocal;
+               trsize += filhdr.a_trsize;
+               drsize += filhdr.a_drsize;
                return(1);
        }
        /*
         * No symbols defined by this library member.
         * Rip out the hash table entries and reset the symbol table.
         */
                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;
+       while (nextsym>savnext)
+               hshtab[(--nextsym)->symhash]=0;
        return(0);
 }
 
 middle()
 {
        return(0);
 }
 
 middle()
 {
-       register struct symbol *sp, *symp;
-       register t, csize;
-       int nund, corigin;
+       register SYMBOL *sp, *symp;
+       long csize, t, corigin, ocsize;
+       int nund, rnd;
+       char s;
 
 
-       torigin=0; 
-       dorigin=0; 
-       borigin=0;
+       torigin = 0; 
+       dorigin = 0; 
+       borigin = 0;
 
 
+       p_data = *slookup("_data");
        p_etext = *slookup("_etext");
        p_edata = *slookup("_edata");
        p_end = *slookup("_end");
        /*
         * If there are any undefined symbols, save the relocation bits.
         */
        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];
+       symp = nextsym;
        if (rflag==0) {
                for (sp = symtab; sp<symp; sp++)
                        if (sp->stype==EXTERN+UNDEF && sp->svalue==0
        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) {
+                               && sp!=p_end && sp!=p_edata && sp!=p_etext
+                               && sp!=p_data) {
                                rflag++;
                                dflag = 0;
                                break;
                        }
        }
                                rflag++;
                                dflag = 0;
                                break;
                        }
        }
-       if (rflag)
-               nflag = sflag = iflag = Oflag = 0;
+       if (rflag) 
+               sflag = iflag = 0;
        /*
         * Assign common locations.
         */
        csize = 0;
        /*
         * Assign common locations.
         */
        csize = 0;
+       database = round(tsize+textbase, (nflag? PAGRND:FW));
        if (dflag || rflag==0) {
        if (dflag || rflag==0) {
+               ldrsym(p_data, (long)0 , EXTERN+DATA);
                ldrsym(p_etext, tsize, EXTERN+TEXT);
                ldrsym(p_edata, dsize, EXTERN+DATA);
                ldrsym(p_end, bsize, EXTERN+BSS);
                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;
+               for (sp = symtab; sp<symp; sp++) {
+                       if ((s=sp->stype)==EXTERN+UNDEF && (t = sp->svalue)!=0) {
+                               if (t>DW)
+                                       rnd = DW;
+                               else if (t>FW)
+                                       rnd = FW;
+                               else
+                                       rnd = HW;
+                               csize = round(csize, rnd);
                                sp->svalue = csize;
                                sp->stype = EXTERN+COMM;
                                sp->svalue = csize;
                                sp->stype = EXTERN+COMM;
-                               csize = add(csize, t, "bss overflow");
+                               ocsize = csize; 
+                               csize += t;
                        }
                        }
+                       if (((s&TMASK) == EXTERN+UNDEF) && (s & STABTYPS)) {
+                               sp->svalue = ocsize;
+                               sp->stype = (s & STABTYPS) | (EXTERN+COMM);
+                       }
+               }
        }
        /*
         * Now set symbols to their final value
         */
        }
        /*
         * 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;
+       csize = round(csize, FW);
+       torigin = textbase;
+       dorigin = database;
        corigin = dorigin + dsize;
        borigin = corigin + csize;
        corigin = dorigin + dsize;
        borigin = corigin + csize;
+/*
+       if (zflag)
+               borigin = round(borigin, PAGRND);
+*/
+       cdorel = 0;
+       cborel = dsize+csize;
        nund = 0;
        nund = 0;
-       for (sp = symtab; sp<symp; sp++) switch (sp->stype) {
+       for (sp = symtab; sp<symp; sp++) switch (sp->stype & TMASK) {
        case EXTERN+UNDEF:
                errlev |= 01;
        case EXTERN+UNDEF:
                errlev |= 01;
-               if (arflag==0 && sp->svalue==0) {
+               if ((arflag==0 || dflag) && sp->svalue==0) {
                        if (nund==0)
                                printf("Undefined:\n");
                        nund++;
                        if (nund==0)
                                printf("Undefined:\n");
                        nund++;
@@ -682,81 +741,99 @@ middle()
                continue;
 
        case EXTERN+COMM:
                continue;
 
        case EXTERN+COMM:
-               sp->stype = EXTERN+BSS;
+               sp->stype = (sp->stype & STABTYPS) | (EXTERN+BSS);
                sp->svalue += corigin;
                continue;
        }
        if (sflag || xflag)
                ssize = 0;
                sp->svalue += corigin;
                continue;
        }
        if (sflag || xflag)
                ssize = 0;
-       bsize = add(bsize, csize, "bss overflow");
+       bsize += csize;
        nsym = ssize / (sizeof cursym);
 }
 
 ldrsym(asp, val, type)
        nsym = ssize / (sizeof cursym);
 }
 
 ldrsym(asp, val, type)
-struct symbol *asp;
+long val;
+SYMBOL *asp;
 {
 {
-       register struct symbol *sp;
+       register SYMBOL *sp;
 
        if ((sp = asp) == 0)
                return;
        if (sp->stype != EXTERN+UNDEF || sp->svalue) {
                printf("%.8s: ", sp->sname);
 
        if ((sp = asp) == 0)
                return;
        if (sp->stype != EXTERN+UNDEF || sp->svalue) {
                printf("%.8s: ", sp->sname);
-               error(1, "Multiply defined");
+               error(0, "Multiply defined (internal)");
                return;
        }
        sp->stype = type;
        sp->svalue = val;
 }
 
                return;
        }
        sp->stype = type;
        sp->svalue = val;
 }
 
+extern char _sibuf[BUFSIZ]; /* the space is forced upon us; might as well use it */
+
 setupout()
 {
 setupout()
 {
-       tcreat(&toutb, 0);
-       mktemp(tfname);
-       tcreat(&doutb, 1);
+       int bss;
+       tout = fopen(ofilename, "w");
+       if (tout==NULL)
+               error(1, "cannot create output");
+       setbuf(tout,_sibuf);
+       dout = tcreat(&doutn, "/tmp/ldaaXXXXX");
        if (sflag==0 || xflag==0)
        if (sflag==0 || xflag==0)
-               tcreat(&soutb, 1);
+               sout = tcreat(&soutn, "/tmp/ldbaXXXXX");
        if (rflag) {
        if (rflag) {
-               tcreat(&troutb, 1);
-               tcreat(&droutb, 1);
+               trout = tcreat(&troutn, "/tmp/ldcaXXXXX");
+               drout = tcreat(&droutn, "/tmp/lddaXXXXX");
        }
        }
-       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);
+       filhdr.a_magic = nflag? NMAGIC:OMAGIC;
+       if (zflag)
+               filhdr.a_magic = nflag?0413:0412;
+       filhdr.a_text = nflag? tsize:round(tsize, FW);
+       if (zflag)
+               filhdr.a_text = round(tsize, PAGRND);
+       filhdr.a_data = dsize;
+       if (zflag)
+               filhdr.a_data = round(dsize, PAGRND);
+       bss = bsize - (filhdr.a_data - dsize);
+       if (bss < 0)
+               bss = 0;
+       filhdr.a_bss = bss;
+       filhdr.a_trsize = trsize;
+       filhdr.a_drsize = drsize;
+       filhdr.a_syms = sflag? 0: (ssize + (sizeof cursym)*(nextsym-symtab));
        if (entrypt) {
                if (entrypt->stype!=EXTERN+TEXT)
        if (entrypt) {
                if (entrypt->stype!=EXTERN+TEXT)
-                       error(1, "Entry point not in text");
+                       error(0, "Entry point not in text");
                else
                else
-                       filhdr.entry = entrypt->svalue | 01;
+                       filhdr.a_entry = entrypt->svalue;
        } else
        } else
-               filhdr.entry=0;
-       filhdr.pad = 0;
-       filhdr.relflg = (rflag==0);
-       mput(&toutb, (int *)&filhdr, sizeof filhdr);
+               filhdr.a_entry=0;
+       filhdr.a_trsize = (rflag ? trsize:0);
+       filhdr.a_drsize = (rflag ? drsize:0);
+       writel(&filhdr,8,tout);
+       if (zflag)
+               fseek(tout, PAGSIZ, 0);
 }
 
 }
 
-tcreat(buf, tempflg)
-struct buf *buf;
+FILE *
+tcreat(namep, name)
+char **namep, *name;
 {
 {
-       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;
+       register FILE *fp;
+       register char *tnm;
+
+       tnm = mktemp(name);
+       if ((fp = fopen(tnm, "w")) == NULL)
+               error(1, "Cannot create temp file");
+       chmod(tnm, 0600);
+       *namep = tnm;
+       return(fp);
 }
 
 load2arg(acp)
 char *acp;
 {
        register char *cp;
 }
 
 load2arg(acp)
 char *acp;
 {
        register char *cp;
-       register struct liblist *lp;
+       register LIBLIST *lp;
 
        cp = acp;
        if (getfile(cp) == 0) {
 
        cp = acp;
        if (getfile(cp) == 0) {
@@ -767,10 +844,10 @@ char *acp;
                load2(0L);
        } else {        /* scan archive members referenced */
                for (lp = libp; lp->loc != -1; lp++) {
                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);
+                       dseek(&text, lp->loc, (long)sizeof(archdr));
+                       mget((short *)&archdr, sizeof(archdr), &text);
+                       mkfsym(archdr.ar_name);
+                       load2(lp->loc + (long)sizeof(archdr));
                }
                libp = ++lp;
        }
                }
                libp = ++lp;
        }
@@ -780,10 +857,10 @@ char *acp;
 load2(loc)
 long loc;
 {
 load2(loc)
 long loc;
 {
-       register struct symbol *sp;
-       register struct local *lp;
+       register SYMBOL *sp;
+       register LOCAL *lp;
        register int symno;
        register int symno;
-       int type, mtype;
+       int type;
 
        readhdr(loc);
        ctrel = torigin;
 
        readhdr(loc);
        ctrel = torigin;
@@ -795,143 +872,158 @@ long loc;
         */
        lp = local;
        symno = -1;
         */
        lp = local;
        symno = -1;
-       loc += (sizeof filhdr)/2;
-       dseek(&text, loc + filhdr.tsize + filhdr.dsize, filhdr.ssize);
+       loc += sizeof(filhdr);
+       dseek(&text, loc+filhdr.a_text+filhdr.a_data+
+               filhdr.a_trsize+filhdr.a_drsize, filhdr.a_syms);
        while (text.size > 0) {
                symno++;
        while (text.size > 0) {
                symno++;
-               mget((int *)&cursym, sizeof cursym);
+               symget(&cursym, &text);
                symreloc();
                type = cursym.stype;
                symreloc();
                type = cursym.stype;
-               if (Sflag) {
-                       mtype = type&037;
-                       if (mtype==1 || mtype>4) continue;
-               }
                if ((type&EXTERN) == 0) {
                if ((type&EXTERN) == 0) {
-                       if (!sflag&&!xflag&&(!Xflag||cursym.sname[0]!='L'))
-                               mput(&soutb, (int *)&cursym, sizeof cursym);
+                       if (!sflag&&!xflag&&
+                               (!Xflag||cursym.sname[0]!='L'||type&STABTYPS))
+                               symwrite(&cursym, 1, sout);
                        continue;
                }
                if ((sp = *lookup()) == 0)
                        continue;
                }
                if ((sp = *lookup()) == 0)
-                       error(2, "internal error: symbol not found");
+                       error(1, "internal error: symbol not found");
                if (cursym.stype == EXTERN+UNDEF) {
                if (cursym.stype == EXTERN+UNDEF) {
-                       if (lp >= &local[NSYMPR])
-                               error(2, "Local symbol overflow");
+                       if (lp >= local+NSYMPR)
+                               error(1, "Local symbol overflow");
                        lp->locindex = symno;
                        lp++->locsymbol = sp;
                        continue;
                }
                        lp->locindex = symno;
                        lp++->locsymbol = sp;
                        continue;
                }
+               if(cursym.stype & STABTYPS) continue;
                if (cursym.stype!=sp->stype || cursym.svalue!=sp->svalue) {
                        printf("%.8s: ", cursym.sname);
                if (cursym.stype!=sp->stype || cursym.svalue!=sp->svalue) {
                        printf("%.8s: ", cursym.sname);
-                       error(1, "Multiply defined");
+                       error(0, "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;
+       dseek(&text, loc, filhdr.a_text);
+       dseek(&reloc, loc+filhdr.a_text+filhdr.a_data, filhdr.a_trsize);
+       load2td(lp, ctrel, tout, trout);
+       dseek(&text, loc+filhdr.a_text, filhdr.a_data);
+       dseek(&reloc, loc+filhdr.a_text+filhdr.a_data+filhdr.a_trsize, filhdr.a_drsize);
+       load2td(lp, cdrel, dout, drout);
+       while (filhdr.a_data&FW) {
+               putc(0, dout); filhdr.a_data++;
+       }
+       torigin += filhdr.a_text;
+       dorigin += filhdr.a_data;
+       borigin += filhdr.a_bss;
+       cdorel += filhdr.a_data;
+       cborel += filhdr.a_bss;
 }
 
 load2td(lp, creloc, b1, b2)
 }
 
 load2td(lp, creloc, b1, b2)
-struct local *lp;
-struct buf *b1, *b2;
+LOCAL *lp;
+long creloc;
+FILE *b1, *b2;
 {
 {
-       register r, t;
-       register struct symbol *sp;
+       register r1;
+       register char r2; 
+       register long t;
+       register SYMBOL *sp;
+       long tw,u,l;
 
        for (;;) {
 
        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;
+       if (reloc.size==0) {while (text.size) putc(get(&text),b1); break;}
+       t=getl(&reloc); /* position of relocatable stuff */
+       if (rflag) putl(t+creloc,b2); /* remember for subsequent link editing */
+       while (text.pos<t) putc(get(&text),b1); /* advance to proper position */
+       r1=get3(&reloc); /* kind of relocation */
+       r2 = getb(&reloc);
+       switch (r2&06) {/* read raw datum according to its length */
+               case LEN1: tw=get(&text); break;
+               case LEN2: tw=gets(&text); break;
+               case LEN4: tw=getl(&text); break;
+       }
+       if (r2&REXT) {
+               sp=lookloc(lp,r1); /* find the symbol */
+               if (sp->stype==EXTERN+UNDEF) { /* still undefined */
+                       r2=(r2&(REFMASK+REXT+ROFF));
+                       r1 = nsym+(sp-symtab); /* new reloc */
+               }
+               else {
+                       if (sp->stype==EXTERN+DATA && r2&ROFF) {
+                               r1=RDATAO;
+                               r2&=REFMASK;
                        }
                        }
-                       t += sp->svalue;
-                       r = (r&01) + ((sp->stype-(EXTERN+ABS))<<1);
-                       break;
+                       else if (sp->stype==EXTERN+BSS && r2&ROFF) {
+                               r1=RBSSO;
+                               r2&=REFMASK;
+                       }
+                       else if (sp->stype==EXTERN+ABS && r2&ROFF) {
+                               r1=RABSO;
+                               r2&=REFMASK;
+                       }
+                       else if (sp->stype==EXTERN+TEXT && r2&ROFF) {
+                               r1=RTEXTO;
+                               r2&=REFMASK;
+                       }
+                       else {if (r2&ROFF) {if (rflag) {error(0,"!-r; see JFR"); rflag=0;}}
+                                else tw += database;
+                                r1=sp->stype&TYPE;
+                                r2&=REFMASK;
+                       }
+                       tw += sp->svalue - database;
                }
                }
-               if (r&01)
-                       t -= creloc;
-               putw(t, b1);
-               if (rflag)
-                       putw(r, b2);
+       } else switch (r1&TYMASK) {
+               case RTEXT:     tw += ctrel; break;
+               case RTEXTO:tw += round(filhdr.a_text,PAGRND)+ctrel-database; break;
+               case RDATA: tw += cdrel; break;
+               case RDATAO:tw += cdorel; break;
+               case RBSS:      tw += cbrel; break;
+               case RBSSO: tw += cborel-filhdr.a_data; break;
+               case RABSO: tw += round(filhdr.a_text,PAGRND)-database; break;
+       }
+       if (rflag) { /* remember for subsequent link editing */
+               put3(r1,b2);
+               putb(r2,b2);
+       }
+       if (r2&PCREL) tw -= creloc; /* assembler already subtracted text.pos */
+       switch (r2&06) {/* output relocated datum according to its length */
+               case LEN1: l= -128; u=127; putc((char)tw,b1); break;
+               case LEN2: l= -32768; u=32767; puts((short)tw,b1); break;
+               case LEN4: l=0x80000000; u=0x7FFFFFFF; putl(tw,b1); break;
+       }
+       if (tw<l || u<tw) error(0,"Displacement overflow");
        }
 }
 
 finishout()
 {
        }
 }
 
 finishout()
 {
-       register n, *p;
-
-       if (nflag||iflag) {
-               n = torigin;
-               while (n&077) {
-                       n += 2;
-                       putw(0, &toutb);
-                       if (rflag)
-                               putw(0, &troutb);
+
+       if (!nflag)
+               while (tsize&FW) {
+                       putc(0, tout); tsize++;
+               }
+       if (zflag) {
+               while (tsize&PAGRND) {
+                       putc(0, tout); tsize++;
+               }
+               while (dsize&PAGRND) {
+                       putc(0, dout); dsize++;
                }
        }
                }
        }
-       copy(&doutb);
+       fclose(dout);
+       copy(doutn);
        if (rflag) {
        if (rflag) {
-               copy(&troutb);
-               copy(&droutb);
+               fclose(trout);
+               copy(troutn);
+               fclose(drout);
+               copy(droutn);
        }
        if (sflag==0) {
        }
        if (sflag==0) {
-               if (xflag==0)
-                       copy(&soutb);
-               for (p = (int *)symtab; p < (int *)&symtab[symindex];)
-                       putw(*p++, &toutb);
+               if (xflag==0) {
+                       fclose(sout);
+                       copy(soutn);
+               }
+               symwrite(symtab, nextsym-symtab, tout);
        }
        }
-       flush(&toutb);
-       close(toutb.fildes);
+       fclose(tout);
        if (!ofilfnd) {
                unlink("a.out");
                link("l.out", "a.out");
        if (!ofilfnd) {
                unlink("a.out");
                link("l.out", "a.out");
@@ -941,21 +1033,17 @@ finishout()
        delexit();
 }
 
        delexit();
 }
 
-copy(buf)
-struct buf *buf;
+copy(np)
+char *np;
 {
 {
-       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);
+       register c;
+       register FILE *fp;
+
+       if ((fp = fopen(np, "r")) == NULL)
+               error(1, "cannot recopy output");
+       while ((c = getc(fp)) != EOF)
+               putc(c, tout);
+       fclose(fp);
 }
 
 mkfsym(s)
 }
 
 mkfsym(s)
@@ -965,65 +1053,78 @@ char *s;
        if (sflag || xflag)
                return;
        cp8c(s, cursym.sname);
        if (sflag || xflag)
                return;
        cp8c(s, cursym.sname);
-       cursym.stype = 037;
+       cursym.stype = TEXT;
        cursym.svalue = torigin;
        cursym.svalue = torigin;
-       mput(&soutb, (int *)&cursym, sizeof cursym);
+       symwrite(&cursym, 1, sout);
 }
 
 }
 
-mget(aloc, an)
-int *aloc;
+mget(loc, n, sp)
+register STREAM *sp;
+register char *loc;
 {
 {
-       register *loc, n;
-       register *p;
-
-       n = an;
-       n >>= 1;
-       loc = aloc;
-       if ((text.nibuf -= n) >= 0) {
-               if ((text.size -= n) > 0) {
-                       p = text.ptr;
+       register char *p;
+
+       if ((sp->nibuf -= n) >= 0) {
+               if ((sp->size -= n) > 0) {
+                       p = sp->ptr;
+                       sp->pos += n;
                        do
                                *loc++ = *p++;
                        while (--n);
                        do
                                *loc++ = *p++;
                        while (--n);
-                       text.ptr = p;
+                       sp->ptr = p;
                        return;
                } else
                        return;
                } else
-                       text.size += n;
+                       sp->size += n;
        }
        }
-       text.nibuf += n;
+       sp->nibuf += n;
        do {
        do {
-               *loc++ = get(&text);
-       } 
-       while (--n);
+               *loc++ = get(sp);
+       } while (--n);
 }
 
 }
 
-mput(buf, aloc, an)
-struct buf *buf; 
-int *aloc;
-{
-       register *loc;
-       register n;
+short
+gets(sp) STREAM *sp; {
+short t; mget(&t,2,sp); return(t);
+}
 
 
-       loc = aloc;
-       n = an>>1;
-       do {
-               putw(*loc++, buf);
-       } 
-       while (--n);
+char
+getb(sp) STREAM *sp; {
+char t; mget(&t,1,sp); return(t);
 }
 
 }
 
-dseek(asp, aloc, s)
-long aloc;
-struct stream *asp;
+long
+get3(sp) STREAM *sp; {
+long t; t=0; mget(&t,3,sp); return(t);
+}
+
+long
+getl(sp) STREAM *sp; {
+       long t; mget(&t,4,sp);
+#ifndef vax
+       fixl(&t);
+#endif
+       return(t);
+}
+
+symget(sp,f) SYMBOL *sp; STREAM *f; {
+       mget(sp,sizeof(*sp),f);
+#ifndef vax
+       fixl(&sp->svalue);
+#endif
+}
+
+dseek(sp, loc, s)
+register STREAM *sp;
+long loc, s;
 {
 {
-       register struct stream *sp;
-       register struct page *p;
-       /* register */ long b, o;
+       register PAGE *p;
+       register b, o;
        int n;
 
        int n;
 
-       b = aloc >> 8;
-       o = aloc & 0377;
-       sp = asp;
+       b = loc>>BSHIFT;
+       o = loc&BMASK;
+       if (o&01)
+               error(1, "loader error; odd offset");
        --sp->pno->nuser;
        if ((p = &page[0])->bno!=b && (p = &page[1])->bno!=b)
                if (p->nuser==0 || (p = &page[0])->nuser==0) {
        --sp->pno->nuser;
        if ((p = &page[0])->bno!=b && (p = &page[1])->bno!=b)
                if (p->nuser==0 || (p = &page[0])->nuser==0) {
@@ -1031,103 +1132,90 @@ struct stream *asp;
                                if (page[0].bno < page[1].bno)
                                        p = &page[0];
                        p->bno = b;
                                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)
+                       lseek(infil, loc & ~(long)BMASK, 0);
+                       if ((n = read(infil, p->buff, sizeof(p->buff))) < 0)
                                n = 0;
                        p->nibuf = n;
        } else
                                n = 0;
                        p->nibuf = n;
        } else
-               error(2, "No pages");
+               error(1, "No pages");
        ++p->nuser;
        sp->bno = b;
        sp->pno = p;
        ++p->nuser;
        sp->bno = b;
        sp->pno = p;
-       sp->ptr = p->buff + o;
-       if (s != -1)
-               sp->size = half(s);
+       if (s != -1) {sp->size = s; sp->pos = 0;}
+       sp->ptr = (short *)(p->buff + o);
        if ((sp->nibuf = p->nibuf-o) <= 0)
                sp->size = 0;
 }
 
        if ((sp->nibuf = p->nibuf-o) <= 0)
                sp->size = 0;
 }
 
-half(i)
-{
-       return((i>>1)&077777);
-}
-
+char
 get(asp)
 get(asp)
-struct stream *asp;
+STREAM *asp;
 {
 {
-       register struct stream *sp;
+       register STREAM *sp;
 
        sp = asp;
 
        sp = asp;
-       if (--sp->nibuf < 0) {
-               dseek(sp, (long)(sp->bno + 1) << 8, -1);
-               --sp->nibuf;
+       if ((sp->nibuf -= sizeof(char)) < 0) {
+               dseek(sp, ((long)(sp->bno+1)<<BSHIFT), (long)-1);
+               sp->nibuf -= sizeof(char);
        }
        }
-       if (--sp->size <= 0) {
+       if ((sp->size -= sizeof(char)) <= 0) {
                if (sp->size < 0)
                if (sp->size < 0)
-                       error(2, premeof);
+                       error(1, premeof);
                ++fpage.nuser;
                --sp->pno->nuser;
                ++fpage.nuser;
                --sp->pno->nuser;
-               sp->pno = (struct page *)&fpage;
+               sp->pno = &fpage;
        }
        }
+       sp->pos += sizeof(char);
        return(*sp->ptr++);
 }
 
 getfile(acp)
        return(*sp->ptr++);
 }
 
 getfile(acp)
-char *acp;
+STRING acp;
 {
 {
-       register char *cp;
+       register STRING cp;
        register int c;
        register int c;
-       struct stat x;
+       int arcmag;
 
        cp = acp; 
        infil = -1;
 
        cp = acp; 
        infil = -1;
-       archdr.aname[0] = '\0';
+       archdr.ar_name[0] = '\0';
        filname = cp;
        if (cp[0]=='-' && cp[1]=='l') {
        filname = cp;
        if (cp[0]=='-' && cp[1]=='l') {
+               char *locfilname = "/usr/local/lib/libxxxxxxxxxxxxxxx";
                if(cp[2] == '\0')
                        cp = "-la";
                filname = "/usr/lib/libxxxxxxxxxxxxxxx";
                if(cp[2] == '\0')
                        cp = "-la";
                filname = "/usr/lib/libxxxxxxxxxxxxxxx";
-               for(c=0; cp[c+2]; c++)
+               for(c=0; cp[c+2]; c++) {
                        filname[c+12] = cp[c+2];
                        filname[c+12] = cp[c+2];
-               filname[c+12] = '.';
-               filname[c+13] = 'a';
-               filname[c+14] = '\0';
+                       locfilname[c+18] = cp[c+2];
+               }
+               filname[c+12] = locfilname[c+18] = '.';
+               filname[c+13] = locfilname[c+19] = 'a';
+               filname[c+14] = locfilname[c+20] = '\0';
                if ((infil = open(filname+4, 0)) >= 0) {
                        filname += 4;
                if ((infil = open(filname+4, 0)) >= 0) {
                        filname += 4;
+               } else if ((infil = open(filname, 0)) < 0) {
+                       filname = locfilname;
                }
        }
        if (infil == -1 && (infil = open(filname, 0)) < 0)
                }
        }
        if (infil == -1 && (infil = open(filname, 0)) < 0)
-               error(2, "cannot open");
+               error(1, "cannot open");
        page[0].bno = page[1].bno = -1;
        page[0].nuser = page[1].nuser = 0;
        page[0].bno = page[1].bno = -1;
        page[0].nuser = page[1].nuser = 0;
-       text.pno = reloc.pno = (struct page *)&fpage;
+       text.pno = reloc.pno = &fpage;
        fpage.nuser = 2;
        fpage.nuser = 2;
-       dseek(&text, 0L, 2);
+       dseek(&text, 0L, (long)sizeof(int));
        if (text.size <= 0)
        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);
-       }
+               error(1, premeof);
+       mget(&arcmag, sizeof(arcmag), &text);
+       return(arcmag==ARMAG);
 }
 
 }
 
-struct symbol **lookup()
+SYMBOL **lookup()
 {
        int i; 
 {
        int i; 
-       int clash;
-       register struct symbol **hp;
+       BOOL clash;
+       register SYMBOL **hp;
        register char *cp, *cp1;
 
        i = 0;
        register char *cp, *cp1;
 
        i = 0;
@@ -1150,7 +1238,7 @@ struct symbol **lookup()
        return(hp);
 }
 
        return(hp);
 }
 
-struct symbol **slookup(s)
+SYMBOL **slookup(s)
 char *s;
 {
        cp8c(s, cursym.sname);
 char *s;
 {
        cp8c(s, cursym.sname);
@@ -1160,17 +1248,21 @@ char *s;
 }
 
 enter(hp)
 }
 
 enter(hp)
-struct symbol **hp;
+register SYMBOL **hp;
 {
 {
-       register struct symbol *sp;
+       register SYMBOL *sp;
 
        if (*hp==0) {
 
        if (*hp==0) {
-               if (symindex>=NSYM)
-                       error(2, "Symbol table overflow");
-               symhash[symindex] = hp;
-               *hp = lastsym = sp = &symtab[symindex++];
+               if ((nextsym-symtab)>=NSYM)
+                       error(1, "Symbol table overflow");
+               if ((nextsym-symtab)>=nsym) {
+                       if (-1==sbrk(NSYM/5 * sizeof(*symtab))) error(1,"Memory overflow");
+                       nsym += NSYM/5;
+               }
+               *hp = lastsym = sp = nextsym++;
                cp8c(cursym.sname, sp->sname);
                sp->stype = cursym.stype;
                cp8c(cursym.sname, sp->sname);
                sp->stype = cursym.stype;
+               sp->symhash = hp-hshtab;
                sp->svalue = cursym.svalue;
                return(1);
        } else {
                sp->svalue = cursym.svalue;
                return(1);
        } else {
@@ -1181,7 +1273,7 @@ struct symbol **hp;
 
 symreloc()
 {
 
 symreloc()
 {
-       switch (cursym.stype) {
+       switch (cursym.stype & 017) {
 
        case TEXT:
        case EXTERN+TEXT:
 
        case TEXT:
        case EXTERN+TEXT:
@@ -1212,46 +1304,55 @@ char *s;
                printf("ld:");
        if (filname) {
                printf("%s", filname);
                printf("ld:");
        if (filname) {
                printf("%s", filname);
-               if (archdr.aname[0])
-                       printf("(%.14s)", archdr.aname);
+               if (archdr.ar_name[0])
+                       printf("(%.14s)", archdr.ar_name);
                printf(": ");
        }
        printf("%s\n", s);
                printf(": ");
        }
        printf("%s\n", s);
-       if (n > 1)
+       if (n)
                delexit();
                delexit();
-       errlev = n;
+       errlev = 2;
 }
 
 }
 
-struct symbol *
-lookloc(alp, r)
-struct local *alp;
+SYMBOL *
+lookloc(lp, r)
+register LOCAL *lp;
 {
 {
-       register struct local *clp, *lp;
+       register LOCAL *clp;
        register sn;
 
        register sn;
 
-       lp = alp;
-       sn = (r>>4) & 07777;
+       sn = r;
        for (clp = local; clp<lp; clp++)
                if (clp->locindex == sn)
                        return(clp->locsymbol);
        for (clp = local; clp<lp; clp++)
                if (clp->locindex == sn)
                        return(clp->locsymbol);
-       error(2, "Local symbol botch");
+       error(1, "Local symbol botch");
 }
 
 readhdr(loc)
 long loc;
 {
 }
 
 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;
+       long *p; int i;
+       dseek(&text, loc, (long)sizeof(filhdr));
+       mget((short *)&filhdr, sizeof(filhdr), &text);
+#ifndef vax
+       for (p= &filhdr,i=8;--i>=0;) fixl(p++);
+#endif
+       if (filhdr.a_magic!=A_MAGIC1 && filhdr.a_magic!=A_MAGIC2 &&
+               filhdr.a_magic!=A_MAGIC3 && filhdr.a_magic!=A_MAGIC4)
+                       error(1,"Bad magic number");
+       if (filhdr.a_text&01 || filhdr.a_data&01) {
+               printf("tsize=%X  dsize=%X\n",filhdr.a_text,filhdr.a_data);
+               error(1, "Text/data size odd");
+       }
+       filhdr.a_bss = round(filhdr.a_bss, FW);
+       if (filhdr.a_magic == NMAGIC) {
+               cdrel = -round(filhdr.a_text, PAGRND);
+               cbrel = cdrel - filhdr.a_data;
+       } else if (filhdr.a_magic == OMAGIC) {
+               cdrel = -filhdr.a_text;
+               cbrel = cdrel - filhdr.a_data;
+       } else
+               error(1, "Bad format");
 }
 
 cp8c(from, to)
 }
 
 cp8c(from, to)
@@ -1268,8 +1369,8 @@ char *from, *to;
 }
 
 eq(s1, s2)
 }
 
 eq(s1, s2)
-char *s1; 
-char *s2;
+STRING s1; 
+STRING s2;
 {
        while (*s1==*s2++)
                if ((*s1++)==0)
 {
        while (*s1==*s2++)
                if ((*s1++)==0)
@@ -1277,22 +1378,35 @@ char *s2;
        return(FALSE);
 }
 
        return(FALSE);
 }
 
-putw(w, b)
-register struct buf *b;
+long
+round(v, r)
+long v;
+unsigned r;
 {
 {
-       *(b->xnext)++ = w;
-       if (--b->nleft <= 0)
-               flush(b);
+       v += r;
+       v &= ~(long)r;
+       return(v);
 }
 
 }
 
-flush(b)
-register struct buf *b;
-{
-       register n;
+puts(w, f)
+FILE *f; short w; {
+fwrite(&w,sizeof(short),1,f);
+}
+
+putb(w, f)
+FILE *f; char w; {
+fwrite(&w,sizeof(char),1,f);
+}
+
+put3(w, f)
+FILE *f; long w; {
+fwrite(&w,3,1,f);
+}
 
 
-       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);
+putl(w, f)
+FILE *f; long w; {
+#ifndef vax
+       fixl(&w);
+#endif
+       fwrite(&w,sizeof(long),1,f);
 }
 }