BSD 4 release
[unix-history] / usr / src / cmd / as / assyms.c
index fe26204..c445471 100644 (file)
@@ -1,14 +1,51 @@
-/* Copyright (c) 1979 Regents of the University of California */
+/* Copyright (c) 1980 Regents of the University of California */
+static char sccsid[] = "@(#)assyms.c 4.6 11/5/80";
 #include <stdio.h>
 #include <stdio.h>
+#include <ctype.h>
 #include "as.h"
 #include "as.h"
+#include "asscan.h"
 #include "assyms.h"
 
 #include "assyms.h"
 
-struct allocbox        *allochead;
-struct allocbox        *alloctail;
-struct symtab          *nextsym;
-struct allocbox        *newbox;
-char                   *namebuffer;
-int                    symsleft;
+/*
+ *     Managers for chunks of symbols allocated from calloc()
+ *     We maintain a linked list of such chunks.
+ *
+ */
+struct allocbox        *allochead;     /*head of chunk list*/
+struct allocbox        *alloctail;     /*tail*/
+struct allocbox        *newbox;        /*for creating a new chunk*/
+struct symtab          *nextsym;       /*next symbol free*/
+int                    symsleft;       /*slots left in current chunk*/
+
+struct symtab          **symptrs;
+struct symtab          **symdelim[NLOC + NLOC +1];
+struct symtab          **symptrub;
+/*
+ *     Managers for the dynamically extendable hash table
+ */
+struct hashdallop      *htab;
+
+struct instab          *itab[NINST];   /*maps opcodes to instructions*/
+/*
+ *     Counts what went into the symbol table, so that the
+ *     size of the symbol table can be computed.
+ */
+int    nsyms;          /* total number in the symbol table */
+int    njxxx;          /* number of jxxx entrys */
+int    nforgotten;     /* number of symbols erroneously entered */
+int    nlabels;        /* number of label entries */
+int    hshused;        /* number of hash slots used */
+
+/*
+ *     Managers of the symbol literal storage.
+ *     If we have flexible names, then we allocate BUFSIZ long
+ *     string, and pack strings into that.  Otherwise, we allocate
+ *     symbol storage in fixed hunks NCPS long when we allocate space
+ *     for other symbol attributes.
+ */
+#ifdef FLEXNAMES
+struct strpool         *strplhead = 0;
+#endif FLEXNAMES
 
 symtabinit()
 {
 
 symtabinit()
 {
@@ -16,6 +53,11 @@ symtabinit()
        alloctail = 0;
        nextsym = 0;
        symsleft = 0;
        alloctail = 0;
        nextsym = 0;
        symsleft = 0;
+#ifdef FLEXNAMES
+       strpoolalloc();         /* get the first strpool storage area */
+#endif FLEXNAMES
+       htab = 0;
+       htaballoc();            /* get the first part of the hash table */
 }
 
 /*
 }
 
 /*
@@ -27,18 +69,22 @@ syminstall()
        register        struct  symtab  **hp;
        register        char    *p1, *p2;
 
        register        struct  symtab  **hp;
        register        char    *p1, *p2;
 
-       for (ip=instab; ip->name[0]!=0; ip++) {
-               p1 = ip->name;
+#ifdef FLEXNAMES
+       for (ip = (struct instab *)instab; ip->s_name != 0; ip++) {
+#else not FLEXNAMES
+       for (ip = (struct instab *)instab; ip->s_name[0] != '\0'; ip++){
+#endif not FLEXNAMES
+               p1 = ip->s_name;
                p2 = yytext;
                while (*p2++ = *p1++);
                hp = lookup(0);         /* 0 => don't install this*/
                if (*hp==NULL) {
                        *hp = (struct symtab *)ip;
                p2 = yytext;
                while (*p2++ = *p1++);
                hp = lookup(0);         /* 0 => don't install this*/
                if (*hp==NULL) {
                        *hp = (struct symtab *)ip;
-                       if (   (ip->tag!=INSTn)
-                           && (ip->tag!=INST0)
-                           && (ip->tag!=0))
+                       if (   (ip->s_tag!=INSTn)
+                           && (ip->s_tag!=INST0)
+                           && (ip->s_tag!=0))
                                continue; /* was pseudo-op */
                                continue; /* was pseudo-op */
-                       itab[ip->opcode & 0xFF] = ip;
+                       itab[ip->i_opcode & 0xFF] = ip;
                }
        }
 }      /*end of syminstall*/
                }
        }
 }      /*end of syminstall*/
@@ -49,50 +95,42 @@ syminstall()
  *     and overwrite the index field with its relative position in
  *     the symbol table we give to the loader.
  */
  *     and overwrite the index field with its relative position in
  *     the symbol table we give to the loader.
  */
