[comp.os.minix] Small-C part 1 of 3

USADACS@wsmr-simtel20.army.mil (Al McIntosh) (12/11/88)

20-May-86 17:20:03-MDT,56738;000000000001
Return-Path: <unix-sources-request@BRL.ARPA>
Received: from BRL-SMOKE.ARPA by SIMTEL20.ARPA with TCP; Tue 20 May 86 17:18:45-MDT
Received: from USENET by SMOKE.BRL.ARPA id a003729; 20 May 86 13:04 EDT
From: sources-request@panda.uucp
Newsgroups: mod.sources
Subject: Small C compiler version C3.0R1.1 (part 1 of 3)
Message-ID: <1890@panda.UUCP>
Date: 19 May 86 12:22:06 GMT
Sender: jpn@panda.uucp
Approved: jpn@panda.UUCP
To:       unix-sources@brl-smoke.arpa

Mod.sources:  Volume 5, Issue 7
Submitted by: genrad!linus!mnetor!clewis (Chris Lewis)

There've been quite a few requests for this via net.micro.cpm, so's I
thought I'd post it thru mod.sources.  This is Ron Cain's original Small
C compiler, but highly extended.  Included are code generators for 8080,
6809, 68000, and VAX, as well as run-time support for 8080 CPM, VAX BSD4.1,
and a FLEX 6809 environment.  See the README for a description of Small C's
limitations.

#! /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:
#	README
#	M_README
#	Makefile
#	Makefile.bsd
#	code8080.c
#	codeas09.c
#	codem68k.c
#	codevax.c
#	data.c
#	data.h
# This archive created: Sun May 18 18:28:42 1986
export PATH; PATH=/bin:$PATH
echo shar: extracting "'README'" '(2959 characters)'
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
cat << \SHAR_EOF > 'README'
			Small C version C3.0R1.1
			      (SCC3)

			    Chris Lewis

This directory contains the source for a version of Ron Cain's Small C 
compiler that I have heavily modified - beyond the Small-C V2.0 later
published in Dr. Dobbs.  This compiler generates assembler source code that
needs to be assembled and linked to make a running program.

Small C is a public domain compiler for a subset of C.  The main things
lacking are "#if", structs/unions, doubles/floats/longs and more than
one level of indirection.  Even so, it's powerful enough to be able to
compile itself.  It's also lots of fun to play around with.  It could
use lots of more work (eg: a real scanner), but what the heck...
Retargetting the compiler requires only relinking the frontend with a new
code generator.

Code generators for 6809 (MIT UNIX-like assembler), M68K (Motorola V/68 UNIX
assembler), VAX (BSD 4.1 assembler), and 8080 (RMAC assembler) are provided.

Users having access to System V make should be able to use the Makefile 
without any modification except for INCDIR and LIBDIR (where you'd like 
to put the compiler itself).

Users not having access to System V will probably have to rewrite the Makefile.
[ I have provided a Makefile that seems to work with bsd systems - mod]

WARNING: you will probably see a great deal of compilation warnings when
you compile this compiler with a "real" UNIX C.  Don't worry - this is
*perfectly* normal - Small C is a subset of real C, and in order to
keep the compiler in this subset you have to bend the rules somewhat.
The only time where this might cause a problem is where pointers are
"different" from ints (ie: different length or on non-byte-addressible
machines).  Small C assumes that ints are the same as pointers.

Invocation:
	scc<6809|vax|m68k|8080> filename

There are other options available - see main.c for details.

The code generated by these compilers need a run-time support library
for two things: operations that are "hard" on a particular processor
(eg: 16 bit multiply on an 8080), or O/S interface (vax is BSD 4.1,
6809 is FLEX, 8080 is CPM, never had one for M68k).

Status: the 6809, VAX and 8080 versions work last I checked - a problem or
two may have crept in during the implementation of the compile/assemble/and
link code for machines that support it.  The M68k version has never been
tested.  I don't have a Pyramid version because Pyrcorp seems reluctant
to publish instruction set information.

So you want to write a new coder do you?  Well, it's easy - read the
comments in one of the coders.  You should not have to modify *any* of
the existing files, just write a new codexxx.c file.  Please contact
me if you run into trouble.  I would be greatly interested in any new
coders or bug reports in the compilers.  As far as I am aware, the
major restriction on porting this thing for different targets is that
pointers and integers *must* be the same length, alignment, and be
interchangeable.
SHAR_EOF
if test 2959 -ne "`wc -c < 'README'`"
then
	echo shar: error transmitting "'README'" '(should have been 2959 characters)'
fi
fi
echo shar: extracting "'M_README'" '(550 characters)'
if test -f 'M_README'
then
	echo shar: will not over-write existing file "'M_README'"
else
cat << \SHAR_EOF > 'M_README'
		***  Moderator's README ***

This directory contains the base source code for the smallC compiler
(actually three versions:  the 8080, 6809 and vax code generators are
here also.)

The "includes" directory contains headers which are intended to be included in
user programs - the place where these files reside should be set in the Makefile
as INCDIR.  The directories "6809", "8080", and "vax" contain runtime support
for the respective compilers.  The directory "lib" contains the source code
for some common C library functions (portable ones).
SHAR_EOF
if test 550 -ne "`wc -c < 'M_README'`"
then
	echo shar: error transmitting "'M_README'" '(should have been 550 characters)'
fi
fi
echo shar: extracting "'Makefile'" '(1429 characters)'
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
#	Requires System V make
#	@(#)Makefile 1.5 86/05/13
.SUFFIXES:	.o .c .c~ .h .h~
.PRECIOUS:	scclib.a
#	You'll probabably want to change these.  These are used by the compilers#	to figure out where the include files should go.
TARGDIR = /u/clewis/lib
INCDIR = "/u/clewis/src/scc/include/"

INSTFLAGS = -DINCDIR=$(INCDIR)
CFLAGS = '$(INSTFLAGS)' -O
AR = ar
ARFLAGS = rv

LIB = scclib.a

FE =	$(LIB)(data.o) \
	$(LIB)(error.o) \
	$(LIB)(expr.o) \
	$(LIB)(function.o) \
	$(LIB)(gen.o) \
	$(LIB)(io.o) \
	$(LIB)(lex.o) \
	$(LIB)(main.o) \
	$(LIB)(preproc.o) \
	$(LIB)(primary.o) \
	$(LIB)(stmt.o) \
	$(LIB)(sym.o) \
	$(LIB)(while.o)

all:	scc8080 sccas09 sccvax sccm68k

$(FE) code8080.o codeas09.o codevax.o codem68k.o: defs.h data.h

install:	all
	mv sccvax scc8080 sccas09 sccm68k $(TARGDIR)

#Alternately, you may have to do an lorder
$(LIB):	$(FE)
	-ranlib $(LIB)
	-ucb ranlib $(LIB)

scc8080:	code8080.o $(LIB)
	$(CC) -o scc8080 $(CFLAGS) $(LIB) code8080.o

sccas09:	codeas09.o $(LIB)
	$(CC) -o sccas09 $(CFLAGS) $(LIB) codeas09.o

sccvax:		codevax.o $(LIB)
	$(CC) -o sccvax $(CFLAGS) $(LIB) codevax.o

sccm68k:	codem68k.o $(LIB)
	$(CC) -o sccm68k $(CFLAGS) $(LIB) codem68k.o

print:
	pr -n defs.h data.h data.c error.c expr.c function.c gen.c \
		io.c lex.c main.c preproc.c primary.c stmt.c \
		sym.c while.c code*.c | lp
clean:
	rm -f $(LIB) code8080.o codeas09.o codevax.o codem68k.o \
		     sccvax scc8080 sccas09 sccm68k
SHAR_EOF
if test 1429 -ne "`wc -c < 'Makefile'`"
then
	echo shar: error transmitting "'Makefile'" '(should have been 1429 characters)'
fi
fi
echo shar: extracting "'Makefile.bsd'" '(1359 characters)'
if test -f 'Makefile.bsd'
then
	echo shar: will not over-write existing file "'Makefile.bsd'"
else
cat << \SHAR_EOF > 'Makefile.bsd'
#	I couldn't get the supplied makefile to work, so I wrote one for
#       BSD systems      - John Nelson, moderator, mod.sources
#
#	You'll probabably want to change these.  These are used by the compilers#	to figure out where the include files should go.
TARGDIR = /u/clewis/lib
INCDIR = "/u/clewis/src/scc/include/"

INSTFLAGS = -DINCDIR=$(INCDIR)
CFLAGS = '$(INSTFLAGS)' -O
AR = ar
ARFLAGS = rv

LIB = scclib.a

FE =	data.o \
	error.o \
	expr.o \
	function.o \
	gen.o \
	io.o \
	lex.o \
	main.o \
	preproc.o \
	primary.o \
	stmt.o \
	sym.o \
	while.o

all:	scc8080 sccas09 sccvax sccm68k

$(FE) code8080.o codeas09.o codevax.o codem68k.o: defs.h data.h

