1
0
mirror of https://github.com/RevCurtisP/C02.git synced 2024-06-15 07:29:29 +00:00

Save entire project before changing condition parser to use JMP

This commit is contained in:
Curtis F Kaylor 2017-04-22 14:39:52 -04:00
parent 91f870bd88
commit 1abb077f09
21 changed files with 1861 additions and 884 deletions

86
asm.c Normal file
View File

@ -0,0 +1,86 @@
/*************************************
* C02 Assembly Language Routines *
*************************************/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include "common.h"
#include "files.h"
#include "parse.h"
#include "asm.h"
char asmcmt[LINELEN]; //Processed Assembly Language Comment
/* Set comment to string */
void setcmt(char *s)
{
strcpy(cmtasm, s);
}
/* Append string to comment */
void addcmt(char *s)
{
strcat(cmtasm, " ");
strcat(cmtasm, s);
}
/* Append character to comment */
void chrcmt(char c)
{
int i = strlen(cmtasm);
cmtasm[i++] = c;
cmtasm[i] = 0;
}
void prccmt()
{
if (strlen(cmtasm)) {
strcpy(asmcmt, ";");
strcat(asmcmt, cmtasm);
}
else
asmcmt[0] = 0;
setcmt("");
}
/* output a single line of assembly code */
void asmlin(char *opcode, char *oprnd)
{
if (strlen(lblasm)) strcat(lblasm, LABSFX);
prccmt();
fprintf(outfil, ASMFMT, lblasm, opcode, oprnd, asmcmt);
if (debug) printf(ASMFMT, lblasm, opcode, oprnd, asmcmt);
lblasm[0] = 0;
}
/* output a single comment line */
void cmtlin()
{
DEBUG("Writing Comment Line: %s\n", cmtasm);
fprintf(outfil, "; %s\n", cmtasm);
setcmt("");
}
/* Output a variable definition line *
* Uses: word - assembly oprnd */
void equlin()
{
fprintf(outfil, ASMFMT, lblasm, EQUOP, word, "");
if (debug) printf(ASMFMT, lblasm, EQUOP, word, "");
lblasm[0] = 0;
}
void prolog()
{
DEBUG("Writing Assembly Prolog\n", 0);
asmlin(CPUOP,CPUARG);
strcpy(cmtasm, "Program ");
strcat(cmtasm, srcnam);
cmtlin();
}

17
asm.h Normal file
View File

@ -0,0 +1,17 @@
/*************************************
* C02 Assembly Language Routines *
*************************************/
char cmtasm[LINELEN]; //Assembly Language Comment Text
char lblasm[LABLEN+2]; //Label to emit on next asm line
void setcmt(char *s); //Set Assembly Line Comment to String
void addcmt(char *s); //Append String to Assembly Line Comment
void chrcmt(char c); //Append Character to Assembly Line Comment
void asmlin(char *opcode, char *oprnd); //Output a line of assembly code
void cmtlin(); //Output a comment lines
void equlin(); //Output an equate line
void prolog(); //Write Assembly Language Initialization Code

965
c02.c

File diff suppressed because it is too large Load Diff

35
common.c Normal file
View File

@ -0,0 +1,35 @@
/*************************************
* C02 Common Definitions & Routines *
*************************************/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include "common.h"
/* Error - Print Input File name & position and exit */
void exterr(int errnum)
{
printf("Line %d Column %d of File %s\n", curlin, curcol, inpnam);
exit(errnum);
}
/* Error - print "Expected" error message *
and exit with general failure code *
Args: expected - Description of what was expected */
void expctd(char *expstr)
{
printf("Expected %s, but found '%c'\n", expstr, nxtchr);
exterr(EXIT_FAILURE);
}
/* Print current position in file */
void prtpos()
{
printf("(%s: %d,%d) ", inpnam, curlin, curcol);
}

53
common.h Normal file
View File

@ -0,0 +1,53 @@
/*************************************
* C02 Common Definitions & Routines *
*************************************/
#define FNAMLEN 255 //Maximum File Name Length
#define LINELEN 255 //Maximum Input/Output Line Length
#define DEFLEN 9 //Maximum Definition Text Length
#define MAXDEF 255 //Maximum Number of Definitions
#define VARLEN 6 //Maximum Variable Length
#define MAXVAR 255 //Maximum Number of Variables
#define DATASPC 2048 //Space to Allocate for
#define LABLEN 6 //Maximum Label Length
#define LABFMT "L_%04d" //Label Format
#define LABSFX ":" //Label Suffix
#define MAXLAB 15 //Maximum Number of Labels (Nesting Depth)
#define CPUOP "PROCESSOR" //Target CPU Pseudo-Operator
#define CPUARG "6502" //Target CPU Operand
#define EQUOP "EQU" //Equate Pseudo-Op
#define BYTEOP "DC" //Define Byte Pseudo-Op
#define STROP "DS" //Define String Pseudo-Op
#define ASMFMT "%-7s %-3s %-12s %s\n" //Assembly Language Line printf Format
/* Internal defines */
#define TRUE -1
#define FALSE 0
#define DEBUG(fmt, val) if (debug) {prtpos(); printf(fmt, val);}
#define ERROR(fmt, val, err) if (debug) {printf(fmt, val);exterr(err);}
#define SCMNT(str) if (gencmt) {setcmt(str);}
#define ACMNT(str) if (gencmt) {addcmt(str);}
#define CCMNT(chr) if (gencmt) {chrcmt(chr);}
int gencmt; //Generate Assembly Language Comments
int debug; //Print Debug Info (TRUE or FALSE)
int curcol, curlin; //Position in Source Code
int savcol, savlin; //Save Position in Source Code
int nxtchr; //Next Character of Source File to Process
int nxtupc; //Next Character Converted to Uppercase
int savchr; //Holds nxtchr when switching input files
char inpnam[FNAMLEN]; //Include File Name
int alcvar; //Allocate Variables Flag
void exterr(int errnum); //Print current file name & position and exit
void expctd(char *expected); //Print Expected message and exit
void prtpos(); //Print current file name and position

