/***********************************************************************
*
* asmpass1 - Pass 1 for the IBM 7090 assembler.
*
* Changes:
*   05/21/03   DGP   Original.
*   08/20/03   DGP   Changed to call the SLR(1) parser.
*   12/20/04   DGP   Add MAP functions and 2.0 additions.
*   02/02/05   DGP   Correct VFD processing.
*   02/09/05   DGP   Added FAP support.
*   03/03/05   DGP   Fixed bugs in FAP EQU processing.
*   03/09/05   DGP   Fixed BCD and BCI processing.
*   03/11/05   DGP   Fixed chained IF[FT] statements.
*   03/15/05   DGP   Fixed "LOC  blank" in FAP mode.
*	
***********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

#include "asmdef.h"


extern int pc;			/* the assembler pc */
extern int symbolcount;		/* Number of symbols in symbol table */
extern int absolute;		/* In absolute section */
extern int radix;		/* Number scanner radix */
extern int linenum;		/* Source line number */
extern int exprtype;		/* Expression type */
extern int p1errcnt;		/* Number of pass 0/1 errors */
extern int pgmlength;		/* Length of program */
extern int absmod;		/* In absolute module */
extern int termparn;		/* Parenthesis are terminals (NO()) */
extern int genxref;		/* Generate cross reference listing */
extern int addext;		/* Add extern for undef'd symbols (!absolute) */
extern int addrel;		/* ADDREL mode */
extern int qualindex;		/* QUALifier table index */
extern int begincount;		/* Number of BEGINs */
extern int litorigin;		/* Literal pool origin */
extern int litpool;		/* Literal pool size */
extern int fapmode;		/* FAP assembly mode */
extern int headcount;		/* Number of entries in headtable */
extern int inpass;		/* Which pass are we in */

extern char inbuf[MAXLINE];	/* The input buffer for the scanners */
extern char deckname[MAXSYMLEN+2];/* The assembly deckname */
extern char lbl[MAXLBLLEN+2];	/* The object label */
extern char ttlbuf[TTLSIZE+2];	/* The assembly TTL buffer */
extern char qualtable[MAXQUALS][MAXSYMLEN+2]; /* The QUALifier table */
extern char headtable[MAXHEADS];/* HEAD table */

extern SymNode *addextsym;	/* Added symbol for externals */
extern SymNode *symbols[MAXSYMBOLS];/* The Symbol table */
extern ErrTable p1error[MAXERRORS];/* The pass 0/1 error table */
extern BeginTable begintable[MAXBEGINS];/* The USE/BEGIN table */


static int curruse;		/* Current USE index */
static int prevuse;		/* Previous USE index */
static int chksyms;		/* Check symbols in this pass */
static int inmode;		/* Source line input mode */
static int asmskip;		/* In skip line mode IFF/IFT */
static int gotoskip;		/* In GOTO mode */
static int gotoblank;		/* BLANK option on GOTO */
static int ifcont;		/* IFF/IFT continued */
static int ifrel;		/* IFF/IFT continue relation OR/AND */
static int ifskip;		/* IFF/IFT prior skip result */
static int commonctr;		/* Common counter */
static int prevloc;		/* Previous LOC pc value */
static int locorg;		/* Origin of current LOC */

static char cursym[MAXSYMLEN+2];/* Current label field symbol */
static char gotosym[MAXSYMLEN+2];/* GOTO target symbol */
static char errtmp[256];	/* Error print string */

/***********************************************************************
* chkerror - Check to see if the Pass 1 error has been recorded.
***********************************************************************/

int
chkerror (int line)
{
   int i;

   for (i = 0; i < p1errcnt; i++)
      if (p1error[i].errorline == line)
         return (TRUE);
   return (FALSE);
}

/***********************************************************************
* p1allop - Operation processors (all we do here is advance the pc).
***********************************************************************/

static void
p1allop (OpCode *op, char *bp)
{
   int relocatable;
   int val;
   char term;

   while (*bp && isspace(*bp)) bp++;
   if (*bp == LITERALSYM)
   {
      bp = exprscan (bp, &val, &term, &relocatable, 1, chksyms, 0);
   }
   pc++;
}

/***********************************************************************
* p1diskop - Disk I/O processors (all we do here is advance the pc).
***********************************************************************/

static void
p1diskop (OpCode *op, char *bp)
{
   pc+=2;
}

/***********************************************************************
* opdadd - Process OPD/OPVFD op adds
***********************************************************************/

static void
opdadd (char *opcode, unsigned op0, unsigned op1)
{
   int newtype;
   unsigned newop, newmode;

   newop = 0;
   newmode = 0;
   newtype = 0;

   if (fapmode)
   {
	 if (op0 & 0300000) newtype = TYPE_A;
	 else if (op0 & 0000060) newtype = TYPE_B;
	 else if (op0 & 0000001) newtype = TYPE_E;
	 else if (op1 & 0000001) newtype = TYPE_D;
	 else if (op1 & 0000002) newtype = TYPE_C;

	 newop = (op0 & 0777700) >> 6;
	 if (op0 & 0000001) newmode = op1 & 0017777;
   }
   else switch ((op0 & 0770000) >> 12)
   {
      case 040: 		/* Type A */
      case 042: 		/* Type A */

	 newtype = TYPE_A;
	 newop = op1 & 0007777;
	 break;

      case 043: 		/* Type B */

	 newtype = TYPE_B;
	 newop = op1 & 0007777;
	 break;

      case 044: 		/* Type C */

	 newtype = TYPE_C;
	 newop = op1 & 0007777;
	 break;

      case 045: 		/* Type D */

	 newtype = TYPE_D;
	 newop = op1 & 0007777;
	 break;

      case 046: 		/* Type E */

	 newtype = TYPE_E;
	 if ((op1 & 0700000) == 0100000)
	    newop = 04760;
	 else
	    newop = 00760;
	 newmode = op1 & 0077777;
	 break;

      default: 

	 logerror ("Unsupported opcode addition");
	 return;
   }

   /*
   ** Add new opcode, if all OK
   */

   opadd (opcode, newop, newmode, newtype);
}

/***********************************************************************
* processliterals - Process literals.
***********************************************************************/

static void
processliterals ()
{
   int i;
   int literalcount = 0;
   int escapecount = 0;

   /*
   ** Get number of literals in symbol table
   */

   for (i = 0; i < symbolcount; i++)
   {
      if (symbols[i]->symbol[0] == LITERALSYM) literalcount++;
   }
   escapecount = literalcount * 2; /* just in case pc is out of wack */

   /*
   ** process found literals
   */

   while (literalcount)
   {
      if (--escapecount == 0) break;
      for (i = 0; i < symbolcount; i++)
      {
	 if (symbols[i]->symbol[0] == LITERALSYM)
	 {
	    SymNode *s;

#ifdef DEBUGLIT
	    printf ("p1-processliterals: pc = %o\n", pc);
#endif
	    s = symbols[i];
	    symdelete (s);
	    pc++;
	    literalcount--;
         }
      }
   }
}