-extern struct hdr hdr;
+extern struct exec hdr;
 
 freezesymtab()
 {
        register        struct  symtab  *sp;
                                long    bs;
        register        int     relpos = 0;
 
 freezesymtab()
 {
        register        struct  symtab  *sp;
                                long    bs;
        register        int     relpos = 0;
-#ifdef SORTEDOUTPUT
-       register        struct  symtab  **cosp;
-#else
        register        struct  symtab          *ubsp;
        register        struct  allocbox        *allocwalk;
        register        struct  symtab          *ubsp;
        register        struct  allocbox        *allocwalk;
-#endif
 
 
-#ifdef SORTEDOUTPUT
-       SYMITERATE(cosp, sp)
-#else
        DECLITERATE(allocwalk, sp, ubsp)
        DECLITERATE(allocwalk, sp, ubsp)
-#endif
        {
        {
-               if (sp->tag >= IGNOREBOUND)
+               if (sp->s_tag >= IGNOREBOUND)
                        continue;               /*totally ignore jxxx entries */
                /*
                 *      Ignore stabs, but give them a symbol table index
                 */
                        continue;               /*totally ignore jxxx entries */
                /*
                 *      Ignore stabs, but give them a symbol table index
                 */
-               if (sp->type & STABFLAG)
+               if (sp->s_type & STABFLAG)
                        goto assignindex;
                        goto assignindex;
-               if ((sp->type&XTYPE)==XUNDEF)
-                       sp->type = XXTRN+XUNDEF;
-               else if ((sp->type&XTYPE)==XDATA)
-                       sp->value += usedot[sp->index].xvalue;
-               else if ((sp->type&XTYPE)==XTEXT)
-                       sp->value += usedot[sp->index].xvalue;
-               else if ((sp->type&XTYPE)==XBSS) {
-                       bs = sp->value;
-                       sp->value = hdr.bsize + datbase;
-                       hdr.bsize += bs;
+               if ((sp->s_type&XTYPE)==XUNDEF)
+                       sp->s_type = XXTRN+XUNDEF;
+               else if ((sp->s_type&XTYPE)==XDATA)
+                       sp->s_value += usedot[sp->s_index].e_xvalue;
+               else if ((sp->s_type&XTYPE)==XTEXT)
+                       sp->s_value += usedot[sp->s_index].e_xvalue;
+               else if ((sp->s_type&XTYPE)==XBSS) {
+                       bs = sp->s_value;
+                       sp->s_value = hdr.a_bss + datbase;
+                       hdr.a_bss += bs;
                }
           assignindex:
                }
           assignindex:
-               if (    (sp->name[0] != 'L')
-                    || (sp->tag != LABELID)
+               if (    (sp->s_name[0] != 'L')
+                    || (sp->s_tag != LABELID)
                     || savelabels
                     )                  /*then, we will write it later on*/
                     || savelabels
                     )                  /*then, we will write it later on*/
-                               sp->index = relpos++;
+                               sp->s_index = relpos++;
        }
 }
 
        }
 }
 
@@ -110,15 +148,11 @@ stabfix() {
        register struct symtab *p;
        
        SYMITERATE(cosp, sp){
        register struct symtab *p;
        
        SYMITERATE(cosp, sp){
-               if(sp->ptype && (sp->type & STABFLAG)) {        
-                       p = sp->dest;   
-                       sp->value = p->value;   
-                       sp->index = p->index;
-                       sp->type = p->type;
-#ifdef DSTAB
-                       printf("STABFIX: %s (old %s) to %d offsets %d %d\n",
-                               sp->name, p->name, sp->value, sp, p);
-#endif
+               if(sp->s_ptype && (sp->s_type & STABFLAG)) {    
+                       p = sp->s_dest; 
+                       sp->s_value = p->s_value;       
+                       sp->s_index = p->s_index;
+                       sp->s_type = p->s_type;
                }
        }
 }
                }
        }
 }
@@ -135,19 +169,22 @@ char *Calloc(number, size)
        return(newstuff);
 }
 
        return(newstuff);
 }
 