134
cond.c Normal file
View File

@ -0,0 +1,134 @@
/************************************
* C02 Conditional Parsing Routines *
************************************/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include "common.h"
#include "asm.h"
#include "parse.h"
#include "vars.h"
#include "expr.h"
#include "label.h"
#include "cond.h"
int cmprtr; //Encoded Comparison Operator
int cmpenc; //Encoded Comparator Character
/* Convert Comparison Operator Character *
* Args: Comparison Operator Character *
* Returns: Comparison Operator Bit Mask */
int enccmp(char c)
{
int e;
switch(c)
{
case '=': e = 1; break;
case '<': e = 2; break;
case '>': e = 4; break;
default: e = 0;
}
if (e) {
CCMNT(c);
skpchr();
}
return e;
}
/* Process and Compile Comparison Operator and *
* Args: comparator - Encoded Comparison Operator *
* Uses: term - Term Being Compared Against *
* label - Branch Target if Comparison is FALSE */
void prccmp(int cmprtr)
{
DEBUG("Processing comparison operator %d\n", cmprtr);
switch(cmprtr) {
case 1: // = or ==
asmlin("CMP", term);
asmlin("BNE", curlbl);
break;
case 2: // <
if (cmpsgn) {
asmlin("CMP", term);
asmlin("BPL", curlbl);
}
else {
asmlin("CMP", term);
asmlin("BCS", curlbl);
}
break;
case 3: // <= or =<
if (cmpsgn) {
asmlin("CMP", term);
asmlin("BPL", curlbl);
asmlin("BNE", curlbl);
}
else {
asmlin("CLC", "");
asmlin("SBC", term);
asmlin("BCS", curlbl);
}
break;
case 4: // >
if (cmpsgn) {
asmlin("CMP", term);
asmlin("BMI", curlbl);
asmlin("BEQ", curlbl);
}
else {
asmlin("CLC", "");
asmlin("SBC", term);
asmlin("BCC", curlbl);
}
break;
case 5: // >= or =>
if (cmpsgn) {
asmlin("CMP", term);
asmlin("BMI", curlbl);
}
else {
asmlin("CMP", term);
asmlin("BCC", curlbl);
}
break;
case 6: // <> or ><
asmlin("CMP", term);
asmlin("BEQ", curlbl);
break;
default:
printf("Unsupported comparison operator index %d\n", cmprtr);
exterr(EXIT_FAILURE);
}
}
/* Parse Comparison Operator *
* Sets: comparitor - Encoded Comparison Operator */
int prscmp()
{
cmpenc = enccmp(nxtchr); //Encode Comparison Character
if (cmpenc == 0)
expctd("comparison operator");
cmprtr = cmpenc; //Set Encoded Comparator
cmpenc = enccmp(nxtchr); //Encode Next Comparison Character
if (cmpenc != 0)
cmprtr = cmprtr | cmpenc; //Combine Encoded Comparator
skpspc();
DEBUG("Parsed comparator %d\n", cmprtr);
}
/* Parse and Compile Conditional Expression *
* Condition = <expression> <comparator> <term> */
void prscnd(char trmntr)
{
DEBUG("Parsing condition\n", 0);
prsxpr(0);
skpspc();
prscmp();
prstrm();
CCMNT(trmntr);
prccmp(cmprtr);
expect(trmntr);
}

8
cond.h Normal file
View File

@ -0,0 +1,8 @@
/************************************
* C02 Conditional Parsing Routines *
************************************/
int cmpsgn; // Comparison contains signed operands
void prscnd(char trmntr); //Parse Conditional Expression

169
expr.c Normal file
View File

@ -0,0 +1,169 @@
/***********************************
* C02 Expression Parsing Routines *
***********************************/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include "common.h"
#include "asm.h"
#include "parse.h"
#include "vars.h"
#include "expr.h"
/* Parse value (constant or identifier) *
* Sets: value - the value (as a string) *
* valtyp - value type */
void prsval()
{
DEBUG("Parsing value\n", 0);
//expdef(); //Check for and expand define -- BROKEN!
if (iscpre())
prscon(0xff); //Parse Constant
else if (isalph())
prsvar(); //Parse Variable
else
expctd("constant or variable");
skpspc();
ACMNT(word);
}
/* Parse array index *
* Sets: value - array index or *
* "" if no index defined */
void prsidx()
{
expect('[');
prsval();
DEBUG("Parsed array index '%s'\n", value);
expect(']');
}
/* Parse term in expression *
* Sets: term - the term (as a string) *
* trmtxt - type of term */
void prstrm()
{
DEBUG("Parsing term\n", 0);
prsval();
if (valtyp == FUNCTION) {
ERROR("Function call only allowed in first term\n", 0, EXIT_FAILURE);
}
strcpy(term, value);
DEBUG("Parsed term %s\n", term);
trmtxt = valtyp;
if (trmtxt == ARRAY) {
prsidx();
asmlin("LDX", value);
strcat(term, ",X");
}
skpspc();
}
/* Parse and Compile Pointer Dereference */
void prsadr(char dlmtr)
{
prsvar();
DEBUG("Dereferencing variable '%s'\n", value);
ACMNT(value);
strcpy(word,"#<");
strcat(word,value);
asmlin("LDX", word);
strcpy(word,"#>");
strcat(word,value);
asmlin("LDY", word);
if (dlmtr) expect(dlmtr);
}
/* Parse function call in first term of expression *
* Function call may include term as an argument */
void prsxfn()
{
char fnname[255]; /*Function name*/
DEBUG("Processing expression function call '%s'...\n", term);
strcpy(fnname, term);
skpchr(); //skip open paren
CCMNT('(');
if (look('&'))
prsadr(0);
else if (isvpre()) {
prstrm();
asmlin("LDA", term);
}
expect(')');
asmlin("JSR", fnname);
skpspc();
}
/* Parse first term of expession *
* First term can include function calls */
void prsftm()
{
prsval();
DEBUG("Processing first term '%s'...\n", value);
strcpy(term, value);
trmtxt = valtyp;
if (trmtxt == FUNCTION) {
prsxfn(); //Parse Expression Function
return;
}
if (trmtxt == ARRAY) {
prsidx();
asmlin("LDX", value);
strcat(term, ",X");
}
asmlin("LDA", term);
}
/* Process Arithmetic or Bitwise Operator *
* and the term that follows it */
void prcopr()
{
DEBUG("Processing operator '%c'\n", oper);
switch(oper)
{
case '+':
asmlin("CLC", "");
asmlin("ADC", term);
break;
case '-':
asmlin("SEC", "");
asmlin("SBC", term);
break;
case '&':
asmlin("AND", term);
break;
case '|':
asmlin("ORA", term);
break;
case '^':
asmlin("EOR", term);
break;
default:
printf("Unrecognized operator '%c'\n", oper);
exterr(EXIT_FAILURE);
}
}
/* Parse and compile expression */
void prsxpr(char trmntr)
{
DEBUG("Parsing expression\n", 0);
skpspc();
if (match('-'))
asmlin("LDA", "#$00"); //Handle Unary Minus
else
prsftm(); //Parse First Term
while (isoper())
{
prsopr(); //Parse Operator
prstrm(); //Parse Term
prcopr(); //Process Operator
}
if (trmntr)
expect(trmntr);
}

