[comp.sources.misc] C-Power Compatible Assembler for Commodore 64

allbery@ncoast.UUCP (05/27/87)

This is a modified version of the C-Power compatible assembler (C-ASSM)
that I posted a couple of weeks ago.  I've made the necessary changes to
get it to compile under System 5.  It should be a small matter to get it
to compile with other flavors of Unix, as well.  Remember that the openfile.c
module is not used with the Unix version.

Mark
#---------------------------c u t   h e r e------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	Makefile
#	assm.d1
#	assm.d2
#	assm0.c
#	assm1.c
#	assm2.c
#	assm3.c
#	assm4.c
#	assm5.c
#	openfile.c
# This archive created: Wed May 27 15:22:11 1987
export PATH; PATH=/bin:$PATH
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
#The define for UNIX distinguishes this version from the C-Power version.
#The secondary system-level defines (SYSV, BSD, etc.) further define the
#compile-time environment.
#
CFLAGS = -g -DUNIX -DSYSV

LINTFLAGS = -DUNIX -DSYSV -a -lc

CFILES = assm0.c assm1.c assm2.c assm3.c assm4.c assm5.c 
OFILES = assm0.o assm1.o assm2.o assm3.o assm4.o assm5.o 

assm:	$(OFILES)
	cc $(CFLAGS) -o assm $(OFILES)

lint:
	lint $(LINTFLAGS) $(CFILES)

tags \
ctags	: $(CFILES)
	ctags $(CFILES)

clean	:
	rm -f $(OFILES) assm

depend	:
	maketd -a -DUNIX $(CFILES)
# DO NOT DELETE THIS LINE - make depend DEPENDS ON IT
I=/usr/include
S=/usr/include/sys

assm0.o: $I/stdio.h assm.d1 assm0.c

#assm1.o: $I/stdio.h $I/strings.h assm.d1 assm.d2 assm1.c

#SYSV:
assm1.o: $I/stdio.h $I/string.h assm.d1 assm.d2 assm1.c

#assm2.o: $I/stdio.h $I/strings.h assm.d1 assm.d2 assm2.c

assm2.o: $I/stdio.h $I/string.h assm.d1 assm.d2 assm2.c

assm3.o: $I/stdio.h assm.d1 assm.d2 assm3.c

assm4.o: $I/stdio.h assm.d1 assm.d2 assm4.c

assm5.o: $I/stdio.h assm.d1 assm.d2 assm5.c


#openfile is not used in the Unix version.
#openfile.o: $I/stdio.h $I/string.h openfile.c
# *** Do not add anything here - It will go away. ***
SHAR_EOF
fi # end of overwriting check
if test -f 'assm.d1'
then
	echo shar: will not over-write existing file "'assm.d1'"
else
cat << \SHAR_EOF > 'assm.d1'
/* 
 * 6502 Assembler - Data Definitions 
 * Filename: assm.d1 
 * 
 */ 
 
/* Define UNIX to compile under unix */ 
/* C-Power is a little brain-damaged in its handling of #ifdef.  Any
 * preprocessor symbol not #define'd must be #undef'ed.
 */
/*#undef UNIX 
 *#undef SYSV
 */

#ifdef SYSV
#define index strchr
#endif
 
/* Limit Values */ 
 
#define HTSIZE  32      /* hash table size */ 
#define LAST_CH_POS     132 
#define NUMOPS  74 
#define OPSZ    5 
#define SFIELD  23 
#define SBOLSZ  12 
 
/* symbol flags */ 
 
#define UNDEF   1       /* undefined - may be zero page */ 
#define DEFZRO  2       /* defined - page zero address  */ 
#define MDEF    3       /* multiply defined             */ 
#define DEFABS  4       /* defined - two byte address   */ 
#define DEFREL  5       /* defined - relocatable */ 
#define XREF    6       /* external reference */ 
 
#define isrel(t) (t==DEFREL) 
 
/* operation code flags */ 
 
#define CASSM   0x7000 
#define PSEUDO  0x6000 
#define CLASS1  0x2000 
#define CLASS2  0x4000 
#define IMM1    0x1000  /* opval + 0x00 2 byte  */ 
#define IMM2    0x0800  /* opval + 0x08 2 byte  */ 
#define ABS     0x0400  /* opval + 0x0C 3 byte  */ 
#define ZER     0x0200  /* opval + 0x04 2 byte  */ 
#define INDX    0x0100  /* opval + 0x00 2 byte  */ 
#define ABSY2   0x0080  /* opval + 0x1C 3 byte  */ 
#define INDY    0x0040  /* opval + 0x10 2 byte  */ 
#define ZERX    0x0020  /* opval + 0x14 2 byte  */ 
#define ABSX    0x0010  /* opval + 0x1C 3 byte  */ 
#define ABSY    0x0008  /* opval + 0x18 3 byte  */ 
#define ACC     0x0004  /* opval + 0x08 1 byte  */ 
#define IND     0x0002  /* opval + 0x2C 3 byte  */ 
#define ZERY    0x0001  /* opval + 0x14 2 byte  */ 
 
/* pass flags */ 
 
#define FIRST_PASS      0 
#define LAST_PASS       1 
 
/* Types */ 
 
struct symtype { 
  struct symtype *next; 
  char *name; 
  char flag; 
  int value; 
  char xdflag; 
}; 
SHAR_EOF
fi # end of overwriting check
if test -f 'assm.d2'
then
	echo shar: will not over-write existing file "'assm.d2'"
else
cat << \SHAR_EOF > 'assm.d2'
/* 
 * 6502 Assembler - External Definitions 
 * Filename: assm.d2 
 * 
 */ 
#ifdef UNIX 
typedef FILE *FILETYPE; 
#else 
typedef int FILETYPE; 
#endif 
 
extern  FILETYPE optr; 
extern  FILETYPE iptr; 
 
extern  char     filename[];     /* current filename */ 
extern  int      ch;             /* current character */ 
extern  char     cpos;           /* current character position */ 
extern  char     dflag;          /* debug flag */ 
extern  char     listed;         /* source line has been listed */ 
extern  unsigned errcnt;         /* error counter */ 
extern  unsigned exprmc;         /* expression modification code */ 
extern  struct symtype *exprsym; /* expression external reference symbol */ 
extern  char     exprtyp;        /* expression relocation type flag */ 
extern  char     hex[];          /* hexadecimal character buffer */ 
extern  char     iflag;          /* ignore .nlst flag */ 
extern  int      lflag;          /* disable listing flag */ 
extern  char     cflag;          /* list excluded cond assmbly */ 
extern  unsigned loccnt;         /* location counter     */ 
extern  char     fflag;          /* formatted listing switch */ 
extern  char     oflag;          /* object output flag */ 
extern  unsigned opflg;          /* operation code flags */ 
extern  char     opval;          /* operation code value */ 
extern  char     pass;           /* pass counter         */ 
extern  char     prlnbuf[];      /* print line buffer    */ 
extern  char     sflag;          /* symbol table output flag */ 
extern  unsigned slnum;          /* source line number counter */ 
extern  char     symbol[];       /* temporary symbol storage     */ 
extern  unsigned value;          /* operand field value */ 
extern  unsigned fullvalue;      /* operand value before 0-pg truncation */ 
extern  char     zpref;          /* zero page reference flag     */ 
extern  char     undef;          /* expression contains undef symbol */ 
extern  char     casmflg;        /* zero to inhibit assembly */ 
 
extern  struct symtype *lablptr; /* statement label pointer */ 
extern  struct symtype *hash_tbl[];/* pointers to symbol lists */ 
 
 
#define VOID int 
 
extern VOID initialize(); 
#ifdef UNIX 
extern FILETYPE fileopen(); 
#endif 
/* c-power bug: don't declare fileopen() */ 
extern VOID usage(); 
extern int readline(); 
extern VOID include(); 
extern VOID error(); 
extern VOID wrapup(); 
extern VOID stprnt(); 
extern char nextch(); 
extern char getch(); 
extern char skip(); 
extern char cskip(); 
extern char tolower (); 
extern VOID assemble(); 
extern VOID println(); 
extern unsigned colsym(); 
extern unsigned islstrt (); 
extern struct symtype *stlook(); 
extern struct symtype *stinstal(); 
extern int oplook(); 
extern VOID loadlc(); 
extern VOID loadv(); 
extern VOID hexcon(); 
extern int labldef(); 
extern VOID class1(); 
extern VOID class2(); 
extern VOID class3(); 
extern VOID pseudo(); 
extern VOID cassm(); 
extern char ca_op(); 
extern char noasm(); 
extern VOID clearln(); 
extern unsigned evaluate(); 
extern unsigned colexpr (); 
extern unsigned colterm (); 
extern unsigned colnum(); 
extern unsigned isabs (); 
extern VOID addrec(); 
extern VOID adddef(); 
extern VOID putoc(); 
extern VOID putrecs(); 
extern VOID putname(); 
extern char *makerec(); 
extern VOID relchk(); 
extern VOID put1r(); 
extern VOID put1(); 
extern VOID put2(); 
extern VOID put3(); 
extern VOID putn(); 
extern VOID putdseg(); 
extern VOID halfchk (); 
extern char *index(); 
extern VOID quit(); 
extern char *malloc();
SHAR_EOF
fi # end of overwriting check
if test -f 'assm0.c'
then
	echo shar: will not over-write existing file "'assm0.c'"
