cpm xasm part 1 of 2

Klotzbach klotz at aicchi.UUCP
Fri Aug 30 15:37:42 AEST 1985


# This is a shell archive.  Remove anything before this line, then
# unpack it by saving it in a file and typing "sh file".  (Files
# unpacked will be owned by you and have default permissions.)
#
# This archive contains:
# asm.h as81.c as82.c as83.c as85.c asmain.c

echo x - asm.h
cat | sed -e "s/^X//" > "asm.h" << '//E*O*F asm.h//'
X
X/*
X * @(#)asm.h	1.3 
X * Header.
X *
X * General assembler header. With this structure you
X * can define the majority of the simple assembler 
X * dependent variables.
X *
X * David A Klotzbach
X *
X * Sizes of tables.
X */
X
X#define NCPS	16		/* Characters per symbol */
X#define CLMAX	256		/* Code bytes, line */
X#define CBMAX	16		/* Code bytes, object */
X#define USERMAX	2		/* User names */
X#define SRCMAX	128		/* Source line length */
X#define ERRMAX	5		/* Maximum errors per line +1 */
X#define FALSE	0		/* not true			*/
X#define TRUE	1		/* You should be able to guess	*/
X#define mxline	55		/* maximum lines per page*/
X
X#define dot	(&ust[0])	/* Location counter */
X#define CDOT	'$'		/* Character that means current PC */
X#define BSWAP   0		/* 1 = High first; 0 = Low first   */
X#define MICRO	"8080"
X#define TASK	"ASM80"		/* The task that is to be run */
X#define HASH	28
X
X/*
X * Listing control modes.
X * Go in `listmode'.
X */
X#define NLIST	0		/* No list */
X#define SLIST	1		/* Source only list */
X#define ALIST	2		/* Just address */
X#define CLIST	3		/* Address and code */
X
X/*
X * Symbol table structure.
X * Used in both the user symbol table and
X * the opcode table.
X */
Xstruct hu{
X	struct hu *next;	/* Next usage	*/
X	int	line;		/* Line used	*/
X	char	how;		/* How it was used */
X	};
X
X#define	U_DEFINE	'd'	/* Defined	*/
X#define U_EXPR		'e'	/* used in expres */
X#define U_EQU		'='	/* EQU or SET	*/
X		
Xstruct sym {
X	char s_name[NCPS];	/* Name */
X	struct sym *left;	/* left member	*/
X	struct sym *right;	/* right member */
X	char s_type;		/* Type */
X	char s_flag;		/* Some flags */
X	int  s_value;		/* Value */
X	struct	hu *howused;	/* First entry in */
X};
X
Xstruct sym *hashtbl[ ];		/* Hash buckets for symbol table	*/
Xstruct sym *lookup();		/* define lookup as a function returning */
X
X#define	B	0
X#define C	1
X#define D	2
X#define E	3
X#define H	4
X#define L	5
X#define M	6
X#define A	7
X#define PSW	6
X#define SP	7
X#define INR	4
X#define DCR	5
X
X
X/*
X * Types.
X */
X#define S_UND	0		/* Undefined */
X#define S_ABS	1		/* Absolute */
X#define S_REG	2		/* Register */
X#define S_REGP	3		/* Register pair */
X#define S_ENTRY	4		/* .entry */
X#define S_BYTE	5		/* .byte */
X#define S_WORD	6		/* .word */
X#define S_ASCII	7		/* .ascii */
X#define S_ASCIZ	8		/* .asciz */
X#define S_BLKB	9		/* .blkb */
X#define S_OP1	10		/* Opcode */
X#define S_OP2	11		/* Accumulator and Memory */
X#define S_OP3	12		/* Index Register and stack */
X#define S_OP4	13		/* Branch */
X#define S_OP5	14		/* Jump   */
X#define S_OP6	15		/* Condition codes */
X#define S_OP7	16		/* limitted to extnd and indexed */
X#define S_OP8	17		/* limitted to direct,extnd and indx */
X#define S_OP9	18		/*					*/
X#define S_OP10	19		/*					*/
X#define S_OP11	20		/*					*/
X#define S_EQU	21		/*					*/
X#define S_SET	22		/*					*/
X#define	S_NAME	23		/* Name the program listing	     */
X#define S_ORG	24		/* Program section origin statement  */
X#define	S_IF	100		/* IF directive			     */
X#define S_ENDIF	102		/* ENDIF directive		     */
X#define S_MACRO	200		/* Define a macro		     */
X#define S_ENDM	202		/* Define macro end		     */
X
X/*
X * Flags.
X */
X#define SF_MDF	01		/* Multiply defined */
X#define SF_ASG	02		/* Defined by assignment */
X#define SF_MAC	04		/* is a MACRO definition */
X
X/*
X * Variables.
X */
X#define	TITLE_LN	40	/* Length of the title	*/
Xextern	struct	sym pst[];	/* Opcode table */
Xextern	struct	sym ust[];	/* User symbols */
Xextern	int	page	;	/* Current page number */
Xextern	int	pline	;	/* Lines on the current page */
Xextern	int	listmode;	/* Listing control */
Xextern	int	listaddr;	/* Listing control */
Xextern	int	entaddr;	/* .entry address */
Xextern	FILE	*src;		/* Source */
Xextern	FILE	*lst;		/* Listing */
Xextern	FILE	*obj;		/* Object */
Xextern	int	lflag;		/* -l flag */
Xextern	int	nflag;		/* -n flag */
Xextern	int	sflag;		/* -s flag		    */
Xextern	int	pass;		/* Which pass? */
Xextern	int	skip;		/* Skipping code lines      */
Xextern	int	inif;		/* in an if block of inif   */
Xextern	int	lineno;		/* Line number */
Xextern	char	*sptr;		/* Source pointer */
Xextern	char	sbuf[];		/* Source buffer */
Xextern	char	*cptr;		/* Listing code pointer */
Xextern	char	cbuf[];		/* Listing code buffer */
Xextern	char	*eptr;		/* Error pointer */
Xextern	char	ebuf[];		/* Error buffer */
Xextern	int	cadr;		/* Object address */
Xextern	int	crec;		/* Object index */
Xextern	char	crbf[];		/* Object buffer */
Xextern	struct	sym *pptr;	/* End of pst */
Xextern	struct	sym *uptr;	/* End of ust */
Xextern  char    title[];         /* Title buffer */
Xextern  int	errcnt;		 /* number of errors encounterd */
Xextern	int	optype;		/* Type of current operand    */
X
X/*
X * Functions.
Xextern	struct	sym *lookup();	/* Search */
X
X
X
//E*O*F asm.h//