11
expr.h Normal file
View File

@ -0,0 +1,11 @@
/**********************************
* C02 Expession Parsing Routines *
**********************************/
char term[255]; /*Term parsed from equation*/
int trmtxt; /*Term Type*/
void prsidx(); //Parse Array Index
void prstrm(); //Parse Term in Expression
void prsxpr(char trmntr); //Parse Expression

103
files.c Normal file
View File

@ -0,0 +1,103 @@
/******************************
* C02 File Handling Routines *
******************************/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include "common.h"
#include "files.h"
/* Error - Print textual description of system error *
* and exit with system error code */
void extsys(char *s)
{
perror(s);
exterr(errno);
}
/* Open Source File *
* Uses: srcnam - Source File Name *
* Sets: srcfil - Source File Handle */
void opnsrc()
{
DEBUG("Processing Source File Name '%s'\n", srcnam);
if (strrchr(srcnam, '.') == NULL) //if no extension
strcat(srcnam, ".c02"); // add ".c02"
DEBUG("opening Source File '%s'\n", srcnam);
srcfil = fopen(srcnam, "r"); //open file
if (srcfil == NULL) extsys(srcnam);
}
/* Close Source File */
void clssrc()
{
fclose(srcfil);
}
/* Open Output File *
* Uses: outnam - Output File Name *
* Sets: outfil - Output File Handle */
void opnout()
{
DEBUG("Processing Output File Name '%s'\n", outnam);
if (strlen(outnam) == 0) //if Output File not specified
{
strcpy(outnam, srcnam); //copy Source Name to Ouput Name
char *dot = strrchr(outnam, '.'); //find extension
if (dot != NULL) *dot = 0; //and remove it
DEBUG("Set Output File Name to '%s'\n", outnam);
}
if (strrchr(outnam, '.') == NULL) //if no extension
strcat(outnam, ".asm"); // add ".asm"
DEBUG("Opening Output File '%s'\n", outnam);
outfil = fopen(outnam, "w"); //open file
if (outfil == NULL) extsys(outnam);
}
/* Close Output File */
void clsout()
{
fprintf(outfil, "\n");
fclose(outfil);
}
/* Open Log File *
* Uses: srcnam - Source File Name *
* Sets: logfil - Log File Handle */
void opnlog()
{
strcpy(lognam, srcnam); //set Log File Name to Source File Name
char *dot = strrchr(lognam, '.'); //find file extension
if (dot != NULL) *dot = 0; //and remove it
strcat(lognam, ".log"); //add extension ".asm"
DEBUG("Opening Log File '%s'\n", lognam);
logfil = fopen(lognam, "w");
if (logfil == NULL) extsys(lognam);
}
/* Close Log File *
* Uses: logfil - Log File Handle */
void clslog() {
fclose(logfil);
}
/* Open Include file *
* Uses: incnam - Include File Name *
* Sets: incfil - Include File Handle */
void opninc()
{
DEBUG("Opening include file '%s'\n", incnam);
incfil = fopen(incnam, "r");
if (incfil == NULL) extsys(incnam);
}
/* Close Include File *
* Uses: incfil - Include File Handle */
void clsinc() {
fclose(incfil);
}

23
files.h Normal file
View File

@ -0,0 +1,23 @@
/******************************
* C02 File Handling Routines *
******************************/
FILE *srcfil; //Source File (Input)
FILE *outfil; //Assembler File (Output)
FILE *logfil; //Log File (Output)
FILE *incfil; //Include File Handle
FILE *inpfil; //Current Input File
char srcnam[FNAMLEN]; //Source File Name
char outnam[FNAMLEN]; //Assembler File Name
char lognam[FNAMLEN]; //Log File Name
char incnam[FNAMLEN]; //Include File Name
void opnsrc(); //Open Source File
void clssrc(); //Close Source File
void opnout(); //Open Output File
void clsout(); //Close Output File
void opninc(); //Open Include File
void clsinc(); //Close Include File

170
include.c Normal file
View File