-struct symtab * symalloc()
+char *ClearCalloc(number, size)
+       int     number, size;
 {
 {
-       if (symsleft == 0){
-               register        int     *p;
+       register        char    *newstuff;              /* r11 */
+       register        int     length = number * size; /* r10 */
+       newstuff = Calloc(number, size);
+       asm("movc5 $0, (r0), $0, r10, (r11)");
+       return(newstuff);
+}
 
 
-               newbox = (struct allocbox *)Calloc(1,ALLOCQTY);
+struct symtab *symalloc()
+{
+       if (symsleft == 0){
+               newbox = (struct allocbox *)ClearCalloc(1,ALLOCQTY);
                symsleft = SYMDALLOP;
                nextsym = &newbox->symslots[0];
                symsleft = SYMDALLOP;
                nextsym = &newbox->symslots[0];
-               namebuffer = &newbox->symnames[0];
-               p = (int *)(&newbox->symnames[SYMDALLOP * NCPS]);
-               while ( p > (int *)newbox){
-                       *--p = 0;
-               }
                if (alloctail == 0){
                        allochead = alloctail = newbox;
                } else {
                if (alloctail == 0){
                        allochead = alloctail = newbox;
                } else {
@@ -157,32 +194,42 @@ struct symtab * symalloc()
        }
        --symsleft;
        ++nsyms;
        }
        --symsleft;
        ++nsyms;
-       nextsym->name = namebuffer;
-       namebuffer += NCPS;
        return(nextsym++);
 }
 
        return(nextsym++);
 }
 
-symcmp(pptr, qptr)
-       struct symtab **pptr, **qptr;
+#ifdef FLEXNAMES
+strpoolalloc()
 {
 {
-       register struct symtab *p = *pptr;
-       register struct symtab *q = *qptr;
-       if (p->index < q->index)
+       register        struct  strpool *new;
+
+       new = (struct strpool *)Calloc(1, sizeof (struct strpool));
+       new->str_nalloc = 0;
+       new->str_next = strplhead;
+       strplhead = new;
+}
+#endif FLEXNAMES
+
+symcmp(Pptr, Qptr)
+       struct symtab **Pptr, **Qptr;
+{
+       register struct symtab *p = *Pptr;
+       register struct symtab *q = *Qptr;
+       if (p->s_index < q->s_index)
                return(-1);
                return(-1);
-       if (p->index > q->index)
+       if (p->s_index > q->s_index)
                return(1);
                return(1);
-       if (p->value < q->value)
+       if (p->s_value < q->s_value)
                return(-1);
                return(-1);
-       if (p->value > q->value)
+       if (p->s_value > q->s_value)
                return(1);
        /*
         *      Force jxxx entries to virtually preceed labels defined
         *      to follow the jxxxx instruction, so that bumping the
         *      jxxx instruction correctly fixes up the following labels
         */
                return(1);
        /*
         *      Force jxxx entries to virtually preceed labels defined
         *      to follow the jxxxx instruction, so that bumping the
         *      jxxx instruction correctly fixes up the following labels
         */
-       if (p->tag >= IGNOREBOUND)      /*p points to a jxxx*/
+       if (p->s_tag >= IGNOREBOUND)    /*p points to a jxxx*/
                return(-1);             
                return(-1);             
-       if (q->tag >= IGNOREBOUND)
+       if (q->s_tag >= IGNOREBOUND)
                return(1);
        /*
         *      both are now just plain labels; the relative order doesn't
                return(1);
        /*
         *      both are now just plain labels; the relative order doesn't
@@ -221,9 +268,9 @@ sortsymtab()
        cowalk = symptrs;
        symsin = 0;
        DECLITERATE(allocwalk, sp, ubsp) {
        cowalk = symptrs;
        symsin = 0;
        DECLITERATE(allocwalk, sp, ubsp) {
-               if (sp->ptype && (sp->type &STABFLAG)){
-                       sp->value = sp->dest->value;
-                       sp->index = sp->dest->index;
+               if (sp->s_ptype && (sp->s_type &STABFLAG)){
+                       sp->s_value = sp->s_dest->s_value;
+                       sp->s_index = sp->s_dest->s_index;
                }
                if (symsin >= nsyms)
                        yyerror("INTERNAL ERROR: overfilled symbol table indirection table");
                }
                if (symsin >= nsyms)
                        yyerror("INTERNAL ERROR: overfilled symbol table indirection table");
@@ -239,7 +286,7 @@ sortsymtab()
        for (cowalk = symptrs, sp = *cowalk, segno = 0, slotno = 1;
             segno < NLOC + NLOC;
             segno++, slotno++){
        for (cowalk = symptrs, sp = *cowalk, segno = 0, slotno = 1;
             segno < NLOC + NLOC;
             segno++, slotno++){
-               for (; sp && sp->index == segno; sp = *++cowalk);
+               for (; sp && sp->s_index == segno; sp = *++cowalk);
                symdelim[slotno] = cowalk;      /*forms the ub delimeter*/
        }
 }      /*end of sortsymtab*/
                symdelim[slotno] = cowalk;      /*forms the ub delimeter*/
        }
 }      /*end of sortsymtab*/