else
cat << \SHAR_EOF > 'assm0.c'
/* 
 * 6502 Assembler - Code Segment 0 
 * Filename: assm0.c 
 * 
 */ 
 
#include "stdio.h" 
#include "assm.d1" 
 
#ifdef UNIX 
FILE *iptr, *optr; 
#else 
FILE iptr, optr; 
#endif 
 
char      filename[20];    /* current filename */ 
int       ch;              /* current input character */ 
char      cpos;            /* current character position */ 
char      dflag;           /* debug flag */ 
char      listed;          /* listing line has been printed */ 
unsigned  errcnt;          /* error counter */ 
unsigned  exprmc;          /* expression modification code */ 
struct symtype *exprsym;   /* expression external reference symbol */ 
char      exprtyp;         /* expression type */ 
char      hex[5];          /* hexadecimal character buffer */ 
char      iflag;           /* ignore .nlst flag */ 
int       lflag;           /* disable listing flag */ 
char      cflag;           /* list excluded conditional assmbly */ 
unsigned  loccnt;          /* location counter     */ 
char      fflag;           /* formatted listing switch */ 
char      oflag;           /* object output flag */ 
unsigned  opflg;           /* operation code flags */ 
char      opval;           /* operation code value */ 
char      pass;            /* pass counter         */ 
char      prlnbuf[LAST_CH_POS+1]; /* print line buffer    */ 
char      sflag;           /* symbol table output flag */ 
unsigned  slnum;           /* source line number counter */ 
char      symbol[SBOLSZ+1];/* temporary symbol storage     */ 
unsigned  value;           /* operand field value */ 
unsigned  fullvalue;       /* operand value before 0-pg truncation */ 
char      zpref;           /* zero page reference flag     */ 
char      undef;           /* expression contains undef symbol */ 
char      casmflg;         /* 0 to inhibit assembly*/ 
 
struct symtype *lablptr;   /* label pointer into symbol table */ 
struct symtype *hash_tbl[HTSIZE];/* pointers to starting symbols */ 
 
/* The opcode mnemonics are stored as an array of fixed length strings */ 
 
char *opmnem[NUMOPS] = 
{ 
        ".bss ", 
        ".byte", /* '.' is 46 decimal */ 
        ".dbyt", 
        ".def ", 
        ".dseg", 
        ".else", 
        ".fi  ", 
        ".ifeq", 
        ".ifge", 
        ".ifgt", 
        ".ifle", 
        ".iflt", 
        ".ifne", 
        ".list", 
        ".nlst", 
        ".ref ", 
        ".word",  
        "=    ", /* '=' is 61 decimal */ 
        "adc  ","and  ","asl  ", 
        "bcc  ","bcs  ","beq  ", 
        "bit  ","bmi  ","bne  ", 
        "bpl  ","brk  ","bvc  ", 
        "bvs  ","clc  ","cld  ", 
        "cli  ","clv  ","cmp  ", 
        "cpx  ","cpy  ","dec  ", 
        "dex  ","dey  ","eor  ", 
        "inc  ","inx  ","iny  ", 
        "jmp  ","jsr  ","lda  ", 
        "ldx  ","ldy  ","lsr  ", 
        "nop  ","ora  ","pha  ", 
        "php  ","pla  ","plp  ", 
        "rol  ","ror  ","rti  ", 
        "rts  ","sbc  ","sec  ", 
        "sed  ","sei  ","sta  ", 
        "stx  ","sty  ","tax  ", 
        "tay  ","tsx  ","txa  ", 
        "txs  ","tya  " 
}; 
 
/* The opcode definitions consist of 2 word pairs: 
   The first word is the instruction class or legal mode flag word. 
   The second word is the base value of the opcode.  
 */ 
  
unsigned optab[2*NUMOPS] =               /* nmemonic  operation code table       */ 
{ 
 
/* .bss  */  PSEUDO,7, 
/* .byte */  PSEUDO,0, 
/* .dbyt */  PSEUDO,6, 
/* .def  */  PSEUDO,8, 
/* .dseg */  PSEUDO,3, 
/* .else */  CASSM,1, 
/* .fi   */  CASSM,0, 
/* .ifeq */  CASSM,4, 
/* .ifge */  CASSM,5, 
/* .ifgt */  CASSM,3, 
/* .ifle */  CASSM,6, 
/* .iflt */  CASSM,2, 
/* .ifne */  CASSM,7, 
/* .list */  PSEUDO,4, 
/* .nlst */  PSEUDO,5, 
/* .ref  */  PSEUDO,9, 
/* .word */  PSEUDO,2, 
 
/* =     */  PSEUDO,1, 
/* adc   */  IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0x61, 
/* and   */  IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0x21, 
/* asl   */  ABS|ZER|ZERX|ABSX|ACC,0x02, 
/* bcc   */  CLASS2,0x90, 
/* bcs   */  CLASS2,0xb0, 
/* beq   */  CLASS2,0xf0, 
/* bit   */  ABS|ZER,0x20, 
/* bmi   */  CLASS2,0x30, 
/* bne   */  CLASS2,0xd0, 
/* bpl   */  CLASS2,0x10, 
/* brk   */  CLASS1,0x00, 
/* bvc   */  CLASS2,0x50, 
/* bvs   */  CLASS2,0x70, 
/* clc   */  CLASS1,0x18, 
/* cld   */  CLASS1,0xd8, 
/* cli   */  CLASS1,0x58, 
/* clv   */  CLASS1,0xb8, 
/* cmp   */  IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0xc1, 
/* cpx   */  IMM1|ABS|ZER,0xe0, 
/* cpy   */  IMM1|ABS|ZER,0xc0, 
/* dec   */  ABS|ZER|ZERX|ABSX,0xc2, 
/* dex   */  CLASS1,0xca, 
/* dey   */  CLASS1,0x88, 
/* eor   */  IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0x41, 
/* inc   */  ABS|ZER|ZERX|ABSX,0xe2, 
/* inx   */  CLASS1,0xe8, 
/* iny   */  CLASS1,0xc8, 
/* jmp   */  ABS|IND,0x40, 
/* jsr   */  ABS,0x14, 
/* lda   */  IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0xa1, 
/* ldx   */  IMM1|ABS|ZER|ABSY2|ZERY,0xa2, 
/* ldy   */  IMM1|ABS|ZER|ABSX|ZERX,0xa0, 
/* lsr   */  ABS|ZER|ZERX|ABSX|ACC,0x42, 
/* nop   */  CLASS1,0xea, 
/* ora   */  IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0x01, 
/* pha   */  CLASS1,0x48, 
/* php   */  CLASS1,0x08, 
/* pla   */  CLASS1,0x68, 
/* plp   */  CLASS1,0x28, 
/* rol   */  ABS|ZER|ZERX|ABSX|ACC,0x22, 
/* ror   */  ABS|ZER|ZERX|ABSX|ACC,0x62, 
/* rti   */  CLASS1,0x40, 
/* rts   */  CLASS1,0x60, 
/* sbc   */  IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0xe1, 
/* sec   */  CLASS1,0x38, 
/* sed   */  CLASS1,0xf8, 
/* sei   */  CLASS1,0x78, 
/* sta   */  ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0x81, 
/* stx   */  ABS|ZER|ZERY,0x82, 
/* sty   */  ABS|ZER|ZERX,0x80, 
/* tax   */  CLASS1,0xaa, 
/* tay   */  CLASS1,0xa8, 
/* tsx   */  CLASS1,0xba, 
/* txa   */  CLASS1,0x8a, 
/* txs   */  CLASS1,0x9a, 
/* tya   */  CLASS1,0x98 
}; 
SHAR_EOF
fi # end of overwriting check
if test -f 'assm1.c'
then
	echo shar: will not over-write existing file "'assm1.c'"