echo x - as81.c
cat | sed -e "s/^X//" > "as81.c" << '//E*O*F as81.c//'
X/*
X * as81.c
X * Assemble a line.
X */
X#include <stdio.h>
X#include "asm.h"
X
Xstatic char *as81="@(#)as81.c	1.3";
X
X/*
X * Assemble a line.
X */
Xasmline()
X{
X	register struct sym *sp,*lsp;
X	register int rs, rd;
X	char	*ptr;
X	int	n;
X	int a, c, opcode;
X	char id[NCPS];
X
X	listaddr = dot->s_value;
X	listmode = skip ? NLIST : SLIST; /* if skiping then no list */
X	lsp = NULL;
X	c = getnb();
X
X	do{
X		if(c=='\0' || c==';' || c=='\n') 
X			break;
X		if( c == '!' )
X			c = getnb();
X		if(!alpha(c)) {
X			if( !skip )
X				err('L');
X			break;
X		}
X		getid(c, id);
X
X		if(( c = getnb()) == ':' ) {
X			if( skip )
X				break;
X			sp=lookup(id, ust ,'d');
X			if(pass==0) {
X				if(sp->s_type!=S_UND &&
X				    (sp->s_flag&SF_ASG)==0)
X					sp->s_flag |= SF_MDF;
X				sp->s_type = S_ABS;
X				sp->s_value = dot->s_value;
X			} 
X			else {
X				if((sp->s_flag&SF_MDF)!=0)
X					err('L');
X				if(sp->s_type!=S_ABS ||
X				    sp->s_value!=dot->s_value)
X					err('L');
X			}
X			listmode = ALIST;
X			continue;
X		} 
X		else
X			putback(c);
X		if((sp=lookup(id, pst)) == NULL){
X			if( !skip ){
X				lsp = lookup( id, ust ,'=' );
X				c = getnb();
X				getid( c , id );
X				if((sp = lookup( id, pst )) == NULL){
X					err('O');
X					break;
X				}
X			}
X			else
X				return;
X		}
X		else if (skip &&(sp->s_type != S_ENDIF))
X			return;
X		else if((skip || inif)&&(sp->s_type == S_ENDIF)) { 
X			skip = 0;
X			if(!(--inif))
X				inif=0;
X			listmode = NLIST;
X			return;
X		}
X		listmode = CLIST;
X		if( lsp != NULL ){
X			switch( sp->s_type){
X			case S_EQU:
X			case S_SET:
X				if( lsp->s_type != S_UND &&
X				    ( lsp->s_flag&SF_ASG) == 0)
X					err('L');
X				lsp->s_type = S_ABS;
X				lsp->s_flag |= SF_ASG;
X				lsp->s_value = listaddr = expr();
X				listmode = ALIST;	
X				lsp = NULL;
X				break;
X			case S_MACRO:
X				lsp = NULL;
X				err('M');
X				break;
X			}
X		}
X		if( lsp != NULL ){
X			if(pass==0) {
X				if(lsp->s_type!=S_UND &&
X				    (lsp->s_flag&SF_ASG)==0)
X					lsp->s_flag |= SF_MDF;
X				lsp->s_type = S_ABS;
X				lsp->s_value = dot->s_value;
X			} 
X			else {
X				if((lsp->s_flag&SF_MDF)!=0)
X					err('L');
X				if(lsp->s_type!=S_ABS ||
X				    lsp->s_value!=dot->s_value)
X					err('p');
X			}
X			lsp = NULL;
X		}
X		listmode = CLIST;
X		opcode = sp->s_value;
X		switch(sp->s_type) {
X
X		case S_EQU:
X		case S_SET:
X		case S_MACRO:
X			break;
X
X		case S_IF:
X			inif += 1;
X			skip = (expr()==0);
X			listmode = NLIST;
X			return;
X
X		case S_NAME:
X			n = TITLE_LN;
X			c=getnb();
X			ptr = title;
X			while((*ptr++ = getraw())!=c && --n>0);
X			*(--ptr) = '\0';
X			return;
X
X		case S_ORG:
X			listaddr = dot->s_value = expr();
X			break;
X
X		case S_ENTRY:
X			entaddr = expr();
X			return;
X
X		case S_BYTE:
X			do {
X				if ( (c=getnb())=='\'')
X					ascii(c);
X				else{
X					putback( c );
X					a = expr();
X					byte(a);
X					codeb(a);
X				}
X			}
X			while((c=getnb()) == ',');
X			putback(c);
X			break;
X
X		case S_WORD:
X			do {
X				codew(expr());
X			} 
X			while((c=getnb()) == ',');
X			putback(c);
X			break;
X
X		case S_BLKB:
X			a = expr();
X			while(a--)
X				codeb(0);
X			listmode = ALIST;
X			break;
X
X		case S_OP1:
X			codeb(opcode);
X			break;
X
X		case S_OP2:
X			a = expr();
X			byte(a);
X			codeb(opcode);
X			codeb(a);
X			break;
X
X		case S_OP3:
X			rd = getreg(S_REG);
X			comma();
X			a = expr();
X			byte(a);
X			code3(opcode, rd);
X			codeb(a);
X			break;
X
X		case S_OP4:
X			rd = getreg(S_REG);
X			comma();
X			rs = getreg(S_REG);
X			codeb(opcode | rd<<3 | rs);
X			break;
X
X		case S_OP5:
X			if((rd=getreg(S_REG))!=B && rd!=D)
X				err('a');
X			code4(opcode, rd);
X			break;
X
X		case S_OP6:
X			if((rd=getreg(S_REG)) == PSW){
X				err('R');
X			}
X			code4(opcode, rd);
X			break;
X
X		case S_OP7:
X			if((rd=getreg(S_REG)) == SP)
X				err('a');
X			code4(opcode, rd);
X			break;
X
X		case S_OP8:
X			a = expr();
X			if(a<0 || a>7)
X				err('t');
X			code3(opcode, a&07);
X			break;
X
X		case S_OP9:
X			rs = getreg(S_REG);
X			if(opcode==INR || opcode==DCR)
X				code3(opcode, rs);
X			else
X				codeb(opcode | rs);
X			break;
X
X		case S_OP10:
X			if((rd=getreg(S_REG)) == PSW)
X				err('a');
X			comma();
X			a = expr();
X			code4(opcode, rd);
X			codew(a);
X			break;
X
X		case S_OP11:
X			a = expr();
X			codeb(opcode);
X			codew(a);
X			break;
X
X		default:
X			err('C');
X		}	/* end of case statement */
X	} 
X	while( ( c = getnb()) != '\0' && c != ';' );
X}
X
X/*
X * Process the body of .ascii
X * and .asciz pseudo ops.
X * The z flag is true for a
X * .asciz
X */
Xascii(delim)
Xchar delim;
X{
X	register int c;
X
X	while((c=getmap())!='\0' && c!=delim)
X		codeb(c);
X	if(c == '\0')
X		err('S');
X}
X
X/*
X * Get a register.
X * Type is either S_REG or S_REGP.
X */
Xgetreg(type)
X{
X	register struct sym *sp;
X	register int c;
X	char id[NCPS];
X
X	if(!alpha(c=getnb())) {
X		err('R');
X		putback(c);
X		return(0);
X	}
X	getid(c, id);
X	if((sp=lookup(id, pst))==NULL || type != sp->s_type) {
X		err('R');
X		return(0);
X	}
X	return(sp->s_value);
X}
X
X/*
X * Insure that the value of
X * an expression is a legal
X * byte value.
X * Error if not.
X */
Xbyte(b)
X{
X	if((b&0200)!=0)
X		b |= ~0377;
X	if(b>127 || b<-128)
X		err('R');
X}
X
X/*
X * Check for `,'.
X */
Xcomma()
X{
X	if(getnb() != ',')
X		err('a');
X}
X
X/*
X * Build instructions of the
X * general form xxrrrxxx.
X */
Xcode3(x, r)
X{
X	codeb(x | r<<3);
X}
X
X/*
X * Build instructions of the
X * general form xxrrxxxx.
X */
Xcode4(x, r)
X{
X	codeb(x | (r&6)<<3);
X}
//E*O*F as81.c//