@@ -255,10 +302,19 @@ dumpsymtab()
        for (segno = 0; segno < NLOC + NLOC; segno++){
                printf("Segment number: %d\n", segno);
                SEGITERATE(segno, 0, 0, cosp, sp, ub, ++){
        for (segno = 0; segno < NLOC + NLOC; segno++){
                printf("Segment number: %d\n", segno);
                SEGITERATE(segno, 0, 0, cosp, sp, ub, ++){
-                       printf("\tSeg: %d \"%8.8s\" value: %d index: %d tag %s\n",
-                               segno, sp->name, sp->value, sp->index, tagstring(sp->tag));
+#ifdef FLEXNAMES
+                       printf("\tSeg: %d \"%s\" value: %d index: %d tag %s\n",
+                               segno, sp->s_name,
+                               sp->s_value, sp->s_index,
+                               tagstring(sp->s_tag));
+#else not FLEXNAMES
+                       printf("\tSeg: %d \"%*.*s\" value: %d index: %d tag %s\n",
+                               segno, NCPS, NCPS, sp->s_name,
+                               sp->s_value, sp->s_index,
+                               tagstring(sp->s_tag));
+#endif not FLEXNAMES
                        printf("\t\ttype: %d jxbump %d jxfear: %d\n",
                        printf("\t\ttype: %d jxbump %d jxfear: %d\n",
-                               sp->type, sp->jxbump, sp->jxfear);
+                               sp->s_type, sp->s_jxbump, sp->s_jxfear);
                }
                printf("\n\n");
        }
                }
                printf("\n\n");
        }
@@ -288,242 +344,360 @@ char *tagstring(tag)
                                        return(tagbuff);
        }
 }
                                        return(tagbuff);
        }
 }