install:	all
	mv sccvax scc8080 sccas09 sccm68k $(TARGDIR)

#Alternately, you may have to do an lorder
$(LIB):	$(FE)
	-rm $@
	ar q $@ $(FE)
	-ranlib $(LIB)

scc8080:	code8080.o $(LIB)
	$(CC) -o scc8080 $(CFLAGS) $(LIB) code8080.o

sccas09:	codeas09.o $(LIB)
	$(CC) -o sccas09 $(CFLAGS) $(LIB) codeas09.o

sccvax:		codevax.o $(LIB)
	$(CC) -o sccvax $(CFLAGS) $(LIB) codevax.o

sccm68k:	codem68k.o $(LIB)
	$(CC) -o sccm68k $(CFLAGS) $(LIB) codem68k.o

print:
	pr -n defs.h data.h data.c error.c expr.c function.c gen.c \
		io.c lex.c main.c preproc.c primary.c stmt.c \
		sym.c while.c code*.c | lp
clean:
	rm -f $(LIB) code8080.o codeas09.o codevax.o codem68k.o \
		     sccvax scc8080 sccas09 sccm68k
SHAR_EOF
if test 1359 -ne "`wc -c < 'Makefile.bsd'`"
then
	echo shar: error transmitting "'Makefile.bsd'" '(should have been 1359 characters)'
fi
fi
echo shar: extracting "'code8080.c'" '(9671 characters)'
if test -f 'code8080.c'
then
	echo shar: will not over-write existing file "'code8080.c'"
else
cat << \SHAR_EOF > 'code8080.c'
/*	File code8080.c: 2.2 (84/08/31,10:05:09) */
/*% cc -O -c %
 *
 */

#include <stdio.h>
#include "defs.h"
#include "data.h"

/*	Define ASNM and LDNM to the names of the assembler and linker
	respectively */

/*
 *	Some predefinitions:
 *
 *	INTSIZE is the size of an integer in the target machine
 *	BYTEOFF is the offset of an byte within an integer on the
 *		target machine. (ie: 8080,pdp11 = 0, 6809 = 1,
 *		360 = 3)
 *	This compiler assumes that an integer is the SAME length as
 *	a pointer - in fact, the compiler uses INTSIZE for both.
 */
#define	INTSIZE	2
#define	BYTEOFF	0

/*
 *	print all assembler info before any code is generated
 *
 */
header ()
{
	outstr (";	Small C 8080;\n;\tCoder (2.4,84/11/27)\n;");
	FEvers();
	nl ();
	ol ("extrn	?gchar,?gint,?pchar,?pint,?bool");
	ol ("extrn	?sxt");
	ol ("extrn	?or,?and,?xor");
	ol ("extrn	?eq,?ne,?gt,?le,?ge,?lt,?uge,?ult,?ugt,?ule");
	ol ("extrn	?asr,?asl");
	ol ("extrn	?sub,?neg,?com,?lneg,?mul,?div");
	ol ("extrn	?case");
}

nl ()
{
	outbyte (EOL);
}
initmac()
{
	defmac("cpm\t1");
	defmac("I8080\t1");
	defmac("RMAC\t1");
	defmac("smallc\t1");
}

galign(t)
int	t;
{
	return(t);
}

/*
 *	return size of an integer
 */
intsize() {
	return(INTSIZE);
}

/*
 *	return offset of ls byte within word
 *	(ie: 8080 & pdp11 is 0, 6809 is 1, 360 is 3)
 */
byteoff() {
	return(BYTEOFF);
}

/*
 *	Output internal generated label prefix
 */
olprfix() {
	outbyte('?');
}

/*
 *	Output a label definition terminator
 */
col ()
{
	outbyte (58);
}

/*
 *	begin a comment line for the assembler
 *
 */
comment ()
{
	outbyte (';');
}

/*
 *	Emit user label prefix
 */
prefix ()
{
}


/*
 *	print any assembler stuff needed after all code
 *
 */
trailer ()
{
	ol ("end");
}

/*
 *	function prologue
 */
prologue ()
{
}

/*
 *	text (code) segment
 */
gtext ()
{
	ol ("cseg");
}

/*
 *	data segment
 */
gdata ()
{
	ol ("dseg");
}

/*
 *  Output the variable symbol at scptr as an extrn or a public
 */
ppubext(scptr) char *scptr; {
	if (cptr[STORAGE] == STATIC) return;
	ot (scptr[STORAGE] == EXTERN ? "extrn\t" : "public\t");
	prefix ();
	outstr (scptr);
	nl();
}

/*
 * Output the function symbol at scptr as an extrn or a public
 */
fpubext(scptr) char *scptr; {
	if (scptr[STORAGE] == STATIC) return;
	ot (scptr[OFFSET] == FUNCTION ? "public\t" : "extrn\t");
	prefix ();
	outstr (scptr);
	nl ();
}

/*
 *  Output a decimal number to the assembler file
 */
onum(num) int num; {
	outdec(num);	/* pdp11 needs a "." here */
}


/*
 *	fetch a static memory cell into the primary register
 */
getmem (sym)
char	*sym;
{
	if ((sym[IDENT] != POINTER) & (sym[TYPE] == CCHAR)) {
		ot ("lda\t");
		outstr (sym + NAME);
		nl ();
		gcall ("?sxt");
	} else {
		ot ("lhld\t");
		outstr (sym + NAME);
		nl ();
	}
}

/*
 *	fetch the address of the specified symbol into the primary register
 *
 */
getloc (sym)
char	*sym;
{
	immed ();
	if (sym[STORAGE] == LSTATIC) {
		printlabel(glint(sym));
		nl();
	} else {
		outdec (glint(sym) - stkp);
		nl ();
		ol ("dad\tsp");
	}
}

/*
 *	store the primary register into the specified static memory cell
 *
 */
putmem (sym)
char	*sym;
{
	if ((sym[IDENT] != POINTER) & (sym[TYPE] == CCHAR)) {
		ol ("mov\ta,l");
		ot ("sta\t");
	} else
		ot ("shld\t");
	outstr (sym + NAME);
	nl ();
}

/*
 *	store the specified object type in the primary register
 *	at the address on the top of the stack
 *
 */
putstk (typeobj)
char	typeobj;
{
	gpop ();
	if (typeobj == CCHAR)
		gcall ("?pchar");
	else
		gcall ("?pint");
}

/*
 *	fetch the specified object type indirect through the primary
 *	register into the primary register
 *
 */
indirect (typeobj)
char	typeobj;
{
	if (typeobj == CCHAR)
		gcall ("?gchar");
	else
		gcall ("?gint");
}

/*
 *	swap the primary and secondary registers
 *
 */
swap ()
{
	ol ("xchg");
}

/*
 *	print partial instruction to get an immediate value into
 *	the primary register
 *
 */
immed ()
{
	ot ("lxi\th,");
}

/*
 *	push the primary register onto the stack
 *
 */
gpush ()
{
	ol ("push\th");
	stkp = stkp - INTSIZE;
}

/*
 *	pop the top of the stack into the secondary register
 *
 */
gpop ()
{
	ol ("pop\td");
	stkp = stkp + INTSIZE;
}

/*
 *	swap the primary register and the top of the stack
 *
 */
swapstk ()
{
	ol ("xthl");
}

/*
 *	call the specified subroutine name
 *
 */
gcall (sname)
char	*sname;
{
	ot ("call\t");
	outstr (sname);
	nl ();
}

/*
 *	return from subroutine
 *
 */
gret ()
{
	ol ("ret");
}

/*
 *	perform subroutine call to value on top of stack
 *
 */
callstk ()
{
	immed ();
	outstr ("$+5");
	nl ();
	swapstk ();
	ol ("pchl");
	stkp = stkp + INTSIZE;
}

/*
 *	jump to specified internal label number
 *
 */
jump (label)
int	label;
{
	ot ("jmp\t");
	printlabel (label);
	nl ();
}

/*
 *	test the primary register and jump if false to label
 *
 */
testjump (label, ft)
int	label,
	ft;
{
	ol ("mov\ta,h");
	ol ("ora\tl");
	if (ft)
		ot ("jnz\t");
	else
		ot ("jz\t");
	printlabel (label);
	nl ();
}

/*
 *	print pseudo-op  to define a byte
 *
 */
defbyte ()
{
	ot ("db\t");
}

/*
 *	print pseudo-op to define storage
 *
 */
defstorage ()
{
	ot ("ds\t");
}

/*
 *	print pseudo-op to define a word
 *
 */
defword ()
{
	ot ("dw\t");
}

/*
 *	modify the stack pointer to the new value indicated
 *
 */