echo x - as82.c
cat | sed -e "s/^X//" > "as82.c" << '//E*O*F as82.c//'
X/*
X * as82.c
X * Expressions.
X */
X#include <stdio.h>
X#include "asm.h"
Xstatic char *as82="@(#)as82.c	1.2";
X
X
X/*
X * Read an expression.
X * Return its value.
X * All expressions are evaluated
X * left to right; parentheses
X * may be used to alter the order
X * of evaluation.
X */
Xint
Xexpr()
X{
X	register int c;
X	int l, r;
X
X	if(!term(&l))
X		return(0);
X	while(validop(c=getopr())) {
X		if(!term(&r)) {
X			err('e');
X			return(l);
X		}
X		switch(c) {
X
X		case '+':
X			l += r;
X			break;
X
X		case '-':
X			l -= r;
X			break;
X
X		case '*':
X			l *= r;
X			break;
X
X		case '/':
X			l /= r;
X			break;
X
X		case '&':
X			l &= r;
X			break;
X
X		case '|':
X			l |= r;
X			break;
X		case '^':
X			l ^= r;
X			break;
X		case '%':
X			l %= r;
X			break;
X		case '<':
X			l <<= r;
X			break;
X		case '>':
X			l >>= r;
X			break;
X		}
X	}
X	putback(c);
X	return(l);
X}
X
X/*
X * Check for valid arithmetic
X * operators.
X */
Xvalidop(c)
X{
X	return( instr( c,"+-*/%&|<>^") >= 0);
X}
X
X/*
X * Get a term.
X * Store its value in the
X * indicated place.
X * Return true if a term is
X * found.
X * If no term is found no
X * characters are read and
X * false is returned.
X */
Xint
Xterm(vp)
Xint *vp;
X{
X	register struct sym *sp;
X	register int c;
X	char id[NCPS];
X
X	/*
X	 * Number.
X	 */
X	if((c=getnb())>='0' && c<='9') {
X		*vp = getnum(c);
X		return(1);
X	/*
X	 * Id.
X	 */
X	} else if(alpha(c)) {
X		getid(c, id);
X		if( strcmp(id,"not")== 0){ /* if the id is 'not' */
X			term(vp);
X			*vp = ~*vp;
X		}else {
X			sp = lookup(id, ust, 'e');
X			if(sp == NULL )
X				err( 'U');
X			else if(sp->s_type == S_UND)
X				err('u');
X			*vp = sp->s_value;
X		}
X		return(1);
X
X	/*
X	 * Unary ops.
X	 */
X	} else if(c=='-') {
X		if(!term(vp)) {
X			err('e');
X			return(0);
X		} 
X		*vp = -*vp;
X	/*
X	 * Parentheses.
X	 */
X	} else if(c == '(') {
X		*vp = expr();
X		if(getnb() != ')')
X			err('(');
X		return(1);
X
X	/*
X	 * Character constant.
X	 */
X	} else if(c == '\'') {
X		*vp = getmap();
X		if(getnb() != '\'')
X		  {
X			putback(c);
X			*vp = *vp+(getmap()<<8);
X			if(getnb() != '\'')
X				err('\'');
X		   }
X		return(1);
X
X	/*
X	 * The current value of DOT
X	 */
X
X	} else if ( c == CDOT ){
X		*vp = dot->s_value;
X		return(1);
X
X	/*
X	 * None.
X	 */
X	} else {
X		putback(c);
X		return(0);
X	}
X}
X
X/*
X * getopr()
X *
X * Get a valid operator.
X *
X * Finds non-unix type operators and returns them as valid
X * Unix operators.
X *
X */
Xgetopr()
X{
X	char ch;
X	char id[ NCPS ];
X	int index;
X
X	if( validop(ch=getnb()) )
X		return(ch);
X	if( alpha(ch))
X		getid( ch, id);
X	else
X		return(ch);
X	if( strcmp( id , "and") == 0)
X		return('&');
X	else if( strcmp( id, "or") == 0)
X		return('|');
X	else if( strcmp( id, "xor") == 0)
X		return('^');
X	else if( strcmp( id, "mod") == 0)
X		return('%');
X	else if( strcmp( id, "shr") == 0)
X		return('>');
X	else if( strcmp( id, "shl") == 0)
X		return('<');
X	else
X		for( index = strlen(id); index==1 ;index--)
X			putback( id[ index] );	
X	return( id[ 0 ]);
X}
//E*O*F as82.c//