/***********************************************************************
* p1lookup - lookup cursym in current context.
***********************************************************************/

static SymNode *
p1lookup (void)
{
   SymNode *s;
   char temp[32];

   s = NULL;
   if (fapmode)
   {
      if (strlen(cursym) == MAXSYMLEN)
      {
	 temp[0] = cursym[0];
	 temp[1] = '\0';
	 s = symlookup (&cursym[1], temp, FALSE, FALSE);
      }
      else if (headcount)
      {
	 sprintf (temp, "%c", headtable[0]);
	 s = symlookup (cursym, temp, FALSE, FALSE);
      }
      if (!s)
      {
	 s = symlookup (cursym, "", FALSE, FALSE);
      }
   }
   else
   {
      s = symlookup (cursym, qualtable[qualindex], FALSE, FALSE);
   }
   return (s);
}

/***********************************************************************
* p1pop - Process Pseudo operation codes. Most ops just advance the pc.
* Most errors are ignored here and reported in pass 2.
***********************************************************************/

static int
p1pop (OpCode *op, char *bp)
{
   SymNode *s;
   OpCode *addop;
   char *token;
   char *cp;
   int tokentype;
   int relocatable;
   int val;
   int i, j;
   int boolrl;
   int boolr;
   int bitcount;
   int tmpnum0;
   int tmpnum1;
   char term;

   switch (op->opvalue)
   {

   case BCD_T:			/* BCD */
      while (*bp && isspace (*bp)) bp++;
      if (isdigit (*bp))
      {
         val = *bp++ - '0';
	 pc += val;
      }
      else
      {
         pc += 10;
      }
      break;

   case BCI_T:			/* BCI */
      while (*bp && isspace (*bp)) bp++;
      if (*bp == ',')
	 val = 10;
      else
	 bp = tokscan (bp, &token, &tokentype, &val, &term);
      pc += val;
      break;

   case BEGIN_T:		/* BEGIN */
      if (!fapmode)
      {
	 if (begincount < MAXBEGINS)
	 {
	    bp = tokscan (bp, &token, &tokentype, &val, &term);
#ifdef DEBUGUSE
            printf ("p1: BEGIN: token = %s, curruse = %d, pc = %05o\n",
		     token, curruse, pc);
#endif
	    bp = exprscan (bp, &val, &term, &relocatable, 1, chksyms, 0);
	    for (i = 0; i < begincount; i++)
	    {
	       if (!strcmp (token, begintable[i].symbol))
	       {
		  begintable[i].bvalue = val;
		  break;
	       }
	    }
	    if (i == begincount)
	    {
	       strcpy (begintable[begincount].symbol, token);
	       begintable[begincount].bvalue = val;
	       begincount++;
	    }
	 }
      }
      break;

   case BES_T:			/* BES */
      bp = exprscan (bp, &val, &term, &relocatable, 1, chksyms, 0);
      pc += val;
      pc &= 077777;
      if (cursym[0])
      {
	 s = p1lookup();
	 if (s)
	 {
	    s->value = pc;
	    s->relocatable = relocatable;
	 }
      }
      break;

   case BFT_T:			/* BFT extended op */
   case BNT_T:			/* BNT extended op */
   case IIB_T:			/* IIB extended op */
   case RIB_T:			/* RIB extended op */
   case SIB_T:			/* SIB extended op */
      pc++;
      break;

   case COMMON_T:		/* COMMON storage */
      /*
      ** FAP COMMON
      */

      if (fapmode)
      {
	 if (cursym[0])
	 {
	    s = p1lookup();
	    if (s)
	    {
	       s->value = commonctr;
	    }
	 }
	 bp = exprscan (bp, &val, &term, &relocatable, 1, FALSE, 0);
	 if (val < 0)
	    commonctr += -val;
	 else
	    commonctr -= val;
	 commonctr &= 077777;
      }

      /*
      ** MAP COMMON
      */

      else if (inpass == 012)
      {
	 i = begincount - 1;
	 if (!begintable[i].value)
	    begintable[i].value = begintable[i].bvalue;
	 val = begintable[i].value;
#ifdef DEBUGUSE
         printf ("asmpass0: COMMON: common = %d, val = %05o\n", i, val);
#endif
         if (cursym[0])
	 {
	    if ((s = p1lookup()) != NULL)
	       s->value = val;
	 }
	 bp = exprscan (bp, &val, &term, &relocatable, 1, FALSE, 0);
	 begintable[i].value += val;
#ifdef DEBUGUSE
         printf ("   new val = %05o\n", begintable[i].value);
#endif
      }
      break;

   case LBOOL_T:		/* Left BOOL */
      boolrl = TRUE;
      boolr = FALSE;
      goto PROCESS_BOOL;

   case RBOOL_T:		/* Right BOOL */
      boolrl = TRUE;
      boolr = TRUE;
      goto PROCESS_BOOL;

   case BOOL_T:			/* BOOL */
      boolrl = FALSE;
      boolr = FALSE;
PROCESS_BOOL:
      radix = 8;
      exprtype = BOOLEXPR | BOOLVALUE;
      bp = exprscan (bp, &val, &term, &relocatable, 1, FALSE, 0);

      /*
      ** Set boolean value into symbol
      */

      if (cursym[0])
      {
	 if (fapmode)
	 {
	    if (headcount && (strlen(cursym) < MAXSYMLEN))
	    {
	       for (i = 0; i < headcount; i++)
	       {
		  char temp[32];

		  sprintf (temp, "%c", headtable[i]);
		  if (!(s = symlookup (cursym, temp, FALSE, FALSE)))
		  {
		     s = symlookup (cursym, temp, TRUE, FALSE);
		  }
		  if (s)
		  {
#ifdef DEBUGBOOLSYM
		     printf (
		 "asmpass1: BOOL sym = %s, val = %o, lrbool = %s, rbool = %s\n",
			      cursym, val, 
			      boolrl ? "TRUE" : "FALSE",
			      boolr ? "TRUE" : "FALSE");
#endif
		     s->value = val;
		     s->relocatable = FALSE; 
		     s->bool = TRUE;
		     s->lrbool = boolrl;
		     s->rbool = boolr;
		  }
	       }
	       s = NULL;
	    }
	    else
	    {
	       if (!(s = symlookup (cursym, "", FALSE, FALSE)))
	       {
		  s = symlookup (cursym, "", TRUE, FALSE);
	       }
	    }
	 }
	 else
	 {
	    if (!(s = symlookup (cursym, qualtable[qualindex], FALSE, FALSE)))
	    {
	       s = symlookup (cursym, qualtable[qualindex], TRUE, FALSE);
	    }
	 }

	 if (s)
	 {
#ifdef DEBUGBOOLSYM
            printf (
	       "asmpass1: BOOL sym = %s, val = %o, lrbool = %s, rbool = %s\n",
		  cursym, val, 
		  boolrl ? "TRUE" : "FALSE",
		  boolr ? "TRUE" : "FALSE");
#endif
	    s->value = val;
	    s->relocatable = FALSE; /* BOOL fields are not relocatable */
	    s->bool = TRUE;
	    s->lrbool = boolrl;
	    s->rbool = boolr;
	 }
      }
      radix = 10;
      break;

   case BSS_T:			/* BSS */
      bp = exprscan (bp, &val, &term, &relocatable, 1, chksyms, 0);
      pc += val;
      pc &= 077777;
      break;

   case DEC_T:			/* DEC */
   case OCT_T:			/* OCT */
      exprtype = DATAEXPR | DATAVALUE;
      do {
	 bp = tokscan (bp, &token, &tokentype, &val, &term);
	 if (tokentype == '-' || tokentype == '+')
	 {
	    bp = tokscan (bp, &token, &tokentype, &val, &term);
	 }
	 if (tokentype == DBLFNUM || tokentype == DBLBNUM) pc++;
	 pc ++;
      } while (term == ',');
      break;

   case END_T:			/* END */
      val = pc;
      if (!litorigin) litorigin = pc;
      processliterals();
      pgmlength = val + litpool;
      litpool = 0;
      return (TRUE);

   case ENDQ_T:			/* ENDQ */
      if (!fapmode)
      {
	 qualindex --;
	 if (qualindex < 0) qualindex = 0;
      }
      break;

   case EQU_T:			/* EQU */
      bp = exprscan (bp, &val, &term, &relocatable, 1, chksyms, 0);

      /*
      ** Set symbol to value
      */

DO_EQU:
      if (cursym[0])
      {
#ifdef DEBUGEQU
	 printf ("p1pop: EQU: cursym = '%s', val = %05o\n", cursym, val);
#endif
	 if (fapmode)
	 {
	    if (headcount && (strlen(cursym) < MAXSYMLEN))
	    {
	       for (i = 0; i < headcount; i++)
	       {
		  char temp[32];

		  sprintf (temp, "%c", headtable[i]);
#ifdef DEBUGEQU
		  printf ("   cursym = '%s', head = '%s' \n", cursym, temp);
#endif
		  if (!(s = symlookup (cursym, temp, FALSE, FALSE)))
		     s = symlookup (cursym, temp, TRUE, FALSE);

		  if (s)
		  {
		     s->line = linenum;
		     if (addextsym)
		     {
#ifdef DEBUGEQU
			printf ("   cursym value = 0%o\n", s->value);
			printf ("   addextsym = '%s', val = 0%o\n",
				 addextsym->symbol, addextsym->value);
#endif
			addextsym->value = s->value;
			s->external = addextsym->external;
			s->noexport = TRUE;
			s->vsym = addextsym;
		     }
		     else
		     {
			s->value = val;
#ifdef DEBUGEQU
			printf ("   cursym value = 0%o\n", s->value);
#endif
			s->line = linenum;
			s->relocatable = relocatable;
		     }
		  }
	       }
	       s = NULL;
	    }
	    else
	    {
#ifdef DEBUGEQU
	       printf ("   cursym = '%s', head = '%s' \n", cursym, "");
#endif
	       if (!(s = symlookup (cursym, "", FALSE, FALSE)))
		  s = symlookup (cursym, "", TRUE, FALSE);
	    }
	 }
	 else
	 {
#ifdef DEBUGEQU
	    printf ("   cursym = '%s', qual = '%s' \n",
		    cursym, qualtable[qualindex]);
#endif
	    if (!(s = symlookup (cursym, qualtable[qualindex], FALSE, FALSE)))
	       s = symlookup (cursym, qualtable[qualindex], TRUE, FALSE);
	 }

	 if (s)
	 {
	    s->line = linenum;
	    if (addextsym)
	    {
#ifdef DEBUGEQU
	       printf ("   cursym value = 0%o\n", s->value);
	       printf ("   addextsym = '%s', val = 0%o\n",
			addextsym->symbol, addextsym->value);
#endif
	       addextsym->value = s->value;
	       s->external = addextsym->external;
	       s->noexport = TRUE;
	       s->vsym = addextsym;
	    }
	    else
	    {
	       s->value = val;
#ifdef DEBUGEQU
	       printf ("   cursym value = 0%o\n", s->value);
#endif
	       s->relocatable = relocatable;
	    }
	 }
      }
      break;

   case EVEN_T:			/* EVEN */
      if (absolute & (pc & 00001)) pc++;
      break;

   case EXT_T:			/* EXTern */
      if (!chksyms) do
      {
	 bp = tokscan (bp, &token, &tokentype, &val, &term);
	 if (tokentype != SYM)
	 {
	    sprintf (errtmp, "EXTRN requires symbol: %s",
		     token);
	    logerror (errtmp);
	    return(FALSE);
	 }
	 if (strlen(token) > MAXSYMLEN)
	 {
	    sprintf (errtmp, "Symbol too long: %s", token);
	    logerror (errtmp);
	    return(FALSE);
	 }
	 if (!(s = symlookup (token, qualtable[qualindex], FALSE, TRUE)))
	    s = symlookup (token, qualtable[qualindex], TRUE, TRUE);
	 if (s)
	 {
	    s->value = 0;
	    if (absmod || absolute)
	       s->relocatable = FALSE;
	    else
	       s->relocatable = TRUE;
	    s->external = TRUE;
	 }
      } while (term == ',');
      break;

   case GOTO_T:			/* GOTO */
      bp = tokscan (bp, &token, &tokentype, &val, &term);
      if (strlen(token) > MAXSYMLEN) token[MAXSYMLEN] = '\0';
      gotoblank = FALSE;
      strcpy (gotosym, token);
      if (term == ',')
      {
	 bp = tokscan (bp, &token, &tokentype, &val, &term);
	 if (!strcmp (token, "BLANK"))
	    gotoblank = TRUE;
      }
#ifdef DEBUGGOTO
      printf ("asmpass1: GOTO: gotosym = '%s', gotoblank = %s\n",
	    gotosym, gotoblank ? "TRUE" : "FALSE");
#endif
      gotoskip = TRUE;
      break;

   case HEAD_T:			/* HEAD */
      if (fapmode)
      {
	 headcount = 0;
	 do {
	    bp = tokscan (bp, &token, &tokentype, &val, &term);
	    headtable[headcount++] = token[0];
	    if (headcount >= MAXHEADS)
	    {
	       break;
	    }
	 } while (term == ',');
	 if (headtable[0] == '0') headcount = 0;
      }
      break;

   case IFF_T:			/* IF False */

      if (fapmode)
      {
	 char tok1[MAXSYMLEN+2];
	 char tok2[MAXSYMLEN+2];

	 tok1[0] = '\0';
	 tok2[0] = '\0';
	 asmskip = 0;
	 bp = exprscan (bp, &val, &term, &relocatable, 1, chksyms, 0);
	 if (term == ',')
	 {
	    bp = tokscan (bp, &token, &tokentype, &i, &term);
	    strcpy (tok1, token);
	    if (term == ',')
	    {
	       strcpy (tok1, token);
	    }
	 }
	 i = strcmp (tok1, tok2);
	 if (val)
	 {
	    if (i) asmskip = 2;
	 }
	 else
	 {
	    if (!i) asmskip = 2;
	 }
      }
      else
      {
	 /*
	 ** Scan the conditional expression and get result
	 */

	 bp = condexpr (bp, &val, &term);
	 if (val >= 0)
	 {
	    int skip;

#ifdef DEBUGIF
	    printf ("p1IFF: val = %d, ifcont = %s\n",
		  val, ifcont ? "TRUE" : "FALSE");
#endif
	    skip = val;
	    asmskip = 0;

	    /*
	    ** If continued, use last result here
	    */

	    if (ifcont)
	    {
#ifdef DEBUGIF
	       printf ("   ifrel = %s, ifskip = %s, skip = %s",
		  ifrel == IFOR ? "OR" : "AND",
		  ifskip ? "TRUE" : "FALSE",
		  skip ? "TRUE" : "FALSE");
#endif
	       if (term == ',')
	       {
		  if (ifrel == IFAND) skip = ifskip || skip;
		  else                skip = ifskip && skip;
		  goto NEXT_IFF_RELATION;
	       }
	       ifcont = FALSE;
	       if (ifrel == IFAND)
	       {
		  if (ifskip || skip)
		     asmskip = 2;
	       }
	       else if (ifrel == IFOR)
	       {
		  if (ifskip && skip)
		     asmskip = 2;
	       }
#ifdef DEBUGIF
	       printf ("   asmskip = %d\n", asmskip);
#endif
	    }

	    /*
	    ** If not continued, check for relation
	    */

	    else if (term == ',')
	    {
	    NEXT_IFF_RELATION:
	       ifcont = TRUE;
	       ifskip = skip;
	       if (!(strcmp (bp, "OR")))
		  ifrel = IFOR;
	       else if (!(strcmp (bp, "AND")))
		  ifrel = IFAND;
#ifdef DEBUGIF
	       printf ("   ifskip = %s\n", ifskip ? "TRUE" : "FALSE");
#endif
	    }

	    /*
	    ** Neither, just do it
	    */

	    else if (skip)
	    {
	       asmskip = 2;
#ifdef DEBUGIF
	       printf ("   asmskip = %d\n", asmskip);
#endif
	    }
	 }
      }
      break;

   case IFT_T:			/* IF True */

      if (!fapmode)
      {
	 /*
	 ** Scan the conditional expression and get result
	 */

	 bp = condexpr (bp, &val, &term);
	 if (val >= 0)
	 {
	    int skip;

#ifdef DEBUGIF
	    printf ("p1IFT: val = %d, ifcont = %s\n",
		  val, ifcont ? "TRUE" : "FALSE");
#endif
	    skip = !val;
	    asmskip = 0;

	    /*
	    ** If continued, use last result here
	    */

	    if (ifcont)
	    {
#ifdef DEBUGIF
	       printf ("   ifrel = %s, ifskip = %s, skip = %s",
		  ifrel == IFOR ? "OR" : "AND",
		  ifskip ? "TRUE" : "FALSE",
		  skip ? "TRUE" : "FALSE");
#endif
	       if (term == ',')
	       {
		  if (ifrel == IFAND) skip = ifskip || skip;
		  else                skip = ifskip && skip;
		  goto NEXT_IFT_RELATION;
	       }
	       ifcont = FALSE;
	       if (ifrel == IFAND)
	       {
		  if (ifskip || skip)
		     asmskip = 2;
	       }
	       else if (ifrel == IFOR)
	       {
		  if (ifskip && skip)
		     asmskip = 2;
	       }
#ifdef DEBUGIF
	       printf ("   asmskip = %d\n", asmskip);
#endif
	    }

	    /*
	    ** If not continued, check for relation
	    */

	    else if (term == ',')
	    {
	    NEXT_IFT_RELATION:
	       ifcont = TRUE;
	       ifskip = skip;
	       if (!(strcmp (bp, "OR")))
		  ifrel = IFOR;
	       else if (!(strcmp (bp, "AND")))
		  ifrel = IFAND;
#ifdef DEBUGIF
	       printf ("   ifskip = %s\n", ifskip ? "TRUE" : "FALSE");
#endif
	    }

	    /*
	    ** Neither, just do it
	    */

	    else if (skip)
	    {
	       asmskip = 2;
#ifdef DEBUGIF
	       printf ("   asmskip = %d\n", asmskip);
#endif
	    }
	 }
      }
      break;

   case LIT_T:			/* LITeral to pool */
      exprtype = DATAEXPR | DATAVALUE;
      do {
	 bp = tokscan (bp, &token, &tokentype, &val, &term);
	 if (tokentype == '-' || tokentype == '+')
	 {
	    bp = tokscan (bp, &token, &tokentype, &val, &term);
	 }
	 if (tokentype == DBLFNUM || tokentype == DBLBNUM) litpool++;
	 litpool++;
      } while (term == ',');
      break;

   case LOC_T:			/* LOC */
      val = -1;
      if (fapmode)
      {
         cp = tokscan (bp, &token, &tokentype, &j, &term);
	 if (tokentype == EOS) val = prevloc + (pc - locorg);
      }
      if (val < 0)
	 bp = exprscan (bp, &val, &term, &relocatable, 1, chksyms, 0);
      absolute = TRUE;
      prevloc = pc;
      pc = val;
      locorg = val;
      if (cursym[0])
      {
	 s = p1lookup();
	 if (s);
	 {
	    s->value = pc;
	    s->relocatable = FALSE;
	 }
      }
      break;

   case LORG_T:			/* Literal ORiGin */
      if (!fapmode)
      {
#ifdef DEBUGLIT
	 printf ("p1-LORG: litorigin = %o, litpool = %d, new pc = %o\n",
		  pc, litpool, pc+litpool);
#endif
	 litorigin = pc;
	 val = pc;
	 processliterals();
	 pc = val + litpool;
	 litpool = 0;
      }
      break;

   case MAX_T:			/* MAX */
      val = 0;
      do {
	 bp = exprscan (bp, &i, &term, &relocatable, 1, chksyms, 0);
	 if (i > val) val = i;
      } while (term == ',');
      if (cursym[0])
      {
	 s = p1lookup();
	 if (s)
	 {
	    s->value = val;
	    s->relocatable = FALSE;
	 }
      }
      break;

   case MIN_T:			/* MIN */
      val = 0777777777;
      do {
	 bp = exprscan (bp, &i, &term, &relocatable, 1, chksyms, 0);
	 if (i < val) val = i;
      } while (term == ',');
      if (cursym[0])
      {
	 s = p1lookup();
	 if (s)
	 {
	    s->value = val;
	    s->relocatable = FALSE;
	 }
      }
      break;

   case NULL_T:			/* NULL */
      val = pc;
      goto DO_EQU;

   case OPD_T:			/* OP Definition */
      if (!chksyms)
      {
	 radix = 8;
	 exprtype = DATAEXPR | DATAVALUE;

	 /*
	 ** Scan off new opcode definition value 
	 */

	 bp = tokscan (bp, &token, &tokentype, &val, &term);
	 if (strlen(token) != 12)
	 {
	    sprintf (errtmp, "Invalid octal number for OPD: %s", bp);
	    logerror (errtmp);
	    return(FALSE);
	 }
#ifdef DEBUGOPD
	 printf ("OPD: token = %s, tokentype = %d, val = %o, term = %c\n",
		 token, tokentype, val, term);
#endif
	 sscanf (&token[6], "%o", &tmpnum1);
	 token[6] = '\0';
	 sscanf (token, "%o", &tmpnum0);
#ifdef DEBUGOPD
	 printf (" tmpnum0 = %o, tmpnum1 = %o\n", tmpnum0, tmpnum1);
#endif
	 /*
	 ** Go add it
	 */

	 opdadd (cursym, tmpnum0, tmpnum1);
	 radix = 10;
      }
      break;

   case OPSYN_T:		/* OP SYNonym */
      bp = tokscan (bp, &token, &tokentype, &val, &term);
#ifdef DEBUGOPSYN
      printf (
       "OPSYN1: cursym = %s, token = %s, tokentype = %d, val = %o, term = %c\n",
	      cursym, token, tokentype, val, term);
#endif
      /*
      ** Delete any previous definition and add
      */

      if ((addop = oplookup (token)) != NULL)
      {
	 opdel (cursym);
	 opadd (cursym, addop->opvalue, addop->opmod, addop->optype);
      }
      break;

   case OPVFD_T:		/* OP Variable Field Definition */
      if (!chksyms)
      {
	 /*
	 ** Scan off VFD fields and build op definition
	 */

	 bitcount = 0;
	 tmpnum0 = 0;
	 tmpnum1 = 0;

	 while (bp)
	 {
	    int bits;
	    unsigned mask;
	    char ctype;

	    bp = tokscan (bp, &token, &tokentype, &val, &term);
	    
#ifdef DEBUGOPD
	    printf ("OPVFD: token = %s, tokentype = %d, val = %o, term = %c\n",
		  token, tokentype, val, term);
#endif
	    ctype = token[0];
	    if (term != '/')
	    {
	       sprintf (errtmp, "Invalid OPVFD specification: %s", token);
	       logerror (errtmp);
	       return(FALSE);
	    }
	    if (ctype == 'O')
	    {
	       bits = atoi (&token[1]);
	       radix = 8;
	    }
	    else
	    {
	       bits = atoi (token);
	       radix = 10;
	    }
	    bp++;
	    mask = 0;
	    for (i = 0; i < bits; i++) mask = (mask << 1) | 1;
	    bp = tokscan (bp, &token, &tokentype, &val, &term);
#ifdef DEBUGOPD
	    printf ("   token = %s, tokentype = %d, val = %o, term = %c\n",
		    token, tokentype, val, term);
	    printf ("   tmpnum0 = %o, tmpnum1 = %o, mask = %o, bitcount = %d\n", 
		    tmpnum0, tmpnum1, mask, bitcount);
#endif
	    val &= mask;
	    if (bitcount < 18)
	    {
	       if (bitcount + bits <= 18)
		  tmpnum0 = (tmpnum0 << bits) | val;
#ifdef DEBUGOPD
	       else
	       {
		  int resid = 18 - (bitcount + bits);
		  printf ("   resid = %d\n", resid);
	       }
#endif
	    }
	    else
	    {
	       tmpnum1 = (tmpnum1 << bits) | val;
	    }
	    bitcount += bits;
	    if (isspace(term)) break;
	 }
#ifdef DEBUGOPD
	 printf ("   tmpnum0 = %o, tmpnum1 = %o\n", 
		 tmpnum0, tmpnum1);
#endif
	 /*
	 ** Go add it
	 */

	 opdadd (cursym, tmpnum0, tmpnum1);
	 radix = 10;
      }
      break;

   case ORG_T:			/* ORiGin */
      bp = exprscan (bp, &val, &term, &relocatable, 1, chksyms, 0);
      if (absmod)
	 absolute = TRUE;
      else
	 absolute = relocatable;
      pc = val;
      if (cursym[0])
      {
	 if (fapmode)
	 {
	    if (headcount && (strlen(cursym) < MAXSYMLEN))
	    {
	       for (i = 0; i < headcount; i++)
	       {
		  char temp[32];

		  sprintf (temp, "%c", headtable[i]);
		  s = symlookup (cursym, temp, FALSE, FALSE);
		  if (s) 
		     s->value = pc;
	       }
	       s = NULL;
	    }
	    else
	    {
	       s = symlookup (cursym, "", FALSE, FALSE);
	    }
	 }
	 else
	 {
	    s = symlookup (cursym, qualtable[qualindex], FALSE, FALSE);
	 }

	 if (s)
	 {
	    s->value = pc;
	 }
      }
      break;

   case QUAL_T:			/* QUALified section */
      if (!fapmode)
      {
	 qualindex ++;
	 bp = tokscan (bp, &token, &tokentype, &val, &term);
	 if (strlen(token) > MAXSYMLEN) token[MAXSYMLEN] = '\0';
	 strcpy (qualtable[qualindex], token);
      }
      break;

   case SET_T:			/* SET value immediately */
      bp = exprscan (bp, &val, &term, &relocatable, 1, FALSE, 0);
      if (cursym[0])
      {
	 if (!(s = symlookup (cursym, "", FALSE, FALSE)))
	    s = symlookup (cursym, "", TRUE, FALSE);
	 if (s)
	 {
	    s->value = val;
	    s->relocatable = FALSE;
	 }
      }
      break;

   case TTL_T:			/* TiTLe - sub title */
      if (!ttlbuf[0])
      {
	 char *cp;

	 while (*bp && isspace (*bp)) bp++;
	 cp = bp;
	 while (*bp != '\n')
	 {
	    if (bp - inbuf > RIGHTMARGIN) break;
	    if (bp - cp == TTLSIZE) break;
	    bp++;
	 }
	 *bp = '\0';
	 strcpy (ttlbuf, cp);
      }
      break;

   case USE_T:			/* USE */
      if (!fapmode)
      {
	 bp = tokscan (bp, &token, &tokentype, &val, &term);
	 if (tokentype != EOS)
	 {
#ifdef DEBUGUSE
	    printf (
	       "p1: USE: token = %s, curruse = %d, prevuse = %d, pc = %05o\n",
		     token, curruse, prevuse, pc);
#endif
	    begintable[curruse].value = pc;
	    if (!strcmp (token, "PREVIOUS"))
	    {
	       curruse = prevuse;
	       prevuse = curruse - 1;
	    }
	    else
	    {
	       prevuse = curruse;
	       for (i = 0; i < begincount; i++)
	       {
		  if (!strcmp (token, begintable[i].symbol))
		  {
		     if (!begintable[i].value)
		     {
			if (begintable[i].bvalue)
			   begintable[i].value = begintable[i].bvalue;
			else
			   begintable[i].value = begintable[i-1].value;
		     }
		     curruse = i;
		     break;
		  }
	       }
	       if (i == begincount)
	       {
#ifdef DEBUGUSE
		  printf ("   Add USE: token = %s, chain = %d, value = %05o\n",
		     token, curruse, begintable[curruse].value);
#endif
		  prevuse = begincount - 1;
		  if (prevuse < 0) prevuse = 0;
		  strcpy (begintable[begincount].symbol, token);
		  begintable[begincount].chain = curruse;
		  begintable[begincount].bvalue = 0;
		  begintable[begincount].value = begintable[prevuse].value;
		  curruse = begincount;
		  begincount++;
	       }
	    }
	    pc = begintable[curruse].value;
#ifdef DEBUGUSE
            printf ("   new curruse = %d, prevuse = %d, pc = %05o\n",
		     curruse, prevuse, pc);
#endif
	 }
      }
      break;

   case VFD_T:			/* Variable Field Definition */
      bitcount = 0;

      /*
      ** Skip leading blanks
      */

      i = FALSE;
      while (*bp && isspace(*bp))
      {
	 i = TRUE;
	 bp++;
      }

      /*
      ** If no operands, set zero value;
      */

      if (i && (bp - inbuf >= NOOPERAND))
      {
#ifdef DEBUGP1VFD
	 printf ("VFD-p1: NO Operand\n");
#endif
         bitcount = 36;
      }

      /*
      ** Operands present, process.
      */

      else
      {
	 cp = bp;
	 while (*bp && !isspace(*cp)) cp++;
	 *cp++ = '\n';
	 *cp++ = '\0';
#ifdef DEBUGP2VFD
	 printf ("VFD-p1: bp = %s\n", bp);
#endif

	 /*
	 ** Scan off VFD fields and calulate length
	 */

	 while (bp)
	 {
	    int bits;
	    int chartype;
	    char ctype;

	    bp = tokscan (bp, &token, &tokentype, &val, &term);
	    
#ifdef DEBUGP1VFD
	    printf ("   token = %s, tokentype = %d, val = %o, term = %c\n",
		  token, tokentype, val, term);
#endif
	    ctype = token[0];
	    chartype = FALSE;
	    if (term != '/')
	    {
	       sprintf (errtmp, "Invalid VFD specification: %s", token);
#ifdef DEBUGP1VFD
	       printf ("ERROR: %d: %s\n", linenum, errtmp);
#endif
	       logerror (errtmp);
	       return(FALSE);
	    }
	    if (ctype == 'O')
	    {
	       if (*(bp+1) == '/')
		  exprtype = BOOLEXPR | BOOLVALUE;
	       else
		  exprtype = ADDREXPR | BOOLVALUE;
	       bits = atoi (&token[1]);
	       radix = 8;
	    }
	    else if (ctype == 'H')
	    {
	       bits = atoi (&token[1]);
	       chartype = TRUE;
	    }
	    else
	    {
	       exprtype = ADDREXPR | BOOLVALUE;
	       bits = atoi (token);
	       radix = 10;
	    }
	    bp++;
	    if (chartype)
	    {
	       char lcltoken[TOKENLEN];

	       cp = bp;
	       while (*bp && *bp != ',' && !isspace(*bp)) bp++;
	       term = *bp;
	       *bp++ = '\0';
	       strcpy (lcltoken, cp);
	       val = 0;
#ifdef DEBUGP1VFD
	       printf (
		"   H%d: token = %s, tokentype = %d, val = %o, term = %c(%x)\n",
		     bits, lcltoken, tokentype, val, term, term);
#endif
	    }
	    else
	    {
	       bp = exprscan (bp, &val, &term, &relocatable, 1, chksyms, 0);
	    }
#ifdef DEBUGP1VFD
	    printf ("   bits = %d, val = %o, term = %c(%x)\n",
		    bits, val, term, term);
#endif
	    radix = 10;
	    bitcount += bits;
	    if (term == '\n') break;
	 }
      }
#ifdef DEBUGP1VFD
      printf ("   bitcount = %d\n", bitcount);
#endif

      /*
      ** Convert bits to words
      */

      val = bitcount / 36;
      val = val + ((bitcount - (val * 36)) ? 1 : 0);
#ifdef DEBUGP1VFD
      printf ("   val = %d\n", val);
#endif
      radix = 10;

      /*
      ** Add word count to pc
      */

      pc += val;
      break;

   default: ;
   }
   return (FALSE);
}