-#endif
+#endif DEBUG
+
+htaballoc()
+{
+       register        struct  hashdallop      *new;
+       new = (struct hashdallop *)ClearCalloc(1, sizeof (struct hashdallop));
+       if (htab == 0)
+               htab = new;
+       else {          /* add AFTER the 1st slot */
+               new->h_next = htab->h_next;
+               htab->h_next = new;
+       }
+}
 
 
-#define        HASHCLOGGED     (NHASH * 3 ) / 4
+#define        HASHCLOGGED     (NHASH / 2)
 
 
+/*
+ *     Lookup a symbol stored in extern yytext.
+ *     All strings passed in via extern yytext had better have
+ *     a trailing null.  Strings are placed in yytext for hashing by
+ *     syminstall() and by yylex();
+ *
+ *     We take pains to avoid function calls; this functdion
+ *     is called quite frequently, and the calls overhead
+ *     in the vax contributes significantly to the overall
+ *     execution speed of as.
+ */
 struct symtab **lookup(instflg)
        int     instflg;                /* 0: don't install */
 {
 struct symtab **lookup(instflg)
        int     instflg;                /* 0: don't install */
 {
-       register int            ihash;
+       static   int            initialprobe;
        register struct symtab  **hp;
        register struct symtab  **hp;
-       register char           *p1, *p2;
-       register        int     i;
-
-#ifdef METRIC
-       nhashed++;
-#endif
-
-       /*
-        *      All strings passed in in yytext had better have
-        *      a trailing null.  Strings are placed in yytext for
-        *      hashing by syminstall() and yylex()
-        */
-       for (ihash = 0, p1 = yytext ; *p1; ihash <<= 2, ihash += *p1++);
-       ihash += p1[-1] << 5;
-       ihash %= NHASH;
-       if (ihash < 0) ihash += NHASH;
-       hp = &hshtab[ihash];
-       ihash = 1;              /*now, it counts the number of times we rehash*/
-       while (*hp) {
-               p1 = yytext;
-               p2 = (*hp)->name;
-               for (i = 0; (i<NCPS) && *p1; i++)
-                       if (*p1++ != *p2++)
-                               goto no;
-               if (i >= NCPS)          /*both symbols are maximal length*/
-                       return(hp);
-               if (*p2 == 0)   /*assert *p1 == 0*/
-                       return(hp);
-           no:
-#ifdef METRIC
-               nhcollisions++;
-#endif
-               hp += ihash;
-               ihash += 2;
-               if (hp >= &hshtab[NHASH])
-                       hp -= NHASH;
+       register char           *from;
+       register char           *to;
+       register        int     len;
+       register        int     nprobes;
+       static   struct hashdallop *hdallop;
+       static   struct symtab  **emptyslot;
+       static   struct hashdallop *emptyhd;
+       static   struct symtab  **hp_ub;
+
+       emptyslot = 0;
+       for (nprobes = 0, from = yytext;
+            *from;
+            nprobes <<= 2, nprobes += *from++)
+               continue;
+       nprobes += from[-1] << 5;
+       nprobes %= NHASH;
+       if (nprobes < 0)
+               nprobes += NHASH;
+
+       initialprobe = nprobes;
+       for (hdallop = htab; hdallop != 0; hdallop = hdallop->h_next){
+               for (hp = &(hdallop->h_htab[initialprobe]),
+                               nprobes = 1,
+                               hp_ub = &(hdallop->h_htab[NHASH]);
+                    (*hp) && (nprobes < NHASH);
+                               hp += nprobes,
+                               hp -= (hp >= hp_ub) ? NHASH:0,
+                               nprobes += 2)
+               {
+                       from = yytext;
+                       to = (*hp)->s_name;
+#ifndef FLEXNAMES
+                       for (len = 0; (len<NCPS) && *from; len++)
+                               if (*from++ != *to++)
+                                       goto nextprobe;
+                       if (len >= NCPS)        /*both are maximal length*/
+                               return(hp);
+                       if (*to == 0)           /*assert *from == 0*/
+                               return(hp);
+#else FLEXNAMES
+                       while (*from && *to)
+                               if (*from++ != *to++)
+                                       goto nextprobe;
+                       if (*to == *from)       /*assert both are == 0*/
+                               return(hp);
+#endif FLEXNAMES
+
+       nextprobe: ;
+               }
+               if (*hp == 0 && emptyslot == 0 &&
+                   hdallop->h_nused < HASHCLOGGED) {
+                       emptyslot = hp;
+                       emptyhd = hdallop;
+               }
        }
        }
-       if(++hshused >= HASHCLOGGED) {
-               yyerror("Symbol table overflow");
-               delexit();
+       if (emptyslot == 0) {
+               htaballoc();
+               hdallop = htab->h_next;         /* aren't we smart! */
+               hp = &hdallop->h_htab[initialprobe];
+       } else {
+               hdallop = emptyhd;
+               hp = emptyslot;
        }
        if (instflg) {
        }
        if (instflg) {
-#ifdef METRIC
-               nentered++;
-#endif
                *hp = symalloc();
                *hp = symalloc();
-               p1 = yytext;
-               p2 = (*hp)->name;
-               while (*p2++ = *p1++);
+               hdallop->h_nused++;
+#ifndef FLEXNAMES
+               for(len = 0, from = yytext, to = (*hp)->s_name; (len<NCPS); len++)
+                       if ((*to++ = *from++) == '\0')
+                               break;
+#else FLEXNAMES
+               for (from = yytext, len = 1; *from++; len++)
+                       continue;
+               if (len >= (STRPOOLDALLOP - strplhead->str_nalloc))
+                       strpoolalloc();
+               for ( (*hp)->s_name = to = strplhead->str_names + strplhead->str_nalloc, from = yytext;
+                    ( (*to++ = *from++) != '\0'); )
+                       continue;
+               strplhead->str_nalloc += len;
+#endif FLEXNAMES
        }
        return(hp);
        }
        return(hp);
-}      /*end of symlook*/
-
-#ifdef vax
-#define writel(p,n,f) fwrite((long)p, sizeof (long), n, f)
-#else
-writel(p,n,f)
-       long *p;
-       FILE *f;
+}      /*end of lookup*/
+
+#ifdef FLEXNAMES
+char *savestr(str)
+       char *str;
 {
 {
-       while (n--) {
-               fwrite(&(*p).loword,2,1,f);
-               fwrite(&(*p).hiword,2,1,f);
-               p++;
-       }
+       register int len;
+       register char *from, *to;
+       char *res;
+
+       for (from = str, len = 1; *from++; len++)
+               continue;
+       if (len >= (STRPOOLDALLOP - strplhead->str_nalloc))
+               strpoolalloc();
+       for ( res = to = strplhead->str_names + strplhead->str_nalloc, from = str;
+                    ( (*to++ = *from++) != '\0'); )
+                       continue;
+       strplhead->str_nalloc += len;
+       return (res);
 }
 }
-#endif
-
-int reflen[] = {0,0,1,1,2,2,4,4,8,8};
+#endif FLEXNAMES
 
 /*
 
 /*
- *     Save the relocation information
+ *     The relocation information is saved internally in an array of
+ *     lists of relocation buffers.  The relocation buffers are
+ *     exactly the same size as a token buffer; if we use VM for the
+ *     temporary file we reclaim this storage, otherwise we create
+ *     them by mallocing.
  */
  */