echo x - as83.c
cat | sed -e "s/^X//" > "as83.c" << '//E*O*F as83.c//'
X/*
X * Lex.
X */
X#include <stdio.h>
X#include "asm.h"
Xstatic char *sccsid="@(#)as83.c	1.2";
X
X
X/*
X * Get the next non white
X * character.
X */
Xgetnb()
X{
X	register int c;
X
X	while((c=getraw())==' ' || c=='\t');
X	return(c);
X}
X
X/*
X * Get next character from
X * the input.
X * Apply string mappings.
X */
Xgetmap()
X{
X	register int n, c, v;
X
X	if((c=getraw()) == '\\')
X		switch(c = getraw()) {
X
X		case 'n':
X			c = '\n';
X			break;
X
X		case 'r':
X			c = '\r';
X			break;
X
X		case 't':
X			c = '\t';
X			break;
X
X		case 'b':
X			c = '\b';
X			break;
X
X		case '0':
X		case '1':
X		case '2':
X		case '3':
X		case '4':
X		case '5':
X		case '6':
X		case '7':
X			v = n = 0;
X			while(++n<=3 && c>='0' && c<='7') {
X				v = 8*v + c - '0';
X				c = getraw();
X			}
X			putback(c);
X			c = v;
X			break;
X
X		default:
X			putback(c);
X			c = '\\';
X		}
X	return(c);
X}
X
X/*
X * Get next character.
X * Basic routine.
X * Don't screw up on end of
X * line.
X */
Xgetraw()
X{
X	register int c;
X
X	if((c = *sptr) != '\0')
X		++sptr;
X	return(c);
X}
X
X/*
X * Check for alpha.
X */
Xalpha(c)
Xregister int c;
X{
X	return(c=='?'|| (c>='a' && c<='z') || (c>='A' && c<='Z'));
X}
X
X/*
X * Put a character back.
X * A line at a time version
X * of ungetc.
X * Die if too many characters
X * are put back.
X */
Xputback(c)
X{
X	if(c != '\0')
X		if(--sptr < sbuf)
X			abort();
X}
X
X/*
X * Read in an indentifier.
X * Store it (padded with nulls) into the
X * supplied buffer.
X */
Xgetid(c, id)
Xregister int c;
Xchar *id;
X{
X	register char *p;
X
X	p = id;
X	while(alpha(c) || c== '$' || (c>='0' && c<='9')) {
X		if(p < &id[NCPS]){
X			if ( c>='A' && c<='Z' )
X				c |=' ';
X			if( c != '$' )
X				*p++ = c;
X		}
X		c = getraw();
X	}
X	while(p < &id[NCPS])
X		*p++ = '\0';
X	putback(c);
X}
X
X/*
X * instr( c,str)
X *
X * returns the index to locate c in str if c is in str.
X * if c is not in str then returns -1.
X */
X
Xint
Xinstr( c, str )
Xchar c;
Xchar *str;
X{
X	register char *lp;
X	lp = str;
X	while( *lp != '\0' )
X		if( *lp++ == c )
X			return( lp-str-1 );
X	return( -1 );
X}
Xchar
Xucase( c )
Xchar c;
X{
X	if( c >= 'a' && c <= 'z')
X		c = ( c - ( 'a' - 'A' ));
X	return( c );
X}
X
X/*
X * get a number;
X *
X */
Xstatic  char *hexstr = "0123456789ABCDEF";
Xint
Xgetnum(c)
Xchar c;
X{
X	static  char *radix = "BDHOQ";		
X	static int radv[]={ 10,2,10,16,8,8};
X	int value;
X
X	char numbstr[ 16 ];
X	char *np;
X
X	np = numbstr;
X	while( instr( ucase( c ), hexstr) >= 0 ){
X		*np++=ucase( c );
X		c = getraw();
X	}
X	*np-- = '\0';
X	if( instr( ucase( c ), radix ) < 0 ){
X		putback(c );			/* if terminal not right */
X		c = *np;			/* then the previous is	 */
X		if( instr( ucase( c ), radix ) >= 0 )
X			*np = '\0';
X	}
X	/*
X	 * The following code uses the index into the radix array to
X         * calculate the correct index into radix value table and 
X	 * use the value found to determine the correct conversion 
X	 * routine.
X	 *
X	 * Think carefully before changing the following code.
X	 *
X 	 */
X	return( scnnumb( numbstr, radv[ 1 + instr( ucase( c ), radix )]));
X}
X
Xint
Xscnnumb( str ,radix )
Xchar *str;
Xint	radix;
X{
X	int v ,d;
X	v = 0;
X	while( *str )
X		if( (d=instr( *str++, hexstr)) >= 0 && d < radix )
X			v = v*radix + d;
X		else
X			return( err( 'N' ), 0 );
X	return( v );
X}
//E*O*F as83.c//