modstk (newstkp)
int	newstkp;
{
	int	k;

	k = galign(newstkp - stkp);
	if (k == 0)
		return (newstkp);
	if (k > 0) {
		if (k < 7) {
			if (k & 1) {
				ol ("inx\tsp");
				k--;
			}
			while (k) {
				ol ("pop\tb");
				k = k - INTSIZE;
			}
			return (newstkp);
		}
	} else {
		if (k > -7) {
			if (k & 1) {
				ol ("dcx\tsp");
				k++;
			}
			while (k) {
				ol ("push\tb");
				k = k + INTSIZE;
			}
			return (newstkp);
		}
	}
	swap ();
	immed ();
	outdec (k);
	nl ();
	ol ("dad\tsp");
	ol ("sphl");
	swap ();
	return (newstkp);
}

/*
 *	multiply the primary register by INTSIZE
 */
gaslint ()
{
	ol ("dad\th");
}

/*
 *	divide the primary register by INTSIZE
 */
gasrint()
{
	gpush();	/* push primary in prep for gasr */
	immed ();
	onum (1);
	nl ();
	gasr ();  /* divide by two */
}

/*
 *	Case jump instruction
 */
gjcase() {
	ot ("jmp\t?case");
	nl ();
}

/*
 *	add the primary and secondary registers
 *	if lval2 is int pointer and lval is not, scale lval
 */
gadd (lval,lval2) int *lval,*lval2;
{
	gpop ();
	if (dbltest (lval2, lval)) {
		swap ();
		gaslint ();
		swap ();
	}
	ol ("dad\td");
}

/*
 *	subtract the primary register from the secondary
 *
 */
gsub ()
{
	gpop ();
	gcall ("?sub");
}

/*
 *	multiply the primary and secondary registers
 *	(result in primary)
 *
 */
gmult ()
{
	gpop();
	gcall ("?mul");
}

/*
 *	divide the secondary register by the primary
 *	(quotient in primary, remainder in secondary)
 *
 */
gdiv ()
{
	gpop();
	gcall ("?div");
}

/*
 *	compute the remainder (mod) of the secondary register
 *	divided by the primary register
 *	(remainder in primary, quotient in secondary)
 *
 */
gmod ()
{
	gdiv ();
	swap ();
}

/*
 *	inclusive 'or' the primary and secondary registers
 *
 */
gor ()
{
	gpop();
	gcall ("?or");
}

/*
 *	exclusive 'or' the primary and secondary registers
 *
 */
gxor ()
{
	gpop();
	gcall ("?xor");
}

/*
 *	'and' the primary and secondary registers
 *
 */
gand ()
{
	gpop();
	gcall ("?and");
}

/*
 *	arithmetic shift right the secondary register the number of
 *	times in the primary register
 *	(results in primary register)
 *
 */
gasr ()
{
	gpop();
	gcall ("?asr");
}

/*
 *	arithmetic shift left the secondary register the number of
 *	times in the primary register
 *	(results in primary register)
 *
 */
gasl ()
{
	gpop ();
	gcall ("?asl");
}

/*
 *	two's complement of primary register
 *
 */
gneg ()
{
	gcall ("?neg");
}

/*
 *	logical complement of primary register
 *
 */
glneg ()
{
	gcall ("?lneg");
}

/*
 *	one's complement of primary register
 *
 */
gcom ()
{
	gcall ("?com");
}

/*
 *	Convert primary value into logical value (0 if 0, 1 otherwise)
 *
 */
gbool ()
{
	gcall ("?bool");
}

/*
 *	increment the primary register by 1 if char, INTSIZE if
 *      int
 */
ginc (lval) int lval[];
{
	ol ("inx\th");
	if (lval[2] == CINT)
		ol ("inx\th");
}

/*
 *	decrement the primary register by one if char, INTSIZE if
 *	int
 */
gdec (lval) int lval[];
{
	ol ("dcx\th");
	if (lval[2] == CINT)
		ol("dcx\th");
}

/*
 *	following are the conditional operators.
 *	they compare the secondary register against the primary register
 *	and put a literl 1 in the primary if the condition is true,
 *	otherwise they clear the primary register
 *
 */

/*
 *	equal
 *
 */
geq ()
{
	gpop();
	gcall ("?eq");
}

/*
 *	not equal
 *
 */
gne ()
{
	gpop();
	gcall ("?ne");
}

/*
 *	less than (signed)
 *
 */
glt ()
{
	gpop();
	gcall ("?lt");
}

/*
 *	less than or equal (signed)
 *
 */
gle ()
{
	gpop();
	gcall ("?le");
}

/*
 *	greater than (signed)
 *
 */
ggt ()
{
	gpop();
	gcall ("?gt");
}

/*
 *	greater than or equal (signed)
 *
 */
gge ()
{
	gpop();
	gcall ("?ge");
}

/*
 *	less than (unsigned)
 *
 */
gult ()
{
	gpop();
	gcall ("?ult");
}

/*
 *	less than or equal (unsigned)
 *
 */
gule ()
{
	gpop();
	gcall ("?ule");
}

/*
 *	greater than (unsigned)
 *
 */
gugt ()
{
	gpop();
	gcall ("?ugt");
}

/*
 *	greater than or equal (unsigned)
 *
 */
guge ()
{
	gpop();
	gcall ("?uge");
}

inclib() {
#ifdef	cpm
	return("B:");
#endif
#ifdef	unix
	return(INCDIR);
#endif
}

/*	Squirrel away argument count in a register that modstk
	doesn't touch.
*/

gnargs(d)
int	d; {
	ot ("mvi\ta,");
	onum(d);
	nl ();
}

assemble(s)
char	*s; {
#ifdef	ASNM
	char buf[100];
	strcpy(buf, ASNM);
	strcat(buf, " ");
	strcat(buf, s);
	buf[strlen(buf)-1] = 's';
	return(system(buf));
#else
	return(0);
#endif
}

link() {
#ifdef	LDNM
	fputs("I don't know how to link files yet\n", stderr);
#else
	return(0);
#endif
}
SHAR_EOF
if test 9671 -ne "`wc -c < 'code8080.c'`"
then
	echo shar: error transmitting "'code8080.c'" '(should have been 9671 characters)'
fi
fi
echo shar: extracting "'codeas09.c'" '(9534 characters)'
if test -f 'codeas09.c'
then
	echo shar: will not over-write existing file "'codeas09.c'"
else
cat << \SHAR_EOF > 'codeas09.c'
/*	File codeas09.c: 2.2 (84/08/31,10:05:13) */
/*% cc -O -c %
 *
 */

#include <stdio.h>
#include "defs.h"
#include "data.h"

/*	Define ASNM and LDNM to the names of the assembler and linker
	respectively */

/*
 *	Some predefinitions:
 *
 *	INTSIZE is the size of an integer in the target machine
 *	BYTEOFF is the offset of an byte within an integer on the
 *		target machine. (ie: 8080,pdp11 = 0, 6809 = 1,
 *		360 = 3)
 *	This compiler assumes that an integer is the SAME length as
 *	a pointer - in fact, the compiler uses INTSIZE for both.
 */
#define	INTSIZE	2
#define	BYTEOFF	1

/*
 *	print all assembler info before any code is generated
 *
 */
header ()
{
	outstr("|\tSmall C MC6809\n|\tCoder (2.4,84/11/27)\n|");
	FEvers();
	nl ();
	ol (".globl\tsmul,sdiv,smod,asr,asl,neg,lneg,case");
	ol (".globl\teq,ne,lt,le,gt,ge,ult,ule,ugt,uge,bool");
}
nl ()
{
	outbyte (EOL);
}

initmac() {
	defmac("mc6809\t1");
	defmac("mitas09\t1");
	defmac("smallc\t1");
}

galign(t)
int t;
{
	return (t);
}


/*
 *	return size of an integer
 */
intsize() {
	return(INTSIZE);
}

/*
 *	return offset of ls byte within word
 *	(ie: 8080 & pdp11 is 0, 6809 is 1, 360 is 3)
 */
byteoff() {
	return(BYTEOFF);
}

/*
 *	Output internal generated label prefix
 */
olprfix() {
	outstr("LL");
}

/*
 *	Output a label definition terminator
 */
col ()
{
	outstr ("=.\n");
}

/*
 *	begin a comment line for the assembler
 *
 */
comment ()
{
	outbyte ('|');
}

/*
 *	Output a prefix in front of user labels
 */
prefix () {
	outbyte ('_');
}


/*
 *	print any assembler stuff needed after all code
 *
 */
trailer ()
{
	ol (".end");
}

/*
 *	function prologue
 */
prologue ()
{
}

/*
 *	text (code) segment
 */
gtext ()
{
	ol (".text");
}

/*
 *	data segment
 */
gdata ()
{
	ol (".data");
}

/*
 *  Output the variable symbol at scptr as an extrn or a public
 */
ppubext(scptr) char *scptr; {
	if (scptr[STORAGE] == STATIC) return;
	ot (".globl\t");
	prefix ();
	outstr (scptr);
	nl();
}

/*
 * Output the function symbol at scptr as an extrn or a public
 */
fpubext(scptr) char *scptr; {
	ppubext(scptr);
}

/*
 *  Output a decimal number to the assembler file
 */