-outrel(pval,reftype,reltype,xsym)
-       long            *pval;
-       register int    reftype,reltype;
-       struct symtab   *xsym;
+#define        RELBUFLG        TOKBUFLG
+#define        NRELOC          ((TOKBUFLG - \
+                         (sizeof (int) + sizeof (struct relbufdesc *)) \
+                       ) / (sizeof (struct relocation_info)))
+
+struct relbufdesc{
+       int     rel_count;
+       struct  relbufdesc      *rel_next;
+       struct  relocation_info rel_reloc[NRELOC];
+};
+extern struct  relbufdesc      *tok_free;
+#define        rel_free tok_free
+static struct  relbufdesc      *rel_temp;
+struct relocation_info r_can_1PC;
+struct relocation_info r_can_0PC;
+
+initoutrel()
 {
 {
+       r_can_0PC.r_address = 0;
+       r_can_0PC.r_symbolnum = 0;
+       r_can_0PC.r_pcrel = 0;
+       r_can_0PC.r_length = 0;
+       r_can_0PC.r_extern = 0;
+
+       r_can_1PC = r_can_0PC;
+       r_can_1PC.r_pcrel = 1;
+}
 
 
-/*
- *     reftype: PCREL or not, plus length LEN1, LEN2, LEN4, LEN8
- *     reltype: csect ("segment") number (XTEXT, XDATA, ...) associated with 'val'
- *     xsym: symbol table pointer
- */
-       long ts;
-       char tc;
-       long tl;
-       short t;
-       if (passno!=2) {
-               dotp->xvalue += reflen[reftype];
-               return;
-       }
+outrel(xp, reloc_how)
+       register        struct  exp     *xp;
+       int             reloc_how;      /* TYPB..TYPD + (possibly)RELOC_PCREL */
+{
+       struct          relocation_info reloc;
+       register        int     x_type_mask;    
+       int             pcrel;
+
+       x_type_mask = xp->e_xtype & ~XFORW;
+       pcrel = reloc_how & RELOC_PCREL;
+       reloc_how &= ~RELOC_PCREL;
+       
        if (bitoff&07)
                yyerror("Padding error");
        if (bitoff&07)
                yyerror("Padding error");
-       reltype &= ~XFORW;
-       if (reltype == XUNDEF)
+       if (x_type_mask == XUNDEF)
                yyerror("Undefined reference");
                yyerror("Undefined reference");
-       if (reltype != XABS || reftype & PCREL) {
-               /* write the address portion of a relocation datum */
-               if (dotp >= &usedot[NLOC]) {
-                       hdr.drsize += sizeof(dotp->xvalue) + 3 + sizeof tc;
-                       tl = dotp->xvalue-datbase;
-                       writel(&tl,1,relfil);
-               } else {
-                       hdr.trsize += sizeof(dotp->xvalue) + 3 + sizeof tc;
-                       writel(&dotp->xvalue,1,relfil);
+
+       if ( (x_type_mask != XABS) || pcrel ) {
+               if (ty_NORELOC[reloc_how])
+                       yyerror("Illegal Relocation of float, double or quad.");
+               reloc = pcrel ? r_can_1PC : r_can_0PC;
+               reloc.r_address = dotp->e_xvalue -
+                   ( (dotp < &usedot[NLOC] || readonlydata) ? 0 : datbase );
+               reloc.r_length = ty_nlg[reloc_how];
+               switch(x_type_mask){
+                       case XXTRN | XUNDEF:
+                               reloc.r_symbolnum = xp->e_xname->s_index;
+                               reloc.r_extern = 1;
+                               break;
+                       default:
+                               if (readonlydata && (x_type_mask&~XXTRN) == XDATA)
+                                       x_type_mask = XTEXT | (x_type_mask&XXTRN);
+                               reloc.r_symbolnum = x_type_mask;
+                               break;
                }
                }
-               /* write the properties portion of a relocation datum */
-               if (reltype == XXTRN+XUNDEF) {
-                       ts = (xsym->index);
-                       tc = (XXTRN<<3) | (reftype-LEN1);
-               } else if ((reltype&XTYPE) == XUNDEFO) {
-                       ts = (xsym->index);
-                       tc = ((XXTRN+2)<<3) | (reftype-LEN1);
-               } else  {
-                       ts = (reltype);
-                       tc = (reftype-LEN1);
+               if ( (relfil == 0) || (relfil->rel_count >= NRELOC) ){
+                       if (rel_free){
+                               rel_temp = rel_free;
+                               rel_free = rel_temp->rel_next;
+                       } else {
+                               rel_temp = (struct relbufdesc *)
+                                       Calloc(1,sizeof (struct relbufdesc));
+                       }
+                       rel_temp->rel_count = 0;
+                       rel_temp->rel_next = relfil;
+                       relfil = rusefile[dotp - &usedot[0]] = rel_temp;
                }
                }
-               fwrite((char *)&ts, 3, 1, relfil);
-               fwrite(&tc, sizeof(tc), 1, relfil);
+               relfil->rel_reloc[relfil->rel_count++] = reloc;
        }
        }
-       /* write the raw ("unrelocated") value to the text file */
-       t = reflen[reftype];
-       dotp->xvalue += t;
-       if (reftype & PCREL)
-               *pval -= dotp->xvalue;
-#ifdef vax
-       fwrite(pval,1,t,txtfil);
-#else
-       if (t>2) {
-               fwrite(&((*pval).loword),1,2,txtfil);
-               fwrite(&((*pval).hiword),1,t-2,txtfil);
-       } else fwrite(&((*pval).loword),1,t,txtfil);
-#endif
+       /*
+        *      write the unrelocated value to the text file
+        */
+       dotp->e_xvalue += ty_nbyte[reloc_how];
+       if (pcrel)
+               xp->e_xvalue -= dotp->e_xvalue;
+       bwrite((char *)&(xp->e_xvalue), ty_nbyte[reloc_how], txtfil);
 }
 }