@ -0,0 +1,170 @@
/*************************************
* C02 Include File Parsing Routines *
*************************************/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include "common.h"
#include "files.h"
#include "asm.h"
#include "parse.h"
#include "vars.h"
#include "include.h"
/* Reads next include file name from Source File *
* Sets: incnam - the include file name */
void pincnm()
{
char dlmtr;
int inclen = 0;
skpspc();
dlmtr = getnxt();
if (dlmtr == '<') {
strcpy(incnam, "include/");
inclen = strlen(incnam);
dlmtr = '>';
}
else if (dlmtr != '"')
ERROR("Unexpected character '%c' after include\n", dlmtr, EXIT_FAILURE);
while (!match(dlmtr))
{
incnam[inclen++] = nxtchr;
skpchr();
}
skpchr(); //skip end dlmtr
incnam[inclen] = 0;
}
/* Process assembly language include file */
void incasm() {
opninc();
setcmt("======== Assembler File ");
addcmt(incnam);
addcmt(" =======");
cmtlin();
while (fgets(line, sizeof line, incfil) != NULL) {
DEBUG("Writing line: %s", line);
fputs(line, outfil);
}
setcmt("==========================================");
cmtlin();
clsinc();
}
/* Process Include File Directive */
void pincdr()
{
skpchr(); //skip '#'
getwrd(); //read directive into word
DEBUG("Processing include file directive '%s'\n", word);
if (wordis("define"))
prsdef();
else {
printf("Unrecognized directive '%s'\n", word);
exterr(EXIT_FAILURE);
}
}
/* Parse Header Word */
void phdwrd() {
getwrd();
if (wordis("void"))
pdecl(VTVOID);
else if (wordis("byte"))
pdecl(VTBYTE);
else if (wordis("char"))
pdecl(VTCHAR);
else {
printf("Unexpected word '%s' in header\n", word);
exterr(EXIT_FAILURE);
}
}
/* Save Source File Information */
void savsrc() {
savchr = nxtchr;
savcol = curcol;
savlin = curlin;
}
/* Set Include File Information */
void setinc() {
curcol = 0;
curlin = 0;
inpfil = incfil;
strcpy(inpnam, incnam);
alcvar = FALSE;
}
/* Restore Source File Pointer*/
void rstsrc() {
nxtchr = savchr;
nxtupc = toupper(nxtchr);
curcol = savcol;
curlin = savlin;
inpfil = srcfil;
strcpy(inpnam, srcnam);
alcvar = TRUE;
}
/* Process header include file */
void inchdr() {
savsrc(); //Save Source File Information
opninc(); //Open Include File
setinc(); //Set Include File Information
skpchr();
while (TRUE)
{
skpspc();
if (match(EOF)) break;
DEBUG("Checking next character '%c'\n", nxtchr);
if (match('#'))
pincdr();
else if (match('/'))
skpcmt();
else if (isalph())
phdwrd();
else
{
printf("Unexpected character '%c'\n", nxtchr);
exterr(EXIT_FAILURE);
}
}
clsinc();
rstsrc();
nxtchr = savchr;
}
/* Process header include file */
void include_hfil() {
ERROR("Header files with extension .h not supported", 0, EXIT_FAILURE);
}
/* Process include file */
void pincfl()
{
pincnm(); //Parse Include File Name
DEBUG("Processing include file '%s'\n", incnam);
char *dot = strrchr(incnam, '.'); //find extension
if (dot == NULL) {
printf("Invalid include file name '%sn", incnam);
exterr(EXIT_FAILURE);
}
if (strcmp(dot, ".asm") == 0)
incasm();
else if (strcmp(dot, ".h") == 0)
include_hfil();
else if (strcmp(dot, ".h02") == 0) {
inchdr(); //Process Header File
strcpy(dot, ".asm");
incasm(); //Process Assembly File with Same Name
}
else {
printf("Unrecognized include file extension '%s'\n'", dot);
exterr(EXIT_FAILURE);
}
}

7
include.h Normal file
View File

@ -0,0 +1,7 @@
/*************************************
* C02 Include File Parsing Routines *
*************************************/
char line[255]; /*Entire line parsed from include file*/

61
label.c Normal file
View File

@ -0,0 +1,61 @@
/******************************************************
* C02 Label Parsing, Generation, and Lookup Routines *
******************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include "common.h"
#include "asm.h"
#include "parse.h"
#include "label.h"
/* Set label for next line of *
* Assembly Language Code *
* to word */
void setlbl(char *lblset)
{
DEBUG("Setting Label '%s''\n", lblset);
if (strlen(lblasm) > 0)
asmlin("",""); //Emit Block End Label on it's own line
if (strlen(word) > LABLEN)
ERROR("Label '%s' exceeds maximum size", word, EXIT_FAILURE);
strcpy(lblasm, lblset);
}
/* parse label in code */
void prslbl()
{
DEBUG("Parsing Label '%s''\n", word);
skpchr(); //skip ':'
setlbl(word);
}
/* generate new label */
void newlbl(int lbtype)
{
sprintf(curlbl, LABFMT, lblnxt++);
DEBUG("Generated new label '%s'\n", curlbl);
strcpy(lblnam[lblcnt++], curlbl);
lbltyp[lblcnt] = lbtype;
}
/* set label to emit on next line and remove from stack */
void lbllin()
{
int lbtype = lbltyp[--lblcnt];
if (lbtype == 1) {
DEBUG("Ending Loop at Level %d'\n", lblcnt);
strcpy(endlbl, lblnam[lblcnt]); //Save End of Loop Label
asmlin("JMP", lblnam[--lblcnt]); //Jump to Beginning of Loop
setlbl(endlbl); //Set End of Loop Label
}
else
setlbl(lblnam[lblcnt]);
DEBUG("Set label '%s' to emit on next line\n", lblasm);
}

19
label.h Normal file
View File