/***********************************************************************
* asmpass1 - Pass 1
***********************************************************************/

int
asmpass1 (FILE *tmpfd, int symonly)
{
   char *token;
   char *bp;
   char *cp;
   int i;
   int status = 0;
   int tokentype;
   int val;
   int done;
   int srcmode;
   char term;
   char opcode[MAXSYMLEN+2];
   char srcbuf[MAXSRCLINE];

#ifdef DEBUGP1RDR
   printf ("asmpass1: Entered: symonly = %s\n", symonly ? "TRUE" : "FALSE");
#endif

   /*
   ** Rewind the input.
   */

   if (fseek (tmpfd, 0, SEEK_SET) < 0)
   {
      perror ("asm7090: Can't rewind temp file");
      return (-1);
   }

   /*
   ** Process the source.
   */

   chksyms = symonly;

   commonctr = FAPCOMMONSTART;

   gotoskip = FALSE;
   gotoblank = FALSE;
   pgmlength = 0;
   litorigin = 0;
   headcount = 0;
   curruse = 0;
   prevuse = 0;
   pc = 0;
   qualindex = 0;
   asmskip = 0;
   linenum = 0;
   litpool = 0;
   litorigin = 0;
   ttlbuf[0] = '\0';
   gotosym[0] = '\0';

   for (i = 0; i < begincount; i++)
      begintable[i].value = 0;

   done = FALSE;
   while (!done)
   {
      /*
      ** Read source line mode and text
      */

      if (fread (&srcmode, 1, 4, tmpfd) != 4)
      {
         done = TRUE;
	 break;
      }
      if (fgets(srcbuf, MAXSRCLINE, tmpfd) == NULL)
      {
         done = TRUE;
	 break;
      }

#ifdef DEBUGP1RDR
      printf (
        "asmpass1: linenum = %d, srcmode = %06x, gotoskip = %s, asmskip = %s\n",
	       linenum + 1, srcmode,
	       gotoskip ? "TRUE" : "FALSE",
	       asmskip ? "TRUE" : "FALSE");
      printf ("   srcbuf = %s", srcbuf);
#endif

      /*
      ** If IBSYS control card, ignore
      */

      if (srcmode & CTLCARD)
      {
	 linenum = 0;
	 continue;
      }

      linenum++;

#ifdef DEBUGP1RDRM
      if (srcmode & MACDEF)
	 printf ("min = %s", inbuf);
#endif
      /*
      ** If not a MACRO definition line, process
      */

      if (!(srcmode & (MACDEF | SKPINST)))
      {
	 inmode = srcmode;
	 if (strlen (srcbuf) > RIGHTMARGIN)
	    srcbuf[RIGHTMARGIN+1] = '\0';
	 strcpy (inbuf, srcbuf);

	 /*
	 ** If a continued line get the next one and append to inbuf
	 */

	 if (srcmode & CONTINU)
	 {
	    bp = &inbuf[VARSTART];
	    while (*bp && !isspace(*bp)) bp++;
	    *bp = '\0';
	    while (srcmode & CONTINU)
	    {
	       if (fread (&srcmode, 1, 4, tmpfd) != 4)
	       {
		  done = TRUE;
		  break;
	       }
	       if (fgets(srcbuf, MAXSRCLINE, tmpfd) == NULL)
	       {
		  done = TRUE;
		  break;
	       }
	       if (strlen (srcbuf) > RIGHTMARGIN)
		  srcbuf[RIGHTMARGIN+1] = '\0';
	       linenum++;
	       cp = &srcbuf[VARSTART];
	       while (*cp && !isspace(*cp)) cp++;
	       *cp = '\0';
	       strcat (inbuf, &srcbuf[VARSTART]);
	    }
	 }
	 strcat (inbuf, "\n");
#ifdef DEBUGP1RDRC
	 if (inmode & CONTINU)
	    printf ("cin = %s", inbuf);
#endif
	 bp = inbuf;
	 exprtype = ADDREXPR;
	 radix = 10;
	 pc &= 077777;

	 /*
	 ** If not skip, IF[FT] mode, process
	 */

	 if (!asmskip)
	 {
	    /*
	    ** If not a comment, then process.
	    */

	    if (*bp != COMMENTSYM)
	    {
	       SymNode *s;
	       OpCode *op;

	       /*
	       ** If label present, scan it off. Check later to add.
	       ** On MAP/FAP the symbol can start in any column up to 6.
	       ** And FAP can have embedded blanks, eg. "( 3.4)"
	       */

	       if (strncmp (bp, "      ", 6))
	       {
		  char *cp;
		  char *dp;
		  char temp[8];

		  strncpy (temp, bp, 6);
		  cp = temp+6;
		  *cp-- = '\0';
		  while (*cp == ' ') *cp-- = '\0';
		  cp = dp = temp;
		  while (*cp)
		  {
		     if (*cp == ' ') cp++;
		     else *dp++ = *cp++;
		  }
		  *dp = '\0';

		  strcpy (cursym, temp);
#ifdef DEBUGCURSYM
		  printf ("asmpass1: cursym = %s\n", cursym);
#endif
		  bp += 6;
		  while (*bp && isspace (*bp)) bp++;
	       }
	       else 
	       {
		  cursym[0] = '\0';
		  while (*bp && isspace (*bp)) bp++;
	       }

	       /*
	       ** Check if in GOTO skip
	       */

	       if (gotoskip)
	       {
#ifdef DEBUGGOTO
		  printf ("   cursym = '%s', gotosym = '%s'\n",
			   cursym, gotosym);
#endif
		  if (cursym[0] && !strcmp (cursym, gotosym))
		  {
		     gotosym[0] = '\0';
		     if (gotoblank) cursym[0] = '\0';
		     gotoskip = FALSE;
		     gotoblank = FALSE;
		  }
		  else continue;
	       }
	       else if (gotosym[0])
	       {
	          if (!strcmp (cursym, gotosym))
		  {
		     gotosym[0] = '\0';
		     if (gotoblank) cursym[0] = '\0';
		     gotoblank = FALSE;
		  }
	       }

	       /*
	       ** Scan off opcode.
	       */

	       if (!strncmp (&inbuf[OPCSTART], "   ", 3))
	       {
		  strcpy (opcode, "PZE");
		  bp = &inbuf[10];
	       }
	       else
	       {
		  bp = tokscan (bp, &token, &tokentype, &val, &term);
		  strcpy (opcode, token);
	       }

	       op = oplookup (opcode);

	       /*
	       ** Add symbol now if not specialy handled.
	       */

	       if (cursym[0])
	       {
		  int addit = TRUE;

		  if (op && op->optype == TYPE_P)
		  {
		     switch (op->opvalue)
		     {
		     case BOOL_T:
		     case EQU_T:
		     case LBOOL_T:
		     case MACRO_T:
		     case NULL_T:
		     case OPD_T:
		     case OPSYN_T:
		     case OPVFD_T:
		     case RBOOL_T:
		     case SAVE_T:
		     case SAVEN_T:
		     case SET_T:
		     case ENT_T:
		     case REM_T:
		     case SPC_T:
		     case EJE_T:
		     case TTL_T:
			addit = FALSE;
		        break;
		     default: ;
		     }
		  }

		  if (chksyms)
		  {
		     if (addit)
		     {
			if (fapmode)
			{
			   if (headcount && (strlen(cursym) < MAXSYMLEN))
			   {
			      int i;

#ifdef DEBUGEQU
			      printf (
				   "asmpass1: Add: cursym = '%s', val = %05o\n",
			            cursym, pc);
#endif
			      for (i = 0; i < headcount; i++)
			      {
				 char temp[32];

				 sprintf (temp, "%c", headtable[i]);
#ifdef DEBUGEQU
				 printf ("   cursym = '%s', head = '%s' \n",
					  cursym, temp);
#endif
				 s = symlookup (cursym, temp, TRUE, TRUE);
				 if (!s)
				 {
				    sprintf (errtmp, "Duplicate symbol: %s$%s",
					     temp, cursym);
				    logerror (errtmp);
				    status = -1;
				 }
			      }
			   }
			   else
			   {
#ifdef DEBUGEQU
			      printf ("   cursym = '%s', head = '%s' \n",
				       cursym, "");
#endif
			      s = symlookup (cursym, "", TRUE, TRUE);
			      if (!s)
			      {
				 sprintf (errtmp, "Duplicate symbol: %s",
					  cursym);
				 logerror (errtmp);
				 status = -1;
			      }
			   }
			}
			else
			{
#ifdef DEBUGEQU
                           printf ("asmpass1: Add: cursym = '%s', val = %05o\n",
			            cursym, pc);
			   printf ("   cursym = '%s', qual = '%s' \n",
				   cursym, qualtable[qualindex]);
#endif
			   s = symlookup (cursym, qualtable[qualindex],
					  TRUE, TRUE);
			   if (!s)
			   {
			      if (qualtable[qualindex][0] == '\0')
				 sprintf (errtmp, "Duplicate symbol: %s",
					  cursym);
			      else
				 sprintf (errtmp, "Duplicate symbol: %s$%s",
					  qualtable[qualindex], cursym);
			   }
			}
		     }
		  }
		  else
		  {
		     if (addit)
		     {
			if (fapmode)
			{
#ifdef DEBUGEQU
                           printf ("asmpass1: Mod: cursym = '%s', val = %05o\n",
			            cursym, pc);
#endif
			   if (headcount && (strlen(cursym) < MAXSYMLEN))
			   {
			      int i;

			      for (i = 0; i < headcount; i++)
			      {
				 char temp[32];

				 sprintf (temp, "%c", headtable[i]);
#ifdef DEBUGEQU
				 printf ("   cursym = '%s', head = '%s' \n",
					  cursym, temp);
#endif
				 s = symlookup (cursym, temp, FALSE, FALSE);
				 if (s)
				 {
				    s->value = pc;
				 }
			      }
			      s = NULL;
			   }
			   else
			   {
#ifdef DEBUGEQU
			      printf ("   cursym = '%s', head = '%s' \n",
				       cursym, "");
#endif
			      s = symlookup (cursym, "", FALSE, FALSE);
			   }
			}
			else
			{
#ifdef DEBUGEQU
                           printf ("asmpass1: Mod: cursym = '%s', val = %05o\n",
			            cursym, pc);
			   printf ("   cursym = '%s', qual = '%s' \n",
				   cursym, qualtable[qualindex]);
#endif
			   s = symlookup (cursym, qualtable[qualindex],
					  FALSE, FALSE);
			}

			if (s)
			{
			   s->value = pc;
			}
		     }
		  }
	       }

	       /*
	       ** If not a macro call ref, then process
	       */

	       if (!(inmode & MACCALL))
	       {
		  if (op)
		  {
		     switch (op->optype)
		     {

			case TYPE_DISK:
			   p1diskop (op, bp);
			   break;

			case TYPE_P:
			   done = p1pop (op, bp);
			   if (done) status = 0;
			   break;

			default:
			   p1allop (op, bp);
		     }
		  }
		  else
		  {
		     if (!gotoskip)
		     {
			/* Missing op may not be a problem */
			pc++; 
		     }
		  }
	       }
	       
	    }
	 }

	 /*
	 ** If skip mode, check if skipping a GOTO for label BLANK option.
	 */

	 if (asmskip)
	 {
	    if (asmskip == 1)
	    {
	       if (strncmp (&inbuf[OPCSTART], "   ", 3))
	       {
	          bp = &inbuf[OPCSTART];
		  bp = tokscan (bp, &token, &tokentype, &val, &term);
		  if (!strcmp(token, "GOTO"))
		  {
		     bp = tokscan (bp, &token, &tokentype, &val, &term);
		     if (strlen(token) > MAXSYMLEN) token[MAXSYMLEN] = '\0';
		     gotoblank = FALSE;
		     strcpy (gotosym, token);
		     if (term == ',')
		     {
			bp = tokscan (bp, &token, &tokentype, &val, &term);
			if (!strcmp (token, "BLANK"))
			gotoblank = TRUE;
		     }
#ifdef DEBUGGOTO
		     printf ("asmpass1: GOTO: gotosym = '%s', gotoblank = %s\n",
			gotosym, gotoblank ? "TRUE" : "FALSE");
#endif
		  }
	       }
	    }
	    asmskip--;   
	 }
      }

   }

   /*
   ** If MAP, Set BEGIN/USE beginning values.
   */

   if (!fapmode)
   {
      if (inpass == 011)
      {
	 /*
	 ** Add blank common location counter, always last
	 */

	 begintable[0].value = pc;
	 strcpy (begintable[begincount].symbol, "//");
	 begintable[begincount].bvalue = 0;
	 begintable[begincount].value = 0;
	 begintable[begincount].chain = 0;
	 begincount++;

	 for (i = begincount-1; i > 0; i--)
	 {
	    if (!begintable[i].bvalue)
	       begintable[i].bvalue = begintable[i-1].value;
#ifdef DEBUGUSE
	    printf (
	      "use[%d]: symbol = %s, value = %05o, bvalue = %05o, chain = %d\n",
	       i, begintable[i].symbol, begintable[i].value, 
		  begintable[i].bvalue, begintable[i].chain); 
#endif
	 }
#ifdef DEBUGUSE
	 i = 0;
	 printf (
	    "use[%d]: symbol = %s, value = %05o, bvalue = %05o, chain = %d\n",
	       i, begintable[i].symbol, begintable[i].value, 
		  begintable[i].bvalue, begintable[i].chain); 
#endif
      }
      else if (inpass == 012)
      {
	 i = begincount - 1;
	 if (begintable[i].value)
	    pgmlength += (begintable[i].value - begintable[i].bvalue);
#ifdef DEBUGUSE
	 printf (
	    "cmn[%d]: symbol = %s, value = %05o, bvalue = %05o, chain = %d\n",
	       i, begintable[i].symbol, begintable[i].value, 
		  begintable[i].bvalue, begintable[i].chain); 
#endif
      }
   }

   return (status);
}