onum(num) int num; {
	outdec(num);	/* pdp11 needs a "." here */
	outbyte('.');
}


/*
 *	fetch a static memory cell into the primary register
 */
getmem (sym)
char	*sym;
{
	if ((sym[IDENT] != POINTER) & (sym[TYPE] == CCHAR)) {
		ot ("ldb\t");
		prefix ();
		outstr (sym + NAME);
		nl ();
		ot ("sex");
		nl ();
	} else {
		ot ("ldd\t");
		prefix ();
		outstr (sym + NAME);
		nl ();
	}
}

/*
 *	fetch the address of the specified symbol into the primary register
 *
 */
getloc (sym)
char	*sym;
{
	if (sym[STORAGE] == LSTATIC) {
		immed();
		printlabel(glint(sym));
		nl();
	} else {
		ot ("leay\t");
		onum (glint(sym) - stkp);
		outstr ("(s)\n\ttfr\ty,d\n");
	}
}

/*
 *	store the primary register into the specified static memory cell
 *
 */
putmem (sym)
char	*sym;
{
	if ((sym[IDENT] != POINTER) & (sym[TYPE] == CCHAR)) {
		ot ("stb\t");
	} else
		ot ("std\t");
	prefix ();
	outstr (sym + NAME);
	nl ();
}

/*
 *	store the specified object type in the primary register
 *	at the address on the top of the stack
 *
 */
putstk (typeobj)
char	typeobj;
{
	if (typeobj == CCHAR)
		ol ("stb\t@(s)++");
	else
		ol ("std\t@(s)++");
	stkp = stkp + INTSIZE;
}

/*
 *	fetch the specified object type indirect through the primary
 *	register into the primary register
 *
 */
indirect (typeobj)
char	typeobj;
{
	ol("tfr\td,y");
	if (typeobj == CCHAR)
		ol ("ldb\t(y)\n\tsex");
	else
		ol ("ldd\t(y)");
}

/*
 *	swap the primary and secondary registers
 *
 */
swap ()
{
	ol ("exg\td,x");
}

/*
 *	print partial instruction to get an immediate value into
 *	the primary register
 *
 */
immed ()
{
	ot ("ldd\t#");
}

/*
 *	push the primary register onto the stack
 *
 */
gpush ()
{
	ol ("pshs\td");
	stkp = stkp - INTSIZE;
}

/*
 *	pop the top of the stack into the secondary register
 *
 */
gpop ()
{
	ol ("puls\td");
	stkp = stkp + INTSIZE;
}

/*
 *	swap the primary register and the top of the stack
 *
 */
swapstk ()
{
	ol ("ldy\t(s)\nstd\t(s)\n\ttfr\ty,d");
}

/*
 *	call the specified subroutine name
 *
 */
gcall (sname)
char	*sname;
{
	ot ("jsr\t");
	if (*sname == '^')
		outstr (++sname);
	else {
		prefix ();
		outstr (sname);
	}
	nl ();
}

/*
 *	return from subroutine
 *
 */
gret ()
{
	ol ("rts");
}

/*
 *	perform subroutine call to value on top of stack
 *
 */
callstk ()
{
	gpop();
	ol ("jsr\t(x)");
}

/*
 *	jump to specified internal label number
 *
 */
jump (label)
int	label;
{
	ot ("lbra\t");
	printlabel (label);
	nl ();
}

/*
 *	test the primary register and jump if false to label
 *
 */
testjump (label, ft)
int	label,
	ft;
{
	ol ("cmpd\t#0");
	if (ft)
		ot ("lbne\t");
	else
		ot ("lbeq\t");
	printlabel (label);
	nl ();
}

/*
 *	print pseudo-op  to define a byte
 *
 */
defbyte ()
{
	ot (".byte\t");
}

/*
 *	print pseudo-op to define storage
 *
 */
defstorage ()
{
	ot (".blkb\t");
}

/*
 *	print pseudo-op to define a word
 *
 */
defword ()
{
	ot (".word\t");
}

/*
 *	modify the stack pointer to the new value indicated
 *
 */
modstk (newstkp)
int	newstkp;
{
	int	k;

	k = galign(newstkp - stkp);
	if (k == 0)
		return (newstkp);
	ot ("leas\t");
	onum (k);
	outstr ("(s)\n");
	return (newstkp);
}

/*
 *	multiply the primary register by INTSIZE
 */
gaslint ()
{
	ol ("aslb\n\trola");
}

/*
 *	divide the primary register by INTSIZE
 */
gasrint()
{
	ol ("asra\n\trorb");
}

/*
 *	Case jump instruction
 */
gjcase() {
	ot ("jmp\tcase");
	nl ();
}

/*
 *	add the primary and secondary registers
 *	if lval2 is int pointer and lval is int, scale lval
 */
gadd (lval, lval2) int *lval, *lval2;
{
	if (dbltest (lval2, lval)) {
		ol ("asl\t1(s)\n\trol\t(s)");
	}
	ol ("addd\t(s)++");
	stkp = stkp + INTSIZE;
}

/*
 *	subtract the primary register from the secondary
 *
 */
gsub ()
{
	ol ("subd\t(s)++\n\tcoma\n\tcomb\n\taddd\t#1");
	stkp = stkp + INTSIZE;
}

/*
 *	multiply the primary and secondary registers
 *	(result in primary)
 *
 */
gmult ()
{
	gcall ("^smul");
	stkp = stkp + INTSIZE;
}

/*
 *	divide the secondary register by the primary
 *	(quotient in primary, remainder in secondary)
 *
 */
gdiv ()
{
	gcall ("^sdiv");
	stkp = stkp + INTSIZE;
}

/*
 *	compute the remainder (mod) of the secondary register
 *	divided by the primary register
 *	(remainder in primary, quotient in secondary)
 *
 */
gmod ()
{
	gcall ("^smod");
	stkp = stkp + INTSIZE;
}

/*
 *	inclusive 'or' the primary and secondary registers
 *
 */
gor ()
{
	ol ("ora\t(s)+\n\torb\t(s)+");
	stkp = stkp + INTSIZE;
}

/*
 *	exclusive 'or' the primary and secondary registers
 *
 */
gxor ()
{
	ol ("eora\t(s)+\n\teorb\t(s)+");
	stkp = stkp + INTSIZE;
}

/*
 *	'and' the primary and secondary registers
 *
 */
gand ()
{
	ol ("anda\t(s)+\n\tandb\t(s)+");
	stkp = stkp + INTSIZE;
}

/*
 *	arithmetic shift right the secondary register the number of
 *	times in the primary register
 *	(results in primary register)
 *
 */
gasr ()
{
	gcall ("^asr");
	stkp = stkp + INTSIZE;
}

/*
 *	arithmetic shift left the secondary register the number of
 *	times in the primary register
 *	(results in primary register)
 *
 */
gasl ()
{
	gcall ("^asl");
	stkp = stkp + INTSIZE;
}

/*
 *	two's complement of primary register
 *
 */
gneg ()
{
	gcall ("^neg");
}

/*
 *	logical complement of primary register
 *
 */
glneg ()
{
	gcall ("^lneg");
}

/*
 *	one's complement of primary register
 *
 */
gcom ()
{
	ol ("coma\n\tcomb");
}

/*
 *	convert primary register into logical value
 *
 */
gbool ()
{
	gcall ("^bool");
}
/*
 *	increment the primary register by 1 if char, INTSIZE if
 *      int
 */
ginc (lval) int lval[];
{
	if (lval[2] == CINT)
		ol ("addd\t#2");
	else
		ol ("addd\t#1");
}

/*
 *	decrement the primary register by one if char, INTSIZE if
 *	int
 */
gdec (lval) int lval[];
{
	if (lval[2] == CINT)
		ol ("subd\t#2");
	else
		ol ("subd\t#1");
}

/*
 *	following are the conditional operators.
 *	they compare the secondary register against the primary register
 *	and put a literl 1 in the primary if the condition is true,
 *	otherwise they clear the primary register
 *
 */

/*
 *	equal
 *
 */
geq ()
{
	gcall ("^eq");
	stkp = stkp + INTSIZE;
}

/*
 *	not equal
 *
 */
gne ()
{
	gcall ("^ne");
	stkp = stkp + INTSIZE;
}

/*
 *	less than (signed)
 *
 */
glt ()
{
	gcall ("^lt");
	stkp = stkp + INTSIZE;
}
/*
 *	less than or equal (signed)
 *
 */
gle ()
{
	gcall ("^le");
	stkp = stkp + INTSIZE;
}

/*
 *	greater than (signed)
 *
 */
ggt ()
{
	gcall ("^gt");
	stkp = stkp + INTSIZE;
}

/*
 *	greater than or equal (signed)
 *
 */
gge ()
{
	gcall ("^ge");
	stkp = stkp + INTSIZE;
}

/*
 *	less than (unsigned)
 *
 */
gult ()
{
	gcall ("^ult");
	stkp = stkp + INTSIZE;
}