-
-
 /*
 /*
- *     Write out n symbols to file f, beginning at p
- *     ignoring symbols that are obsolete, jxxx instructions, and
- *     possibly, labels
+ *     Flush out all of the relocation information.
+ *     Note that the individual lists of buffers are in
+ *     reverse order, so we must reverse them
  */
  */
+off_t closeoutrel(relocfile)
+       BFILE   *relocfile;
+{
+       int     locindex;
+       u_long  Closeoutrel();
 
 
-int sizesymtab()
+       trsize = 0;
+       for (locindex = 0; locindex < NLOC; locindex++){
+               trsize += Closeoutrel(rusefile[locindex], relocfile);
+       }
+       drsize = 0;
+       for (locindex = 0; locindex < NLOC; locindex++){
+               drsize += Closeoutrel(rusefile[NLOC + locindex], relocfile);
+       }
+       return(trsize + drsize);
+}
+
+u_long Closeoutrel(relfil, relocfile)
+       struct  relbufdesc      *relfil;
+       BFILE   *relocfile;
 {
 {
-       struct symtab *sp;
+       u_long  tail;
+       if (relfil == 0)
+               return(0L);
+       tail = Closeoutrel(relfil->rel_next, relocfile);
+       bwrite((char *)&relfil->rel_reloc[0],
+               relfil->rel_count * sizeof (struct relocation_info),
+               relocfile);
+       return(tail + relfil->rel_count * sizeof (struct relocation_info));
+}
 
 #define NOUTSYMS (nsyms - njxxx - nforgotten - (savelabels ? 0 : nlabels))
 
 #define NOUTSYMS (nsyms - njxxx - nforgotten - (savelabels ? 0 : nlabels))
-
-       return (
-               (  NCPS
-                + sizeof (sp->ptype)
-                + sizeof (sp->other)
-                + sizeof (sp->desc)
-                + sizeof (sp->value)
-               ) 
-               *       NOUTSYMS
-       );
+int sizesymtab()
+{
+       return (sizeof (struct nlist) * NOUTSYMS);
 }
 
 }
 