else
cat << \SHAR_EOF > 'assm1.c'
/* 
 * 6502 Assembler - Code segment 1 
 * Filename: assm1.c 
 * History: 
 *   05/23/87 - v 2.1 - Unix SYSv wants string.h vs. strings.h
 *   05/09/86 - v 2.1 - removed open and replace (@0:) on object file 
 *   05/21/86 - v 2.1 - object filename was not correctly formed for  
 *                      multi-file assemblies 
 *   05/21/86 - v 2.1 - allow abort via stop key 
 *   05/22/86 - v 2.1 - sped up readline processing 
 */ 
 
#include <stdio.h> 
#ifdef UNIX
#include <string.h>
#else
#include <strings.h> 
#endif
#include "assm.d1" 
#include "assm.d2" 
 
#define peek(x)   *((char *)x) 
#define poke(x,y) *((char *)x)=y 
 
 
static unsigned including; 
 
static FILETYPE sviptr; /* saved input file pointer */ 
static unsigned svline; 
 
static char *progname; /* name of this assembler */ 
 
main(argc, argv) 
unsigned argc; 
char *argv[]; 
{ 
  char c; 
  unsigned cnt; 
  unsigned i; 
 
  progname = argv[0]; 
  printf("C/ASSM - version 2.1 - 05/09/86\n"); 
 
  dflag = 0; 
  iflag = 0; 
  lflag = 0; 
  fflag = 1; /* default formatted listing */ 
  cflag = 1; /* default list excluded cond assembly */ 
  oflag = 1; /* default = create object */ 
  sflag = 0; 
 
  while (--argc && (*++argv)[0] == '-') 
  { 
    for (i = 1; (c = tolower((*argv)[i])) != '\0'; i++) 
    { 
      if (c == 'd')     /* debug flag */ 
        dflag++; 
      else if (c == 'i')/* ignore .nlst flag */ 
        iflag++; 
      else if (c == 'l')/* disable listing flag */ 
        lflag--; 
      else if (c == 'f')/* inhibit formatting listing */ 
        fflag = 0; 
      else if (c == 'c')/* no list excluded conditional assmbly */ 
        cflag = 0; 
      else if (c == 'o')/* object output flag */ 
        oflag = 0; 
      else if (c == 's')/* list symbol table flag */ 
        sflag = 1; 
      else usage(); 
    } 
  } 
 
  if (!argc) usage(); 
 
  while ( argc ) 
  { 
    pass = FIRST_PASS; 
    for (i = 0; i < HTSIZE; i++) 
      hash_tbl[i] = NULL; 
    initialize( argc, argv ); 
    while (readline() != EOF) 
      assemble(); 
    wrapup(); 
    pass = LAST_PASS; 
    if (!errcnt) 
    { 
      if (lflag == 0) 
        lflag++; 
      initialize ( argc, argv ); 
      while ( readline() != EOF ) 
      { 
        listed = 0; 
        assemble(); 
        if (!listed) 
          println(); 
      } 
    } 
    wrapup(); 
    stprnt(); 
    printf( "End of assembly, %d errors\n", errcnt); 
    if (dflag) 
    { 
      cnt = 0; 
      for (i = 0; i < HTSIZE; i++) 
        if (!hash_tbl[i]) cnt++; 
      printf( "%d unused hash table pointers out of %d\n", 
        cnt, HTSIZE); 
    } 
    argc--; 
    argv++; 
  } 
} 
 
/* initialize this pass */ 
 
VOID initialize (ac, av) 
unsigned  ac; 
char      *av[]; 
{ 
  unsigned lng;  
  char *s,oname[30]; 
 
  s = *av; 
  lng = strlen(s); /* look for '.a' suffix */ 
  if (pass == FIRST_PASS) 
    printf("%s:\n", s); 
 
  if (lng <= 2 || strcmp(&s[lng-2],".a")) { 
    printf("Not an assembler source (.a expected).\n"); 
    quit(); 
  } 
 
  strncpy ( filename, s, lng-2 ); 
  filename[lng-2] = '\0'; /* strncpy doesn't do it?? */ 
  if (pass == LAST_PASS && oflag) { 
    strcpy(oname,filename); 
    strcat(oname,".o"); 
    optr = fileopen(oname, "w"); 
    putoc();    /* initialize object output routines */ 
  } 
 
  iptr = fileopen(s, "r"); 
 
  including = 0; 
  errcnt = 0; 
  loccnt = 0; 
  slnum = 0; 
  casmflg = 1; 
} 
 
FILETYPE fileopen(fname,dir) 
char *fname, *dir; 
{ 
  FILETYPE fd; 
  char err; 
#ifndef UNIX 
  char scrcmd[41]; /* scratch file command string */ 
#endif 
 
  err = 0; 
#ifdef UNIX 
  if ((fd = fopen(fname,dir))==NULL) 
#else 
  if (*dir=='w') { 
    strcpy(scrcmd,"s0:"); /* scratch old object */ 
    strcat(scrcmd,fname); 
    open(9,8,15,scrcmd); 
    fclose(9); 
  } 
  if ((fd = openfile(fname,dir))==NULL 
  || (err = ferror())) 
#endif 
  { 
    printf("Can't open %s", fname); 
    if (err) printf(", error = %d", err); 
    putchar('\n'); 
    quit(); 
  } 
  return fd; 
} 
 
VOID usage() 
{ 
    printf( "Usage: %s [-cdfilos] file.a [file.a ...]\n",progname); 
    quit(); 
} 
 
char field[] = 
{ 
  SFIELD, 
  SFIELD + SBOLSZ, 
  SFIELD + SBOLSZ + 6, 
  SFIELD + SBOLSZ + 15 
}; 
 
/* See if user wants an abort.  This is signalled by depressing the 
 * stop key. 
 */ 
ckabort() 
{ 
  if (peek(197)==63) exit(1); 
} 
 
/* readline reads and formats an input line, returns 
 * -1 at end of file. 
 */ 

/* static char inbuf[81];  */

int readline() 
{ 
  unsigned i;       /* pointer into prlnbuf */ 
  unsigned j;       /* pointer to current field start */ 
  char cmnt;        /* comment line flag */ 
  unsigned spcnt;   /* consecutive space counter */ 
  char string;      /* ASCII string flag */ 
  unsigned temp1;   /* temp used for line number conversion */ 
/*  unsigned endfile; */ /* local eof signal */ 
/*  char *s;          */ /* temp string pointer */ 
 
  do { 
 
/* 05/21/86 - Test for user abort */ 
 
    ckabort(); 
    cpos = SFIELD; 
    temp1 = ++slnum; 
    for (i = 0; i < LAST_CH_POS; i++) 
      prlnbuf[i] = ' '; 
    i = 3; 
    while (temp1) { /* put source line number into prlnbuf */ 
      prlnbuf[i--] = temp1 % 10 + '0'; 
      temp1 /= 10; 
    } 
    if (including) prlnbuf[4] = '#'; 
    i = SFIELD; 
    cmnt = 0; spcnt = 0; string = 0; 
    j = 1; 
/* 
    endfile = (fgets(inbuf,81,iptr)==0); 
*/ 
/*    s = inbuf; */ 
/*    while (((ch = *s++) != '\n') && ch) { */ 
/*      if (endfile) ch = EOF; */ 
      while ((ch = getc(iptr)) !='\n') { 
      prlnbuf[i++] = ch; 
      if (ch == EOF) { 
        if (including) { 
          prlnbuf[--i] = '\0'; /* erase EOF character */ 
          fclose(iptr); 
          iptr = sviptr; /* restore previous file */ 
          slnum = svline; 
          including--; 
        } 
        else return(EOF); 
      } 
      else if (fflag == 0) 
        ; 
      else if ((ch == ' ') && (string == 0)) { 
        if (spcnt) 
          --i; 
        else if (cmnt == 0) { 
          ++spcnt; 
          if (i < field[j]) 
            i = field[j]; 
          if (++j > 3) { 
            spcnt = 0; 
            ++cmnt; 
          } 
        } 
      } 
 
      else if ((ch == ';') && (string == 0)) { 
        spcnt = 0; 
        if (i == SFIELD + 1) 
          ++cmnt; 
        else if (prlnbuf[i - 2] != '\'') { 
          ++cmnt; 
          prlnbuf[i-1] = ' '; 
          if (i < field[3]) 
            i = field[3]; 
          prlnbuf[i++] = ';'; 
        } 
      } 
      else { 
        if ((ch == '"') && (cmnt == 0)) 
          string = string ^ 1; 
        spcnt = 0; 
        if (i >= LAST_CH_POS - 1) 
          --i; 
      } 
    } 
    prlnbuf[i] = 0; 
    if (prlnbuf[SFIELD]=='#') include(); 
  } while (prlnbuf[SFIELD]=='#'); 
  return(0); 
} 
 
