BSD 4_3_Tahoe development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Tue, 31 May 1988 13:55:07 +0000 (05:55 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Tue, 31 May 1988 13:55:07 +0000 (05:55 -0800)
Work on file usr/src/bin/as/as.tahoe/asparse.c

Synthesized-from: CSRG/cd2/4.3tahoe

usr/src/bin/as/as.tahoe/asparse.c [new file with mode: 0644]

diff --git a/usr/src/bin/as/as.tahoe/asparse.c b/usr/src/bin/as/as.tahoe/asparse.c
new file mode 100644 (file)
index 0000000..193b842
--- /dev/null
@@ -0,0 +1,1215 @@
+/*
+ *     Copyright (c) 1982 Regents of the University of California
+ */
+#ifndef lint
+static char sccsid[] = "$W$ (Berkeley) 5/31/88";
+#endif not lint
+
+#include <stdio.h>
+#include "as.h"
+#include "asscan.h"
+#include "assyms.h"
+#include "asexpr.h"
+
+int    lgensym[10];
+char   genref[10];
+
+long   bitfield;
+int    bitoff;
+int    curlen;                 /* current length of literals */
+int    printblank;
+
+/*
+ *     The following three variables are communication between various
+ *     modules to special case a number of things.  They are properly
+ *     categorized as hacks.
+ */
+extern struct  symtab *lastnam;/*last name seen by the lexical analyzer*/
+int    exprisname;             /*last factor in an expression was a name*/
+int    droppedLP;              /*one is analyzing an expression beginning with*/
+                               /*a left parenthesis, which has already been*/
+                               /*shifted. (Used to parse (<expr>)(rn)*/
+
+char   yytext[NCPName+2];      /*the lexical image*/
+int    yylval;                 /*the lexical value; sloppy typing*/
+u_char yyopcode;               /* lexical value for an opcode */
+Bignum yybignum;               /* lexical value for a big number */
+int    num_type;               /* type of bignums */
+/*
+ *     Expression and argument managers
+ */
+struct exp     *xp;            /*next free expression slot, used by expr.c*/
+struct exp     explist[NEXP];  /*max of 20 expressions in one opcode*/
+struct arg     arglist[NARG];  /*building up operands in instructions*/
+/*
+ *     Sets to accelerate token discrimination
+ */
+char   tokensets[(LASTTOKEN) - (FIRSTTOKEN) + 1];
+
+static char    UDotsname[64];  /*name of the assembly source*/
+
+yyparse()
+{
+       reg     struct  exp     *locxp;
+               /*
+                *      loc1xp and ptrloc1xp are used in the
+                *      expression lookahead
+                */
+               struct  exp     *loc1xp;        /*must be non register*/
+               struct  exp     **ptrloc1xp = & loc1xp;
+               struct  exp     *pval;          /*hacking expr:expr*/
+
+       reg     struct  symtab  *np;
+       reg     int             argcnt;
+
+       reg     inttoktype      val;            /*what yylex gives*/
+       reg     inttoktype      auxval;         /*saves val*/
+
+       reg     struct  arg     *ap;            /*first free argument*/
+
+       reg     struct  symtab  *p;
+       reg     struct  symtab  *stpt;
+
+               struct  strdesc *stringp;       /*handles string lists*/
+
+               int     regno;          /*handles arguments*/
+               int     *ptrregno = &regno;
+               int     sawmul;         /*saw * */
+               int     sawindex;       /*saw [rn]*/
+               int     sawsize;
+               int     seg_type;       /*the kind of segment: data or text*/
+               int     seg_number;     /*the segment number*/
+               int     space_value;    /*how much .space needs*/
+               int     fill_rep;       /*how many reps for .fill */
+               int     rep_fill;       /*the same - temprary */
+               int     fill_size;      /*how many bytes for .fill */
+
+               int     field_width;    /*how wide a field is to be*/
+               int     field_value;    /*the value to stuff in a field*/
+               char    *stabname;      /*name of stab dealing with*/
+               ptrall  stabstart;      /*where the stab starts in the buffer*/
+               int     reloc_how;      /* how to relocate expressions */
+               int     incasetable;    /* set if in a case table */
+               int     j, k;
+               char    ch;
+               int     length;         /* for printout */
+       union twolong
+       {
+               long lpart[2];
+               char strpart [8];
+       }fillval;
+
+
+       incasetable = 0;
+       xp = explist;
+       ap = arglist;
+
+       val = yylex();
+
+    while (val != PARSEEOF){   /* primary loop */
+
+       while (INTOKSET(val, LINSTBEGIN)){
+               if (val == INT) {
+                       int i = ((struct exp *)yylval)->e_xvalue;
+                       shift;
+                       if (val != COLON){
+                               yyerror("Local label %d is not followed by a ':' for a label definition",
+                                       i);
+                               goto  errorfix;
+                       }
+                       if (i < 0 || i > 9) {
+                               yyerror("Local labels are 0-9");
+                               goto errorfix;
+                       }
+                       (void)sprintf(yytext, "L%d\001%d", i, lgensym[i]);
+                       lgensym[i]++;
+                       genref[i] = 0;
+                       yylval = (int)*lookup(passno == 1);
+                       val = NAME;
+                       np = (struct symtab *)yylval;
+                       goto restlab;
+               }
+               if (val == NL){
+                       lineno++;
+                       if (liston && (passno == 2) && (! endofsource)) 
+                       {
+                               /* printing previous line & layout */
+                               length = strlen (layout);
+                               fprintf (listfile, "%*.*s", LHEAD, LHEAD, layout);
+                               if (length <= LHEAD+LLEN)
+                                       j = LLEN;
+                               else {  /* break line at last blank */
+                                       j = LHEAD+LLEN;
+                                       while(j>LHEAD && layout[j]!= ' ')
+                                               j--;
+                                       if(j == LHEAD)
+                                               j = LLEN;
+                                       else
+                                               j -= LHEAD;
+                               }
+                               k = LHEAD+j;
+                               fprintf (listfile, "%-*.*s", LLEN, j, &layout[LHEAD]);
+                               fprintf (listfile, "     ");
+                               do {
+                                       ch = getc (source);
+                                       putc (ch, listfile);
+                               } while (ch != '\n');
+                               while (k < length)
+                               {
+                                       fprintf (listfile, "%*s", LHEAD, "");
+                                       /* break line at last blank */
+                                       if(layout[k] == ' ')
+                                               k++;
+                                       if((j = k+LLEN) >= length)
+                                               j = length;
+                                       else
+                                               while(j>k && layout[j]!= ' ')
+                                                       j--;
+                                       if(j == k)
+                                               j = LLEN;
+                                       else
+                                               j -= k;
+                                       fprintf (listfile, "%-*.*s\n", j, j, &layout[k]);
+                                       k += j;
+                               }
+                               k = 0;
+                               while (layout[k] != '\0')
+                                       layout[k++] = '\0';
+                               ch = getc (source);
+                               if (ch == EOF)
+                               {
+                                       if (ind == ninfiles)
+                                               endofsource = 1;
+                                       else
+                                       {
+                                               source = fopen (innames[ind++], "r");
+                                               lineno = 1;
+                                       }
+                               }
+                               else
+                                       ungetc (ch, source);
+                               layoutpos = layout;
+                               (void)sprintf (layoutpos, "%4ld  ", lineno);
+                               layoutpos += 6;
+                               long_out (dotp->e_xvalue);
+                               if (dotp->e_xvalue >= datbase)
+                                       (void)sprintf (layoutpos," *  ");
+                               else
+                                       (void)sprintf (layoutpos,"    ");
+                               layoutpos += 4;
+                       }
+                       shift;
+               } else
+               if (val == SEMI) 
+                       shift;
+               else {  /*its a name, so we have a label or def */
+                       if (val != NAME){
+                               ERROR("Name expected for a label");
+                       }
+                       np = (struct symtab *)yylval;
+                       shiftover(NAME);
+                       if (val != COLON) {
+                               yyerror("\"%s\" is not followed by a ':' for a label definition",
+                                       FETCHNAME(np));
+                               goto  errorfix;
+                       }
+restlab:
+                       shift;
+                       flushfield(NBPW/4);
+                       if ((np->s_type&XTYPE)!=XUNDEF) {
+                               if(  (np->s_type&XTYPE)!=dotp->e_xtype 
+                                  || np->s_value!=dotp->e_xvalue
+                                  || (  (passno==1)
+                                      &&(np->s_index != dotp->e_xloc)
+                                     )
+                                 ){
+#ifndef DEBUG
+                                       if (FETCHNAME(np)[0] != 'L')
+#endif not DEBUG
+                                       {
+                                               if (passno == 1)
+                                                 yyerror("%s redefined",
+                                                       FETCHNAME(np));
+                                               else
+                                                 yyerror("%s redefined: PHASE ERROR, 1st: %d, 2nd: %d",
+                                                       FETCHNAME(np),
+                                                       np->s_value,
+                                                       dotp->e_xvalue);
+                                       }
+                               }
+                       }
+                       np->s_type &= ~(XTYPE|XFORW);
+                       np->s_type |= dotp->e_xtype;
+                       np->s_value = dotp->e_xvalue;
+                       if (passno == 1){
+                               np->s_index = dotp-usedot;
+                               if (FETCHNAME(np)[0] == 'L'){
+                                       nlabels++;
+                               }
+                               np->s_tag = LABELID;
+                       }
+               }       /*end of this being a label*/
+       }       /*end of to consuming all labels, NLs and SEMIS */ 
+
+       xp = explist;
+       ap = arglist;
+
+       /*
+        *      process the INSTRUCTION body
+        */
+       switch(val){
+
+    default:
+       ERROR("Unrecognized instruction or directive");
+
+   case IABORT:
+       shift;
+       sawabort();
+       /*NOTREACHED*/
+       break;
+
+   case PARSEEOF:
+       tokptr -= sizeof(bytetoktype);
+       *tokptr++ = VOID;
+       tokptr[1] = VOID;
+       tokptr[2] = PARSEEOF;
+       break;
+
+   case IFILE:
+       shift;
+       stringp = (struct strdesc *)yylval;
+       shiftover(STRING);
+       dotsname = &UDotsname[0];
+       movestr(dotsname, stringp->sd_string,
+               min(stringp->sd_strlen, sizeof(UDotsname)));
+       break;
+
+   case ILINENO:
+       shift;          /*over the ILINENO*/
+       expr(locxp, val);
+       lineno = locxp->e_xvalue;
+       break;
+
+   case ISET:  /* .set  <name> , <expr> */
+       shift;
+       np = (struct symtab *)yylval;
+       shiftover(NAME);
+       shiftover(CM);
+       expr(locxp, val);
+       np->s_type &= (XXTRN|XFORW);
+       np->s_type |= locxp->e_xtype&(XTYPE|XFORW);
+       np->s_value = locxp->e_xvalue;
+       if (passno==1)
+               np->s_index = locxp->e_xloc;
+       if ((locxp->e_xtype&XTYPE) == XUNDEF)
+               yyerror("Illegal set?");
+       break;
+
+   case ILSYM:         /*.lsym name , expr */
+       shift;
+       np = (struct symtab *)yylval;
+       shiftover(NAME);
+       shiftover(CM);
+       expr(locxp, val);
+       /*
+        *      Build the unique occurance of the
+        *      symbol.
+        *      The character scanner will have
+        *      already entered it into the symbol
+        *      table, but we should remove it
+        */
+       if (passno == 1){
+               stpt = (struct symtab *)symalloc();
+               stpt->s_name = np->s_name;
+               np->s_tag = OBSOLETE;   /*invalidate original */
+               nforgotten++;
+               np = stpt;
+               if ( (locxp->e_xtype & XTYPE) != XABS)
+                       yyerror("Illegal second argument to lsym");
+               np->s_value = locxp->e_xvalue;
+               np->s_type = XABS;
+               np->s_tag = ILSYM;
+       }
+       break;
+
+   case IGLOBAL:       /*.globl <name> */
+       shift;
+       np = (struct symtab *)yylval;
+       shiftover(NAME);
+       np->s_type |= XXTRN;
+       break;
+
+   case IDATA:         /*.data [ <expr> ] */
+   case ITEXT:         /*.text [ <expr> ] */
+       incasetable = 0;
+       seg_type = -val;
+       shift;
+       if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){
+               expr(locxp, val);
+               seg_type = -seg_type;   /*now, it is positive*/
+       }
+
+       if (seg_type < 0) {     /*there wasn't an associated expr*/
+               seg_number = 0;
+               seg_type = -seg_type;
+       } else {
+               if (   ((locxp->e_xtype & XTYPE) != XABS)       /* tekmdp */
+                   || (seg_number = locxp->e_xvalue) >= NLOC) {
+                       yyerror("illegal location counter");
+                       seg_number = 0;
+               }
+       }
+       if (seg_type == IDATA)
+               seg_number += NLOC;
+       flushfield(NBPW/4);
+       dotp = &usedot[seg_number];
+       if (passno==2) {        /* go salt away in pass 2*/
+               txtfil = usefile[seg_number];
+               relfil = rusefile[seg_number];
+       }
+       break;
+
+       /*
+        *      Storage filler directives:
+        *
+        *      .byte   [<exprlist>]
+        *
+        *      exprlist:  empty | exprlist outexpr
+        *      outexpr:   <expr> | <expr> : <expr>
+        */
+   case IBYTE: curlen = NBPW/4; goto elist;
+   case IWORD: curlen = NBPW/2; goto elist;
+   case IINT:  curlen = NBPW;   goto elist;
+   case ILONG: curlen = NBPW;   goto elist;
+
+   elist:
+       seg_type = val;
+       shift;
+
+       /*
+        *      Expression List processing
+        */
+       if (INTOKSET(val, EBEGOPS+YUKKYEXPRBEG+SAFEEXPRBEG)){
+           do{
+               /*
+                *      expression list consists of a list of :
+                *      <expr>
+                *      <expr> : <expr> 
+                *              (pack expr2 into expr1 bits
+                */
+               expr(locxp, val);
+               /*
+                *      now, pointing at the next token
+                */
+               /* if (val == COLON){ */
+               /*      shiftover(COLON); */
+               /*      expr(pval, val); */
+               /*      if ((locxp->e_xtype & XTYPE) != XABS)  */
+               /*              yyerror("Width not absolute"); */
+               /*      field_width = locxp->e_xvalue; */
+               /*      locxp = pval; */
+               /*      if (bitoff + field_width > curlen) */
+               /*              flushfield(curlen); */
+               /*      if (field_width > curlen) */
+               /*              yyerror("Expression crosses field boundary"); */
+               /* } else { */
+                       field_width = curlen;
+                       if (bitoff == 0)        printblank = 0;
+                       else                    printblank = 1;
+                       flushfield(curlen);
+                       if (liston && (passno == 2) && printblank)
+                               *layoutpos++ = ' ';
+               /* } */
+
+               if ((locxp->e_xtype & XTYPE) != XABS) {
+                       if (bitoff)
+                               yyerror("Illegal relocation in field");
+                       switch(curlen){
+                               case NBPW/4:    reloc_how = TYPB; break;
+                               case NBPW/2:    reloc_how = TYPW; break;
+                               case NBPW:      reloc_how = TYPL; break;
+                       }
+                       if (passno == 1){
+                               dotp->e_xvalue += ty_nbyte[reloc_how];
+                       } else {
+                               outrel(locxp, reloc_how);
+                               if (liston)
+                                       *layoutpos++ = ' ';
+                       }
+               } else {
+                       /*
+                        *      
+                        *      See if we are doing a case instruction.
+                        *      If so, then see if the branch distance,
+                        *      stored as a word,
+                        *      is going to loose sig bits.
+                        */
+                       if (passno == 2 && incasetable){
+                               if (  !(ISWORD(locxp->e_xvalue)))
+                                       yyerror("Case will branch too far");
+                       }
+                       field_value = locxp->e_xvalue & ( (1L << field_width)-1);
+                       bitfield |= field_value << bitoff;
+                       bitoff += field_width;
+               }
+               xp = explist;
+               if (auxval = (val == CM))
+                       shift;
+           } while (auxval);
+       }       /* there existed an expression at all */
+
+       flushfield(curlen);
+       if ( ( curlen == NBPW/4) && bitoff)
+               dotp->e_xvalue ++;
+       break;
+       /*end of case IBYTE, IWORD, ILONG, IINT*/
+
+   case ISPACE:        /* .space <expr> */
+       shift;
+       expr(locxp, val);
+       if ((locxp->e_xtype & XTYPE) != XABS)   /* tekmdp */
+               yyerror("Space size not absolute");
+       if (locxp->e_xvalue < 0)
+               yyerror("Space size not positive");
+       space_value = locxp->e_xvalue;
+  ospace:
+       flushfield(NBPW/4);
+       {
+               static char spacebuf[128];
+               while (space_value > sizeof(spacebuf)){
+                       outs(spacebuf, sizeof(spacebuf));
+                       space_value -= sizeof(spacebuf);
+               }
+               outs(spacebuf, space_value);
+       }
+       if (liston && (passno == 2))
+               (void)sprintf (layoutpos, "****");
+       break;
+
+       /*
+        *      .fill rep, size, value
+        *      repeat rep times: fill size bytes with (truncated) value
+        *      size must be between 1 and 8
+        */
+   case        IFILL:
+       shift;
+       expr(locxp, val);
+       if ( (locxp->e_xtype & XTYPE) != XABS)  /* tekmdp */
+               yyerror("Fill repetition count not absolute");
+       rep_fill = fill_rep = locxp->e_xvalue;
+       shiftover(CM);
+       expr(locxp, val);
+       if ( (locxp->e_xtype & XTYPE) != XABS)  /* tekmdp */
+               yyerror("Fill size not absolute");
+       fill_size = locxp->e_xvalue;
+       if (fill_size <= 0 || fill_size > 8)
+               yyerror("Fill count not in in 1..8");
+       shiftover(CM);
+       expr(locxp, val);
+       if (passno == 2 && (locxp->e_xtype & XTYPE) != XABS)    /* tekmdp */
+               yyerror("Fill value not absolute");
+       flushfield(NBPW/4);
+       dotp->e_xvalue += fill_rep * fill_size;
+       if (passno == 1) {
+               locxp->e_xvalue += fill_rep * fill_size;
+       } else {
+               fillval.lpart[0] = locxp->e_yvalue;
+               fillval.lpart[1] = locxp->e_xvalue;
+               while (fill_rep-- > 0)
+                       bwrite(&(fillval.strpart[8-fill_size]),fill_size,txtfil);
+               if (liston) {
+                  while (rep_fill--  > 0)
+                  {
+                       switch (fill_size)
+                       {
+                               case 1: 
+                                       byte_out (locxp->e_xvalue);
+                                       *layoutpos++ = ' ';
+                                       break;
+                               case 2: 
+                                       word_out (locxp->e_xvalue);
+                                       *layoutpos++ = ' ';
+                                       break;
+                               case 3: 
+                                       byte_out (locxp->e_xvalue >> 16);
+                                       byte_out (locxp->e_xvalue >>  8);
+                                       byte_out (locxp->e_xvalue);
+                                       *layoutpos++ = ' ';
+                                       break;
+                               case 4: 
+                                       long_out (locxp->e_xvalue);
+                                       *layoutpos++ = ' ';
+                                       break;
+                               case 5: 
+                                       byte_out (locxp->e_yvalue);
+                                       long_out (locxp->e_xvalue);
+                                       *layoutpos++ = ' ';
+                                       break;
+                               case 6: 
+                                       word_out (locxp->e_yvalue);
+                                       long_out (locxp->e_xvalue);
+                                       *layoutpos++ = ' ';
+                                       break;
+                               case 7: 
+                                       byte_out (locxp->e_yvalue >> 16);
+                                       byte_out (locxp->e_yvalue >>  8);
+                                       byte_out (locxp->e_yvalue);
+                                       long_out (locxp->e_xvalue);
+                                       *layoutpos++ = ' ';
+                                       break;
+                               case 8: 
+                                       long_out (locxp->e_yvalue);
+                                       long_out (locxp->e_xvalue);
+                                       *layoutpos++ = ' ';
+                                       break;
+                               }
+                           }
+               }
+       }
+       break;
+
+   case IASCII:                /* .ascii [ <stringlist> ] */
+   case IASCIZ:        /* .asciz [ <stringlist> ] */
+       auxval = val;
+       shift;
+       /*
+        *      Code to consume a string list
+        *
+        *      stringlist: empty | STRING | stringlist STRING
+        */
+       while (val == STRING){
+               int     mystrlen;
+               flushfield(NBPW/4);
+               if (bitoff)
+                       dotp->e_xvalue++;
+               stringp = (struct strdesc *)yylval;
+               /*
+                *      utilize the string scanner cheat;
+                *      the scanner appended a null byte on the string,
+                *      but didn't charge it to sd_strlen
+                */
+               mystrlen = stringp->sd_strlen;
+               mystrlen += (auxval == IASCIZ) ? 1 : 0;
+               if (passno == 2){
+                       if (stringp->sd_place & STR_CORE){
+                               outs(stringp->sd_string, mystrlen);
+                               if (liston)
+                               {
+                                       int i;
+                                       for (i = 0;i < mystrlen; i++)
+                                       {
+                                               (void)sprintf (layoutpos, "%02x",
+                                               stringp->sd_string[i]);
+                                               layoutpos += 2;
+                                       }
+                               }
+                       } else {
+                               int     i, nread;
+                               fseek(strfile, stringp->sd_stroff, 0);
+                               for (i = 0; i < mystrlen;/*VOID*/){
+                                       nread = fread(yytext, 1,
+                                               min(mystrlen - i,
+                                                 sizeof(yytext)), strfile);
+                                       outs(yytext, nread);
+                                       if (liston)
+                                       {
+                                               int k;
+                                               for (k = 0;k < nread; k++)
+                                               {
+                                                       (void)sprintf (layoutpos,
+                                                        "%02x", yytext[k]);
+                                                       layoutpos += 2;
+                                               }
+                                       }
+                                       i += nread;
+                               }
+                       }
+               } else {
+                       dotp->e_xvalue += mystrlen;
+               }
+               shift;          /*over the STRING*/
+               if (val == CM)  /*could be a split string*/
+                       shift;
+       }
+       break;
+       
+   case IORG:  /* .org <expr> */
+       shift;
+       expr(locxp, val);
+
+       if ((locxp->e_xtype & XTYPE) == XABS)   /* tekmdp */
+               orgwarn++;
+       else if ((locxp->e_xtype & ~XXTRN) != dotp->e_xtype)
+               yyerror("Illegal expression to set origin");
+       if ((unsigned)locxp->e_xvalue < (unsigned)dotp->e_xvalue)
+       {
+               ERROR("Backwards 'org'");
+       }
+       space_value = locxp->e_xvalue - dotp->e_xvalue;
+       goto ospace;
+       break;
+
+/*
+ *
+ *     Process stabs.  Stabs are created only by the f77
+ *     and the C compiler with the -g flag set.
+ *     We only look at the stab ONCE, during pass 1, and
+ *     virtually remove the stab from the intermediate file
+ *     so it isn't seen during pass2.  This makes for some
+ *     hairy processing to handle labels occuring in
+ *     stab entries, but since most expressions in the
+ *     stab are integral we save lots of time in the second
+ *     pass by not looking at the stabs.
+ *     A stab that is tagged floating will be bumped during
+ *     the jxxx resolution phase.  A stab tagged fixed will
+ *     not be be bumped.
+ *
+ *     .stab:  Old fashioned stabs
+ *     .stabn: For stabs without names
+ *     .stabs: For stabs with string names
+ *     .stabd: For stabs for line numbers or bracketing,
+ *             without a string name, without
+ *             a final expression.  The value of the
+ *             final expression is taken to be  the current
+ *             location counter, and is patched by the 2nd pass
+ *
+ *     .stab{<expr>,}*NCPName,<expr>, <expr>, <expr>, <expr>
+ *     .stabn           <expr>, <expr>, <expr>, <expr>
+ *     .stabs   STRING, <expr>, <expr>, <expr>, <expr>
+ *     .stabd           <expr>, <expr>, <expr> # . 
+ */
+   case ISTAB: 
+       yyerror(".stab directive no longer supported");
+       goto errorfix;
+
+  tailstab:
+       expr(locxp, val);
+       if (! (locxp->e_xvalue & STABTYPS)){
+               yyerror("Invalid type in %s", stabname);
+               goto errorfix;
+       }
+       stpt->s_ptype = locxp->e_xvalue;
+       shiftover(CM);
+       expr(locxp, val);
+       stpt->s_other = locxp->e_xvalue;
+       shiftover(CM);
+       expr(locxp, val);
+       stpt->s_desc = locxp->e_xvalue;
+       shiftover(CM);
+       exprisname = 0;
+       expr(locxp, val);
+       p = locxp->e_xname;
+       if (p == NULL) {        /*absolute expr to begin with*/
+               stpt->s_value = locxp->e_xvalue;
+               stpt->s_index = dotp - usedot;
+               if (exprisname){
+                       stpt->s_type = locxp->e_xtype;
+                       switch(stpt->s_ptype){
+                               case N_LCSYM:
+                                       stpt->s_dest = (struct symtab *)exprisname;
+                                       stpt->s_type |= STABFLAG;
+                               case N_GSYM:
+                               case N_FNAME:
+                               case N_RSYM:
+                               case N_SSYM:
+                               case N_LSYM:
+                               case N_PSYM:
+                               case N_BCOMM:
+                               case N_ECOMM:
+                               case N_LENG:
+                                       stpt->s_tag = STABFIXED;
+                                       break;
+                               default:
+                                       stpt->s_tag = STABFLOATING;
+                                       break;
+                       }
+               } else
+                       stpt->s_tag = STABFIXED;
+       }
+       else {          /*really have a name*/
+               stpt->s_dest = locxp->e_xname;
+               stpt->s_index = p->s_index;
+               stpt->s_type = p->s_type | STABFLAG;
+               /*
+                *      We will assign a more accruate
+                *      guess of locxp's location when
+                *      we sort the symbol table
+                *      The final value of value is
+                *      given by stabfix()
+                */
+/*
+ * For exprs of the form (name + value) one needs to remember locxp->e_xvalue
+ * for use in stabfix. The right place to keep this is in stpt->s_value
+ * however this gets corrupted at an unknown point.
+ * As a bandaid hack the value is preserved in s_desc and s_other (a
+ * short and a char). This destroys these two values and will
+ * be fixed. May 19 ,1983 Alastair Fyfe
+ */
+               if(locxp->e_xvalue) {
+                       stpt->s_other = (locxp->e_xvalue >> 16);
+                       stpt->s_desc =  (locxp->e_xvalue  & 0x0000ffff);
+                       stpt->s_tag = STABFLOATING;
+               }
+       }
+       /*
+        *      tokptr now points at one token beyond
+        *      the current token stored in val and yylval,
+        *      which are the next tokens after the end of
+        *      this .stab directive.  This next token must
+        *      be either a SEMI or NL, so is of width just
+        *      one.  Therefore, to point to the next token
+        *      after the end of this stab, just back up one..
+        */
+       buildskip(stabstart, (bytetoktype *)tokptr - sizeof(bytetoktype));
+       break;  /*end of the .stab*/
+
+   case ISTABDOT:      
+       stabname = ".stabd";
+       stpt = (struct symtab *)yylval;
+       /*
+        *      We clobber everything after the
+        *      .stabd and its pointer... we MUST
+        *      be able to get back to this .stabd
+        *      so that we can resolve its final value
+        */
+       stabstart = tokptr;
+       shift;          /*over the ISTABDOT*/
+       if (passno == 1){
+               expr(locxp, val);
+               if (! (locxp->e_xvalue & STABTYPS)){
+                       yyerror("Invalid type in .stabd");
+                       goto errorfix;
+               }
+               stpt->s_ptype = locxp->e_xvalue;
+               shiftover(CM);
+               expr(locxp, val);
+               stpt->s_other = locxp->e_xvalue;
+               shiftover(CM);
+               expr(locxp, val);
+               stpt->s_desc = locxp->e_xvalue;
+               /*
+                *
+                *      Now, clobber everything but the
+                *      .stabd pseudo and the pointer
+                *      to its symbol table entry
+                *      tokptr points to the next token,
+                *      build the skip up to this
+                */
+               buildskip(stabstart, (bytetoktype *)tokptr - sizeof(bytetoktype));
+       }
+       /*
+        *      pass 1: Assign a good guess for its position
+        *              (ensures they are sorted into right place)/
+        *      pass 2: Fix the actual value
+        */
+       stpt->s_value = dotp->e_xvalue;
+       stpt->s_index = dotp - usedot;
+       stpt->s_tag = STABFLOATING;     /*although it has no effect in pass 2*/
+       break;
+
+   case ISTABNONE:     stabname = ".stabn"; goto shortstab;
+
+   case ISTABSTR:      stabname = ".stabs";
+   shortstab:
+       auxval = val;
+       if (passno == 2) goto errorfix;
+       stpt = (struct symtab *)yylval;
+       stabstart = tokptr;
+       (bytetoktype *)stabstart -= sizeof(struct symtab *);
+       (bytetoktype *)stabstart -= sizeof(bytetoktype);
+       shift;
+       if (auxval == ISTABSTR){
+               stringp = (struct strdesc *)yylval;
+               shiftover(STRING);
+               stpt->s_name = (char *)stringp;
+               /*
+                *      We want the trailing null included in this string.
+                *      We utilize the cheat the string scanner used,
+                *      and merely increment the string length
+                */
+               stringp->sd_strlen += 1;
+               shiftover(CM);
+       } else {
+               stpt->s_name = (char *)savestr("\0", 0, STR_BOTH);
+       }
+       goto tailstab;
+       break;
+
+   case ICOMM:         /* .comm  <name> , <expr> */
+   case ILCOMM:        /* .lcomm <name> , <expr> */
+       auxval = val;
+       shift;
+       np = (struct symtab *)yylval;
+       shiftover(NAME);
+       shiftover(CM);
+       expr(locxp, val);
+
+       if ( (locxp->e_xtype & XTYPE) != XABS)  /* tekmdp */
+               yyerror("comm size not absolute");
+       if (passno == 1 && (np->s_type&XTYPE) != XUNDEF)
+               yyerror("Redefinition of %s", FETCHNAME(np));
+       if (passno==1) {
+               np->s_value = locxp->e_xvalue;
+               if (auxval == ICOMM)
+                       np->s_type |= XXTRN;
+               else {
+                       np->s_type &= ~XTYPE;
+                       np->s_type |= XBSS;
+               }
+       }
+       break;
+
+   case IALIGN:                /* .align <expr> */
+       stpt = (struct symtab *)yylval;
+       shift;
+       expr(locxp, val);
+       if ((dotp->e_xtype & XTYPE) == XDATA)
+               djalign(locxp, stpt);
+       else
+               jalign(locxp, stpt);
+       break;
+
+   case INST0:                 /* instructions w/o arguments*/
+       incasetable = 0;
+       insout(yyopcode, (struct arg *)0, 0);
+       shift;  
+       break;
+
+   case INSTn:         /* instructions with arguments*/
+   case IJXXX:                 /* UNIX style jump instructions */
+       auxval = val;
+       /*
+        *      Code to process an argument list
+        */
+       ap = arglist;
+       xp = explist;   
+
+       shift;          /* bring in the first token for the arg list*/
+
+       for (argcnt = 1; argcnt <= 6; argcnt++, ap++){
+               /*
+                *      code to process an argument proper
+                */
+           sawindex  = sawmul = sawsize = 0;
+           {
+               switch(val) {
+
+                  default:
+                    disp:
+                       if( !(INTOKSET(val,
+                                EBEGOPS
+                               +YUKKYEXPRBEG
+                               +SAFEEXPRBEG)) ) {
+                               ERROR("expression expected");
+                       }
+                       expr(ap->a_xp,val);
+                    overdisp:
+                       if ( val == LP || sawsize){
+                               shiftover(LP);
+                               findreg(regno);
+                               shiftover(RP);
+                               ap->a_atype = ADISP;
+                               ap->a_areg1 = regno;
+                       } else {
+                               ap->a_atype = AEXP;
+                               ap->a_areg1 = 0;
+                       }
+                       goto index;
+
+                  case SIZESPEC: 
+                    sizespec:
+                       sawsize = yylval;
+                       shift;
+                       goto disp;
+
+                  case REG:
+                  case REGOP: 
+                       findreg(regno);
+                       ap->a_atype = AREG;
+                       ap->a_areg1 = regno;
+                       break;
+                   
+                  case MUL: 
+                       sawmul = 1;
+                       shift;
+                       if (val == LP) goto base;
+                       if (val == LITOP) goto imm;
+                       if (val == SIZESPEC) goto sizespec;
+                       if (INTOKSET(val,
+                                EBEGOPS
+                               +YUKKYEXPRBEG
+                               +SAFEEXPRBEG)) goto disp;
+                       ERROR("expression, '(' or '$' expected");
+                       break;
+
+                  case LP: 
+                    base:
+                       shift;  /*consume the LP*/
+                       /*
+                        *      hack the ambiguity of
+                        *      movl (expr) (rn), ...
+                        *      note that (expr) could also
+                        *      be (rn) (by special hole in the
+                        *      grammar), which we ensure
+                        *      means register indirection, instead
+                        *      of an expression with value n
+                        */
+                       if (val != REG && val != REGOP){
+                               droppedLP = 1;
+                               val = exprparse(val, &(ap->a_xp));
+                               droppedLP = 0;
+                               goto overdisp;
+                       }
+                       findreg(regno);
+                       shiftover(RP);
+                       if (val == PLUS){
+                               shift;
+                               ap->a_atype = AINCR;
+                               if (sawmul && regno != 0xE)
+                                       yyerror ("Autoincrement deferred register must be SP");
+                               if (!(sawmul || regno == 0xE))
+                                       yyerror ("Autoincrement register must be SP");
+                       } else
+                               ap->a_atype = ABASE;
+                       ap->a_areg1 = regno;
+                       goto index;
+
+                  case LITOP: 
+                     imm:
+                       shift;
+                       expr(locxp, val);
+                       ap->a_atype = AIMM;
+                       ap->a_areg1 = 0;
+                       ap->a_xp = locxp;
+                       goto index;
+
+                  case MP: 
+                       shift;  /* -(reg) */
+                       findreg(regno);
+                       if (regno != 0xE)
+                               yyerror ("Autodecrement register must be SP");
+                       shiftover(RP);
+                       ap->a_atype = ADECR;
+                       ap->a_areg1 = regno;
+         index:                        /*look for [reg] */
+                       if (val == LB){
+                               shift;
+                               findreg(regno);
+                               shiftover(RB);
+                               sawindex = 1;
+                               ap->a_areg2 = regno;
+                       }
+                       break;
+
+               }       /*end of the switch to process an arg*/
+           }   /*end of processing an argument*/
+
+           if (sawmul){
+                       /*
+                        * Make a concession for *(%r)
+                        * meaning *0(%r) 
+                        */
+                       if (ap->a_atype == ABASE) {
+                               ap->a_atype = ADISP;
+                               xp->e_xtype = XABS;
+                               xp->e_number = Znumber;
+                               xp->e_number.num_tag = TYPL;
+                               xp->e_xloc = 0;
+                               ap->a_xp = xp++;
+                       }
+                       ap->a_atype |= ASTAR;
+                       sawmul = 0;
+           }
+           if (sawindex){
+               ap->a_atype |= AINDX;
+               sawindex = 0;
+           }
+           ap->a_dispsize = sawsize == 0 ? d124 : sawsize;
+               if (val != CM) break;
+               shiftover(CM);
+       }       /*processing all the arguments*/
+
+       if (argcnt > 6){
+               yyerror("More than 6 arguments");
+               goto errorfix;
+       }
+
+       /*
+        *      See if this is a case instruction,
+        *      so we can set up tests on the following
+        *      vector of branch displacements
+        */
+       if (yyopcode == 0xfc)   /* 'casel' instruction */
+               incasetable++;
+       else
+               incasetable = 0;
+
+       insout(yyopcode, arglist,
+               auxval == INSTn ? argcnt : - argcnt);
+       break;
+
+   case IQUAD:         num_type = TYPQ;        goto bignumlist;
+   case IFFLOAT:       num_type = TYPF;        goto bignumlist;
+   case IDFLOAT:       num_type = TYPD;        
+   bignumlist: 
+       /*
+        *      eat a list of non 32 bit numbers.
+        *      IQUAD can, possibly, return
+        *      INT's, if the numbers are "small".
+        *
+        *      The value of the numbers is coming back
+        *      as an expression, NOT in yybignum.
+        */
+       shift;  /* over the opener */
+       if ((val == BIGNUM) || (val == INT)){
+               do{
+                       if ((val != BIGNUM) && (val != INT)){
+                               ERROR(ty_float[num_type]
+                                  ? "floating number expected"
+                                  : "integer number expected" );
+                       }
+                       dotp->e_xvalue += ty_nbyte[num_type];
+                       if (passno == 2){
+                          switch (num_type) {
+                               case TYPF:
+                                       bwrite(((struct exp *)yylval)->e_number.num_num.numFf_float.Ff_ulong,
+                                               ty_nbyte[num_type], txtfil);
+                                       if (liston)
+                                       {
+                                        long_out(((struct exp *)yylval)->e_number.num_num.numFf_float.Ff_ulong[0]);
+                                        *layoutpos++ = ' ';
+                                       }
+                                       break;
+                               case TYPD:
+                                       bwrite(&((struct exp *)yylval)->e_number.num_num.numFd_float.Fd_ulong[0],
+                                               sizeof (long), txtfil);
+                                       bwrite(&((struct exp *)yylval)->e_number.num_num.numFd_float.Fd_ulong[1],
+                                               sizeof (long), txtfil);
+                                       if (liston)
+                                       {
+                                        long_out(((struct exp *)yylval)->e_number.num_num.numIq_int.Iq_ulong[0]);
+                                        long_out(((struct exp *)yylval)->e_number.num_num.numIq_int.Iq_ulong[1]);
+                                        *layoutpos++ = ' ';
+                                       }
+                                       break;
+                               case TYPQ:
+                                       bwrite(&((struct exp *)yylval)->e_number.num_num.numIq_int.Iq_ulong[1],
+                                               sizeof (long), txtfil);
+                                       bwrite(&((struct exp *)yylval)->e_number.num_num.numIq_int.Iq_ulong[0],
+                                               sizeof (long), txtfil);
+                                       if (liston)
+                                       {
+                                        long_out(((struct exp *)yylval)->e_number.num_num.numIq_int.Iq_ulong[1]);
+                                        long_out(((struct exp *)yylval)->e_number.num_num.numIq_int.Iq_ulong[0]);
+                                        *layoutpos++ = ' ';
+                                       }
+                                       break;
+                          }
+                       }
+                       xp = explist;
+                       shift;          /* over this number */
+                       if (auxval = (val == CM))
+                               shift;  /* over the comma */
+               } while (auxval);       /* as long as there are commas */
+       }
+       break;
+       /* end of the case for initialized big numbers */
+    }  /*end of the switch for looking at each reserved word*/
+
+       continue;
+
+   errorfix: 
+       /*
+        *      got here by either requesting to skip to the
+        *      end of this statement, or by erroring out and
+        *      wanting to apply panic mode recovery
+        */
+       while (    (val != NL) 
+               && (val != SEMI) 
+               && (val != PARSEEOF)
+             ){
+               shift;
+       }
+       if (val == NL)
+               lineno++;
+       shift;
+
+    }  /*end of the loop to read the entire file, line by line*/
+
+}      /*end of yyparse*/
+       
+/*
+ *     Process a register declaration of the form
+ *     % <expr>
+ *
+ *     Note:
+ *             The scanner has already processed funny registers of the form
+ *     %dd[+-]*, where dd is a decimal number in the range 00 to 15 (optional
+ *     preceding zero digit).  If there was any space between the % and
+ *     the digit, the scanner wouldn't have recognized it, so we
+ *     hack it out here.
+ */
+inttoktype funnyreg(val, regnoback)    /*what the read head will sit on*/
+       inttoktype      val;            /*what the read head is sitting on*/
+       int     *regnoback;             /*call by return*/
+{
+       reg     struct  exp *locxp;
+               struct  exp *loc1xp;
+               struct  exp **ptrloc1xp = & loc1xp;
+
+       expr(locxp, val);       /*and leave the current read head with value*/
+       if ( (passno == 2) &&
+           (   (locxp->e_xtype & XTYPE) != XABS
+            || (locxp->e_xvalue < 0)
+            || (locxp->e_xvalue >= 16)
+           )
+         ){
+               yyerror("Illegal register");
+               return(0);
+       }
+       *regnoback = locxp->e_xvalue;
+       return(val);
+} 
+/*
+ *     Shift over error
+ */
+shiftoerror(token)
+       int     token;
+{
+       char    *tok_to_name();
+       yyerror("%s expected", tok_to_name(token));
+}
+
+/*VARARGS1*/
+yyerror(s, a1, a2,a3,a4,a5)
+       char    *s;
+{
+
+#define        sink stdout
+
+       if (anyerrs == 0 && anywarnings == 0 && ! silent) 
+               fprintf(sink, "Assembler:\n");
+       anyerrs++;
+       if (silent)
+               return;
+       fprintf(sink, "\"%s\", line %d: ", dotsname, lineno);
+       fprintf(sink, s, a1, a2,a3,a4,a5);
+       fprintf(sink, "\n");
+#undef sink
+}
+
+/*VARARGS1*/
+yywarning(s, a1, a2,a3,a4,a5)
+       char    *s;
+{
+#define        sink stdout
+       if (anyerrs == 0 && anywarnings == 0 && ! silent) 
+               fprintf(sink, "Assembler:\n");
+       anywarnings++;
+       if (silent)
+               return;
+       fprintf(sink, "\"%s\", line %d: WARNING: ", dotsname, lineno);
+       fprintf(sink, s, a1, a2,a3,a4,a5);
+       fprintf(sink, "\n");
+#undef sink
+}