/*
 *	less than or equal (unsigned)
 *
 */
gule ()
{
	gcall ("^ule");
	stkp = stkp + INTSIZE;
}

/*
 *	greater than (unsigned)
 *
 */
gugt ()
{
	gcall ("^ugt");
	stkp = stkp + INTSIZE;
}

/*
 *	greater than or equal (unsigned)
 *
 */
guge ()
{
	gcall ("^uge");
	stkp = stkp + INTSIZE;
}

inclib() {
#ifdef	flex
	return("B.");
#endif
#ifdef	unix
	return(INCDIR);
#endif
#ifdef	cpm
	return("B:");
#endif
}

/*	Squirrel away argument count in a register that modstk/getloc/stloc
	doesn't touch.
*/

gnargs(d)
int	d; {
	ot ("ldu\t#");
	onum(d);
	nl ();
}

assemble(s)
char	*s; {
#ifdef	ASNM
	char buf[100];
	strcpy(buf, ASNM);
	strcat(buf, " ");
	strcat(buf, s);
	buf[strlen(buf)-1] = 's';
	return(system(buf));
#else
	return(0);
#endif
}

link() {
#ifdef	LDNM
	fputs("I don't know how to link files yet\n", stderr);
#else
	return(0);
#endif
}
SHAR_EOF
if test 9534 -ne "`wc -c < 'codeas09.c'`"
then
	echo shar: error transmitting "'codeas09.c'" '(should have been 9534 characters)'
fi
fi
echo shar: extracting "'codem68k.c'" '(11259 characters)'
if test -f 'codem68k.c'
then
	echo shar: will not over-write existing file "'codem68k.c'"
else
cat << \SHAR_EOF > 'codem68k.c'
/*	File codem68k.c: 1.2 (84/11/28,10:15:09) */
/*% cc -O -c %
 *
 */

#include <stdio.h>
#include "defs.h"
#include "data.h"

#ifdef	unix
#ifdef	m68k
#define	ASNM	"as -o "
#define	LDNM	"ld -o a.out /lib/crt0.o "
#endif
#ifdef	pyr
#define	ASNM	"/u1/cx/bin/m68kas -o "
#define	LDNM	"/u1/cx/bin/m68kld -o a.out /u1/cx/lib/m68kcrt0.o "
#endif
#endif

int	needr0;
int	needh;
/*
 *	Some predefinitions:
 *
 *	INTSIZE is the size of an integer in the target machine
 *	BYTEOFF is the offset of an byte within an integer on the
 *		target machine. (ie: 8080,pdp11 = 0, 6809 = 1,
 *		360 = 3)
 *	This compiler assumes that an integer is the SAME length as
 *	a pointer - in fact, the compiler uses INTSIZE for both.
 */
#define	INTSIZE	4
#define	BYTEOFF	3

/*
 *	print all assembler info before any code is generated
 *
 */
header ()
{
	outstr("#\tSmall C M68000\n#\tCoder (1.2,84/11/28)\n#");
	FEvers();
	nl ();
	ol ("global\tTlneg");
	ol ("global\tTcase");
	ol ("global\tTeq");
	ol ("global\tTne");
	ol ("global\tTlt");
	ol ("global\tTle");
	ol ("global\tTgt");
	ol ("global\tTge");
	ol ("global\tTult");
	ol ("global\tTule");
	ol ("global\tTugt");
	ol ("global\tTuge");
	ol ("global\tTbool");
	ol ("global\tTmult");
	ol ("global\tTdiv");
	ol ("global\tTmod");
}

nl()
{
	if (needh) {
		ol ("word\t0");
		needh = 0;
	}
	if (needr0) {
		needr0 = 0;
		outstr(",%d0");
	}
	outbyte(EOL);
}

initmac() {
	defmac("m68k\t1");
	defmac("unix\t1");
	defmac("smallc\t1");
}

galign(t)
int t;
{
	int sign;
	if (t < 0) {
		sign = 1;
		t = -t;
	} else
		sign = 0;
	t = (t + INTSIZE - 1) & ~(INTSIZE - 1);
	t = sign? -t: t;
	return (t);
}



/*
 *	return size of an integer
 */
intsize() {
	return(INTSIZE);
}

/*
 *	return offset of ls byte within word
 *	(ie: 8080 & pdp11 is 0, 6809 is 1, 360 is 3)
 */
byteoff() {
	return(BYTEOFF);
}

/*
 *	Output internal generated label prefix
 */
olprfix() {
	outstr("LL");
}

/*
 *	Output a label definition terminator
 */
col ()
{
	outstr (":\n");
}

/*
 *	begin a comment line for the assembler
 *
 */
comment ()
{
	outbyte ('#');
}

/*
 *	Output a prefix in front of user labels
 */
prefix () {
/*	outbyte ('_'); */
}


/*
 *	print any assembler stuff needed after all code
 *
 */
trailer ()
{
}

/*
 *	function prologue
 */
prologue ()
{
	/* this is where we'd put splimit stuff */
}

/*
 *	text (code) segment
 */
gtext ()
{
	ol ("text");
}

/*
 *	data segment
 */
gdata ()
{
	ol ("data");
}

/*
 *  Output the variable symbol at scptr as an extrn or a public
 */
ppubext(scptr) char *scptr; {
	if (scptr[STORAGE] == STATIC) return;
	ot ("global\t");
	prefix ();
	outstr (scptr);
	nl();
}

/*
 * Output the function symbol at scptr as an extrn or a public
 */
fpubext(scptr) char *scptr; {
	ppubext(scptr);
}

/*
 *  Output a decimal number to the assembler file
 */
onum(num) int num; {
	outdec(num);	/* pdp11 needs a "." here */
}


/*
 *	fetch a static memory cell into the primary register
 */
getmem (sym)
char	*sym;
{
	int ischr;
	if ((sym[IDENT] != POINTER) & (sym[TYPE] == CCHAR)) {
		ischr = 1;
		ot ("mov.b\t");
		prefix ();
		outstr (sym + NAME);
	} else {
		ischr = 0;
		ot ("mov.l\t");
		prefix ();
		outstr (sym + NAME);
	}
	outstr(",%d0\n");
	if (ischr)
		ol ("ext.b\t%d0");
}

/*
 *	fetch the address of the specified symbol into the primary register
 *
 */
getloc (sym)
char	*sym;
{
	if (sym[STORAGE] == LSTATIC) {
		immed();
		printlabel(glint(sym));
		nl();
	} else {
		ot ("lea.l\t");
		onum (glint(sym) - stkp);
		outstr (",%a0\n");
		ol ("mov.l\t%a0,%d0");
	}
}

/*
 *	store the primary register into the specified static memory cell
 *
 */
putmem (sym)
char	*sym;
{
	if ((sym[IDENT] != POINTER) & (sym[TYPE] == CCHAR)) {
		ot ("mov.b\t%d0,");
	} else
		ot ("mov.l\t%d0,");
	prefix ();
	outstr (sym + NAME);
	nl ();
}

/*
 *	store the specified object type in the primary register
 *	at the address on the top of the stack
 *
 */
putstk (typeobj)
char	typeobj;
{
	ol ("mov.l\t(%sp)+,%a0");
	if (typeobj == CCHAR)
		ol ("mov.b\t%d0,(%a0)");
	else
		ol ("mov.l\t%d0,(%a0)");
	stkp = stkp + INTSIZE;
}

/*
 *	fetch the specified object type indirect through the primary
 *	register into the primary register
 *
 */
indirect (typeobj)
char	typeobj;
{
	ol ("mov.l\t%d0,%a0");
	if (typeobj == CCHAR)
		ol ("mov.b\t(%a0),%d0");
	else
		ol ("mov.l\t(%a0),%d0");
}

/*
 *	swap the primary and secondary registers
 *
 */
swap ()
{
	ol ("mov.l\t%d0,%d2\n\tmov.l\t%d1,%d0\n\tmov.l\t%d2,%d1");
}

/*
 *	print partial instruction to get an immediate value into
 *	the primary register
 *
 */
immed ()
{
	ot ("mov.l\t&");
	needr0 = 1;
}

/*
 *	push the primary register onto the stack
 *
 */
gpush ()
{
	ol ("mov.l\t%d0,-(%sp)");
	stkp = stkp - INTSIZE;
}

/*
 *	pop the top of the stack into the secondary register
 *
 */
gpop ()
{
	ol ("mov.l\t(%sp)+,%d1");
	stkp = stkp + INTSIZE;
}

/*
 *	swap the primary register and the top of the stack
 *
 */
swapstk ()
{
	ol ("mov.l\t(%sp)+,%d2\nmov.l\t%d0,-(%sp)\nmov.l\t%d2,%d0");
}

/*
 *	call the specified subroutine name
 *
 */
gcall (sname)
char	*sname;
{
	if (*sname == '^') {
		ot ("jsr\tT");
		outstr (++sname);
	} else {
		ot ("jsr\t");
		prefix ();
		outstr (sname);
	}
	nl ();
}