/*  
** Process include statement. 
** 
*/ 
VOID include() 
{ 
  static char *icldstr = "include "; 
 
  char c,flnm[30]; 
  unsigned i; 
 
  if (including) { 
    printf("Only one include level supported!\n"); 
    quit(); 
  } 
  i=0; 
  while (nextch()!=' ' && ch==icldstr[i]) i++; 
  if (i!=7) { 
bad: 
    printf("%s\n",prlnbuf); 
    printf("Bad include syntax\n"); 
    quit(); 
  } 
  skip(); 
  if ( !index("\"<",(c=ch)) ) goto bad; 
  if (pass == LAST_PASS) 
    println(); 
  if (c=='<') c='>';  
  i=0; 
  while (nextch()!=c && ch) 
    flnm[i++]=ch; 
  flnm[i]='\0'; 
  svline = slnum; 
  slnum = 0; 
  sviptr = iptr; 
  including++; 
#ifdef UNIX 
  if ((iptr=fileopen(flnm,"r")) == NULL) 
#else 
  if ((iptr=openfile(flnm,"r")) == NULL || ferror()) 
#endif 
  { 
    printf("Can't open include: %s\n",flnm); 
    quit(); 
  } 
} 
 
/* 
** 08/04/85 - Centralize error strings 
** to avoid redundancy and eliminate 
** 'pseudo-xrefs' in other objects. 
*/ 
VOID error(code) 
unsigned code; 
{ 
static char *errmsg[] = { 
/*  0 */ "UNKNOWN ERROR!!!", 
/*  1 */ "Internal error", 
/*  2 */ "Invalid operation code", 
/*  3 */ "A,X,Y are reserved symbols", 
/*  4 */ "Symbol table overflow", 
/*  5 */ "Duplicate definition", 
/*  6 */ "Sync error", 
/*  7 */ "Branch out of range", 
/*  8 */ "Missing operand", 
/*  9 */ "Invalid addressing mode", 
/* 10 */ "Missing string terminator", 
/* 11 */ "Value error", 
/* 12 */ "Undefined symbol", 
/* 13 */ "Symbol required", 
/* 14 */ "Multiply defined", 
/* 15 */ "Relocation error", 
/* 16 */ "Cond assbly nested too deeply", 
/* 17 */ "Unbalanced parentheses", 
/* 18 */ "Divide by zero", 
/* 19 */ "Hi/Lo operator must be first", 
/* 20 */ "Invalid operand field", 
/* 21 */ "Out of memory", 
/* 22 */ ".fi without .if", 
/* 23 */ "Label required", 
/* 24 */ "Label not allowed" 
}; 
 
  printf("%s\n",prlnbuf); 
  listed = 1; 
 
/* Output a position marker */ 
 
  printf ("%*s!\n", cpos, ""); 
  if (code<1 || code>24) code = 0; 
  printf("%2d %s\n\n", code, errmsg[code]); 
 
  errcnt++; 
} 
 
/* 
 * wrapup() closes the source, 
 * outputs remaining object data and 
 * closes the object file. 
 */ 
 
VOID wrapup() 
{ 
  fclose(iptr); 
 
  if (pass == LAST_PASS && oflag && !errcnt) { 
    putrecs(0); /* relocation data */ 
    putrecs(1); /* external identifiers */ 
    putrecs(2); /* external references */ 
    putrecs(3); /* data blocks */ 
    fclose(optr); 
  } 
 
  return; 
} 
 
/* symbol table print 
 */ 
 
VOID stprnt() 
{ 
  static char symtp[] = { 
    /* ??????  */ '?', 
    /* UNDEF   */ 'U', 
    /* DEFZRO  */ 'Z', 
    /* MDEF    */ 'M', 
    /* DEFABS  */ 'A', 
    /* DEFREL  */ 'R', 
    /* XREF    */ 'X' 
  }; 
 
  char i,j; 
  struct symtype *ptr, *nxtptr; 
 
  if (sflag) 
    printf("\nSYMBOL TABLE:\n"); 
  j = 1; 
  for (i=0; i<HTSIZE; i++) { 
    for (ptr = hash_tbl[i]; ptr ; ptr=nxtptr) { 
      if (sflag) 
      { 
        printf("%-*s%04x %c", SBOLSZ, 
        ptr->name,ptr->value, 
        symtp[ptr->flag]); 
        if (ptr->xdflag) 
          putchar('D'); 
        else 
          putchar(' '); 
        if (j ^= 1) 
          putchar('\n'); 
        else putchar(' '); 
      } 
      nxtptr = ptr->next; 
      free(ptr->name); 
      free(ptr); 
    } 
  } 
  if (sflag && !j) 
    putchar('\n'); 
} 
SHAR_EOF
fi # end of overwriting check
if test -f 'assm2.c'
then
	echo shar: will not over-write existing file "'assm2.c'"
else
cat << \SHAR_EOF > 'assm2.c'
/* 
 * 6502 Assembler - Code Segment 2 
 * Filename: assm2.c 
 * 
 */ 
 
#include <stdio.h> 
#ifdef UNIX
#include <string.h>
#else
#include <strings.h> 
#endif
 
#include "assm.d1" 
#include "assm.d2" 
 
extern char *opmnem[]; 
extern unsigned optab[]; 
 
struct symtype *stlook(); 
struct symtype *stinstal(); 
 
static unsigned symlen; 
 
/* Advance line pointer to next character and store character in 'ch' */ 
char nextch() 
{ 
  return((ch = prlnbuf[++cpos])); 
} 
 
 
/* Insure we have the current character */ 
 
char getch() 
{ 
  return((ch = prlnbuf[cpos])); 
} 
 
/* Unconditional skip to next non-blank */ 
char skip() 
{ 
  while (nextch()==' '); 
  return (ch); 
} 
 
/* Conditional skip to next non-blank */ 
char cskip() 
{ 
  if (ch==' ') skip(); 
  return (ch); 
} 
 
#ifndef UNIX
char tolower ( c ) 
char c; 
{ 
  return (c>='A' && c<='Z'? c+'a'-'A': c); 
} 
#endif
 
/* translate source line to machine language */ 
 
VOID assemble() 
{ 
  int flg; 
 
  cpos = SFIELD; /* set starting position */ 
  getch();       /* get starting character */ 
 
  if ((ch == ';') || (ch == 0)) 
    return; 
  lablptr = NULL; 
  if ( colsym() ) lablptr = stlook(); 
 
  cskip(); 
 
  if ((flg = oplook()) >= 0 && opflg == CASSM) 
  { 
    cassm(); 
    return; 
  } 
  if (noasm()) 
  { 
    listed |= !cflag; 
    return; 
  } 
 
  if (flg < 0) { 
    labldef(loccnt,DEFREL); 
    if (flg == -1) 
      error(2); /* invalid opcode */ 
    if ((flg == -2) && (pass == LAST_PASS)) 
      if (lablptr) 
        loadlc(loccnt, 1); 
    return; 
  } 
  if (opflg == PSEUDO) 
    pseudo(); 
  else { 
    labldef(loccnt,DEFREL); 
    if (opflg == CLASS1) 
      class1(); 
    else if (opflg == CLASS2) 
      class2(); 
    else class3(); 
  } 
  return; 
} 
 
/* printline prints the contents of prlnbuf */ 
 
VOID println() 
{ 
  if (lflag > 0) 
    printf("%s\n", prlnbuf); 
} 
 
/* colsym() collects a symbol from prlnbuf into symbol[], 
 *    leaves prlnbuf pointer at first invalid symbol character, 
 *    returns 
 *      symbol length, or 
 *      0 => no symbol collected 
 */ 
 
unsigned colsym() 
{ 
  unsigned i,valid; 
 
  valid = 1; 
  i = 0; 
  while (valid) { 
    if ( islstrt() ); 
    else if (i >= 1 && index("0123456789$",ch)); 
    else valid = 0; 
    if (valid) { 
      if (i < SBOLSZ ) 
        symbol[i++] = ch; 
      nextch(); 
    } 
  } 
  if (i == 1 && index("AaXxYy", *symbol)) { 
    error(3); /* reserved symbol */ 
    i = 0; 
  } 
  symbol[i] = 0; 
  return(i); 
} 
 
unsigned islstrt () 
{ 
  char c; 
 
  c = tolower( ch ); 
  return (index("_.abcdefghijklmnopqrstuvwxyz", c) != NULL); 
} 
 