echo x - as85.c
cat | sed -e "s/^X//" > "as85.c" << '//E*O*F as85.c//'
X/*
X * as85.c
X * Tables.
X */
X#include <stdio.h>
X#include "asm.h"
X
X/*
X * Assorted variables.
X */
Xstatic char *as85="@(#)as85.c	1.2";
X
Xint	listmode;		/* Listing control */
Xint	listaddr;		/* Listing control */
Xint	entaddr;		/* Entry address */
XFILE	*src;			/* Source */
XFILE	*lst;			/* Listing */
XFILE	*obj;			/* Object */
Xint	lflag;			/* -l flag */
Xint	nflag;			/* -n flag */
Xint	sflag;			/* -s flag */
Xint	pass;			/* Which pass? */
Xint	skip;			/* skipping code */
Xint	inif;			/* in an if block */
Xint	lineno;			/* Line number */
Xchar	*sptr;			/* Source pointer */
Xchar	sbuf[SRCMAX];		/* Source buffer */
Xchar	*cptr;			/* Listing code pointer */
Xchar	cbuf[CLMAX];		/* Listing code buffer */
Xchar	*eptr;			/* Error pointer */
Xchar	ebuf[ERRMAX];		/* Error buffer */
Xint	cadr;			/* Object address */
Xint	crec;			/* Object index */
Xchar	crbf[CBMAX];		/* Object buffer */
Xint	errcnt;			/* error count   */
Xint	page;			/* current page number */
Xint	pline;			/* lines on the current page */
Xchar	title[TITLE_LN+1];	/* program listing title*/
Xstruct sym *hashtbl[ HASH ];	/* symbol table hashbuckets	*/ 
X
X/*
X * User symbol table.
X * The first item must be '$'.
X */
Xstruct sym ust[USERMAX] = {
X	"$",	NULL,NULL,	S_ABS,		SF_ASG,	0
X};
X
X/*
X * Opcode table.
X * Also contains pseudo operations and
X * registers.
X */
Xstruct sym pst[] = {
X	"b",NULL,NULL,		S_REG,		0,	0,	NULL,
X	"c",NULL,NULL,		S_REG,		0,	1,	NULL,
X	"d",NULL,NULL,		S_REG,		0,	2,	NULL,
X	"e",NULL,NULL,		S_REG,		0,	3,	NULL,
X	"h",NULL,NULL,		S_REG,		0,	4,	NULL,
X	"l",NULL,NULL,		S_REG,		0,	5,	NULL,
X	"m",NULL,NULL,		S_REG,		0,	6,	NULL,
X	"a",NULL,NULL,		S_REG,		0,	7,	NULL,
X	"sp",NULL,NULL,		S_REG,		0,	SP,	NULL,
X	"psw",NULL,NULL,		S_REG,		0,	PSW,	NULL,
X	"org",NULL,NULL,		S_ORG,		0,	0,	NULL,
X	"end",NULL,NULL,		S_ENTRY,	0,	0,	NULL,
X	"db",NULL,NULL,		S_BYTE,		0,	0,	NULL,
X	"dw",NULL,NULL,		S_WORD,		0,	0,	NULL,
X	"ds",NULL,NULL,		S_BLKB,		0,	0,	NULL,
X	"set",NULL,NULL,		S_SET,		0,	0,	NULL,
X	"equ",NULL,NULL,		S_EQU,		0,	0,	NULL,
X	"if",NULL,NULL,		S_IF,		0,	0,	NULL,
X	"endif",NULL,NULL,	S_ENDIF,	0,	0,	NULL,
X	"macro",NULL,NULL,	S_MACRO,	0,	0,	NULL,
X	"endm",NULL,NULL,		S_ENDM,		0,	0,	NULL,
X	"title",NULL,NULL,	S_NAME,		0,	0,	NULL,
X	"pchl",NULL,NULL,		S_OP1,		0,	0351,	NULL,
X	"ret",NULL,NULL,		S_OP1,		0,	0311,	NULL,
X	"rc",NULL,NULL,		S_OP1,		0,	0330,	NULL,
X	"rnc",NULL,NULL,		S_OP1,		0,	0320,	NULL,
X	"rz",NULL,NULL,		S_OP1,		0,	0310,	NULL,
X	"rnz",NULL,NULL,		S_OP1,		0,	0300,	NULL,
X	"rm",NULL,NULL,		S_OP1,		0,	0370,	NULL,
X	"rp",NULL,NULL,		S_OP1,		0,	0360,	NULL,
X	"rpe",NULL,NULL,		S_OP1,		0,	0350,	NULL,
X	"rpo",NULL,NULL,		S_OP1,		0,	0340,	NULL,
X	"xchg",NULL,NULL,		S_OP1,		0,	0353,	NULL,
X	"sphl",NULL,NULL,		S_OP1,		0,	0371,	NULL,
X	"cma",NULL,NULL,		S_OP1,		0,	0057,	NULL,
X	"cmc",NULL,NULL,		S_OP1,		0,	0077,	NULL,
X	"daa",NULL,NULL,		S_OP1,		0,	0047,	NULL,
X	"rlc",NULL,NULL,		S_OP1,		0,	0007,	NULL,
X	"rrc",NULL,NULL,		S_OP1,		0,	0017,	NULL,
X	"ral",NULL,NULL,		S_OP1,		0,	0027,	NULL,
X	"rar",NULL,NULL,		S_OP1,		0,	0037,	NULL,
X	"xthl",NULL,NULL,		S_OP1,		0,	0343,	NULL,
X	"ei",NULL,NULL,		S_OP1,		0,	0373,	NULL,
X	"di",NULL,NULL,		S_OP1,		0,	0363,	NULL,
X	"stc",NULL,NULL,		S_OP1,		0,	0067,	NULL,
X	"nop",NULL,NULL,		S_OP1,		0,	0000,	NULL,
X	"hlt",NULL,NULL,		S_OP1,		0,	0166,	NULL,
X	"in",NULL,NULL,		S_OP2,		0,	0333,	NULL,
X	"out",NULL,NULL,		S_OP2,		0,	0323,	NULL,
X	"adi",NULL,NULL,		S_OP2,		0,	0306,	NULL,
X	"aci",NULL,NULL,		S_OP2,		0,	0316,	NULL,
X	"sui",NULL,NULL,		S_OP2,		0,	0326,	NULL,
X	"sbi",NULL,NULL,		S_OP2,		0,	0336,	NULL,
X	"ani",NULL,NULL,		S_OP2,		0,	0346,	NULL,
X	"xri",NULL,NULL,		S_OP2,		0,	0356,	NULL,
X	"ori",NULL,NULL,		S_OP2,		0,	0366,	NULL,
X	"cpi",NULL,NULL,		S_OP2,		0,	0376,	NULL,
X	"mvi",NULL,NULL,		S_OP3,		0,	0006,	NULL,
X	"mov",NULL,NULL,		S_OP4,		0,	0100,	NULL,
X	"ldax",NULL,NULL,		S_OP5,		0,	0012,	NULL,
X	"stax",NULL,NULL,		S_OP5,		0,	0002,	NULL,
X	"dad",NULL,NULL,		S_OP6,		0,	0011,	NULL,
X	"inx",NULL,NULL,		S_OP6,		0,	0003,	NULL,
X	"dcx",NULL,NULL,		S_OP6,		0,	0013,	NULL,
X	"push",NULL,NULL,		S_OP7,		0,	0305,	NULL,
X	"pop",NULL,NULL,		S_OP7,		0,	0301,	NULL,
X	"rst",NULL,NULL,		S_OP8,		0,	0307,	NULL,
X	"add",NULL,NULL,		S_OP9,		0,	0200,	NULL,
X	"sub",NULL,NULL,		S_OP9,		0,	0220,	NULL,
X	"adc",NULL,NULL,		S_OP9,		0,	0210,	NULL,
X	"sbb",NULL,NULL,		S_OP9,		0,	0230,	NULL,
X	"ana",NULL,NULL,		S_OP9,		0,	0240,	NULL,
X	"xra",NULL,NULL,		S_OP9,		0,	0250,	NULL,
X	"ora",NULL,NULL,		S_OP9,		0,	0260,	NULL,
X	"cmp",NULL,NULL,		S_OP9,		0,	0270,	NULL,
X	"inr",NULL,NULL,		S_OP9,		0,	0004,	NULL,
X	"dcr",NULL,NULL,		S_OP9,		0,	0005,	NULL,
X	"lxi",NULL,NULL,		S_OP10,		0,	0001,	NULL,
X	"jpo",NULL,NULL,		S_OP11,		0,	0342,	NULL,
X	"jpe",NULL,NULL,		S_OP11,		0,	0352,	NULL,
X	"jm",NULL,NULL,		S_OP11,		0,	0372,	NULL,
X	"jp",NULL,NULL,		S_OP11,		0,	0362,	NULL,
X	"jnz",NULL,NULL,		S_OP11,		0,	0302,	NULL,
X	"jz",NULL,NULL,		S_OP11,		0,	0312,	NULL,
X	"jnc",NULL,NULL,		S_OP11,		0,	0322,	NULL,
X	"jc",NULL,NULL,		S_OP11,		0,	0332,	NULL,
X	"cpo",NULL,NULL,		S_OP11,		0,	0344,	NULL,
X	"cpe",NULL,NULL,		S_OP11,		0,	0354,	NULL,
X	"cm",NULL,NULL,		S_OP11,		0,	0374,	NULL,
X	"cp",NULL,NULL,		S_OP11,		0,	0364,	NULL,
X	"cnz",NULL,NULL,		S_OP11,		0,	0304,	NULL,
X	"cz",NULL,NULL,		S_OP11,		0,	0314,	NULL,
X	"cnc",NULL,NULL,		S_OP11,		0,	0324,	NULL,
X	"cc",NULL,NULL,		S_OP11,		0,	0334,	NULL,
X	"call",NULL,NULL,		S_OP11,		0,	0315,	NULL,
X	"jmp",NULL,NULL,		S_OP11,		0,	0303,	NULL,
X	"lda",NULL,NULL,		S_OP11,		0,	0072,	NULL,
X	"sta",NULL,NULL,		S_OP11,		0,	0062,	NULL,
X	"lhld",NULL,NULL,		S_OP11,		0,	0052,	NULL,
X	"shld",NULL,NULL,		S_OP11,		0,	0042,	NULL,
X};
X
X/*
X * Pointers to the end of the
X * tables.
X * Must be here!
X */
Xstruct sym *pptr = &pst[sizeof(pst)/sizeof(pst[0])]; /* Ditto */
Xstruct sym *uptr = &ust[1];	/* Pointer to end of ust */
X
//E*O*F as85.c//

