games@tekred.CNA.TEK.COM (02/14/89)
Submitted by: Na Choom Piaw <c60a-3ci@wolf.Berkeley.EDU> Comp.sources.games: Volume 6, Issue 2 Archive-name: corewars/Part01 [I've taken the liberty to fold the standard and Sun versions into a single set of source files (the Sun versions already had #ifdef SUN in them) and to create a set of unified Makefiles - one for the standard version and one for the Sun. Copy the appropriate Makefile.xxx to Makefile. -br] #! /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