/* symbol table lookup 
 *      if found, return pointer to symbol 
 *      else, install symbol as undefined, and return pointer 
 */ 
 
struct symtype *stlook() 
{ 
  char *sym; 
  struct symtype *ptr; 
  int hashv; 
 
  hashv = 0; 
 
  for (sym=symbol; *sym ; sym++) 
    hashv += *sym; 
  symlen = sym - symbol; 
 
  hashv %= HTSIZE; 
  for (ptr=hash_tbl[hashv]; ptr ; ptr = ptr->next) { 
    if (!strcmp(symbol,ptr->name)) 
      return(ptr); 
  } 
   
  return(stinstal(hashv)); 
} 
 
/*  install symbol 
 */ 
struct symtype *stinstal(hv) 
int hv; 
{ 
  struct symtype *newsym; 
 
  newsym = (struct symtype *) makerec(sizeof(struct symtype)); 
 
  newsym->flag = UNDEF; 
  newsym->xdflag = 0; 
  newsym->name = (char *) makerec(symlen+1); 
  strcpy(newsym->name,symbol); 
  newsym->value = 0; 
  newsym->next = hash_tbl[hv]; 
  hash_tbl[hv] = newsym; /* put at head of list */ 
 
  return(newsym); 
} 
 
/* operation code table lookup 
 * returns: 
 *      index in 'opmnem' of symbol, if valid 
 *      -1 if invalid 
 *      -2 if no opcode collected 
 */ 
 
int oplook() 
{ 
  unsigned c,i; 
  unsigned j; 
  int k; 
  char temp[OPSZ+1]; 
 
  for (i=0;i<OPSZ;i++)  
    temp[i] = ' '; 
 
  i = 0; 
  j = 0; 
  while( ch && !index(" ;", ch) ) { 
    c = tolower(ch); 
    if ( index(".=abcdefghijklmnopqrstuvwxyz", c) ) 
       temp[j] = c; 
    else return(-1); 
 
    if (++j > OPSZ)     /* too long? */ 
        return(-1); 
 
    if (c == '=') 
      break; 
 
    nextch(); 
  } 
  if (j==0) return(-2); /* no opcode field */ 
 
/* use variables as follows: 
 * i = mnemonic table index 
 * j = 2 * i for optab index 
 * k = compare designator 
 */ 
 
  temp[OPSZ] = '\0'; /* terminate with null */  
 
/* Do this quick and dirty for now... */ 
 
  for (i=0;i<NUMOPS;i++) { 
     
    if (!(k=strcmp(temp,opmnem[i]))) { 
      j = i << 1 ; /* fast multiply x 2 */ 
      opflg = optab[j]; 
      opval = optab[++j]; 
      return(i); 
    } 
    if (k<0) return(-1); /* beyond? */ 
  } 
  return(-1); 
} 
 
/* load 16 bit value in printable form into prlnbuf */ 
 
VOID loadlc(val, f) 
unsigned val,f; 
{ 
  char i; 
  char *p1, *p2; 
  static char pos[] = {6, 13, 18}; 
 
  i = pos[ f ]; 
  hexcon(4, val); 
  for (p1 = &prlnbuf[i],p2=hex; p2<hex+4; ) 
    *p1++ = *p2++; 
} 
 
 
/* load value in hex into prlnbuf[contents[i]] */ 
 
VOID loadv(val,f) 
unsigned  val,f; 
{ 
  char i; 
 
  i = 3*f; 
  hexcon(2, val); 
  prlnbuf[13 + i] = hex[0]; 
  prlnbuf[14 + i] = hex[1]; 
} 
 
/* convert number supplied as argument to hexadecimal in hex[digit-1] (lsd) 
    through hex[0] (msd)      */ 
 
VOID hexcon(digit, num) 
  unsigned digit,num; 
{ 
  hex[digit] = 0; 
  while (digit) 
  { 
    hex[--digit] = (num & 0x0f) + '0'; 
    if (hex[digit] > '9') 
      hex[digit] += 'A' -'9' - 1; 
    num >>= 4; 
  } 
} 
 
/* assign <value> to label pointed to by lablptr, 
 *      checking for valid definition, etc. 
 * called with: 
 *          value to be assigned 
 *          label type (flag) 
 * returns: 
 *          0 => success 
 *          1 => multiply defined label 
 *          2 => sync error 
 */ 
 
VOID labldef(lval,ltyp) 
unsigned lval,ltyp; 
{ 
  if (lablptr) { 
 
    if (pass == FIRST_PASS) { 
      if (lablptr->flag == UNDEF ) { 
        lablptr->value = lval; 
        lablptr->flag = ltyp; 
      } 
      else { 
        lablptr->flag = MDEF; 
        lablptr->value = 0; 
        error(5); /* multiply defined */ 
        return; 
      } 
    } 
    else { 
      if (pass == LAST_PASS) { 
        if (lablptr->value != lval) { 
          error(6); 
          return; 
        } 
        else { /* Add XDEF to reloc. info? */ 
          if (lablptr->xdflag) adddef(lablptr); 
        } 
      } 
    } 
  } 
  return; 
} 
SHAR_EOF
fi # end of overwriting check
if test -f 'assm3.c'
then
	echo shar: will not over-write existing file "'assm3.c'"
else
cat << \SHAR_EOF > 'assm3.c'
/*
 * 6502 Assembler - Code Segment 3
 * Filename: assm3.c
 *
 */

#include "stdio.h"
#include "assm.d1"
#include "assm.d2"

/* class 1 machine operations processor - 1 byte, no operand field */

VOID class1()
{
  if (pass == LAST_PASS) {
    loadlc(loccnt, 0);
    loadv(opval, 0);
    if (oflag) put1(opval);
  }
  loccnt++;
}


/* class 2 machine operations processor - 2 byte, relative addressing */

VOID class2()
{
  loadlc(loccnt, 0);
  loadv(opval, 0);
  skip();
  if (pass != LAST_PASS || evaluate())
  {
    loccnt += 2;
    return;
  }

  loccnt += 2;
  if (!isrel(exprtyp))
  {
    error(15);
    return;
  }

  if ((int)(value -= loccnt) < -128 || (int) value > 127)
  {
    error(7);
    return;
  }
  loadv(value, 1);
  if (oflag) {
    exprtyp = NULL; 
    put2(opval,value);
  }
}


/* class 3 machine operations processor - various addressing modes */

VOID class3()
{
  unsigned code,flag,i,ztmask;
  char c;

  skip();
  loadlc(loccnt, 0);

  switch(ch) {
  case 0:
  case ';':
    error(8);
    return;
  case 'A':
  case 'a':
    if ( (c = prlnbuf[cpos + 1])==' ' || c==0 )
    {
      flag = ACC;
      break;
    }
  default:
    switch(ch) {
    case '#': case '=':
      flag = IMM1 | IMM2;
      nextch();
      break;
    case '(':
      flag = IND | INDX | INDY;
      nextch();
      break;
    default:
      flag = ABS | ZER | ZERX | ABSX | ABSY | ABSY2 | ZERY;
    }
    if (evaluate())
    {
      if ((flag & IMM1)
      || (ch == ')' && prlnbuf[cpos+1] == ',' ))
        loccnt += 2;
      else
        loccnt += 3;
      return;
    }
    if (undef)
      ztmask = ABS | ABSX | ABSY | ABSY2;
    else if (zpref) {
      flag &= (ABS | ABSX | ABSY | ABSY2 | IND);
      ztmask = 0;
    }
    else ztmask = ZER | ZERX | ZERY;
    code = 0;
    i = 0;

    while (ch != ' ' && ch != ';' && ch != 0 && i++ < 4) {
      code *= 8;
      switch(ch) {
      case ')':   /* ) = 4 */
        ++code;
      case ',':   /* , = 3 */
        ++code;
      case 'X':   /* X = 2 */
      case 'x':
        ++code;
      case 'Y':   /* Y = 1 */
      case 'y':
        ++code;
        break;
      default:
        flag = 0;

      }
      nextch();
    }
    switch(code) {
    case 0:   /* no termination characters */
      flag &= (ABS | ZER | IMM1 | IMM2);
      break;
    case 4:   /* termination = ) */
      flag &= IND;
      break;
    case 25:    /* termination = ,Y */
      flag &= (ABSY | ABSY2 | ZERY);
      break;
    case 26:    /* termination = ,X */
      flag &= (ABSX | ZERX);
      break;
    case 212:   /* termination = ,X) */
      flag &= INDX;
      break;
    case 281:   /* termination = ),Y */
      flag &= INDY;
      break;
    default:
      flag = 0;

    }
  }
  if ((opflg &= flag) == 0) {
    loccnt += 3;
    error(9);
    return;
  }
  if ((opflg & ztmask) )
    opflg &= ztmask;
  switch(opflg) {
  case ACC:   /* single byte - class 3 */
    loadv(opval + 8, 0);
    if (pass == LAST_PASS)
      put1(opval + 8);
    loccnt++;
    return;
  case ZERX: case ZERY:   /* double byte - class 3 */
    opval += 4;
  case INDY:
    opval += 8;
  case IMM2:
    opval += 4;
  case ZER:
    opval += 4;
  case INDX: case IMM1:
    loadv(opval, 0);
    loadv(value, 1);
    if (pass == LAST_PASS)
      put2(opval,value);
    loccnt += 2;
    return;
  case IND:   /* triple byte - class 3 */
    opval += 16;
  case ABSX:
  case ABSY2:
    opval += 4;
  case ABSY:
    opval += 12;
  case ABS:
    opval += 12;
    loadv(opval, 0);
    loadv(value, 1);
    loadv(value >> 8, 2);
    if (pass == LAST_PASS)
      put3(opval,value);
    loccnt += 3;
    return;
  default:
    error(9);
    loccnt += 3;
    return;
  }
}