/*
 *	return from subroutine
 *
 */
gret ()
{
	ol ("rts");
}

/*
 *	perform subroutine call to value on top of stack
 *
 */
callstk ()
{
	ol ("jsr\t(%sp)+");
	stkp = stkp + INTSIZE;
}

/*
 *	jump to specified internal label number
 *
 */
jump (label)
int	label;
{
	ot ("jmp\t");
	printlabel (label);
	nl ();
}

/*
 *	test the primary register and jump if false to label
 *
 */
testjump (label, ft)
int	label,
	ft;
{
	ol ("cmp.l\t%d0,&0");
	if (ft)
		ot ("beq\t");
	else
		ot ("bne\t");
	printlabel (label);
	nl ();
}

/*
 *	print pseudo-op  to define a byte
 *
 */
defbyte ()
{
	ot ("byte\t");
}

/*
 *	print pseudo-op to define storage
 *
 */
defstorage ()
{
	ot ("space\t");
}

/*
 *	print pseudo-op to define a word
 *
 */
defword ()
{
	ot ("long\t");
}

/*
 *	modify the stack pointer to the new value indicated
 *
 */
modstk (newstkp)
int	newstkp;
{
	int	k;

	k = newstkp - stkp;
	if (k % INTSIZE)
		error("Bad stack alignment (compiler error)");
	if (k == 0)
		return (newstkp);
	ot ("add.l\t&");
	onum (k);
	outstr (",sp");
	nl();
	return (newstkp);
}

/*
 *	multiply the primary register by INTSIZE
 */
gaslint ()
{
	ol ("asl.l\t&2,%d0");
}

/*
 *	divide the primary register by INTSIZE
 */
gasrint()
{
	ol ("asr.l\t&2,%d0");
}

/*
 *	Case jump instruction
 */
gjcase() {
	gcall ("^case");
}

/*
 *	add the primary and secondary registers
 *	if lval2 is int pointer and lval is int, scale lval
 */
gadd (lval, lval2) int *lval, *lval2;
{
	if (dbltest (lval2, lval)) {
		ol ("asl.l\t&2,(%sp)");
	}
	ol ("add.l\t(%sp)+,%d0");
	stkp = stkp + INTSIZE;
}

/*
 *	subtract the primary register from the secondary
 *
 */
gsub ()
{
	ol ("mov.l\t(%sp)+,%d2");
	ol ("sub.l\t%d0,%d2");
	ol ("mov.l\t%d2,%d0");
	stkp = stkp + INTSIZE;
}

/*
 *	multiply the primary and secondary registers
 *	(result in primary)
 *
 */
gmult ()
{
	gcall ("^mult");
	stkp = stkp + INTSIZE;
}

/*
 *	divide the secondary register by the primary
 *	(quotient in primary, remainder in secondary)
 *
 */
gdiv ()
{
	gcall ("^div");
	stkp = stkp + INTSIZE;
}

/*
 *	compute the remainder (mod) of the secondary register
 *	divided by the primary register
 *	(remainder in primary, quotient in secondary)
 *
 */
gmod ()
{
	gcall ("^mod");
	stkp = stkp + INTSIZE;
}

/*
 *	inclusive 'or' the primary and secondary registers
 *
 */
gor ()
{
	ol ("or.l\t(%sp)+,%d0");
	stkp = stkp + INTSIZE;
}

/*
 *	exclusive 'or' the primary and secondary registers
 *
 */
gxor ()
{
	ol ("mov.l\t(%sp)+,%d1");
	ol ("eor.l\t%d1,%d0");
	stkp = stkp + INTSIZE;
}

/*
 *	'and' the primary and secondary registers
 *
 */
gand ()
{
	ol ("and.l\t(%sp)+,%d0");
	stkp = stkp + INTSIZE;
}

/*
 *	arithmetic shift right the secondary register the number of
 *	times in the primary register
 *	(results in primary register)
 *
 */
gasr ()
{
	ol ("mov.l\t(%sp)+,%d1");
	ol ("asr.l\t%d0,%d1");
	ol ("mov.l\t%d1,%d0");
	stkp = stkp + INTSIZE;
}

/*
 *	arithmetic shift left the secondary register the number of
 *	times in the primary register
 *	(results in primary register)
 *
 */
gasl ()
{
	ol ("mov.l\t(%sp)+,%d1");
	ol ("asl.l\t%d0,%d1");
	ol ("mov.l\t%d1,%d0");
	stkp = stkp + INTSIZE;
}

/*
 *	two's complement of primary register
 *
 */
gneg ()
{
	ol ("neg.l\t%d0");
}

/*
 *	logical complement of primary register
 *
 */
glneg ()
{
	gcall ("^lneg");
}

/*
 *	one's complement of primary register
 *
 */
gcom ()
{
	ol ("not\t%d0");
}

/*
 *	convert primary register into logical value
 *
 */
gbool ()
{
	gcall ("^bool");
}
/*
 *	increment the primary register by 1 if char, INTSIZE if
 *      int
 */
ginc (lval) int lval[];
{
	if (lval[2] == CINT)
		ol ("addq.l\t&4,%d0");
	else
		ol ("addq.l\t&1,%d0");
}

/*
 *	decrement the primary register by one if char, INTSIZE if
 *	int
 */
gdec (lval) int lval[];
{
	if (lval[2] == CINT)
		ol ("subq.l\t&4,%d0");
	else
		ol ("subq.l\t&1,%d0");
}

/*
 *	following are the conditional operators.
 *	they compare the secondary register against the primary register
 *	and put a literl 1 in the primary if the condition is true,
 *	otherwise they clear the primary register
 *
 */

/*
 *	equal
 *
 */
geq ()
{
	gcall ("^eq");
	stkp = stkp + INTSIZE;
}

/*
 *	not equal
 *
 */
gne ()
{
	gcall ("^ne");
	stkp = stkp + INTSIZE;
}

/*
 *	less than (signed)
 *
 */
glt ()
{
	gcall ("^lt");
	stkp = stkp + INTSIZE;
}
/*
 *	less than or equal (signed)
 *
 */
gle ()
{
	gcall ("^le");
	stkp = stkp + INTSIZE;
}

/*
 *	greater than (signed)
 *
 */
ggt ()
{
	gcall ("^gt");
	stkp = stkp + INTSIZE;
}

/*
 *	greater than or equal (signed)
 *
 */
gge ()
{
	gcall ("^ge");
	stkp = stkp + INTSIZE;
}

/*
 *	less than (unsigned)
 *
 */
gult ()
{
	gcall ("^ult");
	stkp = stkp + INTSIZE;
}

/*
 *	less than or equal (unsigned)
 *
 */
gule ()
{
	gcall ("^ule");
	stkp = stkp + INTSIZE;
}

/*
 *	greater than (unsigned)
 *
 */
gugt ()
{
	gcall ("^ugt");
	stkp = stkp + INTSIZE;
}

/*
 *	greater than or equal (unsigned)
 *
 */
guge ()
{
	gcall ("^uge");
	stkp = stkp + INTSIZE;
}

inclib() {
#ifdef	flex
	return("B.");
#endif
#ifdef	unix
	return(INCDIR);
#endif
#ifdef	cpm
	return("B:");
#endif
}

/*	Squirrel away argument count in a register that modstk/getloc/stloc
	doesn't touch.
*/

gnargs(d)
int	d; {
	ot ("mov.l\t&");
	onum(d);
	outstr(",%d3\n");
}

#ifndef	NOASLD
char	assems[400];
int	assinit;
assemble(s)
char	*s; {
#ifdef	ASNM
	char	cmd[100],buf[100];
	char	*p;
	int	ex, rc, delaft;
#ifdef	unix
	p = strrchr(s, '/');
	if (p)
		strcat(buf, p+1);
	else
#endif
		strcat(buf, s);
	p = buf + strlen(buf) - 1;
	rc = typeof(s);
	delaft = (rc == 'c');
	if (rc == 'c' || rc == 's') {
		ex = 0;
		*p = 'o';
	} else
		ex = 1;
	if (!assinit) {
		strcat(assems, LDNM);
		assinit = 1;
	}
	strcat(assems, buf);
	strcat(assems, " ");
	if (ex)
		return(0);
	strcpy(cmd, ASNM);
	strcat(cmd, buf);
	strcat(cmd, " ");
	*p = 's';
	strcat(cmd, buf);
	rc = system(cmd);
	if (!rc && delaft)
		unlink(buf);
	return(rc);
#else
	return(0);
#endif
}

link() {
#ifdef	LDNM
#ifdef	unix
#ifdef	m68k
	strcat(assems, " -lc");
#else
	strcat(assems, " /u1/cx/lib/libc.a");
#endif
#endif
	return(system(assems));
#else
	return(0);
#endif
}
#endif
SHAR_EOF
if test 11259 -ne "`wc -c < 'codem68k.c'`"
then
	echo shar: error transmitting "'codem68k.c'" '(should have been 11259 characters)'