@ -0,0 +1,19 @@
/******************************************************
* C02 Label Parsing, Generation, and Lookup Routines *
******************************************************/
char curlbl[LABLEN+1]; //Most recently generated label
char endlbl[LABLEN+1]; //Label at end of block
char lblnam[MAXLAB+1][LABLEN+1]; //Label Name Table
int lbltyp[MAXLAB+1]; //Label Type
int lblcnt; //Number of Labels in stack
int lblnxt; //Sequence of next label to be generated
char lbltmp[LABLEN+1]; //Label Temporary Storage
enum ltypes {LTIF, LTLOOP, LTEND}; //Label Types
void prslbl(); //Parse Label From Code
void newlbl(); //Generate New Block Label
void lbllin(); //Pull Last Label and Emit on Next Line
void setlbl(); //Emit word as Label on Next Line

385
parse.c Normal file
View File

@ -0,0 +1,385 @@
/*************************************
* C02 Input File Parsing Routines *
*************************************/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include "common.h"
#include "files.h"
#include "parse.h"
char opstr[2]; //Operator as a String
/* Various tests against nxtchr */
int match(char c) {return (nxtchr == c);}
int inbtwn(char mn, char mx) {return nxtchr >= mn && nxtchr <= mx;}
int isprnt() {return isprint(nxtchr);}
int isalph() {return isalpha(nxtchr);}
int isanum() {return isalnum(nxtchr);}
int isdec() {return inbtwn('0', '9');}
int ishexd() {return isdec() || inbtwn('A', 'Z');}
int isbin() {return inbtwn('0', '1');}
int isnl() {return match('\n') || match('\r');}
int isspc() {return isspace(nxtchr);}
int isnpre() {return isdec() || match('$') || match('%');}
int isapos() {return match('\'');}
int iscpre() {return isnpre() || isapos();}
int isvpre() {return isalph() || iscpre();}
int isoper() {return (strchr("+-&|^", nxtchr)) ? TRUE : FALSE;}
int ispopr() {return (strchr("+-<>", nxtchr)) ? TRUE : FALSE;}
/* if Word is s then return TRUE else return FALSE*/
int wordis(char *s)
{
return strcmp(word, s) == 0;
}
/* Get Next Character from Current Input File *
* Uses: inpfil - Input File Handle *
* Sets: nxtchr - Next Character in Source File */
char getnxt()
{
int i;
int wascr = match('\r');
char c = nxtchr;
//if (nxtwrd[nxtptr]) //If nxtwrd is set
// nxtchr = nxtwrd[nxtptr++]; // Pop First Character from nxtwrd
//else
nxtchr = fgetc(inpfil);
nxtupc = toupper(nxtchr);
if (wascr && match('\n')) return c; //Skip NL after CR
if (isnl()) curcol=1; else curcol++;
if (curcol == 1) curlin++;
return c;
}
/* Advance Input File to next printable character */
void skpspc()
{
DEBUG("Skipping Spaces\n", 0);
while (isspc())
getnxt();
}
/* Check if the next printable character is c *
* and advance past it if it is *
* Returns TRUE is character is found, *
* otherwise FALSE */
int look(char c)
{
int found;
skpspc();
found = match(c);
if (found) {
skpchr();
CCMNT(c);
}
return found;
}
/* if next printable character is c then skip, else generate error */
void expect(char c)
{
if (look(c))
return;
else {
printf("Expected Character '%c', but found '%c'\n", c, nxtchr);
exterr(EXIT_FAILURE);
}
}
/* Advance Input File to next printable character */
void skpchr() {char skip = getnxt();}
/* Advance Input File to end of line */
void skpeol() {while (!isnl()) getnxt();}
/* Advance Source File to end of comment *
* Recognizes both C and C++ style comments */
void skpcmt()
{
DEBUG("Skipping Comment\n", 0);
skpchr(); //skip initial /
if (match('/')) //if C style comment
skpeol(); // skip rest of line
else if (match('*')) //if C++ style comment
while (TRUE) // skip to */
{
skpchr();
if (!match('*')) continue;
while (match('*')) skpchr();
if (!match('/')) continue;
skpchr();
break;
//todo: add code to catch unterminated comment
}
else //if neither
expctd("/ or *"); // error out
}
/* Reads next Word in current Input File, where *
* a Word is a sequence of AlphaNumeric characters *
* Sets: word - the Word read from the source file */
void getwrd()
{
int wrdlen = 0;
skpspc();
if (!isalph()) expctd("Alphabetic Character");
while (isanum())
{
word[wrdlen++] = getnxt();
}
word[wrdlen] = 0;
}
/* Get Definition Text */
void getdef()
{
int wrdlen = 0;
skpspc();
while (isprnt()) {
word[wrdlen++] = getnxt();
}
word[wrdlen] = 0;
}
/* Process define directive */
void prsdef()
{
getwrd(); //get defined identifier
DEBUG("Defining '%s'\n", word);
strncpy(defnam[defcnt], word, VARLEN);
getdef();
DEBUG("Defined as '%s'\n", word);
strncat(deftxt[defcnt], word, DEFLEN);
defcnt++;
}
/* Check for and Expand DEFINE *
* Sets: nxtwrd, nxtchr, nxtupr *
* if match is found */
void expdef()
{
int i;
if (!isalph()) return;
DEBUG("Checking for definition '%s'\n", word);
nxtptr = 0;
for (i=0; i<defcnt; i++) {
if (strcmp(word, defnam[i]) == 0) {
strcpy(nxtwrd, deftxt[i]);
nxtchr = nxtwrd[0];
nxtupc = toupper(nxtchr);
DEBUG("Expanded to '%s'\n", word);
return;
}
}
strcpy(nxtwrd, word);
}
char escape(char c)
{
switch (c) {
case 'r': return 0x0d;
default: return c;
}
}
void get_string() {
char str_del, tmp_char;
int wrdlen = 0, esc_next = FALSE;
DEBUG("Parsing string\n", 0);
str_del = getnxt();
while(!match(str_del)) {
if (esc_next)
word[wrdlen++] = escape(getnxt());
else {
if (match('\\'))
esc_next = TRUE;
else
word[wrdlen++] = nxtchr;
skpchr();
}
}
skpchr();
word[wrdlen++] = 0;
}
/* Read Binary number from input file *
* a Binary is a series of binary digits (0 or 1) *
* prefixed with '%' *
* Sets: word - binary number including leading '%' *
* Returns: integer value of number */
int prsbin()
{
int wrdlen = 0;
int digit;
int number = 0;
if (!match('%'))
expctd("hexadecimal number");
word[wrdlen++] = nxtchr;
getnxt();
while (isbin()) {
word[wrdlen++] = nxtchr;
digit = nxtchr - '0';
number = number * 2 + digit;
skpchr();
}
word[wrdlen] = 0;
return (number);
}
/* Read Decimal number from input file *
* a Decimal is a series of digits (0-9) *
* Sets: word - number without leading 0's *
* Returns: integer value of number */
int prsdec()
{
int wrdlen = 0;
int digit;
int number = 0;
if (!isdec()) expctd("Digit");
while (isdec())
{
if (!match('0') || number != 0) //skip leading zeros
word[wrdlen++] = nxtchr;
digit = getnxt() - '0';
number = number * 10 + digit;
}
if (number == 0) word[wrdlen++] = '0';
word[wrdlen] = 0;
return(number);
}
/* Reads Hexadecimal number from input file *
* Sets: word - Hex number including leading '$' *
* Returns: integer value of number */
int prshex()
{
int wrdlen = 0;
int digit;
int number = 0;
DEBUG("Parsing hexadecimal constant\n", 0);
if (!match('$'))
expctd("hexadecimal number");
word[wrdlen++] = getnxt();
while (ishexd()) {
DEBUG("Found hex digit '%c'\n", nxtchr);
word[wrdlen++] = nxtchr;
if (isdec())
digit = nxtchr - '0';
else
digit = nxtchr - 'A' + 10;
number = number * 16 + digit;
skpchr();
}
word[wrdlen] = 0;
return (number);
}
/* Reads Character constant from input file *
* Sets: word - Character constant including *
* single quotes *
* Returns: ASCII value of constant */
int prschr()
{
int wrdlen = 0;
char c;
DEBUG("Parsing character constant\n", 0);
expect('\'');
word[wrdlen++] = '\'';
if (match('\\'))
word[wrdlen++] = getnxt();
c = getnxt();
DEBUG("Extracted character %c\n", c);
word[wrdlen++] = c;
expect('\'');
word[wrdlen++] = '\'';
word[wrdlen] = 0;
return (int)c;
}
/* Parse numeric value *
* Args: maxval - maximum allowed value *
* Sets: value - parsed number (as string) *
* Returns: parsed number */
int prsnum(int maxval)
{
int number;
skpspc();
if (!iscpre()) expctd("constant value");
switch(nxtchr) {
case '%':
number = prsbin();
break;
case '$':
number = prshex();
break;
case '\'':
number = prschr();
break;
default:
number = prsdec();
}
DEBUG("Parsed number '%s'\n", word);
DEBUG("with value '%d'\n", number);
if (number > maxval) {
ERROR("Out of bounds constant '%d';\n", number, EXIT_FAILURE);
}
if (maxval > 255)
sprintf(value, "$%04X", number);
else
sprintf(value, "$%02X", number);
return number;
}
/* Parse numeric constant *
* Args: maxval - maximum allowed value *
* Sets: value - the constant (as a string) *
* valtyp - value type (CONSTANT) */
void prscon(int maxval)
{
int constant = prsnum(maxval);
valtyp = CONSTANT;
if (maxval > 255)
sprintf(value, "#$%04X", constant);
else
sprintf(value, "#$%02X", constant);
DEBUG("Generated constant '%s'\n", value);
}
int get_vartyp()
{
if (match('(')) return FUNCTION;
else if (match('[')) return ARRAY;
else return VARIABLE;
}
/* Parse next word as variable or function name *
* Sets: value - Identifier Name *
* valtyp - Identifier Type */
void prsvar()
{
getwrd();
valtyp = get_vartyp();
if (valtyp != FUNCTION) chksym(word);
strcpy(value, word);
DEBUG("Parsed variable '%s'\n", value);
}
/* Parse arithmetic or bitwise operator */
void prsopr()
{
if (!isoper)
expctd("Arithmetic or bitwise operator");
oper = getnxt();
DEBUG("Parsed operator '%c'\n", oper);
opstr[0] = oper;
opstr[1] = 0;
ACMNT(opstr);
skpspc();
}