/* 
pseudo operations processor */

VOID pseudo()
{
  unsigned count,tvalue;

  switch(opval)
  {
  case 0:       /* .byte pseudo */
    labldef(loccnt,DEFREL);
    loadlc(loccnt, 0);
    count = 0;
    do {
      skip();
      if (ch == '"') {
        while ((ch=nextch()) != '"') {        
          if ((tvalue=ch) == 0) {
            error(10);
            return;
          }
          if (tvalue == '\\') {
            if ((tvalue=nextch())=='l')
              tvalue = '\014'; /* form feed */

            else if (tvalue=='n')
              tvalue = '\n';
          }
          loccnt++;
          if (pass == LAST_PASS) {
            put1(tvalue);
            loadv(tvalue, count);
            if (++count >= 3) {
              println();
              clearln();
              count = 0;
              loadlc(loccnt, 0);
            }
          }
        }
        nextch();
      }
      else {
        evaluate();
        if (value > 0xff) {
          error(11);
          value = 0;
        }
        loccnt++;
        if (pass == LAST_PASS) {
          put1r(value);
          loadv(value, count);
          if (++count >= 3) {
            println();
            clearln();
            count = 0;
            loadlc(loccnt, 0);
          }
        }
      }
    } while (ch == ',');
    listed = (count == 0);
    return;

  case 1:       /* = pseudo */
    if (!lablptr)
    {
      error(23);
      return;
    }
    skip();     /* oplook leaves '=' current */
    if (evaluate())
      return;
    if ( !isrel(exprtyp) && !isabs(exprtyp) )
      error(15);
    labldef(value,exprtyp);
    if (pass == LAST_PASS)
      loadlc(value, 1);
    return;

  case 2:       /* .word pseudo */
    labldef(loccnt,DEFREL);
    do {
      loadlc(loccnt, 0);
      skip();
      listed = evaluate();
      if (pass == LAST_PASS) {
        loadv(value, 0);
        loadv(value>>8, 1);
        put2(value,value>>8);
        if (!listed) println();
        clearln();
      }
      loccnt += 2;
    } while (ch == ',');
    listed = 1;
    return;

  case 3:       /* .dseg pseudo */
    if (!lablptr)
    {
      error( 23 );
      return;
    }
    if (pass == FIRST_PASS)
    {
      if (lablptr->flag != UNDEF)
      {
        error(14); /* multiply defined */
        return;
      }
      labldef ( 0, XREF );
    }
    else
    {
      if ( evaluate() )
        return;
      loadlc ( value, 1 );
      putdseg ( value );
    }
    return;

  case 4:       /* .list pseudo */
  case 5:       /* .nlst pseudo */
    if (lablptr)
    {
      error(24);
      return;
    }
    if (lflag >= 0)
      lflag = (opval==4? 1: iflag);
    return;

  case 6:       /* .dbyt pseudo */
    labldef(loccnt,DEFREL);
    loadlc(loccnt, 0);
    do {
      skip();
      listed = evaluate();
      loccnt += 2;
      if (pass == LAST_PASS) {
        loadv(value>>8, 0);
        loadv(value, 1);
        put1r(value>>8);
        put1r(value);
        if (!listed) println();
        loadlc(loccnt, 0);
      }
      clearln();
    } while (ch == ',');
    listed = 1;
    return;

  case 7:     /* .bss */
    labldef(loccnt,DEFREL);
    loadlc(loccnt, 0);
    if (evaluate())
      return;
    if (undef) {
      error(12);
      return;
    }
    if ( !isabs ( exprtyp ) )
    {
      error(15);
      return;
    }
    if ( value & 0x8000 ) /* negative? */
    {
      error(11);
      return;
    }
    loadlc(value, 1);
    if (pass == LAST_PASS) {
      putn ( value );
    }
    loccnt += value;
    return;

  case 8:     /* .def */
  case 9:     /* .ref */
    if (lablptr)
    {
      error(24);
      return;
    }
    do {
      skip();
      if (!colsym()) {
        error(13);
        return;
      }
      lablptr = stlook(); /* define label */
      if (opval==8)
      {
        if (pass == FIRST_PASS)
          lablptr->xdflag = 1;
      }
      else
      {
        if (lablptr->flag != UNDEF && lablptr->flag != XREF)
          error(15);
        else
        {
          lablptr->flag = XREF;
          lablptr->xdflag = 0;
        }
      }
    } while (ch == ',');
  return;       
  }
}

VOID cassm()
{
  unsigned tval;

  if (lablptr)
    error(24);
  if (opval == 0) /* .fi */
  {
    if (casmflg == 1)
      error(22); /* .fi without .if */
    else
      casmflg >>= 1;
    return;
  }
  else if (opval == 1) /* .else */
  {
    casmflg = casmflg ^ 1;
    return;
  }
  casmflg <<= 1;
  casmflg |= 1;
  if (noasm()) return;
  if (ca_op(1)) return;
  tval = value;
  if (ch != ',')
  {
    error(8);
    return;
  }
  nextch();
  if (ca_op(2)) return;
  casmflg &= 0xfffe;
  if (casmflg & 0x80)
  {
    error(16);
    quit();
  }
  switch (opval)
  {
  case 2: /* .iflt */
    casmflg |= (tval < value);
    break;
  case 3: /* .ifgt */
    casmflg |= (tval > value);
    break;
  case 4: /* .ifeq */
    casmflg |= (tval == value);
    break;
  case 5: /* .ifge */
    casmflg |= (tval >= value);
    break;
  case 6: /* .ifle */
    casmflg |= (tval <= value);
    break;
  case 7: /* .ifne */
    casmflg |= (tval != value);
    break;
  }
}

/* evaluate operand #f for cond asm */

char ca_op( f )
char f;
{
  if (evaluate())
    return 1;
  if (undef)
  {
    error(12);
    return 1;
  }
  loadlc ( value, f );
  return 0;
}

/* determine whether to assemble code
   due to conditional assembly */

char noasm()
{
  return !index("\01\03\07\017\037\077\177", casmflg);
}

/* Clear contents of print line buffer */
VOID clearln()
{
  unsigned i;

  for (i = 0; i < SFIELD; i++) prlnbuf[i] = ' ';
  prlnbuf[i] = 0;
}
SHAR_EOF
fi # end of overwriting check
if test -f 'assm4.c'
then
	echo shar: will not over-write existing file "'assm4.c'"
else
cat << \SHAR_EOF > 'assm4.c'
/*
 * 6502 Assembler - Code Segment 4
 * Filename: assm4.c
 *
 */

#undef EXPRTRACE

#include "stdio.h"
#include "assm.d1"
#include "assm.d2"
#ifdef UNIX
#include <string.h>
#else
#include <strings.h>
#endif

static char err;

/* evaluate expression */

unsigned evaluate()
{
   if ( colexpr () )
   {
      error ( err );
      return err;
   }
   if ( undef && pass != FIRST_PASS )
   {
      error ( 12 );
      return 12;
   }
   return 0;
}