fi
fi
echo shar: extracting "'codevax.c'" '(10274 characters)'
if test -f 'codevax.c'
then
	echo shar: will not over-write existing file "'codevax.c'"
else
cat << \SHAR_EOF > 'codevax.c'
/*	File codevax.c: 2.2 (84/08/31,10:05:16) */
/*% cc -O -c %
 *
 */

#include <stdio.h>
#include "defs.h"
#include "data.h"

#ifdef	vax
#define	ASNM	"/bin/as"
#define	LDNM	"/bin/ld"
#endif

/*	Define ASNM and LDNM to the names of the assembler and linker
	respectively */

int	needr0;
int	needh;
/*
 *	Some predefinitions:
 *
 *	INTSIZE is the size of an integer in the target machine
 *	BYTEOFF is the offset of an byte within an integer on the
 *		target machine. (ie: 8080,pdp11 = 0, 6809 = 1,
 *		360 = 3)
 *	This compiler assumes that an integer is the SAME length as
 *	a pointer - in fact, the compiler uses INTSIZE for both.
 */
#define	INTSIZE	4
#define	BYTEOFF	0

/*
 *	print all assembler info before any code is generated
 *
 */
header ()
{
	outstr("#\tSmall C VAX\n#\tCoder (2.4,84/11/27)\n#");
	FEvers();
	nl ();
	ol (".globl\tlneg");
	ol (".globl\tcase");
	ol (".globl\teq");
	ol (".globl\tne");
	ol (".globl\tlt");
	ol (".globl\tle");
	ol (".globl\tgt");
	ol (".globl\tge");
	ol (".globl\tult");
	ol (".globl\tule");
	ol (".globl\tugt");
	ol (".globl\tuge");
	ol (".globl\tbool");
}

nl()
{
	if (needh) {
		ol (".word\t0");
		needh = 0;
	}
	if (needr0) {
		needr0 = 0;
		outstr(",r0");
	}
	outbyte(EOL);
}

initmac() {
	defmac("vax\t1");
	defmac("unix\t1");
	defmac("smallc\t1");
}

galign(t)
int t;
{
	int sign;
	if (t < 0) {
		sign = 1;
		t = -t;
	} else
		sign = 0;
	t = (t + INTSIZE - 1) & ~(INTSIZE - 1);
	t = sign? -t: t;
	return (t);
}



/*
 *	return size of an integer
 */
intsize() {
	return(INTSIZE);
}

/*
 *	return offset of ls byte within word
 *	(ie: 8080 & pdp11 is 0, 6809 is 1, 360 is 3)
 */
byteoff() {
	return(BYTEOFF);
}

/*
 *	Output internal generated label prefix
 */
olprfix() {
	outstr("LL");
}

/*
 *	Output a label definition terminator
 */
col ()
{
	outstr (":\n");
}

/*
 *	begin a comment line for the assembler
 *
 */
comment ()
{
	outbyte ('#');
}

/*
 *	Output a prefix in front of user labels
 */
prefix () {
	outbyte ('_');
}


/*
 *	print any assembler stuff needed after all code
 *
 */
trailer ()
{
}

/*
 *	function prologue
 */
prologue ()
{
	ol (".align\t1");
}

/*
 *	text (code) segment
 */
gtext ()
{
	ol (".text");
}

/*
 *	data segment
 */
gdata ()
{
	ol (".data");
}

/*
 *  Output the variable symbol at scptr as an extrn or a public
 */
ppubext(scptr) char *scptr; {
	if (scptr[STORAGE] == STATIC) return;
	ot (".globl\t");
	prefix ();
	outstr (scptr);
	nl();
}

/*
 * Output the function symbol at scptr as an extrn or a public
 */
fpubext(scptr) char *scptr; {
	ppubext(scptr);
}

/*
 *  Output a decimal number to the assembler file
 */
onum(num) int num; {
	outdec(num);	/* pdp11 needs a "." here */
}


/*
 *	fetch a static memory cell into the primary register
 */
getmem (sym)
char	*sym;
{
	if ((sym[IDENT] != POINTER) & (sym[TYPE] == CCHAR)) {
		ot ("cvtbl\t");
		prefix ();
		outstr (sym + NAME);
	} else {
		ot ("movl\t");
		prefix ();
		outstr (sym + NAME);
	}
	outstr(",r0\n");
}

/*
 *	fetch the address of the specified symbol into the primary register
 *
 */
getloc (sym)
char	*sym;
{
	if (sym[STORAGE] == LSTATIC) {
		immed();
		printlabel(glint(sym));
		nl();
	} else {
		ot ("moval\t");
		onum (glint(sym) - stkp);
		outstr ("(sp),r0\n");
	}
}

/*
 *	store the primary register into the specified static memory cell
 *
 */
putmem (sym)
char	*sym;
{
	if ((sym[IDENT] != POINTER) & (sym[TYPE] == CCHAR)) {
		ot ("cvtlb\tr0,");
	} else
		ot ("movl\tr0,");
	prefix ();
	outstr (sym + NAME);
	nl ();
}

/*
 *	store the specified object type in the primary register
 *	at the address on the top of the stack
 *
 */
putstk (typeobj)
char	typeobj;
{
	if (typeobj == CCHAR)
		ol ("cvtlb\tr0,*(sp)+");
	else
		ol ("movl\tr0,*(sp)+");
	stkp = stkp + INTSIZE;
}

/*
 *	fetch the specified object type indirect through the primary
 *	register into the primary register
 *
 */
indirect (typeobj)
char	typeobj;
{
	if (typeobj == CCHAR)
		ol ("cvtbl\t(r0),r0");
	else
		ol ("movl\t(r0),r0");
}

/*
 *	swap the primary and secondary registers
 *
 */
swap ()
{
	ol ("movl\tr0,r2\n\tmovl\tr1,r0\n\tmovl\tr2,r1");
}

/*
 *	print partial instruction to get an immediate value into
 *	the primary register
 *
 */
immed ()
{
	ot ("movl\t$");
	needr0 = 1;
}

/*
 *	push the primary register onto the stack
 *
 */
gpush ()
{
	ol ("pushl\tr0");
	stkp = stkp - INTSIZE;
}

/*
 *	pop the top of the stack into the secondary register
 *
 */
gpop ()
{
	ol ("movl\t(sp)+,r1");
	stkp = stkp + INTSIZE;
}

/*
 *	swap the primary register and the top of the stack
 *
 */
swapstk ()
{
	ol ("popl\tr2\npushl\tr0\nmovl\tr2,r0");
}

/*
 *	call the specified subroutine name
 *
 */
gcall (sname)
char	*sname;
{
	if (*sname == '^') {
		ot ("jsb\t");
		outstr (++sname);
	} else {
		ot ("jsb\t");
		prefix ();
		outstr (sname);
	}
	nl ();
}

/*
 *	return from subroutine
 *
 */
gret ()
{
	ol ("rsb");
}

/*
 *	perform subroutine call to value on top of stack
 *
 */
callstk ()
{
	ol ("jsb\t(sp)+");
	stkp = stkp + INTSIZE;
}

/*
 *	jump to specified internal label number
 *
 */
jump (label)
int	label;
{
	ot ("jmp\t");
	printlabel (label);
	nl ();
}

/*
 *	test the primary register and jump if false to label
 *
 */
testjump (label, ft)
int	label,
	ft;
{
	ol ("cmpl\tr0,$0");
	if (ft)
		ot ("jneq\t");
	else
		ot ("jeql\t");
	printlabel (label);
	nl ();
}

/*
 *	print pseudo-op  to define a byte
 *
 */
defbyte ()
{
	ot (".byte\t");
}

/*
 *	print pseudo-op to define storage
 *
 */
defstorage ()
{
	ot (".space\t");
}

/*
 *	print pseudo-op to define a word
 *
 */
defword ()
{
	ot (".long\t");
}

/*
 *	modify the stack pointer to the new value indicated
 *
 */
modstk (newstkp)
int	newstkp;
{
	int	k;

	k = newstkp - stkp;
	if (k % INTSIZE)
		error("Bad stack alignment (compiler error)");
	if (k == 0)
		return (newstkp);
	ot ("addl2\t$");
	onum (k);
	outstr (",sp");
	nl();
	return (newstkp);
}

/*
 *	multiply the primary register by INTSIZE
 */
gaslint ()
{
	ol ("ashl\t$2,r0,r0");
}

/*
 *	divide the primary register by INTSIZE
 */
gasrint()
{
	ol ("ashl\t$-2,r0,r0");
}

/*
 *	Case jump instruction
 */
gjcase() {
	ot ("jmp\tcase");
	nl ();
}

/*
 *	add the primary and secondary registers
 *	if lval2 is int pointer and lval is int, scale lval
 */