-symwrite(f)
-       FILE *f;
+#ifdef FLEXNAMES
+/*
+ *     We write out the flexible length character strings for  names
+ *     in two stages.
+ *     1)      We have always! maintain a fixed sized name list entry;
+ *     the string is indexed by a four byte quantity from the beginning
+ *     of the string pool area.  Index 0 is reserved, and indicates
+ *     that there is no associated string. The first valid index is 4.
+ *     2)       We concatenate together and write all of the strings
+ *     in the string pool at the end of the name list. The first 
+ *     four bytes in the string pool are indexed only by 0 (see above);
+ *     they contain the total number of bytes in the string pool.
+ */
+#endif FLEXNAMES
+
+/*
+ *     Write out n symbols to file f, beginning at p
+ *     ignoring symbols that are obsolete, jxxx instructions, and
+ *     possibly, labels
+ */
+
+int symwrite(symfile)
+       BFILE *symfile;
 {
        int     symsout;                        /*those actually written*/
        int     symsdesired = NOUTSYMS;
        register        struct  symtab *sp, *ub;
 {
        int     symsout;                        /*those actually written*/
        int     symsdesired = NOUTSYMS;
        register        struct  symtab *sp, *ub;
-#ifdef SORTEDOUTPUT
-       int     segno;
-       register        struct  symtab          **copointer;
-#else
+#ifdef FLEXNAMES
+       char            *name;                  /* temp to save the name */
+       long            stroff  = sizeof (stroff);
+       /*
+        *      We use sp->s_index to hold the length of the
+        *      name; it isn't used for anything else
+        */
+#endif FLEXNAMES
+
        register        struct  allocbox        *allocwalk;
        register        struct  allocbox        *allocwalk;
-#endif
 
 
-#ifdef SORTEDOUTPUT
-       for (segno = 0, symsout = 0; segno < NLOC + NLOC; segno++)
-               SEGITERATE(segno, 0, 0, copointer, sp, ub, ++)
-#else
        symsout = 0;
        DECLITERATE(allocwalk, sp, ub)
        symsout = 0;
        DECLITERATE(allocwalk, sp, ub)
-#endif
        {
        {
-               if (sp->tag >= IGNOREBOUND) 
+               if (sp->s_tag >= IGNOREBOUND) 
                        continue;
                        continue;
-               if ((sp->name[0] == 'L') && (sp->tag == LABELID) && !savelabels)
+               if ((sp->s_name[0] == 'L') && (sp->s_tag == LABELID) && !savelabels)
                        continue;
                symsout++;
                        continue;
                symsout++;
-               fwrite(sp->name, NCPS, 1, f);
-               sp->type &= ~XFORW;
-               fwrite((sp->ptype) ? (char *)(&(sp->ptype)) : (char *)(&(sp->type)),
-                       sizeof(char), 1, f);
-       /*
-        *      WATCH OUT.  THIS DEPENDS THAT THE ALLOCATION OF
-        *      the four fields ptype, other, desc and value are
-        *      contiguous.  This may have to be changed!
-        *      This is safe (as of 2-Nov-79).
-        */
-               fwrite(&(sp->other),
-                       sizeof (sp->other)
-                      + sizeof (sp->desc)
-                      + sizeof (sp->value), 1, f
-               );
-#ifdef fooie
-#ifdef vax
-               fwrite(&(sp->name[0]), sizeof(symtab[0].name), 1, f);
-               fwrite(sp->ptype ? &(sp->ptype) : &(sp->type),
-                       sizeof(symtab[0].type), 1, f);
-               fwrite(&(sp->other), sizeof(symtab[0].other), 1, f);
-               fwrite(&(sp->desc), sizeof(symtab[0].desc), 1, f);
-               fwrite(&(sp->value), sizeof(symtab[0].value), 1, f);
-#else
-               writel(&(p->value), 1, f);
-#endif
+
+#ifdef FLEXNAMES
+               name = sp->s_name;              /* save pointer */
+               if ( (sp->s_index = strlen(sp->s_name)) != 0){
+                       sp->s_nmx = stroff;     /* clobber pointer */
+                       stroff += sp->s_index + 1;
+               } else {
+                       sp->s_nmx = 0;          /* clobber pointer */
+               }
 #endif
 #endif
+               sp->s_type = (sp->s_ptype != 0) ? sp->s_ptype : (sp->s_type & (~XFORW));
+               if (readonlydata && (sp->s_type&~N_EXT) == N_DATA)
+                       sp->s_type = N_TEXT | (sp->s_type & N_EXT);
+               bwrite(&sp->s_nm, sizeof (struct nlist), symfile);
+#ifdef FLEXNAMES
+               sp->s_name = name;              /* restore pointer */
+#endif FLEXNAMES
        }
        if (symsout != symsdesired)
                yyerror("INTERNAL ERROR: Wrote %d symbols, wanted to write %d symbols\n",
                        symsout, symsdesired);
        }
        if (symsout != symsdesired)
                yyerror("INTERNAL ERROR: Wrote %d symbols, wanted to write %d symbols\n",
                        symsout, symsdesired);
-}
-
-Flushfield(n)
-       register int n;
-{
-       while (n>0) {
-               outb(bitfield);
-               bitfield >>= 8;
-               n -= 8;
+#ifdef FLEXNAMES
+       /*
+        *      Pass 2 through the string pool
+        */
+       symsout = 0;
+       bwrite(&stroff, sizeof (stroff), symfile);
+       stroff = sizeof (stroff);
+       symsout = 0;
+       DECLITERATE(allocwalk, sp, ub)
+       {
+               if (sp->s_tag >= IGNOREBOUND) 
+                       continue;
+               if ((sp->s_name[0] == 'L') && (sp->s_tag == LABELID) && !savelabels)
+                       continue;
+               sp->s_index = strlen(sp->s_name);
+               if (sp->s_index)
+                       bwrite(sp->s_name, sp->s_index + 1, symfile);
        }
        }
-       bitoff=0;
-       bitfield=0;
+#endif FLEXNAMES
 }
 }