unsigned colexpr ()
/* calculate the value and type of an
expression.  returns 0 if no errors;
else error message number.  sets globals:
   value = value of expression
   exprtyp = type of expression
   exprsym = ptr to symbol table entry for
             expressions which consist of a
             single symbolic entry
   exprmc = 1 or 2 if high byte or low byte
   undef = 1 if any term is undefined.  in
           that case, value, exprtyp, exprsym
           are meaningless.
*/
{
   char force;
   static char terms[] = "\n ,;)"; /* \n will be changed to \0 */

   *terms = '\0';

#ifdef EXPRTRACE
   if (dflag) printf ( ">>colexpr:\n" );
#endif

   undef = 0;
   err = 0;
   exprmc = NULL;   /* both bytes of operand assumed */
   exprsym = NULL;
   exprtyp = NULL;
   value = 0;
   cskip ();
   if ( index ("!<>",ch) )
   {
      force = ch;
      nextch ();
   }
   else
      force = ' ';
   zpref = 1;

   if ( colterm (terms) || undef )
   {
      exprtyp = NULL;
      value = 0;
   }

   fullvalue = value;
   if ( isabs ( exprtyp )
      && value < 256 )
      zpref = 0;

   switch (force)
   {
   case '!': zpref = 1;
             break;
   case '<': zpref = 0;
             exprmc = 2;
             value &= 0xff;
             break;
   case '>': zpref = 0;
             exprmc = 1;
             value >>= 8;
             break;
   }

#ifdef EXPRTRACE
   if (dflag) printf ( "<< value=%x(%x),undef=%d,zpref=%d,err=%d,exprmc=%d\n",
      value, exprtyp, undef, zpref, err, exprmc );
#endif

   if (pass != FIRST_PASS)
      halfchk ();
   return err;
}

unsigned colterm ( ts )
char *ts;
/*
ts is a string of valid terminators.  If
end of line is to be a terminator, \0 must
be the first character of the string.
*/
{
   unsigned tvalue, evalue, ttype, etype;
   char op, monop;
   struct symtype *xsym;

   evalue = 0;
   etype = NULL;
   op = ' ';
   monop = ' ';

   while ( 1 )
   {
      /* recognize monadic operators */
      if ( index("~-+", ch ) )
      {
         monop = ch;
         nextch ();
      }

      /* recognize a term */

      if ( etype == XREF )
      {
         cpos--; getch(); /* include + or - as monadic */
         op = '+';
         xsym = exprsym; /* save ext sym data */
         if (colterm ( ts )) /* evaluate offset */
            return err;
         exprsym = xsym;
         tvalue = value;
         ttype = exprtyp;
      }
      else if ( index ("0123456789$@%", ch) )
      {
         tvalue = colnum ();
         ttype = DEFABS;
      }
      else if ( islstrt () )
      {
         colsym ();
         exprsym = stlook();
         if (exprsym->flag == UNDEF)
         {
            undef = 1;
            tvalue = 0;
            ttype = UNDEF;
         }
         else
         {
            tvalue = exprsym->value;
            ttype = exprsym->flag;
         }
      }
      else switch ( ch )
      {
      case '*':
         tvalue = loccnt;
         ttype = DEFREL;
         nextch ();
         break;
      case '\'':
         tvalue = nextch ();
         ttype = DEFABS;
         if (tvalue)
            nextch ();
         else
            tvalue = ' ';
         break;
      case '[':
         nextch ();
         if ( colterm ( "]" ) )
            return err;
         if ( ch != ']' )
            return (err = 17);
         tvalue = value;
         ttype = exprtyp;
         nextch ();
         break;
      default:
         return ( err = 20 );
      }

#ifdef EXPRTRACE
      if (dflag) printf("op=%c,monop=%c,e=%x(%x),t=%x(%x),err=%d\n",
         op,monop,evalue,etype,tvalue,ttype,err);
#endif

      /* do any monadic operator */
      switch ( monop )
      {
      case '+':
      case ' ':
         break;
      case '~':
      case '-':
         exprsym = NULL;
         if ( isabs ( ttype ) )
            tvalue =
               (monop=='-'? -tvalue: ~tvalue);
         else
            return ( err = 15 );
         break;
      default:
         return ( err = 16 );
      }
      monop = ' ';

      /* Relocatability checks */

      if ( etype == XREF )
         if ((isabs(ttype) || undef)
         && op == '+')
            evalue = tvalue;
         else
            return ( err = 15 );
      else if ( op != ' ' )
      {
         exprsym = NULL;
         if ( ttype == XREF )
            return ( err = 15 );
      }

      /* Do any dyadic operation */

      if ( etype != XREF && !undef)
      switch(op)
      {
      case ' ':
         evalue = tvalue;
         etype = ttype;
         break;
      case '+':
         if ( isrel ( etype ) && isrel ( ttype ) )
            return ( err = 15 );
         evalue += tvalue;
         if ( isrel ( etype ) || isrel ( ttype ) )
            etype = DEFREL;
         else
            etype = DEFABS;
         break;
      case '-':
         if ( isabs ( etype ) && isrel ( ttype ) )
            return ( err = 15 );
         evalue -= tvalue;
         if ( isrel ( etype ) && isabs ( ttype ) )
            etype = DEFREL;
         else
            etype = DEFABS;
         break;
      default:
         if ( isrel ( etype ) || isrel (ttype ) )
            return ( err = 15 );
         switch (op)
         {
         case '/': case '%':
            if (!tvalue)
               return ( err = 18 );
            if (op=='/')
               evalue /= tvalue;
            else
               evalue %= tvalue;
            break;
         case '*':
            evalue *= tvalue;
            break;
         case '^':
            evalue ^= tvalue;
            break;
         case '&':
            evalue &= tvalue;
            break;
         case '|':
            evalue |= tvalue;
            break;
         default:
            return (err = 1);
         }
      }

      /* get next dyadic operator */
      if ( index ("+-*/%^&|", ch) )
      {
         op = ch;
         nextch ();
      }

      /* check for end of expression */
      else if ( ch == *ts || index ( ts+1, ch ) )
      {
         value = evalue;
         exprtyp = etype;
         return err;
      }

      else
      {
#ifdef EXPRTRACE
         if (dflag) printf ( "Illegal operator = %d\n", ch );
#endif

         return ( err = 20 );
      }
   }
}

/* collect number operand   */

unsigned colnum()
{
  char c;   /* local copy of 'ch' */
  unsigned mul = 0,nval;

  nval = 0;
  c=ch; /* copy to local */

  if (c == '$')
    mul = 16;
  else if (c >= '1' && c <= '9') {
    mul = 10;
    nval = c - '0';
  }
  else if (c == '@' || c == '0')
    mul = 8;
  else if (c == '%')
    mul = 2;
  c = nextch();
  while ((c = tolower(c)) >= '0') {
    if (c > '9') 
      c = c - 'a' + 10;
	else
	  c -= '0';
    if (c >= mul)
      break;
    nval = (nval * mul) + c;
    c = nextch();
  }
  return(nval);
}

unsigned isabs ( t )
unsigned t;
{
   return t==DEFABS || t==DEFZRO;
}
SHAR_EOF
fi # end of overwriting check
if test -f 'assm5.c'
then
	echo shar: will not over-write existing file "'assm5.c'"
else
cat << \SHAR_EOF > 'assm5.c'
/*
 * 6502 Assembler Object Ouptput
 * Filename:  assm5.c
 *
 */

#undef DEFTRACE

#include <stdio.h>
#include "assm.d1"
#include "assm.d2"

/*
 * The structures describing the various
 * external and relocatable objects must
 * all have a link pointer as the first
 * field, so they may be processed using
 * a common routine.  Struct extrec is
 * a generic name for this common structure.
 */

struct extrec /* generic relocation/external record */
{
  struct extrec *ext_next;
};

struct relrec /* relocation record */
{
  struct relrec *rel_next;
  unsigned rel_offset;
};

struct defrec /* external definition */
{
  struct defrec *def_next;
  struct symtype *def_symdef;
};

struct refrec /* external reference */
{
  struct refrec *ref_next;
  struct symtype *ref_symdef;
  unsigned modcode; /* 0,1 or 2, plus (increment << 2) */
  unsigned ref_offset;
};

struct datrec /* data segment */
{
  struct datrec *dat_next;
  struct symtype *dat_symdef;
  unsigned size;
};

/* pointers to the ends of four circular
 * lists:
 */
#define REL 0
#define DEF 1
#define REF 2
#define DAT 3
static struct extrec *listtail[4];
static unsigned cnt[4];

static unsigned objloc;

/**************************************
 *
 * Add item to a relocation info list.
 *
 */
VOID addrec(p, list)
struct extrec *p;
char list;
{
  struct extrec *tail;

  tail = listtail[list];
  if ( tail )
  {
    p->ext_next = tail->ext_next;
    tail->ext_next = p;
  }
  else
    p->ext_next = p;

  listtail[list] = p;
  cnt[list]++;

#ifdef DEFTRACE
  if (dflag)
    printf("Ext/Rel record, type %d\n", list);
#endif
}