gadd (lval, lval2) int *lval, *lval2;
{
	if (dbltest (lval2, lval)) {
		ol ("ashl\t$2,(sp),(sp)");
	}
	ol ("addl2\t(sp)+,r0");
	stkp = stkp + INTSIZE;
}

/*
 *	subtract the primary register from the secondary
 *
 */
gsub ()
{
	ol ("subl3\tr0,(sp)+,r0");
	stkp = stkp + INTSIZE;
}

/*
 *	multiply the primary and secondary registers
 *	(result in primary)
 *
 */
gmult ()
{
	ol ("mull2\t(sp)+,r0");
	stkp = stkp + INTSIZE;
}

/*
 *	divide the secondary register by the primary
 *	(quotient in primary, remainder in secondary)
 *
 */
gdiv ()
{
	ol ("divl3\tr0,(sp)+,r0");
	stkp = stkp + INTSIZE;
}

/*
 *	compute the remainder (mod) of the secondary register
 *	divided by the primary register
 *	(remainder in primary, quotient in secondary)
 *
 */
gmod ()
{
	ol ("movl\t(sp)+,r2\n\tmovl\t$0,r3\nediv\tr0,r2,r1,r0");
	stkp = stkp + INTSIZE;
}

/*
 *	inclusive 'or' the primary and secondary registers
 *
 */
gor ()
{
	ol ("bisl2\t(sp)+,r0");
	stkp = stkp + INTSIZE;
}

/*
 *	exclusive 'or' the primary and secondary registers
 *
 */
gxor ()
{
	ol ("xorl2\t(sp)+,r0");
	stkp = stkp + INTSIZE;
}

/*
 *	'and' the primary and secondary registers
 *
 */
gand ()
{
	ol ("mcoml\t(sp)+,r1\n\tbicl2\tr1,r0");
	stkp = stkp + INTSIZE;
}

/*
 *	arithmetic shift right the secondary register the number of
 *	times in the primary register
 *	(results in primary register)
 *
 */
gasr ()
{
	ol("mnegl\tr0,r0\n\tashl\tr0,(sp)+,r0");
	stkp = stkp + INTSIZE;
}

/*
 *	arithmetic shift left the secondary register the number of
 *	times in the primary register
 *	(results in primary register)
 *
 */
gasl ()
{
	ol ("ashl\tr0,(sp)+,r0");
	stkp = stkp + INTSIZE;
}

/*
 *	two's complement of primary register
 *
 */
gneg ()
{
	ol ("mnegl\tr0,r0");
}

/*
 *	logical complement of primary register
 *
 */
glneg ()
{
	gcall ("^lneg");
}

/*
 *	one's complement of primary register
 *
 */
gcom ()
{
	ol ("mcoml\tr0,r0");
}

/*
 *	convert primary register into logical value
 *
 */
gbool ()
{
	gcall ("^bool");
}
/*
 *	increment the primary register by 1 if char, INTSIZE if
 *      int
 */
ginc (lval) int lval[];
{
	if (lval[2] == CINT)
		ol ("addl2\t$4,r0");
	else
		ol ("incl\tr0");
}

/*
 *	decrement the primary register by one if char, INTSIZE if
 *	int
 */
gdec (lval) int lval[];
{
	if (lval[2] == CINT)
		ol ("subl2\t$4,r0");
	else
		ol ("decl\tr0");
}

/*
 *	following are the conditional operators.
 *	they compare the secondary register against the primary register
 *	and put a literl 1 in the primary if the condition is true,
 *	otherwise they clear the primary register
 *
 */

/*
 *	equal
 *
 */
geq ()
{
	gcall ("^eq");
	stkp = stkp + INTSIZE;
}

/*
 *	not equal
 *
 */
gne ()
{
	gcall ("^ne");
	stkp = stkp + INTSIZE;
}

/*
 *	less than (signed)
 *
 */
glt ()
{
	gcall ("^lt");
	stkp = stkp + INTSIZE;
}
/*
 *	less than or equal (signed)
 *
 */
gle ()
{
	gcall ("^le");
	stkp = stkp + INTSIZE;
}

/*
 *	greater than (signed)
 *
 */
ggt ()
{
	gcall ("^gt");
	stkp = stkp + INTSIZE;
}

/*
 *	greater than or equal (signed)
 *
 */
gge ()
{
	gcall ("^ge");
	stkp = stkp + INTSIZE;
}

/*
 *	less than (unsigned)
 *
 */
gult ()
{
	gcall ("^ult");
	stkp = stkp + INTSIZE;
}

/*
 *	less than or equal (unsigned)
 *
 */
gule ()
{
	gcall ("^ule");
	stkp = stkp + INTSIZE;
}

/*
 *	greater than (unsigned)
 *
 */
gugt ()
{
	gcall ("^ugt");
	stkp = stkp + INTSIZE;
}

/*
 *	greater than or equal (unsigned)
 *
 */
guge ()
{
	gcall ("^uge");
	stkp = stkp + INTSIZE;
}

/*	Squirrel away argument count in a register that modstk
	doesn't touch.
*/

gnargs(d)
int	d; {
	ot ("movl\t$");
	onum(d);
	outstr (",r6\n");
}

inclib() {
#ifdef	flex
	return("B.");
#endif
#ifdef	unix
	return(INCDIR);
#endif
#ifdef	cpm
	return("B:");
#endif
}

assemble(s)
char	*s; {
#ifdef	ASNM
	char buf[100];
	strcpy(buf, ASNM);
	strcat(buf, " -o ");
	strcat(buf, s);
	buf[strlen(buf)-1] = 'o';
	strcat(buf, " ");
	strcat(buf, s);
	buf[strlen(buf)-1] = 's';
	return(system(buf));
#else
	return(0);
#endif
}

link() {
#ifdef	LDNM
	fputs("I don't know how to link files yet\n", stderr);
#else
	return(0);
#endif
}
SHAR_EOF
if test 10274 -ne "`wc -c < 'codevax.c'`"
then
	echo shar: error transmitting "'codevax.c'" '(should have been 10274 characters)'
fi
fi
echo shar: extracting "'data.c'" '(722 characters)'
if test -f 'data.c'
then
	echo shar: will not over-write existing file "'data.c'"
else
cat << \SHAR_EOF > 'data.c'
/*	File data.c: 2.2 (84/11/27,16:26:13) */
/*% cc -O -c %
 *
 */

#include <stdio.h>
#include "defs.h"

/* storage words */

char	symtab[SYMTBSZ];
char	*glbptr, *rglbptr, *locptr;
int	ws[WSTABSZ];
int	*wsptr;
int	swstcase[SWSTSZ];
int	swstlab[SWSTSZ];
int	swstp;
char	litq[LITABSZ];
int	litptr;
char	macq[MACQSIZE];
int	macptr;
char	line[LINESIZE];
char	mline[LINESIZE];
int	lptr, mptr;

/* miscellaneous storage */

int	nxtlab,
	litlab,
	stkp,
	argstk,
	ncmp,
	errcnt,
	glbflag,
	ctext,
	cmode,
	lastst;

FILE	*input, *input2, *output;
FILE	*inclstk[INCLSIZ];
int	inclsp;
char	fname[20];

char	quote[2];
char	*cptr;
int	*iptr;
int	fexitlab;
int	iflevel, skiplevel;
int	errfile;
int	sflag;
int	cflag;
int	errs;
int	aflag;
SHAR_EOF
if test 722 -ne "`wc -c < 'data.c'`"
then
	echo shar: error transmitting "'data.c'" '(should have been 722 characters)'
fi
fi
echo shar: extracting "'data.h'" '(807 characters)'
if test -f 'data.h'
then
	echo shar: will not over-write existing file "'data.h'"
else
cat << \SHAR_EOF > 'data.h'
/*	File data.h: 2.2 (84/11/27,16:26:11) */

/* storage words */

extern	char	symtab[];
extern	char	*glbptr, *rglbptr, *locptr;
extern	int	ws[];
extern	int	*wsptr;
extern	int	swstcase[];
extern	int	swstlab[];
extern	int	swstp;
extern	char	litq[];
extern	int	litptr;
extern	char	macq[];
extern	int	macptr;
extern	char	line[];
extern	char	mline[];
extern	int	lptr, mptr;

/* miscellaneous storage */

extern	int	nxtlab,
		litlab,
		stkp,
		argstk,
		ncmp,
		errcnt,
		glbflag,
		ctext,
		cmode,
		lastst;

extern	FILE	*input, *input2, *output;
extern	FILE	*inclstk[];
extern	int	inclsp;
extern	char	fname[];

extern	char	quote[];
extern	char	*cptr;
extern	int	*iptr;
extern	int	fexitlab;
extern	int	iflevel, skiplevel;
extern	int	errfile;
extern	int	sflag;
extern	int	cflag;
extern	int	errs;
extern	int	aflag;
SHAR_EOF
if test 807 -ne "`wc -c < 'data.h'`"
then
	echo shar: error transmitting "'data.h'" '(should have been 807 characters)'
fi
fi
exit 0
#	End of shell archive
-------