[comp.sources.wanted] Core wars 2 part 01

sbarr@hawk.ulowell.edu (bot man) (05/31/90)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 2)."
# Contents:  README MANIFEST Makefile.std README.sun amain.c assem.h
#   disassem.c inst.c interface2.c load.c lookup.c main.c output.c
#   parse.c play.c tokenize.c
# Wrapped by billr@saab on Mon Feb 13 10:40:10 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(7249 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X/*	Copyrighted (C) 1989 by Na Choon Piaw.  All rights reserved       */
X
X
X
X/*	This program and documentation is Public Domain, and may be	  */
X/*	distributed and copied by everyone provided this header		  */
X/*	remains intact							  */
X
XThis is a new version of corewars I'm working on.  It will feature
XONLY 2 player games (I hate 3 or more players on corewars), some limited
Xamounts of display (using curses) though that will be implemented only
Xafter the non-display functions work.  And an independent, full featured
Xassembler.  The interpreter will load "binary" code only.
X
XFull featured -- 1 physical pass, 2 "in memory" passes.
X		 symbolic memory addresses, immediate, direct, and indirect
X		 addressing modes.
X
XCOREWARS is a where the players each write an assembly language program
Xthat battle each other in the memory of a computer called MARS.  (Memory
XArray Redcode Simulator)  The game ends when (1) all the streams of execution
Xon one side have died out, or (2) when the time limit is up.  In (1) the
Xwinner is the side which still has surviving execution streams.  In (2)
Xthe game is a draw.  Once we are finished with implementing this game,
Xmaybe we can schedule a corewars tournament.
X
XMy version of corewars implements (hopefully in a short while) the following
Xinstructions from World 7 --- The First Corewars Tournament (with some
Xmodifications) (Note: the first two articles have slightly differing
Xdefinitions):
X
XINSTRUCTION	MNEUMONIC	CODE	ARGUMENTS	EXPLANATION
XMove		mov		1	A B		move contents of
X							address A to address B
XAdd		add		2	A B		add contents of address
X							A to address B
XSubtract	sub		3	A B		subtract contents of
X							address A from address
X							B
XJump		jmp		4	  B		Transfer control
X							to address A
XJump if zero	jmz		5	A B		Transfer control
X							to address A if
X							contents of B are
X							greater then 0
XJump if not 0	jmn		6	A B		transfer control to
X							address B if contents
X							of B is != 0
XDecrement jump	djn		7	A B		Subtract 1 from
Xif not zero						contents of address
X							B and transfer
X							control to
X							address A if contents
X							of address B is != 0
XCompare		cmp		8	A B		compare contents of
X							addresses A and B; if
X							they are unequal,
X							skip the next
X							instruction.
XSplit		spl		9	  B		split execution into
X							next instruction and
X							the instruction at A
XData statment	dat		0	  B		A nonexecuatble
X							statement; B is the
X							data value.
X
X
XAddressing modes:-
Ximmediate mode:		#argument
Xdirect mode:		symbol
Xindirect mode:		@symbol
X
XExpected other differences -
X1)	When +/- are conducted to an address that contains other than a
X	data instruction, parameter B is always modified (even in spl
X	instructions).  There is no way and add or sub instruction can
X	change one type of instruction to another, so the CODE part of
X	the table is really rather worthless.
X2)	The assembler will feature the "real" symbol.  In other words,
X	you do not have to convert all your symbols into numbers before
X	feeding your program to the assembler.
X	There will be a reserved symbol, though, called "start" and this
X	will be where your code will start executing.
X	All symbols are characterized by a ':' character at the end, e.g.
X	"start:"
X3)	Separate assembly.  In the interest of modularity and ease of
X	debugging (for my code, of course, not for the redcode assembly
X	program, so I still don't suggest writing 200 instruction redcode
X	programs, even though the assembler permits it), I have decided
X	to separate the assembler from the interpreter.  The interpreter
X	will have to be fed the preassembled programs, etc. in a special
X	format.  (produced by the assembler).
X
X4)	Will not implement stuff like the "<" or the ">".  i.e., decrease
X	stuff pointed to by operand, then get that address.
X
X5)	Randomized starting memory for the redcode programs.
X	Make corewars more deterministic - predictable.
X	Can be implemented later if demand arises.
X
XOther expected differences -
X
XBUGS!!!
X
XBUG REPORT SECTION:-
X
Xassem/main.c	- The program will not accept files with ".e" anywhere
X		  in the last portion of it (i.e., the extension)
X		  These files will be rejected.
X		  e.g.	"mice.eecs" will be rejected
X
Xtokenize.c	- The program will not be able to handle comments without
X		  any delimiters between them and the code.
X		  e.g.  "mov 0 1;;help" will be tokenized into:
X			"mov" "0" "1;;help" which is not acceptable, since
X			the later functions like lookup will not be able
X			to handle it.
X
Xplay.c/main.c:	- The BIG option (to fully bit map the memory array,
X		  doesn't work.   I wonder why?)
X
XNote:
XA.K. Dewdney's THE ARMCHAIR UNIVERSE is available from Freeman (publisher).
XI highly recommend buying a copy and reading it.  It's a whole lot
Xof fun and teaches a lot of great programming techniques.
XIt's moderately priced at around $13.25, and, in my opinion, worth every
Xpenny.
X
XChoon Piaw
X
X
XAssembler portion of corewars
XUsage:
Xassem <file1> <file2> .....
X
XAll output files will have an additional extension ".e"
Xfor instance, if the input file was "help.rc" the ouput file will be "help.e"
X
XAssembler limits: 200 instructions
X		  100 symbols
X		  255 characters in a string
X
XComments are indicated by a ;
XAssembler is not case sensitive.
XRemember that this does not conform to ALL the A.K. Dewdney standards
Xin the implementation of OPCODES/PARAMETERS, but as long as you write
Xcode that does not depend on changing other's opcode, you should be
Xall right.  The instruction set is standard, however.
X
XBUGS:
X	Any file starting with a .e extension is rejected automatically
X	Any character is recognized as a symbol.  Therefore, in
X	mov	0	1;this is a comment
X	1;this will be interpreted as a symbol instead of a number with
X	a comment following it.  The proper form would be:
X	mov	0	1	;this is a comment
X
X
X
XCorewars interpreter
X- started 12/14/88 by Na Choon Piaw (The Existentialist)
X
Xusage:
X
Xinterp cycles file1 file2
X
Xcycles		-number of machine cycles
Xfile1, file2	-preassembled corewars programs
X
XProgrammer's documentation for Redcode interpreter
X
XGoal:
X
XTo provide a visual version of corewars that is fast, standard and portable.
X
XModules
X
X1.	int loader(int position)
X	-	load up files into main memory to position.
X	-	setup the starting pcs
X
X2.	eval
X	-	input the memory element + a host of other info
X		(including the list of streams)
X	-	each of the instructions will be handled by a separate
X		subroutine that will be passed just sufficient info to carry
X		it out.
X
X3.	control
X	-	responsible for keeping track of who's what and passing the
X		correct instruction to the evaluator
X
X4.	Display
X	-	Display in a visual format (to be decided) what's going on
X		in memory at that time.
X
XData Structures
X
XStreams of execution are kept as circularly linked list, with split
Xinstructions adding to the linked list, and with trying to execute data
Xinstructions.
X
XAll parameters will range from 0 to +8000.  Excess will be trimmed off,
Xnegatives will be wrapped back around.
X
XCredit where credit is due:
X
XCase Larsen wrote and debugged the SUN graphics function interface2.c
XAdrain Ho wrote and debugged the loader load.c
XI wrote and debugged the rest.
X
X
XNa Choon Piaw
Xc60a-3ci@wolf.berkeley.edu
X(soon to be changed)
X301P, 2650 Durant,
XBerkeley, CA 94720.
END_OF_FILE
if test 7249 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(1199 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X MANIFEST                   1	This shipping list
X Makefile                   2	
X Makefile.std               1	
X Makefile.sun               2	
X README                     1	
X README.sun                 1	
X amain.c                    1	
X aoutput.c                  2	
X assem.c                    2	
X assem.h                    1	
X bomb.rc                    2	
X chang1.rc                  2	
X commando.rc                2	
X disassem.c                 1	
X dwarf.rc                   2	
X dwarfgun.rc                2	
X gemini.rc                  2	
X imp.rc                     2	
X impstomp.rc                2	
X inst.c                     1	
X interface2.c               1	
X interp.c                   2	
X interp.h                   2	
X load.c                     1	
X lookup.c                   1	
X main.c                     1	
X mice.rc                    2	
X output.c                   1	
X parse.c                    1	
X play.c                     1	
X selfcpy.rc                 2	
X sit.rc                     2	
X test.c                     2	
X testspl.rc                 2	
X tokenize.c                 1	
END_OF_FILE
if test 1199 -ne `wc -c <'MANIFEST'`; then
    echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'Makefile.std' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile.std'\"
else
echo shar: Extracting \"'Makefile.std'\" \(1010 characters\)
sed "s/^X//" >'Makefile.std' <<'END_OF_FILE'
Xall: assem disassem interp
X
XASM_OBJ = amain.o tokenize.o parse.o lookup.o aoutput.o assem.o
X
X# Standard curses version of interpreter
XINT_OBJ = main.o load.o output.o play.o inst.o
XLIBS = -lcurses -ltermcap
X
X# Sun version using pixrect lib of interpreter
XSINT_OBJ = main.o load.o output.o play.o inst.o interface2.o
XSLIBS = -lcurses -ltermcap -lpixrect
X
X# Define one of DEBUG, SMALL, SUN or BIG (BIG is buggy)
XCFLAGS = -O -DSMALL
X
Xassem: $(ASM_OBJ)
X	cc -o assem $(ASM_OBJ)
X
Xdisassem: disassem.c assem.h
X	cc -O disassem.c -o disassem
X
X# Standard version
Xinterp: $(INT_OBJ)
X	cc -o interp  $(INT_OBJ) $(LIBS)
X
X# Sun pixrect version
X#interp: $(SINT_OBJ)
X#	cc -o interp  $(SINT_OBJ) $(SLIBS)
X
Xamain.o: amain.c assem.h
Xtokenize.o: tokenize.c assem.h
Xparse.o: parse.c assem.h
Xlookup.o: lookup.c assem.h
Xoutput.o: aoutput.c assem.h
Xassem.o: assem.c assem.h
X
Xmain.o:	main.c interp.h
Xload.o: load.c interp.h
Xoutput.o: output.c interp.h
Xplay.o: play.c interp.h
Xinst.o: inst.c interp.h
Xinterface2.o: interface2.c interp.h
END_OF_FILE
if test 1010 -ne `wc -c <'Makefile.std'`; then
    echo shar: \"'Makefile.std'\" unpacked with wrong size!
fi
# end of 'Makefile.std'
fi
if test -f 'README.sun' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README.sun'\"
else
echo shar: Extracting \"'README.sun'\" \(558 characters\)
sed "s/^X//" >'README.sun' <<'END_OF_FILE'
XThis is the pixrect version of the corewars interpreter.
XThis is system specific.  It does not depend on SUNVIEW, X, or any other
Xwindowing system.  You will need the pixrect library to run this.
XDo NOT overlap other windows on the window generated, and to remove this
Xwindow, just do a redraw.  (Yes, it does a write to the frame buffer.
XPretty ugly, but.....)
X
XAs usual, bug reports, etc, send to me, and any questions pertaining to
Xinterface2.c direct to Case Larsen (laba-3ar@wolf.berkeley.edu).
X
XNa Choon Piaw
Xc60a-3ci@wolf.berkeley.edu
X(to be changed)
END_OF_FILE
if test 558 -ne `wc -c <'README.sun'`; then
    echo shar: \"'README.sun'\" unpacked with wrong size!
fi
# end of 'README.sun'
fi
if test -f 'amain.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'amain.c'\"
else
echo shar: Extracting \"'amain.c'\" \(2800 characters\)
sed "s/^X//" >'amain.c' <<'END_OF_FILE'
X/* this module contains the main function, which settles open/close
X   file i/o as well as little trivial details like adding an extension
X   and stuff like that.  It has been debuged (except for BUG NOTES)
X   so it's safe to trust. There is a little bit of inefficiency, but
X   that's justified since I want a more easily readable program */
X
X#include "assem.h"
X#include <stdio.h>
X#include <malloc.h>
X#include <strings.h>
X
Xchar	*outname(str)
Xchar	*str;
X/* accepts an input string and outputs a proper output file with ".e"
X   extension.  If already has .e, as an extension, produce an error. 
X   BUG NOTE: even if it's as innoculous as .eex, etc (as long as the
X             extension starts with .e) it will still produce an error
X   Otherwise, remove current extension
X   and add .e extension.
X   returns pointer to new output name                                       */
X{
X	char	*newstr;
X	char	*dot;		/* position of '.' */
X
X	if (!(newstr =(char *) malloc( (unsigned) strlen(str) + 3)))
X	{
X		printf("not enough memory --- outname\n");
X		exit(1);
X	}
X
X	strcpy(newstr,str);
X
X	if (!(dot = rindex(newstr,'.')))
X		strcat(newstr,".e");	/* no extenstion */
X	else if (*(dot + 1) == 'e')	/* same extension as output? */
X	{
X		printf("wrong input file name: %s\n", newstr);
X		printf("try moving to non .e extension --- outname\n");
X		exit(1);
X	}
X	else				/* perform surgery */
X	{
X		(*(dot + 1)) = 'e';
X		(*(dot + 2)) = '\0';
X	}
X
X	return newstr;
X}
X
X
X/* main -- Open input and output files, giving default names if
X           necessary.  Detects errors like not being able to open files
X	   etc.
X*/
Xmain(argc, argv)
Xint	argc;
Xchar	*argv[];
X{
X	FILE	*f1,*f2;		/* input file, output file */
X	char	*outfile = "NONAME",	/* default output file */
X		flag = 0;		/* standard input */
X
X	if (argc == 1)		/* no arguments */
X	{
X		flag = 1;	/* read from standard input */
X		argv[1] = outfile;
X		argc = 2;	/* one file */
X	}
X
X	for (;argc > 1; argc--)
X	{
X		if (flag)
X			f1 = stdin;	/* set file to standard input */
X		else
X			/* open input file */
X			if (!(f1 = fopen(argv[argc - 1],"r")))
X			{
X				printf("oops cannot open file %s",
X					argv[argc - 1]);
X				printf("\n-- in main\n");
X				exit(1);	/* error status 1 */
X			}
X
X			/* open output file */
X			if (!(f2 = fopen(outname(argv[argc - 1]), "w")))
X			{
X
X				printf("cannot open write file %s",
X					outname(argv[argc - 1]));
X				printf("\n --- in main\n");
X				exit(1);
X			}
X
X		printf("%s:\n", argv[argc - 1]);
X		assemble(f1,f2);	/* call assembler */
X
X		if (!flag)	/* close file */
X			fclose(f1);
X
X		fclose(f2);
X	}
X}
X
X/* debugging version of assemble */
X/* commented out because this module is now fully debugged */
X/* --- Na Choon Piaw, 11/14 */
X/*
Xassemble(infile,outfile)
XFILE	*infile, *outfile;
X{
X	int	c;
X
X	while ((c = fgetc(infile)) != EOF)
X		fputc(c, outfile);
X}
X*/
END_OF_FILE
if test 2800 -ne `wc -c <'amain.c'`; then
    echo shar: \"'amain.c'\" unpacked with wrong size!
fi
# end of 'amain.c'
fi
if test -f 'assem.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'assem.h'\"
else
echo shar: Extracting \"'assem.h'\" \(1840 characters\)
sed "s/^X//" >'assem.h' <<'END_OF_FILE'
X/*	Copyrighted (C) 1989 by Na Choon Piaw.  All rights reserved       */
X
X
X
X/*	This program and documentation is Public Domain, and may be	  */
X/*	distributed and copied by everyone provided this header		  */
X/*	remains intact							  */
X
X/* MARS redcode assembler:
X	Header file
X	Restarted in Novemeber '88
X	Na Choon Piaw		*/
X
X/* note that tag is just a generic name for something that I can't think
X   of a name for.                            ---- CP                 */
X
X/* define instruction set */
Xtypedef enum { dat, mov, add, sub, jmp, jmz, jmn, djn, cmp, spl } instr;
X
X/* define addressing modes */
Xtypedef enum { immed, direct, indirect } mode;
X
X/* define structure of an instruction */
X/* NOTE: this will probably differ from the interpreter's version */
Xtypedef struct
X{
X	instr	inst;		/* instruction */
X	int	para1,para2;	/* first parameter, second parameter */
X	mode	m1,m2;		/* addressing modes for parameters */
X} memory;	/* memory element */
X
X/* define compiler limits */
X#define MAXINST	200	/* maximum number of instructions */
X#define SYMBOLS 100	/* maximum number of symbols in symbol table */
X#define MAXBUFFER 256	/* maximum size of string buffer */
X#define COMMENT ';'	/* comment character */
X
X/* linked list of tokens for tokenizer and assembler to work on */
Xtypedef struct tag0
X{
X	char		*token;		/* token as a string */
X	struct tag0	*next;		/* next token */
X} tokenlist;
X
X/* symbol table structure */
Xtypedef struct
X{
X        char    *symbol;                /* pointer to string of symbol */
X        int     position;               /* position the symbol belongs to */
X} tag1;
X
X/* now to define the strings that the assembler recognizes */
X#define MOV	"MOV"
X#define ADD	"ADD"
X#define SUB	"SUB"
X#define JMP	"JMP"
X#define JMZ	"JMZ"
X#define JMN	"JMN"
X#define DJN	"DJN"
X#define CMP	"CMP"
X#define SPL	"SPL"
X#define DAT	"DAT"
END_OF_FILE
if test 1840 -ne `wc -c <'assem.h'`; then
    echo shar: \"'assem.h'\" unpacked with wrong size!
fi
# end of 'assem.h'
fi
if test -f 'disassem.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'disassem.c'\"
else
echo shar: Extracting \"'disassem.c'\" \(1653 characters\)
sed "s/^X//" >'disassem.c' <<'END_OF_FILE'
X/*	Copyrighted (C) 1989 by Na Choon Piaw.  All rights reserved       */
X
X
X
X/*	This program and documentation is Public Domain, and may be	  */
X/*	distributed and copied by everyone provided this header		  */
X/*	remains intact							  */
X
X#include <stdio.h>
X#include "assem.h"
X
X/* dissassembler for red code programs.
X   NOTE:  I'm not bothering with writing code to REALLY disassemble
X          it, just output starting position, number of instructions,
X	  opcode, and operands.
X   11/25 ---- NCP                           */
X#define IO(i,j) if ((i) < (j)) {printf("error reading file\n");exit(1);}
X
X
Xmain(argc, argv)
Xint	argc;
Xchar	*argv[];
X{
X	FILE	*f;
X	int	i,j,k;
X	memory	elements[MAXINST];
X
X	if (argc < 1)
X	{
X		printf("usage: disassem <file>\n");
X		exit(1);
X	}
X
X	if (!(f = fopen(argv[1],"r")))
X	{
X		printf("cannot open file %s\n", argv[1]);
X		printf("------ main\n");
X		exit(1);
X	}
X
X	i = fread(&j, sizeof(int), 1, f);
X	IO(i,1)
X	printf("Number of instructions: %d\n", j);
X
X	i = fread(&k, sizeof(int), 1, f);
X	IO(i,1)
X	printf("Starting instruction: %d\n", k);
X
X	i = fread(elements, sizeof(memory), j, f);
X	IO(i,j)
X
X	printf("NO.\tOPCODE\tFIRSTPARA\tSECONDPARA\n");
X	for (i = 0; i < j;i++)
X	{
X		printf("%d\t", i);
X		printf("%d\t", (int) elements[i].inst);
X		if (elements[i].m1 == immed)
X			putchar('#');
X		else if (elements[i].m1 == indirect)
X			putchar('@');
X		printf("%d\t\t", (int) elements[i].para1);
X                if (elements[i].m2 == immed)
X                        putchar('#');
X                else if (elements[i].m2 == indirect)
X                        putchar('@');
X                printf("%d\n", (int) elements[i].para2);
X	}
X
X	fclose(f);
X}
END_OF_FILE
if test 1653 -ne `wc -c <'disassem.c'`; then
    echo shar: \"'disassem.c'\" unpacked with wrong size!
fi
# end of 'disassem.c'
fi
if test -f 'inst.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'inst.c'\"
else
echo shar: Extracting \"'inst.c'\" \(5953 characters\)
sed "s/^X//" >'inst.c' <<'END_OF_FILE'
X/* execution code for the machine */
X
X/*	This is a replacement for the screwed up code in "execute.c"
X	Each instruction is a function, and accepts just enough information
X	to execute that instruction.
X*/
X
X#include "interp.h"
X#include <malloc.h>
X#include <stdio.h>
X
Xextern	cell	a[];		/* core */
X
Xcorrect(thing)
Xint	*thing;
X{
X	if (*thing >= 0)
X		*thing %= SIZE;
X	else if (*thing < 0)
X	{
X		*thing %= SIZE;
X		*thing = SIZE + *thing;
X	}
X}
X
Xint	getdirect(ins, off)
X/* get position of direct parameter */
Xint	ins;	/* current position */
Xint	off;	/* offset of instruction */
X{
X	int	temp;
X
X	temp = ins + off;
X	correct(&temp);
X	return (temp);
X}
X
Xint	getindirect(ins, off)
X/* get position of indirect parameter */
X/* Note :-
XA.K. Dewdney's specifications say that the pointer points relative to its
Xcurrent position, NOT the instruction's position. */
X
Xint	ins;
Xint	off;
X{
X	int	temp;	/* temporary variable */
X
X	correct(&off);
X	temp = getdirect(ins, off);		/* get direct variable */
X	correct(&temp);				/* correct it */
X	temp = getdirect(temp, a[temp].para2);	/* This time it's for real */
X	correct(&temp);
X	return (temp);
X}
X
Xint	getpara(ins, m, p)
X/* Note:- This routine is designed only to work with indirect and direct
X   operations.  NOT with immediate mode operations. Returns the address
X   of the parameter by calling getdirect or getindirect			*/
Xint	ins;	/* location of current instruction */
Xmode	m;	/* mode */
Xint	p;	/* parameter */
X{
X	if (m == direct)
X		return(getdirect(ins, p));
X	else if (m == indirect)
X		return(getindirect(ins, p));
X
X	/* else */
X	printf("getpara passed wrong parameter --- getpara\n");
X	exit(1);
X}
X
XMov	(ins, pc, pid)
X/* MOV instruction :
Xsets the lastmod flag to the process id					*/
Xint	ins;	/* position of instruction to execute */
Xint	*pc;	/* program counter */
Xint	pid;	/* process ID */
X{
X	int	realpos;
X	cell	temp;		/* store item to be moved */
X
X	if (a[ins].m1 == immed)
X	{
X		temp.inst = dat;
X		temp.para1 = 0;
X		temp.para2 = a[ins].para1;
X		temp.m1 = temp.m2 = immed;
X	}
X	else
X	{
X		realpos = getpara(ins, a[ins].m1, a[ins].para1);
X		temp = a[realpos];
X	}
X
X	if (a[ins].m2 == immed)
X	{
X		printf("Tried to mov to immediate parameter\n");
X		printf("--- mov\n");
X		exit(1);
X	}
X	else
X		realpos = getpara(ins, a[ins].m2, a[ins].para2);
X
X	a[realpos] = temp;
X	a[realpos].lastmod = pid;
X	(*pc)++;
X	correct(pc);
X}
X
XAdd(ins, pc, pid)
X/* ADD instruction */
Xint	ins;
Xint	*pc;
Xint	pid;
X{
X	int	x;		/* parameter A */
X	int	realpos;	/* real position of B */
X
X	if (a[ins].m1 == immed)
X		x = a[ins].para1;
X	else
X		x = a[getpara(ins, a[ins].m1, a[ins].para1)].para2;
X
X	if (a[ins].m2 == immed)
X	{
X		printf("Trying to add to immediate address\n");
X		printf("--- ADD\n");
X		exit(1);
X	}
X	else
X		realpos = getpara(ins, a[ins].m2, a[ins].para2);
X
X	a[realpos].para2 += x;
X	a[realpos].lastmod = pid;
X	correct(&(a[realpos].para2));
X	(*pc)++;
X	correct(pc);
X}
X
X
XSub(ins, pc, pid)
X/* SUB instruction */
Xint	ins;
Xint	*pc;
X{
X	int	x;		/* parameter A */
X	int	realpos;	/* real position of B */
X
X	if (a[ins].m1 == immed)
X		x = a[ins].para1;
X	else
X		x = a[getpara(ins, a[ins].m1, a[ins].para1)].para2;
X
X	if (a[ins].m2 == immed)
X	{
X		printf("Trying to subtract from immediate address\n");
X		printf("--- SUB\n");
X		exit(1);
X	}
X	else
X		realpos = getpara(ins, a[ins].m2, a[ins].para2);
X
X	a[realpos].para2 -= x;
X	a[realpos].lastmod = pid;
X	correct(&(a[realpos].para2));
X	(*pc)++;
X	correct(pc);
X}
X
XJmp(ins,pc)
Xint	ins;
Xint	*pc;
X{
X	if (a[ins].m2 == immed)
X	{
X		printf("attempt to jump to immediate address\n");
X		printf("-- JMP\n");
X		exit(1);
X	}
X	else
X		*pc = getpara(ins, a[ins].m2, a[ins].para2);
X
X	correct(pc);
X}
X
XJmz(ins, pc)
Xint	ins;
Xint	*pc;
X{
X	int	value;	/* value of first parameter */
X
X	if (a[ins].m2 == immed)
X		value = a[ins].para2;
X	else
X	{
X		value = getpara(ins, a[ins].m2, a[ins].para2);
X		correct(&value);
X		value = a[value].para2;
X	}
X
X	correct(&value);
X
X	if (value)
X		(*pc)++;
X	else
X		*pc = getpara(ins, a[ins].m1, a[ins].para1);
X
X	correct(pc);
X}
X
XJmn(ins,pc)
Xint	ins;
Xint	*pc;
X{
X	int	value;
X
X	if (a[ins].m2 == immed)
X		value = a[ins].para2;
X	else
X	{
X		value = getpara(ins, a[ins].m2, a[ins].para2);
X		correct(&value);
X		value = a[value].para2;
X	}
X
X	if (!value)
X		*pc = getpara(ins, a[ins].m1, a[ins].para1);
X	else
X		(*pc)++;
X	correct(pc);
X}
X
XDjn(ins, pc, pid)
Xint	ins;
Xint	*pc;
X{
X	int	temp;	/* position to decrement */
X
X	if (a[ins].m2 == immed)
X	{
X		printf("tried to decrement immediate address\n");
X		printf("--- DJZ\n");
X		exit(1);
X	}
X	else
X		temp = getpara(ins, a[ins].m2, a[ins].para2);
X
X	(a[temp].para2)--;
X	correct(&(a[temp].para2));
X	a[temp].lastmod = pid;
X
X	if (!a[temp].para2)
X		(*pc)++;
X	else
X		*pc = getpara(ins, a[ins].m1, a[ins].para1);
X
X	correct(pc);
X}
X
XCmp(ins, pc)
Xint	ins;
Xint	*pc;
X{
X	int	value1, value2;
X
X	if (a[ins].m1 == immed)
X		value1 = a[ins].para1;
X	else
X		value1 = a[getpara(ins, a[ins].m1, a[ins].para1)].para2;
X
X	if (a[ins].m2 == immed)
X		value2 = a[ins].para2;
X	else
X		value2 = a[getpara(ins, a[ins].m2, a[ins].para2)].para2;
X
X	correct(&value1);
X	correct(&value2);
X	if (value1 == value2)
X		(*pc) += 2;	
X	else
X		(*pc)++;
X
X	correct(pc);
X}
X
XSpl(ins, pc, mem)
Xint	ins;
Xint	*pc;
Xstream	*mem;		/* pointer to structure of current pc */
X{
X	int	newpc;
X	stream	*newmem;
X
X	if (a[ins].m2 == immed)
X	{
X		printf("Tried to split into immediate address\n");
X		printf("--- SPL\n");
X		exit(1);
X	}
X	else
X		newpc = getpara(ins, a[ins].m2, a[ins].para2);
X
X	if (!(newmem = (stream *) malloc(sizeof(stream))))
X	{
X		printf("no more memory!!\n");
X		printf("--- SPL\n");
X		exit(1);
X	}
X
X	correct(&newpc);
X	newmem -> pc = newpc;
X	newmem -> next = mem -> next;
X	mem -> next = newmem;
X	newmem -> prev = mem;
X	newmem -> next -> prev = newmem;
X
X	(*pc)++;
X	correct(pc);
X}
X
Xextern	stream	*exe[];
X
XDat(i)
X/* kill stream */
Xint	i;
X{
X	stream	*curr = exe[i];		/* current */
X
X	if (curr -> next == curr)
X	{
X		exe[i] = NULL;
X		free(curr);
X		return;
X	}
X
X	exe[i] = curr -> next;
X	curr -> next -> prev = curr -> prev;
X	curr -> prev -> next = curr -> next;
X
X	free(curr);
X}
END_OF_FILE
if test 5953 -ne `wc -c <'inst.c'`; then
    echo shar: \"'inst.c'\" unpacked with wrong size!
fi
# end of 'inst.c'
fi
if test -f 'interface2.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'interface2.c'\"
else
echo shar: Extracting \"'interface2.c'\" \(2007 characters\)
sed "s/^X//" >'interface2.c' <<'END_OF_FILE'
X/**********************************************************************
X * 								      *
X * 								      *
X * 		   Copyright 1989 By Case T. Larsen		      *
X * 			 All Rights Reserved			      *
X * 				   				      *
X * 				   				      *
X **********************************************************************/
X
X#include <pixrect/pixrect_hs.h>
X#include "interp.h"
X
X#define Y(x) (((x)/100)*5)
X#define X(x) (((x)%100)*5)
X
Xstatic struct pixrect *screen;
Xstatic struct pixrect *bm;
Xstatic bitm[8000];
Xstatic xpos[8000], ypos[8000];
X
Xxcore_init ()
X{
X  int i;
X
X  screen = pr_open("/dev/fb");
X  bm = mem_create(500,400,1);
X  for (i=0; i<8000;i++) {
X    bitm[i] = 0;
X    xpos[i] = X(i); ypos[i] = Y(i);
X    zero(xpos[i],ypos[i]);
X  }
X  pr_rop (screen,0,0,500,400,PIX_SRC,bm,0,0);
X} /* xcore_init */
X
Xzero (x,y)
X     int x,y;
X{
X  pr_put (bm,x,y,1);
X  pr_put (bm,x,y+1,1);
X  pr_put (bm,x,y+2,1);
X  pr_put (bm,x+1,y,1);
X  pr_put (bm,x+1,y+1,1);
X  pr_put (bm,x+1,y+2,1);
X  pr_put (bm,x+2,y,1);
X  pr_put (bm,x+2,y+1,1);
X  pr_put (bm,x+2,y+2,1);
X} /* zero */
X
Xone (x,y)
X     int x,y;
X{
X  pr_put (bm,x,y,0);
X  pr_put (bm,x,y+1,0);
X  pr_put (bm,x,y+2,0);
X  pr_put (bm,x+1,y,0);
X  pr_put (bm,x+1,y+1,0);
X  pr_put (bm,x+1,y+2,0);
X  pr_put (bm,x+2,y,0);
X  pr_put (bm,x+2,y+1,0);
X  pr_put (bm,x+2,y+2,0);
X} /* zero */
X
Xtwo (x,y)
X     int x,y;
X{
X  pr_put (bm,x,y,1);
X  pr_put (bm,x,y+1,0);
X  pr_put (bm,x,y+2,0);
X  pr_put (bm,x+1,y,0);
X  pr_put (bm,x+1,y+1,1);
X  pr_put (bm,x+1,y+2,0);
X  pr_put (bm,x+2,y,0);
X  pr_put (bm,x+2,y+1,0);
X  pr_put (bm,x+2,y+2,1);
X} /* zero */
X
Xxcore_display (mem)
X     cell mem[];
X{
X  register int i;
X  register int owner;
X
X  for (i=0;i<8000;i++) {
X    if (mem[i].lastmod != bitm[i]) {
X      owner = bitm[i] = mem[i].lastmod;
X      if (owner) {
X	if (owner == 1) {
X	  one (xpos[i],ypos[i]);
X	} else
X	  two (xpos[i],ypos[i]);
X      } else
X	zero (xpos[i],ypos[i]);
X    }
X  }
X  pr_rop (screen,0,0,500,400,PIX_SRC,bm,0,0);
X} /* xcore_display */
X
Xxcore_done ()
X{
X  pr_close(screen);
X} /* xcore_done */
END_OF_FILE
if test 2007 -ne `wc -c <'interface2.c'`; then
    echo shar: \"'interface2.c'\" unpacked with wrong size!
fi
# end of 'interface2.c'
fi
if test -f 'load.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'load.c'\"
else
echo shar: Extracting \"'load.c'\" \(2803 characters\)
sed "s/^X//" >'load.c' <<'END_OF_FILE'
X/* program loader for MARS
X   12/16/88    --- NCP   */
X
X#include "interp.h"
X#include <stdio.h>
X#include <memory.h>
X#include <malloc.h>
X
X#define IO(i,j) if((i) < (j)){printf("error reading file\n");exit(1);}
Xextern	cell	a[];
Xextern	stream	*exe[];
X
X/* generates starting position */
X/* debugging non random version */
Xint	startposition()
X{
X/*  debugging code:
X	static int	i = 0;
X
X	if (i == 0)
X	{
X		i = 1;
X		return(0);
X	}
X	else
X		return((int) SIZE / 2)
X*/
X	return(rand()%SIZE);
X}
X
X
Xload(f, no)
XFILE	*f;		/* file */
Xint	no;		/* player number */
X{
X	memory	ele[MAXINST];
X	int	i;		/* number of instructions */
X	int	test;		/* test instructions read */
X	int	start;		/* starting instruction */
X	int	position;	/* loading position */
X	int	counter;	/* general-purpose counter */
X
X	test = fread(&i, sizeof(int), 1, f);
X	IO(test, 1)
X	printf("Found %d/%d instructions\n", i, MAXINST);
X	if (i > MAXINST) {
X		printf("load: Oops!  Too large!!\n");
X		return(1);	/* oops - too large */
X	}
X
X	test = fread(&start, sizeof(int), 1, f);
X	IO(test, 1)
X
X	test = fread(ele, sizeof(memory), i, f);
X	IO(test, i)
X
X	/* get a new starting position */
X	do {
X		position = startposition();
X		printf("Trying position %d\n", position);
X	} while (testpos(position,i));
X
X	/* and load the code there */
X	printf("Loading %d instructions at location %d\n", i, position);
X	for (counter = 0; counter < i; counter++) {
X		memcpy(&a[(counter+position)%SIZE],&ele[counter],sizeof(memory));
X#ifdef DEBUG
X		if (!(((counter+position)%SIZE)%10)) {
X			printf("%d%",(counter+position)%SIZE);
X		} else {
X			putchar('.');
X		}
X#endif
X		a[(counter+position)%SIZE].lastmod = no;
X		printf("Contents of location %d: %d %d %d %d %d %d\n",
X			(counter+position)%SIZE,
X			a[(counter+position)%SIZE].inst,
X			a[(counter+position)%SIZE].para1,
X			a[(counter+position)%SIZE].para2,
X			a[(counter+position)%SIZE].m1,
X			a[(counter+position)%SIZE].m2,
X			a[(counter+position)%SIZE].lastmod);
X	}
X
X	if ((exe[no] = (stream *) malloc(sizeof(stream))) == NULL) {
X		printf("load: Can't malloc the PC - aborting\n");
X		exit(1);
X	} else {
X		exe[no]->pc = (position + start) % SIZE;
X		exe[no]->next = exe[no]->prev = exe[no];
X#ifdef DEBUG
X		printf("Starting PC: %d %d %d\n", exe[no]->pc, exe[no]->next->pc, exe[no]->prev->pc);
X#endif
X	}
X
X	return(0);	/* all OK */
X}
X
X/* tests for empty segment of *no* bytes starting at *start* */
Xtestpos(start,no)
Xint	start,no;
X{
X	int	counter;	/* general-purpose counter */
X
X	for (counter = 0; counter < no; counter++) {
X#ifdef DEBUG
X		if (!(((counter+start)%SIZE)%10)) {
X			printf("%d%",(counter+start)%SIZE);
X		} else {
X			putchar('.');
X		}
X#endif
X		if (a[(counter+start)%SIZE].lastmod) {
X			printf("testpos: Oops -- something at %d\n",(counter+start)%SIZE);
X			return(1);  /* oops - clash */
X		}
X	}
X	return(0);	/* all clear - segment is free */
X}
END_OF_FILE
if test 2803 -ne `wc -c <'load.c'`; then
    echo shar: \"'load.c'\" unpacked with wrong size!
fi
# end of 'load.c'
fi
if test -f 'lookup.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'lookup.c'\"
else
echo shar: Extracting \"'lookup.c'\" \(5797 characters\)
sed "s/^X//" >'lookup.c' <<'END_OF_FILE'
X/*	Copyrighted (C) 1989 by Na Choon Piaw.  All rights reserved       */
X
X
X
X/*	This program and documentation is Public Domain, and may be	  */
X/*	distributed and copied by everyone provided this header		  */
X/*	remains intact							  */
X
X/* lookup   ---- this is the real core of the assembler.  It will
X		 perform functions such as matching symbols to instructions,
X		 matching symbolic references to absolute code (and performing
X		 whatever calculations necessary).                         */
X
X#include "assem.h"
X#include <malloc.h>
X#include <stdio.h>
X#include <strings.h>
X#include <ctype.h>
X
X/* declare external functions */
Xint		symbol();
Xint		instruction();
Xinstr		getin();
Xint		para();
Xint		getpara();
Xmode		getmode();
X
X/* algorithm :-
X	1)	start from beginning of the list.
X	2)	process element.
X	3)	go on to next element.
X	4)	return number of instructions
X*/
X
Xint lookup(head, table, elements)
Xtokenlist	*head;
Xtag1		table[];
Xmemory		elements[];
X{
X	int	i = 0,			/* instruction pointer */
X		j = 0,			/* number of parameters */
X		k = 0;			/* current parameters */
X
X	initialize(elements);		/* initialize table */
X	while (head && symbol(head))	/* look for first instruction */
X		head = head -> next;
X	while (head)
X	{
X		/* expect instruction */
X		if (!instruction(head))
X		{
X			printf("%s is not instruction\n", head -> token);
X			printf(" --- lookup\n");
X			exit(1);
X		}
X
X		elements[i].inst = getin(head);
X
X		/* expect number of parameters */
X		j = para(head);
X		k = 0;
X		while (k < j)
X		{
X			head = head -> next;
X			if (k == 0 && j == 2)	/* if single para, put in B */
X			{
X				elements[i].para1 = getpara(head,table,i);
X				elements[i].m1 = getmode(head);
X			}
X			else
X			{
X				elements[i].para2 = getpara(head,table,i);
X				elements[i].m2 = getmode(head);
X			}
X			k++;
X		}
X
X		if (head)
X			head = head -> next;	/* next instruction, if any */
X
X		while (head && symbol(head))	/* skim symbols */
X			head = head -> next;
X
X		i++;
X	}	/* while */
X	return i;
X}
X
X/* set all instructions to init */
Xinitialize(elements)
Xmemory	elements[];
X{
X	memory	ele;		/* set all to this initialized variable */
X	int	i;
X
X	ele.inst = dat;
X	ele.para1 = ele.para2 = 0;
X	ele.m1 = ele.m2 = immed;
X
X	for (i = 0; i < MAXINST; i++)
X		elements[i] = ele;
X}
X
X/* get the instr part of an instruction */
Xinstr	getin(ptr)
Xtokenlist	*ptr;
X{
X	char	*t;		/* string */
X	instr	x;		/* return value */
X
X	t = ptr -> token;
X
X	if (!strcmp(t, DAT))
X		x = dat;
X	else if (!strcmp(t, MOV))
X		x = mov;
X	else if (!strcmp(t, ADD))
X		x = add;
X	else if (!strcmp(t, SUB))
X		x = sub;
X	else if (!strcmp(t, JMP))
X		x = jmp;
X	else if (!strcmp(t, JMZ))
X		x = jmz;
X	else if (!strcmp(t, JMN))
X		x = jmn;
X	else if (!strcmp(t, DJN))
X		x = djn;
X	else if (!strcmp(t, CMP))
X		x = cmp;
X	else if (!strcmp(t, SPL))
X		x = spl;
X	else
X	{
X		printf("%s is not an instruction\n", t);
X		printf("--- getin\n");	
X		exit(1);
X	}
X
X	return x;
X}	/* getin */
X
X/* get the actual parameter (not the symbolic one)
XAlgorithm:
X	1)	check if symbol
X	2)	if symbol then look up, compare with current instruction,
X		and calculate what the actual parameter should be.
X	3)	if not symbol, then check that it is a numeric. if not, error.
X	4)	otherwise, return atoi
X*/
Xint	getpara(ptr, table, curr)
Xtokenlist	*ptr;		/* parameter instruction */
Xtag1		table[];	/* symbol table */
Xint		curr;		/* current instruction */
X{
X	char	*t;		/* token string */
X
X	t = ptr -> token;
X
X	if (*t == '@' || *t == '#')	/* ignore these */
X		t++;
X
X	if (number(t))
X		return(atoi(t));
X	else				/* must be symbol */
X		return(getsym(t, table) - curr);
X}
X
X/* return the absolute location (from the beginning of the program) of
X   a symbol                                                         */
Xint	getsym(str, table)
Xchar	*str;
Xtag1	table[];
X{
X	int	i = 0;
X	char	s[MAXBUFFER];
X
X	/* add colon for strcmp */
X	strcpy(s,str);
X	strcat(s,":");
X
X	for (; (i < SYMBOLS) && (table[i].symbol != NULL); i++)
X		if (!strcmp(table[i].symbol, s))
X			return(table[i].position);
X
X	/* out here, not symbol */
X	printf("symbol %s undefined\n", str);
X	printf("--- getsym\n");
X	exit(1);
X}
X
X/* checks that every element in string is a digit */
Xint	number(str)
Xchar	*str;
X{
X	int	i = 1;
X
X	if (*str == '+' || *str == '-')		/* positive or negative */
X		str++;
X
X	while (*str && i)
X	{
X		if (!isdigit(*str))
X			i = 0;
X		str++;
X	}
X
X	return i;
X}
X
Xmode	getmode(ptr)
Xtokenlist	*ptr;
X{
X	char	*t;		/* token string */
X
X	t = ptr -> token;
X
X	if (*t == '@')
X		return(indirect);
X	else if (*t == '#')
X		return(immed);
X	else
X		return(direct);
X}
X
X/* special debugging portion */
X
X/* declared debugged (phew! this one was tough) on 11/23/88 by CP */
X/*
Xtokenlist	*tokenize();
Xtag1 		table[SYMBOLS];
Xmemory		elements[MAXINST];
Xextern tokenlist *tokenize();
X
Xmain(argc, argv)
Xint	argc;
Xchar	*argv[];
X{
X	tokenlist 	*head;
X	FILE		*f;
X	int		i;
X
X	printf("loaded\n");
X	f = fopen(argv[1],"r");
X	printf("%s file opened\n", argv[1]);
X	head = tokenize(f);
X	printf("tokenized\n");
X	parse(head, table);
X	printf("parsed\n");
X	i = lookup(head, table,elements);
X	printf("%d instructions\n", i);
X
X	printf("OPCODE\tFIRSTPARA\tSECONDPARA\n");
X	for (i = 0; i < 20; i++)
X	{
X		printf("%d\t",(int) elements[i].inst);
X		if (elements[i].m1 == indirect)
X			printf("@");
X		else if (elements[i].m1 == immed)
X			printf("#");
X		printf("%d\t\t", elements[i].para1);
X                if (elements[i].m2 == indirect)
X                        printf("@");
X                else if (elements[i].m2 == immed)
X                        printf("#");
X		printf("%d\n", elements[i].para2);
X	}
X	fclose(f);
X}
X
Xprintsymbols(head)
Xtokenlist	*head;
X{
X	while (head != NULL)
X	{
X		printf("%s\n", head -> token);
X		head = head -> next;
X	}
X}
X
Xprintable(t)
Xtag1	t[];
X{
X	int	i;
X	printf("%s\t%s\n","SYMBOL","POSITION");
X	for (i = 0; table[i].symbol != NULL; i++)
X		printf("%s\t%d\n", table[i].symbol,table[i].position);
X}
X
X*/
END_OF_FILE
if test 5797 -ne `wc -c <'lookup.c'`; then
    echo shar: \"'lookup.c'\" unpacked with wrong size!
fi
# end of 'lookup.c'
fi
if test -f 'main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'main.c'\"
else
echo shar: Extracting \"'main.c'\" \(2157 characters\)
sed "s/^X//" >'main.c' <<'END_OF_FILE'
X/* main program for MARS interpreter
X   As usual, this does not do anything important.
X   Just calls all the proper subroutines in the right order and
X   opens files.
X   -- 12/16/88         --- NCP        */
X
X#include "interp.h"
X#include <ctype.h>
X#include <stdio.h>
X#include <memory.h>
X#include <curses.h>
X
Xlong	atol();
X
X/* memory array -- called "a" for easy typing */
Xcell	a[SIZE];
X
X/* next execution for each player */
Xstream	*exe[MAXPLAY];
X
X/* returns which player won */
Xint	play();
X
Xusage()
X{
X	printf("usage: interp cycles file1 file2\n");
X	printf("--- main\n");
X}
X
X/* checks that every element in string is a digit */
Xint	number(str)
Xchar	*str;
X{
X	int	i = 1;
X
X	while (*str && i)
X	{
X		if (!isdigit(*str))
X			i = 0;
X		str++;
X	}
X
X	return i;
X}
X
Xinitialize()
X{
X	int	counter;	/* general-purpose counter */
X
X	counter = (int) time(0);
X#ifndef DEBUG
X	initscr();		/* for "curses" library */
X	scrollok(stdscr, 0);
X	nl();
X	clear();
X	refresh();
X#endif
X
X#ifdef SUN
X	xcore_init();
X#endif
X	srand(counter);
X	for (counter = 0; counter++; counter < SIZE)
X		memset(a[counter],0,sizeof(cell));
X}
X
Xmain(argc, argv)
Xint	argc;
Xchar	*argv[];
X{
X	FILE	*f;
X	int	errcode, result;
X
X	initialize();		/* initialize all global variables */
X
X	if (argc != 4)		/* too many or too few */
X	{
X		usage();
X		exit(1);
X	}
X
X	if (!(number(argv[1])))
X	{
X		usage();
X		exit(1);
X	}
X
X	if ((f = fopen(argv[2], "r")) == NULL)
X	{
X		printf("%s cannot be opened\n", argv[2]);
X		exit(1);
X	}
X
X	errcode = load(f, 1);
X	fclose(f);
X	if (errcode == 1) {
X		printf("main: Sorry, but %s is too large to load\n",argv[2]);
X		exit(1);
X	}
X
X
X	if ((f = fopen(argv[3], "r")) == NULL)
X	{
X		printf("%s cannot be opened\n", argv[3]);
X		exit(1);
X	}
X
X	errcode = load(f,2);
X	fclose(f);
X	if (errcode == 1) {
X		printf("main: Sorry, but %s is too large to load\n",argv[3]);
X		exit(1);
X	}
X
X#ifndef DEBUG
X	clear();
X#endif
X
X	result = play(atol(argv[1]));
X
X#ifndef DEBUG
X#ifndef SUN
X	output(0);
X#endif
X	move(21, 0);
X	if (!result)
X		printw("nobody won!");
X	else
X		printw("%s won!", argv[result + 1]);
X	move(22, 0);
X	printw("Hit any key to continue...");
X	refresh();
X	getch(errcode);
X	endwin();
X#endif
X#ifdef SUN
X	xcore_done();
X#endif
X}
END_OF_FILE
if test 2157 -ne `wc -c <'main.c'`; then
    echo shar: \"'main.c'\" unpacked with wrong size!
fi
# end of 'main.c'
fi
if test -f 'output.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'output.c'\"
else
echo shar: Extracting \"'output.c'\" \(1956 characters\)
sed "s/^X//" >'output.c' <<'END_OF_FILE'
X/** Output function **/
X
X#include <stdio.h>
X#include <curses.h>
X
X#include "interp.h"
X
Xextern	cell	a[];
X
X#if DEBUG
Xoutput()
X{
X	int	i;
X
X	for (i = 0; i < SIZE; i ++)
X	{
X		if (a[i].lastmod == 0)
X			putchar('0');
X		else if (a[i].lastmod == 1)
X			putchar('1');
X		else if (a[i].lastmod == 2)
X			putchar('2');
X		else
X		{
X			printf("\nerror lastmod == %d", a[i].lastmod);
X			printf("i == %d", i);
X			exit(1);
X		}
X	}
X
X	putchar('\n');
X}
X#endif
X
X#ifdef SMALL
X/* assume large, 80 col screen */
X
Xoutput(cycles)
Xlong	cycles;
X{
X	int	map[SIZE / 5];	/* map to one fifth the size */
X	int	i, j, k = 0;
X
X	move(0,0);		/* start from the top */
X
X	domap(map);
X
X	for (i = 0; i < SIZE/5;)
X	{
X		move(k, 0);
X		for (j = 1; j < COLS; i++, j++)
X		{
X			if (SIZE / 5<= i)
X				break;
X
X			if (map[i] == 0)
X				addch('0');
X			else if (map[i] == 1)
X				addch('1');
X			else if (map[i] == 2)
X				addch('2');
X		}
X
X		k++;
X	}
X	move(23, 0);
X	printw("Cycles left: %10d", cycles);
X	refresh();
X}
X
Xdomap(arr)
Xint	arr[];
X{
X	int	i, j, pid1, pid2, pid3;
X
X	for (j = 0; j < SIZE/5; j++)
X	{
X		pid1 = pid2 = pid3 = 0;
X		for (i = j * 5; i < (j+1) * 5; i++)
X		{
X			if (SIZE <= i)
X				break;
X			if (a[i].lastmod == 0)
X				pid1++;
X			else if (a[i].lastmod == 1)
X				pid2++;
X			else if (a[i].lastmod == 2)
X				pid3++;
X			else
X			{
X				printf("invalid modification detected\n");
X				printf("--- domap\n");
X				exit(1);
X			}
X		}
X		arr[j] = max(pid1, pid2, pid3);
X	}
X}
X
Xmax(i, j, k)
Xint	i, j, k;
X{
X	if (i > j && i > k)
X		return 0;
X	else if (j > i && j > k)
X		return 1;
X	else
X		return 2;
X}
X#endif
X
X#ifdef BIG
Xoutput(cycles)
Xint	cycles;
X{
X	int	i, j, k;
X
X	/* perform detailed mapping */
X	for (i = 0, k = 0; i < SIZE; k++)
X	{
X		move (k, 0);
X		for (j = 0; j < COLS; i++, j++)
X		{
X			if (i >= (SIZE - 1))
X				break;
X
X			/* else */
X			if (a[i].lastmod == 0)
X				addch('0');
X			if (a[i].lastmod == 1)
X				addch('1');
X			else
X				addch('2');
X		}
X	}
X	move (k + 2, 0);
X	printw("Cycles left: %10d\n", cycles);
X	refresh();
X}
X#endif
END_OF_FILE
if test 1956 -ne `wc -c <'output.c'`; then
    echo shar: \"'output.c'\" unpacked with wrong size!
fi
# end of 'output.c'
fi
if test -f 'parse.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'parse.c'\"
else
echo shar: Extracting \"'parse.c'\" \(4743 characters\)
sed "s/^X//" >'parse.c' <<'END_OF_FILE'
X/*	Copyrighted (C) 1989 by Na Choon Piaw.  All rights reserved       */
X
X
X
X/*	This program and documentation is Public Domain, and may be	  */
X/*	distributed and copied by everyone provided this header		  */
X/*	remains intact							  */
X
X/* parser portion of the assembler.
X   11/15/88         - NCP        */
X
X#include <strings.h>
X#include <stdio.h>
X#include "assem.h"
X
X/* parser:
X  Algorithm:
X	1)	initialize symbol table
X	2)	Scan first element in token list
X	3)	if symbol declaraion (e.g. "start:") then lookup and enter into
X		symbol table
X	4)	if instruction, skip forward number of parameters
X		that instruction accepts
X	5)	otherwise error (not instruction or symbol)
X	6)	repeat 3-6 until no more tokens.
X*/
Xparse(tokens,table)
Xtokenlist	*tokens;	/* list of tokens */
Xtag1		table[];	/* symbol table */
X{
X	int	i = 0;		/* instructon counter */
X
X	init(table);		/* initialize table */
X
X	while (tokens)
X	{
X		if (symbol(tokens))
X		{
X			insert(tokens,table,i);
X			tokens = tokens -> next;
X		}
X		else if (instruction(tokens))
X		{
X			int	j = 0, k = para(tokens);
X
X			/* move up to next instruction:
X			   i.e., move from instruction + number of parameters
X			   if instruction is one parameter, move twice, etc */
X			while (j <= k)
X			{
X				tokens = tokens -> next;
X				j++;
X			}
X
X			i++;		/* next instruction */
X		}
X		else			/* not instruction or symbol */
X		{
X			printf("%s not symbol or instruction\n",
X				tokens -> token);
X			printf(" --- parse\n");
X			exit(1);
X		}
X	}	/* while */
X
X	/* test for too many instructions */
X	if (i > MAXINST)
X	{
X		printf("too many instructions\n");
X		printf("---- parse\n");
X		exit(1);
X	}
X} /* parse */
X
Xinit(table)		/* function to initialize symbol table (set to 0 */
Xtag1	table[];
X{
X	int	i;
X
X	for (i = 0; i < SYMBOLS; i++)
X	{
X		table[i].symbol = NULL;
X		table[i].position = 0;
X	}
X}
X
Xint symbol(tok)
X/* identifies a symbol:
X	A symbol is just a token that ends with a ':'	*/
Xtokenlist	*tok;
X{
X	char	*t;		/* token string */
X
X	t = tok -> token;
X	if ((t[strlen(t) - 1]) == ':')	/* address last character */
X		return 1;		/* is symbol declaration */
X	else
X		return 0;
X}
X
X/* inserts a token into a symbol table (without stripping the ':') -
X   Algorithm:
X	1)	search until symbol table reads a NULL string or
X		the new symbol is equal to and old one.
X	2)	if the new symbol is not a NULL, then error
X		otherwise, insert
X	3)	if out of space, error
X*/
Xint insert(tok, table, no)
Xtokenlist	*tok;			/* token */
Xtag1		table[];		/* symbol table */
Xint		no;			/* instruction number */
X{
X	char	*t;		/* token string */
X	int	i = 0;		/* index on table */
X
X	t = tok -> token;
X
X	/* search for empty place in table */
X	for (; i < SYMBOLS && table[i].symbol != NULL &&
X	       (strcmp(table[i].symbol,t) != 0); i++)
X		;
X
X	if (table[i].symbol != NULL)
X	{
X		printf("symbol %s already declared\n", t);
X		printf("--- insert\n");
X		exit(1);
X	}
X
X	table[i].symbol = t;
X	table[i].position = no;
X}
X
X/* tests whether instruction */
Xint instruction(tok)
Xtokenlist	*tok;
X{
X	char	*t;		/* token string */
X
X	t = tok -> token;
X	/* note that due to a quirk in strcmp (it returns a zero if the
X	   strings are equal) this looks particularly convoluted, but
X	   the logic is simple.                                        */
X	return(! (strcmp (t,MOV) && strcmp (t,ADD) && strcmp (t,SUB) &&
X		  strcmp (t,JMP) && strcmp (t,JMZ) && strcmp (t,JMN) &&
X		  strcmp (t,DJN) && strcmp (t,CMP) && strcmp (t,SPL) &&
X		  strcmp (t,DAT)));
X}
X
X/* return the number of parameters an instruction has */
Xint para(tok)
Xtokenlist	*tok;
X{
X	char	*t;		/* token string */
X	int	i = 0;		/* return value */
X
X	t = tok -> token;
X
X	/* use a multiple if-elseif statement */
X	if (!strcmp(t, MOV))
X		i = 2;
X	else if (!strcmp(t, ADD))
X		i = 2;
X	else if (!strcmp(t, SUB))
X		i = 2;
X	else if (!strcmp(t, JMP))
X		i = 1;
X	else if (!strcmp(t, JMZ))
X		i = 2;
X	else if (!strcmp(t, JMN))
X		i = 2;
X	else if (!strcmp(t, DJN))
X		i = 2;
X	else if (!strcmp(t, CMP))
X		i = 2;
X	else if (!strcmp(t, SPL))
X		i = 1;
X	else if (!strcmp(t, DAT))
X		i = 1;
X	else	/* unrecognized instruction */
X	{
X		printf("%s is not an instruction\n", t);
X		printf("--- para\n");
X		exit(1);
X	}
X
X	return(i);
X}	/* para */
X
X
X
X
X/* debugging section of parse.c */
X/* code commented out --- given a clean bill of health by Dr. Na Choon Piaw
X   --- 11/15/88                                                           */
X/* declare tokenize */
X/* extern tokenlist *tokenize(); */
X/* declare symbol table */
X/* tag1	table[SYMBOLS]; */
X
X/* main(argc,argv)
Xint	argc;
Xchar	*argv[];
X{
X	tokenlist	*head;
X	FILE		*f;
X	int		i;
X
X	f = fopen(argv[1], "r");
X	head = tokenize(f);
X	parse(head, table);
X
X	printf("%s\t%s\n", "SYMBOL", "POSITION");
X	for (i = 0; table[i].symbol != NULL; i++)
X		printf("%s\t%d\n", table[i].symbol, table[i].position);
X}  */
END_OF_FILE
if test 4743 -ne `wc -c <'parse.c'`; then
    echo shar: \"'parse.c'\" unpacked with wrong size!
fi
# end of 'parse.c'
fi
if test -f 'play.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'play.c'\"
else
echo shar: Extracting \"'play.c'\" \(2003 characters\)
sed "s/^X//" >'play.c' <<'END_OF_FILE'
X/* play.c ---- main program for the interpreter.
X   1.	play player 1
X   2.	play player 2
X   3.   output
X   4.   check deaths
X   5.   repeat
X
X   --- 12/17/88   NCP                             */
X#include <stdio.h>
X#include "interp.h"
X
Xextern	stream *exe[];
Xextern  cell	a[];
X
Xint	dead(i)
Xint	i;
X{
X	if (exe[i])
X		return 0;
X	else
X		return 1;
X}
X
X
Xint	alive()
X{
X	int	i, j = 1;
X
X	for (i = 1; i < MAXPLAY; i ++)
X	{
X		if (!exe[i])
X		{
X			j = 0;
X			break;
X		}
X	}
X
X	return(j);
X}
X
Xint play(cycles)
Xlong cycles;
X{
X	int	i;
X
X	while (alive() && cycles)
X	{
X		for ( i = 1; i < MAXPLAY; i++)
X		{
X			execute(i);	/* play player n */
X#ifdef DEBUG
X			output();
X#endif
X#ifdef BIG
X			output(cycles);
X#endif
X		}
X#ifdef SUN
X		if (!(cycles % 50))
X			xcore_display(a);
X#endif
X#ifdef SMALL
X		if (!(cycles % 100))
X			output(cycles);
X#endif
X		cycles --;
X	}
X
X	if (dead(1) && !dead(2))
X		return(2);		/* process 2 won */
X	else if (dead(2) && !dead(1))
X		return(1);		/* process 1 won */
X	else
X		return(0);		/* nobody won */
X}
X
Xexecute(i)
Xint	(i);
X{
X	instr	temp;			/* instruction */
X	int	x;			/* cell to execute */
X	int	pc;
X
X	if (exe[i] == NULL)
X		return;
X
X	correct(&(exe[i] -> pc));
X	x = pc = exe[i] -> pc;
X	temp = a[x].inst;
X
X	/* this really should have been a switch-case, but I'm using an
X	   elongated if-else because the compiler doesn't accept it.   */
X
X	if (temp == dat)
X		Dat(i);
X	else if (temp == mov)
X		Mov(x, &pc, i);
X	else if (temp == add)
X		Add(x, &pc, i);
X	else if (temp == sub)
X		Sub(x, &pc, i);
X	else if (temp == jmp)
X		Jmp(x, &pc);
X	else if (temp == jmz)
X		Jmz(x, &pc);
X	else if (temp == jmn)
X		Jmn(x, &pc);
X	else if (temp == djn)
X		Djn(x, &pc, i);
X	else if (temp == cmp)
X		Cmp(x, &pc);
X	else if (temp == spl)
X		Spl(x, &pc, exe[i]);
X	else
X	{
X		printf("Instruction not recognized\n");
X		printf("--- execute\n");
X		printf("opcode: %d", temp);
X		printf(" executing no: %d", pc);
X		printf(" process: %d\n", i);
X		exit(1);
X	}
X
X	if (temp != dat)
X		exe[i] -> pc = pc;
X
X	if (exe[i] && (temp != dat))
X		exe[i] = exe[i] -> next;
X}
END_OF_FILE
if test 2003 -ne `wc -c <'play.c'`; then
    echo shar: \"'play.c'\" unpacked with wrong size!
fi
# end of 'play.c'
fi
if test -f 'tokenize.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tokenize.c'\"
else
echo shar: Extracting \"'tokenize.c'\" \(4160 characters\)
sed "s/^X//" >'tokenize.c' <<'END_OF_FILE'
X/*	Copyrighted (C) 1989 by Na Choon Piaw.  All rights reserved       */
X
X
X
X/*	This program and documentation is Public Domain, and may be	  */
X/*	distributed and copied by everyone provided this header		  */
X/*	remains intact							  */
X
X/* tokenize ---- tokenizer for the assembler.  It splits up all of the
X   tokens in the given input file, generate a linked list of such tokens,
X   and outputs the pointer to that linked list.
X  11/14                 ----- NCP                                    */
X#include <stdio.h>
X#include <ctype.h>
X#include <strings.h>
X#include <malloc.h>
X#include "assem.h"
X
X/* tokenize function:
X   separate input stream (infile) into tokens.
X   algorithm:
X	1)	call nextoken to get next token.
X	2)	if "null" then return the first pointer
X	3)	otherwise, add the newtoken to the token list
X	4)	go back to 1.
X*/
Xtokenlist *tokenize(infile)
XFILE	*infile;
X{
X	tokenlist	*head, *tail, *newtail;
X	char		*nextoken(), *newtoken;
X
X	head = tail = NULL;
X	while ((newtoken = nextoken(infile)) != NULL)
X	{
X		if (!(newtail = (tokenlist *) 
X		                 malloc((unsigned) sizeof(tokenlist))))
X		{
X			printf("ran out of space for tokens: %s\n", newtoken);
X			printf("------  tokenize\n");
X			exit(1);
X		}
X
X		/* otherwise , set old stuff to this and move tail one up*/
X		newtail -> token = newtoken;
X		newtail -> next = NULL;
X		if (tail)			/* tail already defined */
X		{
X			tail -> next = newtail;		/* set previous ptr */
X			tail = tail -> next;		/* move up list */
X		}
X		else
X			head = tail = newtail;
X	}	/* end while */
X
X	return (head);	/* return function value */
X}
X
X/* function next token:
X   return next token in the file.
X   Algorithm:
X	1)	read until start of next token or EOF
X	2)	if EOF then return NULL pointer
X	3)	read new token into buffer
X	4)	malloc new string
X	5)	put next token into new string
X	6)	change all characters into upper case
X	7)	return pointer to string created in (4)      */
X/* BUG NOTE:
X   Due to the way it is written, the assembler will not process things like
X   "mov0 1" correctly, and neither will "mov 0 1;imp" work.
X   this is because the tokenize breaks everything down that isn't a
X   delimiter, and a ";" is not a delimiter, even though it's not in
X   the instruction set.                                   NCP - 11/15/88 */
Xchar	*nextoken(infile)
XFILE	*infile;
X{
X	char	buffer[MAXBUFFER],	/* string buffer */
X		*newtoken;		/* new token pointer */
X
X	int	c,			/* character we read in one by one */
X		i = 0;			/* integer counter */
X
X	while ((c = fgetc(infile)) != EOF)
X	{
X		if (!isspace(c))
X			break;		/* not space, so process */
X	}
X
X	if (c == EOF)
X		return(NULL);		/* no more!! */
X
X	if (c == COMMENT)		/* handle comments */
X	{
X		while (((c = fgetc(infile)) != '\n') && c != EOF)
X			;		/* read until end of the line */
X
X		if (c == EOF)
X			return(NULL);
X
X		/* process the rest of the file:
X		   actually, we could have done this by using a goto
X		   the beginning of this function, but I think this
X		   is a lot more elegant                     --- CP */
X		return(nextoken(infile));
X	}
X
X	while ((!isspace(c)) && (c != EOF))	/* read until next space */
X	{
X		if (i >= MAXBUFFER)	/* buffer out */
X		{
X			printf("buffer over extended\n");	
X			printf("--- nextoken\n");
X			exit(1);
X		}
X
X		buffer[i++] = c;
X
X		c = fgetc(infile);
X	}	/* end while */
X	buffer[i] = '\0';		/* terminate with a null */
X
X	if (!(newtoken = (char *) malloc( (unsigned) strlen(buffer) + 1)))
X	{
X		printf("not enough memory for token %s\n", buffer);
X		printf(" ------- nextoken\n");
X		exit(1);
X	}
X
X	strcpy(newtoken, buffer);
X
X	upcase(newtoken);
X
X	return(newtoken);
X}	/* end of nextoken */
X
X/* upcase function -- translate string to upper case (don't trust toupper) */
Xupcase(str)
Xchar	*str;
X{
X	while (*str)
X	{
X		if ((*str <= 'z') && (*str >= 'a'))
X			*str -= 'a' - 'A';
X		str++;
X	}
X}
X
X/* special main to test the above */
X/* section commented out because code has been fully debugged
X   and given a clean bill of health			CP - 11/14/88 
Xmain(argc,argv)
Xint	argc;
Xchar	*argv[];
X{
X	FILE	*f;
X	tokenlist	*head;
X
X	f = fopen(argv[1],"r");
X	head = tokenize(f);
X	while (head != NULL)
X	{
X		printf("%s\n", head -> token);
X		head = head -> next;
X	}
X} */
X
END_OF_FILE
if test 4160 -ne `wc -c <'tokenize.c'`; then
    echo shar: \"'tokenize.c'\" unpacked with wrong size!
fi
# end of 'tokenize.c'
fi
echo shar: End of archive 1 \(of 2\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked both archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0