54
parse.h Normal file
View File

@ -0,0 +1,54 @@
/*************************************
* C02 Input File Parsing Routines *
*************************************/
enum trmtxts {CONSTANT, VARIABLE, ARRAY, FUNCTION};
enum etypes {ETDEF, ETMAC}; //Definition Types
char word[LINELEN]; //Word parsed from source file
char nxtwrd[LINELEN]; //Next Word (from DEFINE lookup)
int nxtptr; //Pointer to next character in nxtwrd
char value[LINELEN]; //Term parsed from equation
int valtyp; //Value Type
char oper; //Arithmetic or Bitwise Operator
char defnam[MAXDEF+1][VARLEN+1]; //Definition Name Table
char deftxt[MAXDEF+1][DEFLEN+1]; //Definition Text Table
int defcnt; //Number of Definitions Defined
int match(char c); //Does Next Character match c
int inbtwn(char mn, char mx); //Is Next Character in Range ()mn - mx)
int isprnt(); //Is Next Character Printable
int isalpa(); //Is Next Character Alphabetic
int isanum(); //Is Next Character AlphaNumeric
int isdec(); //Is Next Character a Decimal Digit
int ishexd(); //Is Next Character a Hexadecimal Digit
int isbin(); //Is Next Character a Binary Digit
int isnl(); //Is Next Character a NewLine
int isnpre(); //Is Next Character a Numeric Prfix
int isspc(); //Is Next Character a Space
int isapos(); //Is Next Character an Apostrophe
int isvpre(); //Is Next Character a Value Prefix
int isoper(); //Is Next Character an Operator
int ispopr(); //Is Next Character a Post-Operator
int wordis(char *s); //Does word match s
char getnxt(); //Return Next Character and Advance
int look(char c); //Look for Character
void expect(char c); //Look for Character and Exit if not found
void skpchr(); //Advance to Next Character
void skpeol(); //Skip to End of Line
void skpspc(); //Advance to Next Printable Character
void skpcmt(); //Skip to End of Comment
void getwrd(); //Get Next Word
void expdef(); //Check for and Expand Definition
int prsdec(); //Get Decimal Number
void prscon(int maxval); //Parse a Constant
void prsopr(); //Parse Arithmetic Operator
void prsvar(); //Parse Variable