/*
 * Add label definition to relocation info list.
 *
 */
VOID adddef(p)
struct symtype *p;
{
  struct defrec *rp;

  if (p->xdflag)
  {
    rp = (struct defrec *) makerec ( sizeof(struct defrec) );
    rp->def_symdef = p;
    addrec(rp,DEF); /* add to info list */
  }
}

/* 
 * Output object count and initialize
 * reference list pointers
 *
 */
VOID putoc()
{
  char i;

  putw(loccnt,optr); /* first word in object file */
  for (i=0; i<4; i++)
  {
    listtail[i] = NULL;
    cnt[i] = 0;
  }
  objloc = 0;
}

/* 
 * Output external/relocation entries and
 * free the records
 *
 */
VOID putrecs(list)
char list;
{
  struct extrec *ptr, *nxtptr;
  struct symtype *sp;
  struct relrec *relptr;
  struct defrec *defptr;
  struct refrec *refptr;
  struct datrec *datptr;

  putw(cnt[list], optr);
  if ((ptr = listtail[list])==NULL)
    return;
  nxtptr = ptr->ext_next;
  do
  {
    ptr = nxtptr;
    switch (list)
    {
    case REL:
      relptr = (struct relrec *) ptr;
      putw(relptr->rel_offset, optr);
      break;
    case DEF:
      defptr = (struct defrec *) ptr;
      sp = defptr->def_symdef;
      putname(sp);
      if (isrel(sp->flag))
        fputc(1,optr);
      else
        fputc(0,optr);
      putw(sp->value, optr);
      break;
    case REF:
      refptr = (struct refrec *) ptr;
      sp = refptr->ref_symdef;
      putname(sp);
      putw(refptr->modcode, optr);
      putw(refptr->ref_offset, optr);
      break;
    case DAT:
      datptr = (struct datrec *) ptr;
      sp = datptr->dat_symdef;
      putname(sp);
      putw(datptr->size, optr);
      break;
    }
    nxtptr = ptr->ext_next;
    free(ptr);
  } while ( ptr != listtail[list] );
}

/* 
** Output symbol name reference.
**
*/
VOID putname(sp)
struct symtype *sp;
{
  char c;
  char *p;

  p = sp->name;
  do {
    c = *p++;
    fputc(c,optr);
    }
  while (c);
}

/*
** Allocate size bytes of storage 
** Returns: pointer to empty entry.
**
*/
char *makerec(size)
unsigned size;
{
  char *ptr;
  char *malloc();

  ptr = malloc(size);
  if (ptr==NULL) {
    error(21);
    quit();
  }
  return (ptr);
}

/*
 * Check the current object byte against
 * 'exprtyp' to determine if it is relocatable,
 * or makes an external reference.
 */
VOID relchk(loc)
unsigned loc;
{
  struct relrec *relptr;
  struct refrec *refptr;

  if (isrel(exprtyp) && !exprmc)
  {
    relptr = (struct relrec *) makerec(sizeof(struct relrec));
    relptr->rel_offset = loc;
    addrec ( relptr, REL );
  }
  else if (exprtyp==XREF || (isrel(exprtyp) && exprmc))
  {
    refptr = (struct refrec *) makerec(sizeof(struct refrec));
    refptr->modcode = exprmc;
    refptr->ref_offset = loc;
    refptr->ref_symdef = exprsym;
    if (exprsym->flag == XREF)
    {
      if ( fullvalue >= 0x2000 && fullvalue < 0xe000 )
        error ( 11 );
      refptr->modcode |= (fullvalue << 2);
    }
    addrec(refptr, REF);
  }
}

/*
 * Put 1 byte value to object file,
 * including relocation check
 *
 */
VOID put1r(v)
unsigned v;
{
  if (oflag)
  {
    relchk(objloc - 1);
    put1(v);
  }
}

/*
 * Put 1 byte value to object file
 *
 * Note: no relocation check performed
 */
VOID put1(v)
unsigned v;
{
  if (oflag) {
    fputc(v,optr);
  }
  objloc++;
}

/*
 * Put 2 byte value to object file
 * 
 */
VOID put2(v1,v2)
unsigned v1,v2;
{
  if (oflag) {
    fputc(v1,optr);
    fputc(v2,optr);
    if (exprmc)
      relchk(objloc);
    else
      relchk(objloc - 1);
  }
  objloc += 2;
}
/*
 * Put 3 bytes to object file.
 * First value is opcode, second is
 * operand.
 *
 */
VOID put3(v1,v2)
unsigned v1,v2;
{
  if (oflag) {
    fputc(v1,optr);
    putw(v2,optr);
    relchk(objloc);
  }
  objloc += 3;
}

VOID putn(n)
int n;
/*
 * put n bytes of zero
 */
{
  char buf[256];
  int i;

  objloc += n;
  if (!oflag) return;

  for (i=0; i<256; i++)
    buf[i] = 0;
  while ( n > 0 )
  {
    if ( n >= 256 )
      i = 256;
    else
      i = n;
    n -= i;
    fwrite ( buf, i, 1, optr );
  }
}

/* create a data segment */

VOID putdseg( len )
unsigned len;
{
  struct datrec *ptr;

  ptr = (struct datrec *) makerec(sizeof(struct datrec));
  ptr->dat_symdef = lablptr;
  ptr->size = len;
  addrec(ptr,DAT);
}

VOID halfchk ()
/* any reloctable expression used with
 * a '<' or '>' operation must be made
 * external, since the linker cannot
 * relocate half-addresses which are not
 * external.
 */
{
  if  ( exprmc )
  {
    if ( exprsym && exprsym->xdflag )
      return;
    if ( isabs ( exprtyp ) || exprtyp==XREF )
      return;
    strcpy ( symbol, ">" );
    strncat ( symbol, filename, SBOLSZ-5 );
    hexcon ( 4, fullvalue );
    strncat ( symbol, hex, 4 );
    exprsym = stlook ();
    if (pass==LAST_PASS && !exprsym->xdflag)
    {
      exprsym->flag = exprtyp;
      exprtyp = XREF;
      exprsym->value = fullvalue;
      exprsym->xdflag = 1;
      if (oflag) adddef ( exprsym );
    }
  }
}

#ifdef UNIX

char *index(s,c)
char *s, c;
{
  while (*s)
    if (c == *s) return s;
    else s++;
  return 0;
}

#endif

VOID quit()
{
#ifdef UNIX
  exit ( 1 );
#else
  exit ();
#endif
}
SHAR_EOF
fi # end of overwriting check
if test -f 'openfile.c'
then
	echo shar: will not over-write existing file "'openfile.c'"
else
cat << \SHAR_EOF > 'openfile.c'
/* home-brew file extensions         */ 
/* author:   Mark R. Rinfret         */ 
/* date:     04/19/84                */ 
/* filename: openfile.c              */ 
 
#include <stdio.h> 
#ifdef UNIX
#include <string.h>
#else
#include <strings.h> 
#endif
 
openfile(name,how) 
char *name,how; 
 
{ 
  char *xname; 
  char c; 
  unsigned dvc; 
 
  xname = name; /* copy pointer */ 
  dvc = 8;  /* default is device 8 */ 
  if ((c=*xname) == '#') { 
    xname++; 
    if (((c=*xname) == '8') || ((c=*xname) == '9')) { 
      xname++; 
      dvc = (8 + (c - '8')); 
      if (*xname==':') xname++; 
      else { 
        printf("missing ':' in device specification\n%s\n",xname); 
        return NULL; 
        } 
      } 
    else { 
      printf("illegal device number:\n%s\n",xname); 
      return NULL; 
      } 
    } 
 
  device(dvc); 
  return (fopen(xname,how)); 
} 
SHAR_EOF
fi # end of overwriting check
#	End of shell archive
exit 0
-- 
| Mark R. Rinfret, SofTech, Inc.		mark@unisec.usi.com |
| Guest of UniSecure Systems, Inc., Newport, RI                     |
| UUCP:  {gatech|mirror|cbosgd|uiucdcs|ihnp4}!rayssd!unisec!mark    |
| work: (401)-849-4174	home: (401)-846-7639                        |
-- 
Brandon S. Allbery	{decvax,cbatt,cbosgd}!cwruecmp!ncoast!allbery
Tridelta Industries	{ames,mit-eddie,talcott}!necntc!ncoast!allbery
7350 Corporate Blvd.	necntc!ncoast!allbery@harvard.HARVARD.EDU
Mentor, OH 44060	+01 216 255 1080	(also eddie.MIT.EDU)