echo x - asmain.c
cat | sed -e "s/^X//" > "asmain.c" << '//E*O*F asmain.c//'
X
X/*
X * asm.c
X * Mainline.
X *
X */
X#include <stdio.h>
X#include "asm.h"
Xstatic char *ident="@(#)asmain.c	1.4";
X
X/*
X * This is the mainline.
X * It scans the command line,
X * collects up a source file,
X * sets option flags and calls
X * the assembler proper.
X */
Xstatic int cflag = 0;		/* cross reference on flag	*/
X
Xmain(argc, argv)
Xchar *argv[];
X{
X	register int i, c;
X	register char *p;
X	char *file;
X
X	file = NULL;
X	for(i=1; i<argc; ++i) {
X		p = argv[i];
X		if(*p++ == '-') {
X			while(c = *p++)
X				switch(c) {
X
X				case 'l':
X				case 'L':
X					++lflag;
X					break;
X				case 'c':
X				case 'C':
X					++lflag;
X					++cflag;
X					break;
X
X				case 'n':
X				case 'N':
X					++nflag;
X					break;
X
X				case 's':
X				case 'S':
X					++lflag;
X					++sflag;
X					break;
X				default:
X					usage();
X				}
X		}
X		else
X		{
X			file = argv[i];
X			if(file == NULL)
X				usage();
X			assemble(file);
X		}
X	}
X}
X
X/*
X * Assemble a file.
X */
X
Xassemble(file)
Xchar *file;
X{
X	char fn[40];
X	int index;
X
X	strncpy(title,file,20);
X	for ( index = 0 ; index < HASH ; index ++)
X		hashtbl[ index ] = NULL;
X	name(fn, file, "asm", 0);
X	if((src=fopen(fn, "r")) == NULL) {
X		fprintf(stderr, "%s: cannot open\n", fn);
X		exit(1);
X	}
X	if(lflag) {
X		name(fn, file, "lst", 1);
X		if((lst=fopen(fn, "w")) == NULL) {
X			fprintf(stderr, "%s: cannot create\n", fn);
X			exit(1);
X		}
X	}
X	if(!nflag) {
X		name(fn, file, "hex", 1);
X		if((obj=fopen(fn, "w")) == NULL) {
X			fprintf(stderr, "%s: cannot create\n", fn);
X			exit(1);
X		}
X		fprintf(obj, "\n");
X	}
X	page = 1;
X	for(pass=0; pass<2; ++pass) {
X		skip = 0; 			/* not currently skipping*/
X		rewind(src);
X		errcnt = 0;
X		lineno = 0;
X		dot->s_type = S_ABS;
X		dot->s_flag = SF_ASG;
X		dot->s_value = 0;
X		if(pass && lflag )
X			top(0);
X
X		while(fgets(sbuf, SRCMAX , src) != NULL) {
X			++lineno;
X			sptr = sbuf;
X			cptr = cbuf;
X			eptr = ebuf;
X			asmline();
X			if(pass) {
X				outerrors();
X				if(lflag)
X					outlisting();
X			}
X		}
X	}
X	if(errcnt)
X		printf(" Total errors = %5d\n",errcnt);
X	if(lflag){
X		if(errcnt){
X			fprintf(lst,"\n Total number of errors = %5d \n",errcnt)
X				;
X		}
X		table();
X		fclose(lst);
X	}
X	if(!nflag){
X		cflush(1);
X		fclose(obj);
X	}
X	printf(" Total bytes assembled = %04X\n",dot->s_value);
X	fclose(src);
X}
X
X/*
X * If the user screws up, put out
X * a usage message.
X * Then quit.
X * Not much sense staying around.
X */
Xusage()
X{
X	fprintf(stderr, "Usage:%4s  [-ln] file file ...\n",TASK);
X	fprintf(stderr, "where: \n");
X	fprintf(stderr, "      l = make a listing \n");
X	fprintf(stderr, " and  n = don't make an object file\n");
X	exit(1);
X}
X
X/*
X * Build RSX file names.
X * The mode argument is either 0
X * which means default, or 1 which
X * means replace with.
X */
Xname(fn, file, type, mode)
Xchar *fn, *file, *type;
X{
X	register char *p1, *p2;
X	register int c;
X
X	p1 = fn;
X	p2 = file;
X	while((c = *p2++) && c!='.')
X		*p1++ = c;
X	if(mode == 0) {
X		if(c == '.') {
X			do {
X				*p1++ = c;
X			} 
X			while(c = *p2++);
X		} 
X		else {
X			*p1++ = '.';
X			p2 = type;
X			while(c = *p2++)
X				*p1++ = c;
X		}
X	} 
X	else {
X		*p1++ = '.';
X		p2 = type;
X		while(c = *p2++)
X			*p1++ = c;
X	}
X	*p1 = '\0';
X}
X
X/*
X * Output code byte.
X * Save it in the per line
X * buffer for outlisting.
X * Update dot.
X */
Xcodeb(b)
X{
X	b &= 0377;
X	if(cptr < &cbuf[CLMAX])
X		*cptr++ = b;
X	if(pass && !nflag) {
X		if(crec>=CBMAX || cadr+crec!=dot->s_value) {
X			cflush(0);
X			cadr = dot->s_value;
X		}
X		crbf[crec++] = b;
X	}
X	++dot->s_value;
X}
X
X/*
X * Output a word.
X * Low then high.
X */
Xcodew(w)
X{
X	if(BSWAP)codeb(w>>8);
X	codeb(w);
X	if(!BSWAP)codeb(w>>8);
X}
X
X/*
X * Signal error.
X * Add it to the error buffer
X * if not already there.
X */
Xerr(c)
X{
X	register char *p;
X
X	errcnt+=1;
X	p = ebuf;
X	if(eptr == &ebuf[ERRMAX-1]) c ='*';
X	while(p < eptr)
X		if(*p++ == c)
X			return;
X	*p++ = c;
X	if ( p> &ebuf[ERRMAX])
X		--p;
X	eptr = p;
X}
X
X/*
X * Format a line for the
X * listing.
X * More work than you would
X * think.
X * Only called if -l.
X */
Xoutlisting()
X{
X	register int nbytes;
X	register char *cp;
X	int w1, w2, w3, w4;
X
X	if(listmode == NLIST)
X		return;
X	for(cp = eptr; cp < &ebuf[ERRMAX-1]; *cp++ = ' ');
X	*cp='\0';
X	if(!(--pline ))
X		top(1);
X	if(listmode == SLIST)
X		fprintf(lst, "%.6s      ", ebuf);
X	else
X		fprintf(lst, "%.6s %04X ", ebuf, listaddr);
X	if(listmode == ALIST)
X		fprintf(lst, "%9s%4d %s", "", lineno, sbuf);
X	else {
X		nbytes = cptr-cbuf;
X		w1 = cbuf[0]&0377;
X		w2 = cbuf[1]&0377;
X		w3 = cbuf[2]&0377;
X		w4 = cbuf[3]&0377;
X		switch(nbytes) {
X		case 0:
X			fprintf(lst, "%9s", ""); 
X			break;
X		case 1:
X			fprintf(lst, "%02X%7s", w1, ""); 
X			break;
X		case 2:
X			fprintf(lst, "%02X%02X%5s", w1, w2, ""); 
X			break;
X		case 3:
X			fprintf(lst, "%02X%02X%02X%3s", w1, w2, w3,""); 
X			break;
X		default:
X			fprintf(lst, "%02X%02X%02X%02X%1s", w1, w2, w3,w4,"");
X		}
X		fprintf(lst, "%4d\t%s", lineno, sbuf);
X		cp = &cbuf[4];
X		while((nbytes -= 4) > 0) {
X			if( --pline < 0  )
X				top(1);
X			listaddr += 4;
X			fprintf(lst, "%5s%04X ", "",listaddr );
X			switch(nbytes) {
X			case 0:	
X				break;
X			case 1:
X				w1 = cp[0]&0377;
X				fprintf(lst, "%02X\n", w1);
X				break;
X			case 2:
X				w1 = cp[0]&0377;
X				w2 = cp[1]&0377;
X				fprintf(lst, "%02X%02X\n", w1, w2);
X				break;
X			case 3:
X				w1 = cp[0]&0377;
X				w2 = cp[1]&0377;
X				w3 = cp[2]&0377;
X				fprintf(lst, "%02X%02X%02X\n", w1, w2, w3);
X				break;
X			default:
X				w1 = cp[0]&0377;
X				w2 = cp[1]&0377;
X				w3 = cp[2]&0377;
X				w4 = cp[3]&0377;
X				fprintf(lst, "%02X%02X%02X%02X\n", w1, w2, w3,w4);
X			}
X			cp += 4;
X		}
X	}
X}
X
X/*
X * Write errors to the tty.
X */
Xouterrors()
X{
X	register char *p;
X	if( lflag )
X		return;
X
X	if( eptr > ebuf ){
X		*eptr='\0';
X		printf("%s\t%04d\t%s", ebuf, lineno, sbuf);
X	}
X}
X
X/*
X * Flush the binary code
X * buffer.
X */
X
Xcflush(lf)
Xint lf;
X{
X	int chksum;		/* checksum for hex file format */
X	register int i;
X
X	if(crec == 0)
X		return;
X	fprintf( obj, ":%02X%04X00",crec,cadr );
X	chksum = 0;
X	chksum += crec;
X	chksum += (( cadr >> 8)& 0xFF);
X	chksum += ( cadr & 0xFF);
X	for(i=0; i<crec; ++i){
X		fprintf( obj,"%02X", crbf[ i ]&0xFF );
X		chksum += crbf[ i ]&0xFF;
X	}
X	fprintf( obj,"%02X\n" , ( 00 -( chksum &0xFF))&0xFF );
X	crec = 0;
X	if(lf)
X		fprintf(obj,":00000000\n");
X}
X/* 
X * Print out the user symbol table
X */
Xtable()
X{
X	register struct sym *mine ;
X	register struct hu *howu;
X	int line,indx,count;
X
X	count =line = 0;
X	page = 1;
X	fprintf(lst,"\f\n%-40s  Symbol table dump \t\t  Page %3d\n\n\n",
X	title,page++) ;
X	for( indx = 0 ; indx < HASH ; indx++){
X		for(mine = hashtbl[ indx ]; mine != NULL; mine = mine->right ){
X			if( line >= mxline ){
X				fprintf(lst,
X				"\f\n Symbol table dump page %3d\n\n\n"
X				    ,page++);
X				line = 0;
X			}
X			fprintf(lst,"%10s = %04X  ",mine->s_name,mine->s_value);
X			if( cflag ){
X				for( howu = mine->howused; howu != NULL ;
X						 howu = howu->next ){
X					    if( count >= 10 ){
X						fprintf(lst,"\n                   ");
X						line++;
X						count = 0;
X					}
X					fprintf(lst,"%6d %c :", howu->line, howu->how );
X					count++;
X				}
X				count = 0;
X				line++;
X				fprintf(lst,"\n");
X			}
X			else{ 
X				if( count >= 4 ){
X					line++;
X					count = 0;
X					fprintf(lst,"\n");
X				}
X				count++;
X			}
X		}
X	}
X	fprintf(lst,"\f\n");
X	fflush(lst);
X}
X
X/*
X *
X * Top - Print the label at the top of the page
X *
X */
X
Xtop(mode)
Xint mode;
X{
X
X	if(mode)putc('\f',lst);
X	pline = mxline;
X	fprintf(lst,"\n %-40s KSE cross assembler for the %-5s",title,MICRO);
X	fprintf(lst,"      page %3d",page++);
X	fprintf(lst," \n\n\n");
X}
X
Xint
Xhash( id )
Xchar *id;
X{
X	if( *id >= 'a' && *id <= 'z' )
X		return( *id - 'a');
X	else if( *id == '?' )
X		return( 26 );
X	else
X		return( 27 );
X}
Xstruct sym *
Xlkup( id , howu )
Xchar *id;
Xchar howu;
X{
X	struct sym *np;
X	struct hu  *usage;
X
X	for( np = hashtbl[hash(id)]; np != NULL; np = np->right ){
X		if( strcmp( id, np->s_name ) == 0){
X			if( cflag ){
X				for( usage = np->howused;
X				usage->line != lineno && usage->next != NULL;
X				usage = usage->next )
X					    ;
X				if( usage->line != lineno ){
X					usage->next =(struct hu *) 
X						malloc( sizeof( *usage));
X					if( usage->next != NULL){
X						usage->next->line = lineno;
X						usage->next->how  =howu;
X						usage->next->next = NULL;
X					} 
X				}
X			}
X			return( np );
X		}
X	}
X	return(NULL );
X}
Xstruct sym *
Xinstall( id , howu )
Xchar *id;
Xchar howu;
X{
X	struct sym *np,*lp;
X	struct sym *lkup();
X	int hashval;
X
X	if( (np = lkup( id , howu ) ) == NULL ) {
X		np= ( struct sym *)malloc( sizeof( *np ));
X		if(np == NULL ){
X			fprintf(stderr,"in line %d ",lineno);
X			fprintf(stderr,"Symbol table overflow\n");
X			return( NULL );
X		}
X		np->right = NULL;
X		np->left  = NULL;
X		np->s_type= 0;
X		np->s_flag= 0;
X		np->s_value = 0;
X		if( cflag ){
X			np->howused = (struct hu *)malloc( sizeof( *np->howused));
X			if( np->howused != NULL ){
X				np->howused->how = howu;
X				np->howused->line = lineno;
X				np->howused->next = NULL;
X			}
X		}
X		strcpy(np->s_name,id);
X		hashval = hash( id );
X		if( hashtbl[ hashval ] == NULL ){
X			hashtbl[ hashval ] = np;
X		}
X		else if( strcmp( id , hashtbl[hashval]->s_name ) > 0 ){
X			hashtbl[ hashval ]->left = np;
X			np->right = hashtbl[ hashval ];
X			hashtbl[ hashval] = np;
X		} 
X		else
X			for( lp = hashtbl[hashval];lp != NULL;lp = lp->right) {
X				if( lp->right == NULL ){
X					lp->right = np;
X					np->left  = lp;
X					break;	
X				}
X				else if ( strcmp( id, lp->right->s_name ) < 0){
X					np->right = lp->right;
X					lp->right->left = np;
X					lp->right = np;
X					np->left  = lp;
X					break;
X				}
X			}
X	}
X	return( np );
X}
X/*
X * Lookup id.
X * The table is either the pst or
X * the ust.
X */
Xstruct sym *
Xlookup(id, stp, howu)
Xchar *id;
Xregister struct sym *stp;
Xchar howu;
X{
X	if(stp == ust)
X		return(install( id ,howu ));
X	while(stp < pptr) 
X		if(strcmp(id, stp->s_name) == 0)
X			break;
X		else
X			++stp;
X	if( stp >= pptr )
X		return( NULL);
X	else
X		return( stp );
X}
//E*O*F asmain.c//

exit 0



More information about the Comp.sources.unix mailing list