209
stmnt.c Normal file
View File

@ -0,0 +1,209 @@
/************************************
* C02 Statement Compiling Routines *
************************************/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include "common.h"
#include "asm.h"
#include "parse.h"
#include "vars.h"
#include "expr.h"
#include "label.h"
#include "stmnt.h"
/* parse and compile if statement */
void pif() {
DEBUG("Parsing IF statement '%c'\n", nxtchr);
expect('(');
newlbl(LTIF);
prscnd(')'); //Parse Conditional Expession
}
/* parse and compile else statement */
void pelse() {
DEBUG("Parsing ELSE statement '%c'\n", nxtchr);
strcpy(lbltmp, lblasm);
lblasm[0] = 0;
newlbl(LTIF);
asmlin("JMP", curlbl);
strcpy(lblasm, lbltmp);
}
/* parse and compile for statement */
void pfor() {
ERROR("Unsupported statement FOR encountered",0, EXIT_FAILURE);
}
/* parse and compile if statement */
void pgoto() {
DEBUG("Parsing GOTO statement\n", 0);
getwrd();
ACMNT(word);
asmlin("JMP", word);
expect(';');
}
/* parse and compile if statement */
void pretrn() {
DEBUG("Parsing RETURN statement\n", 0);
if (!look(';'))
prsxpr(';');
asmlin("RTS", "");
}
/* parse and compile while statement */
void pwhile() {
DEBUG("Parsing WHILE statement '%c'\n", nxtchr);
expect('(');
newlbl(LTLOOP); //create Loop Label
setlbl(curlbl);
newlbl(LTEND); //Create End Label
prscnd(')'); //Parse Conditional Expession
}
/* generate unimplemented statement error */
void punimp() {
ERROR("Unimplemented statement '%s' encountered", word, EXIT_FAILURE);
}
/* Parse and compile assignment */
void prsasn()
{
DEBUG("Parsing assignment of variable '%s''\n", asnvar);
skpchr(); //skip equals sign
ACMNT("=");
prsxpr(';');
if (strlen(asnidx)) {
asmlin("LDX", asnidx);
strcat(asnvar,",X");
}
asmlin("STA", asnvar);
}
void prcpop() {
DEBUG("Processing post operation '%c'\n", oper);
switch(oper)
{
case '+':
asmlin("INC", asnvar);
break;
case '-':
asmlin("DEC", asnvar);
break;
case '<':
asmlin("ASL", asnvar);
break;
case '>':
asmlin("LSR", asnvar);
break;
default:
printf("Unrecognized post operator '%c'\n", oper);
exterr(EXIT_FAILURE);
}
}
/* Parse Post Operator */
void prspop() {
oper = getnxt();
CCMNT(oper); CCMNT(oper);
DEBUG("Checking for post operation '%c'\n", oper);
if (nxtchr == oper) {
skpchr();
prcpop(); //Process Post-Op
expect(';');
}
else
expctd("post operator");
}
/* Parse function call in first expression */
void prsfnc()
{
char fnname[255]; /*Function name*/
DEBUG("Processing function call '%s'...\n", term);
strcpy(fnname, word);
skpchr(); //skip open paren
CCMNT('(');
skpspc();
if (match(')')) //if no arguments
skpchr(); // skip close paren
else { //otherwise
if (look('&')) {
prsadr(')');
}
else
prsxpr(')'); //parse expression
}
asmlin("JSR", fnname);
expect(';');
}
/* parse and compile identifier (variable or function call) */
void prssym()
{
DEBUG("Parsing Identifier %s\n", word);
valtyp = get_vartyp();
if (valtyp == FUNCTION) {
prsfnc(); //Parse Function Call
return;
}
chksym(word);
strcpy(asnvar, word); //sav variable to assign to
if (valtyp == ARRAY) {
prsidx(); //Parse Array Index
strncpy(asnidx, value, VARLEN);
}
else
asnidx[0] = 0;
if (ispopr(nxtchr))
prspop(); //Parse Post Operator
else
{
skpspc();
if (match('='))
prsasn(); //Parse Assignment
else
expctd("=");
}
}
/* parse and compile program statement */
void pstmnt()
{
DEBUG("Parsing statement '%s'\n", word);
if(match(':')) {
prslbl(); //Parse Label
return;
}
if (wordis("if")) {
pif();
return;
}
if (wordis("else")) {
pelse();
return;
}
if (wordis("while")) {
pwhile();
return;
}
if (wordis("for")) {
punimp();
return;
}
else if (wordis("goto"))
pgoto();
else if (wordis("return"))
pretrn();
else
prssym();
if (lblcnt) {
lbllin();
}
}

8
stmnt.h Normal file
View File

@ -0,0 +1,8 @@
/************************************
* C02 Statement Compiling Routines *
************************************/
char asnvar[VARLEN+1]; /*Assigned Variable Name*/
char asnidx[VARLEN+1] ; /*Assigned Variable Index*/

201
vars.c Normal file
View File

@ -0,0 +1,201 @@
/*************************************
* C02 Variable Management Routines *
*************************************/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include "common.h"
#include "files.h"
#include "asm.h"
#include "parse.h"
#include "vars.h"
/* Lookup variable name in variable table *
* Returns index into varnam array *
* FALSE if variable was not found */
int lookup(char *name)
{
int i;
DEBUG("Looking up variable '%s'\n", word);
for (i=0; i<varcnt; i++) {
if (strcmp(varnam[i], name) == 0)
return i;
}
return -1;
}
/* Check if variable has been defined */
int symdef(char *name)
{
if (lookup(name) < 0)
return FALSE;
else
return TRUE;
}
/* Check for variable *
* Generates error if variable is undefined */
void chksym(char *name)
{
if (!symdef(name))
ERROR("Undeclared variable '%s' encountered\n", word, EXIT_FAILURE);
}
/* Check for Array specifier and get size *
* Sets: value - array size (as string) *
* "" if not an array */
void pvarsz()
{
DEBUG("Checking for array definition\n", 0);
value[0] = 0;
if (match('[')) {
skpchr();
if (alcvar) {
DEBUG("Parsing array size\n", 0);
prsnum(0xFF);
}
expect(']');
}
if (!alcvar)
strcpy(value, "*");
}
/* Parse Data Constant */
void prsdtc()
{
dtype = DTBYTE;
prscon(0xff);
}
/* Parse Data String */
void prsdts()
{
dtype = DTSTR;
get_string();
strcpy(value, word);
DEBUG("Parsed Data String '%s'\n", value);
}
/* Parse and store variable data *
* Sets: datvar[] - Variable Data *
* datlen[] - Data Length */
void prsdat()
{
DEBUG("Checking for variable data\n", 0);
int i;
if (!look('=')) {
datlen[varcnt] = 0;
return;
}
skpspc();
if (isnpre())
prsdtc(0xff);
else if (match('"'))
prsdts();
dlen = strlen(value);
datlen[varcnt] = dlen;
dattyp[varcnt] = dtype;
DEBUG("Setting variable data to '%s'\n", value);
for (i=0; i<dlen; i++)
datvar[dsize++] = value[i];
}
/* Add Variable to Variable table *
* Uses: word - variable name */
void addvar(int t)
{
if (symdef(word))
ERROR("Duplicate declaration of variable '%s\n", word,EXIT_FAILURE);
if (t == VTVOID)
ERROR("Illegal Variable Type\n", 0, EXIT_FAILURE);
DEBUG("Adding variable '%s'\n", word);
strncpy(varnam[varcnt], word, VARLEN);
vartyp[varcnt] = t;
pvarsz();
strncpy(varsiz[varcnt], value, 3);
DEBUG("Added at index %d\n", varcnt);
prsdat(); //Parse Variable Data
varcnt++;
}
void addfnc()
{
expect(')');
if (alcvar)
setlbl(word);
}
/* (Check For and) Parse Variable Declaration*/
void pdecl(int t)
{
DEBUG("Processing variable declarations(s) of type %d\n", t);
while(TRUE) {
getwrd();
if (look('(')) {
addfnc();
break;
}
addvar(t);
if (!look(','))
break;
}
expect(';');
}
/* Write Variable Data */
void vardat(int i)
{
int j;
DEBUG("Building Data for Variable '%s'\n", varnam[i]);
value[0] = 0;
for (j=0; j<datlen[i]; j++) {
if (j) strcat(value,",");
sprintf(word, "$%02X", datvar[dlen++]);
strcat(value, word);
}
if (dattyp[i] == DTSTR) strcat(value, ",$00");
DEBUG("Allocating Data for Variable '%s'\n", varnam[i]);
asmlin(BYTEOP, value);
}
/* Write Variable Table */
void vartbl()
{
int i;
DEBUG("Writing Variable Table", 0);
dlen = 0;
for (i=0; i<varcnt; i++) {
strcpy(lblasm, varnam[i]);
DEBUG("Set Label to '%s'\n", lblasm);
if (strcmp(varsiz[i], "*") == 0)
continue;
else if (datlen[i])
vardat(i); //Write Variable Data
else if (strlen(varsiz[i]) > 0) {
DEBUG("Allocating array '%s'\n", varnam[i]);
asmlin(STROP, varsiz[i]);
}
else {
DEBUG("Allocating variable '%s'\n", varnam[i]);
asmlin(BYTEOP, "0");
}
}
}
/* Print Variable Table to Log File */
void logvar()
{
int i;
fprintf(logfil, "\n%-31s %s %s\n", "Variable", "Type", "Size");
for (i=0; i<varcnt; i++)
{
fprintf(logfil, "%-31s %4d %s\n", varnam[i], vartyp[i], varsiz[i]);
}
}

27
vars.h Normal file
View File

@ -0,0 +1,27 @@
/*************************************
* C02 Variable Management Routines *
*************************************/
/* Variable Table */
char varnam[MAXVAR+1][VARLEN+1]; //Variable Name
char vartyp[MAXVAR+1]; //Variable Type
char varsiz[MAXVAR+1][4]; //Variable Array
int varcnt; //Number of Variables in Table
enum vtypes {VTVOID, VTBYTE, VTCHAR}; //Variable Types
char datvar[DATASPC+1]; //Variable Data Storage
char datlen[MAXVAR+1]; //Variable Data Length
char dattyp[MAXVAR+1]; //Variable Data Type
int dtype; //Data Type
int dlen; //Length of Variable Data
int dsize; //Total Data Length
enum dtypes {DTBYTE, DTSTR}; //Variable Data Types
int symdef(char *name); //Is Variable defined (TRUE or FALSE)
void chksym(char *name); //Error if Variable not defined
void pdecl(int t); //Parse Variable Declaration
void vartbl(); //Create Variable Table