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

Fixed undeclared function warnings

This commit is contained in:
Curtis F Kaylor 2018-02-13 17:25:57 -05:00
parent 44410ce0ce
commit 2edb6da3cb
23 changed files with 1103 additions and 1027 deletions

View File

@ -1,5 +1,5 @@
gccopts=-Wno-format-extra-args
incfiles=common.c files.c label.c asm.c parse.c vars.c expr.c cond.c stmnt.c include.c
incfiles=common.c files.c label.c asm.c parse.c vars.c expr.c cond.c stmnt.c dclrtn.c include.c
mainfile=c02.c
outfile=c02
c02: ${incfiles} ${mainfile}

28
asm.c
View File

@ -10,33 +10,9 @@
#include "common.h"
#include "files.h"
#include "parse.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)
{
if (cmtasm[0] == 0 && c == ' ') return;
int i = strlen(cmtasm);
cmtasm[i++] = c;
cmtasm[i] = 0;
}
/* Process comment */
void prccmt()
{
@ -84,5 +60,3 @@ void prolog()
strcat(cmtasm, srcnam);
cmtlin();
}

19
asm.h
View File

@ -2,16 +2,13 @@
* 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
char lblasm[LABLEN+2]; //Label to emit on next asm line
void addcmt(char *s); //Append String 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
void chrcmt(char c); //Append Character to Assembly Line Comment
void cmtlin(); //Output a comment lines
void equlin(); //Output an equate line
void prccmt(); //Process comment
void prolog(); //Write Assembly Language Initialization Code
void setcmt(char *s); //Set Assembly Line Comment to String

1
c02.c
View File

@ -22,6 +22,7 @@
#include "label.h" //Label Parsing, Generation, and Lookup
#include "cond.h" //Conditional Parsing
#include "stmnt.h" //Statement Compiling Code
#include "dclrtn.h" //Statement Compiling Code
#include "include.h" //Include File Parsing
/* Initilize Compiler Variables */

View File

@ -32,4 +32,23 @@ void prtpos()
printf("(%s: %d,%d) ", inpnam, curlin, curcol);
}
/* Set comment to string */
void setcmt(char *s)
{
strcpy(cmtasm, s);
}
/* Append string to comment */
void addcmt(char *s)
{
strcat(cmtasm, s);
}
/* Append character to comment */
void chrcmt(char c)
{
if (cmtasm[0] == 0 && c == ' ') return;
int i = strlen(cmtasm);
cmtasm[i++] = c;
cmtasm[i] = 0;
}

View File

@ -2,10 +2,6 @@
* C02 Common Definitions & Routines *
*************************************/
#ifndef COMMON_H
#define COMMON_H //Define Guard
#define FNAMLEN 255 //Maximum File Name Length
#define LINELEN 255 //Maximum Input/Output Line Length
#define DEFLEN 6 //Maximum Definition Text Length
@ -36,13 +32,12 @@
#define DEBUG(fmt, val) if (debug) {prtpos(); printf(fmt, val);}
#define DETAIL(fmt, val) if (debug) {printf(fmt, val);}
#define ERROR(fmt, val, err) if (debug) {fprintf(stderr, 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 gencmt; //Generate Assembly Language Comments
char asmcmt[LINELEN]; //Processed Assembly Language Comment
int curcol, curlin; //Position in Source Code
int savcol, savlin; //Save Position in Source Code
@ -50,16 +45,25 @@ 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 word[LINELEN]; //Word parsed from source file
char uword[LINELEN]; //Word converted too uppercase
char cmtasm[LINELEN]; //Assembly Language Comment Text
char incdir[FNAMLEN]; //Include File Directory
char inpnam[FNAMLEN]; //Include File Name
int alcvar; //Allocate Variables Flag
int inblck; //Multiline Block Flag
int lsrtrn; //Last Statement was a Return
void exterr(int errnum); //Print current file name & position and exit
void expctd(char *expected); //Print Expected message and exit
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
void setblk(int blkflg); //Set Block Flag for Last Label
void prtpos(); //Print current file name and position
#endif
void addcmt(char *s); //Append string to comment
void chrcmt(char c); //Append character to comment
void setcmt(char *s); //Set comment to string
#define SCMNT(str) if (gencmt) {setcmt(str);}
#define ACMNT(str) if (gencmt) {addcmt(str);}
#define CCMNT(chr) if (gencmt) {chrcmt(chr);}

3
cond.c
View File

@ -17,7 +17,7 @@
int cmprtr; //Encoded Comparison Operator
int cmpenc; //Encoded Comparator Character
/* Convert Comparison Operator Character *
/* Encode Comparison Operator Character *
* Args: Comparison Operator Character *
* Returns: Comparison Operator Bit Mask */
int enccmp(char c)
@ -139,4 +139,3 @@ void prscnd(char trmntr, int revrse)
prscmp(revrse); //Parse Comparison Operator
expect(trmntr);
}

5
cond.h
View File

@ -4,5 +4,8 @@
int cmpsgn; // Comparison contains signed operands
int enccmp(char c); //Encode Comparison Operator Character
void prccmp(); //Process and Compile Comparison Operator
void prsflg(int revrse); //Parse Flag Operator
int prscmp(int revrse); //Parse Comparison
void prscnd(char trmntr, int revrse); //Parse Conditional Expression

110
dclrtn.c Normal file
View File

@ -0,0 +1,110 @@
/************************************
* C02 Declaration 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 "label.h"
#include "vars.h"
#include "cond.h"
#include "expr.h"
#include "stmnt.h"
#include "dclrtn.h"
/* Add Function Definition */
void addfnc()
{
ACMNT(word);
expect('(');
strcpy(fncnam, word); //Save Function Name
prmcnt = 0; //Set Number of Parameters
skpspc(); //Skip Spaces
if (isalph()) { //Parse Parameters
reqvar(FALSE); //Get First Parameter
strcpy(prmtra, value);
prmcnt++;
if (look(',')) {
reqvar(FALSE); //Get Second Parameter
strcpy(prmtry, value);
prmcnt++;
if (look(',')) {
reqvar(FALSE); //Third Parameter
strcpy(prmtrx, value);
prmcnt++;
}
}
}
expect(')');
if (look(';')) //Forward Definition
return;
setlbl(fncnam); //Set Function Entry Point
if (prmcnt > 0)
asmlin("STA", prmtra); //Store First Parameter
if (prmcnt > 1)
asmlin("STY", prmtry); //Store Second Parameter
if (prmcnt > 2)
asmlin("STX", prmtrx); //Store Third Parameter
endlbl[0] = 0; //Create Dummy End Label
pshlbl(LTFUNC, endlbl); //and Push onto Stack
bgnblk('{'); //Start Program Block
}
/* (Check For and) Parse Variable Declaration*/
void pdecl(int m, int t)
{
DEBUG("Processing variable declarations(s) of type %d\n", t);
while(TRUE) {
getwrd();
if (match('(')) {
if (m != MTNONE) {
ERROR("Illegal Modifier %d in Function Definion", m, EXIT_FAILURE);
}
addfnc(); //Add Function Call
return;
}
addvar(m, t);
if (!look(','))
break;
}
expect(';');
DEBUG("Variable Declaration Completed\n", 0);
SCMNT(""); //Clear Assembler Comment
}
/* Check for and Parse Type Keyword */
int ptype(int m)
{
int result = TRUE;
if (wordis("VOID"))
pdecl(m, VTVOID); //Parse 'void' declaration
else if (wordis("CHAR"))
pdecl(m, VTCHAR); //Parse 'char' declaration
else
result = FALSE;
//DEBUG("Returning %d from function ptype\n", result)'
return result;
}
/* Check for and Parse Modifier */
int pmodfr()
{
DEBUG("Parsing modifier '%s'\n", word);
int result = TRUE;
if (wordis("ALIGNED")) {
getwrd();
ptype(MTALGN);
}
else if (wordis("ZEROPAGE")) {
getwrd();
ptype(MTZP);
}
else
result = FALSE;
return result;
}

6
dclrtn.h Normal file
View File

@ -0,0 +1,6 @@
/************************************
* C02 Declaration Compiling Routines *
************************************/
int pmodfr(); //Check for and Parse Modifier
int ptype(int m); //Check for and Parse Type Keyword

11
expr.c
View File

@ -43,7 +43,7 @@ void prsidx()
expect(']');
}
/* Check for, Parse, and Process index */
/* Check for, Parse, and Process Index */
void chkidx()
{
//DEBUG("Checking for Array Index with valtyp=%d\n", valtyp);
@ -65,7 +65,7 @@ void chkidx()
}
}
/* Parse term in expression *
/* Parse Term in Expression *
* Sets: term - the term (as a string) */
void prstrm()
{
@ -81,7 +81,7 @@ void prstrm()
skpspc();
}
/* Compile Address Reference */
/* Process Address Reference */
void prcadr(int adract, char* symbol)
{
DEBUG("Processing address '%s'\n", word);
@ -115,7 +115,7 @@ void prsadr(int adract)
}
/* Parse and Create Anonymous String */
void prsstr(adract)
void prsstr(int adract)
{
DEBUG("Parsing anonymous string\n", 0);
newlbl(vrname); //Generate Variable Name
@ -128,7 +128,7 @@ void prsstr(adract)
}
/* Check for and Process Address or String */
int chkadr(adract)
int chkadr(int adract)
{
DEBUG("Checking for Address or String\n", 0);
int result = TRUE;
@ -249,4 +249,3 @@ void prsxpr(char trmntr)
}
expect(trmntr);
}

19
expr.h
View File

@ -2,15 +2,24 @@
* C02 Expession Parsing Routines *
**********************************/
char term[255]; /*Term parsed from equation*/
char term[255]; //Term parsed from equation
char fnstck[MAXFNS][VARLEN+1]; //Function Call Stack
int fnscnt; //Number of Functions in Stack
int chkpst; //Check for Post-Operator
int chkpst; //Check for Post-Operator
void prsidx(); //Parse Array Index
void prstrm(); //Parse Term in Expression
void prsxpr(char trmntr); //Parse Expression
int chkadr(int adract); //Check for and Process Address or String
void chkidx(); //Check for, Parse, and Process Index
void prcadr(int adract, char* symbol); //Process Address Reference
void prcopr(); //Process Arithmetic or Bitwise Operator
void prsadr(int adract); //Parse and Compile Address of Operator
void prsfnc(char trmntr); //Parse function call
void prsftm(); //Parse first term of expession
void prsidx(); //Parse Array Index
void prstrm(); //Parse Term in Expression
void prsstr(int adract); //Parse and Create Anonymous String
void prsval(int alwreg); //Parse value (constant or identifier)
void prsxpr(char trmntr); //Parse Expression

View File

@ -14,10 +14,13 @@ char lognam[FNAMLEN]; //Log File Name
char incnam[FNAMLEN]; //Include File Name
void opnsrc(); //Open Source File
void clssrc(); //Close Source File
void clssrc(); //Close Source File
void opnout(); //Open Output File
void clsout(); //Close Output File
void clsout(); //Close Output File
void opnlog(); //Open Log File
void clslog(); //Close Log File
void opninc(); //Open Include File
void clsinc(); //Close Include File
void clsinc(); //Close Include File

View File

@ -12,10 +12,13 @@
#include "files.h"
#include "asm.h"
#include "parse.h"
#include "label.h"
#include "vars.h"
#include "stmnt.h"
#include "dclrtn.h"
#include "include.h"
/* Reads next include file name from Source File *
/* Read next include file name from Source File *
* Sets: incnam - the include file name */
void pincnm()
{
@ -79,7 +82,6 @@ void pascii()
fprintf(stderr, "Unrecognized option '%s'\n", word);
exterr(EXIT_FAILURE);
}
}
/* Parse Origin Subdirective */
@ -90,7 +92,7 @@ void porign()
DEBUG("Set origin to %s\n", value);
}
/* Parse Origin Subdirective */
/* Parse Zeropage Subdirective */
void prszpg()
{
zpaddr = prsnum(0xFF); //Set Zero Page Address to Constant
@ -202,10 +204,6 @@ void inchdr() {
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()
{
@ -220,8 +218,6 @@ void pincfl()
incasm();
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, ".a02");
@ -243,5 +239,3 @@ void logdef()
fprintf(logfil, "%-31s %5d\n", defnam[i], defval[i]);
}
}

View File

@ -4,4 +4,19 @@
char line[255]; /*Entire line parsed from include file*/
void incasm(); //Process assembly language include file
void inchdr(); //Process header include file
void logdef(); //Print Definition Table to Log File
void pascii(); //Parse ASCII Subdirective
void pdefin(); //Process define directive
void phdwrd(); //Parse Header Word
void pincdr(); //Process Include File Directive
void pincfl(); //Process include file
void pincnm(); //Parse Include File Name
void porign(); //Parse Origin Subdirective
void pprgma(); //Parse Pragma Directive
void pvrtbl(); //Process Vartable Subdirective
void prszpg(); //Parse Zeropage Subdirective
void rstsrc(); //Restore Source File Pointer
void savsrc(); //Save Source File Information
void setinc(); //Set Include File Information

View File

@ -72,14 +72,16 @@ void newlbl(char* lbname)
DEBUG("Generated new label '%s'\n", lbname);
}
/* if label is blank, generate a new one */
/* Check Label Contents *
* If lbname is blank, generate new *
* label and copy into lbname */
void chklbl(char* lbname)
{
if (lbname[0]) return;
newlbl(lbname);
}
/* require label *
/* Require Label *
* if label is already set, returns that label *
* else generates new label and sets it */
void reqlbl(char* lbname)
@ -139,4 +141,3 @@ void pshlbl(int lbtype, char* lbname)
lblblk[lblcnt++] = FALSE;
DEBUG("Pushed label '%s' onto stack\n", lbname);
}

14
label.h
View File

@ -2,8 +2,6 @@
* C02 Label Parsing, Generation, and Lookup Routines *
******************************************************/
int inblck; //Multiline Block Flag
char curlbl[LABLEN+1]; //Most recently generated label
char cndlbl[LABLEN+1]; //Label for Conditional Code
char endlbl[LABLEN+1]; //End Label
@ -21,8 +19,14 @@ char lbltmp[LABLEN+1]; //Label Temporary Storage
enum ltypes {LTNONE, LTIF, LTLOOP, LTEND, LTDO, LTDWHL, LTSLCT, LTCASE, LTFUNC}; //Label Types
enum lflags {LFNONE, LFBGN, LFEND}; //Label Flag Types
void prslbl(); //Parse Label From Code
void chklbl(char* lbname); //Check Label Contents
int lstlbl(int lbflag); //Find Last Label of Specified Types *
void newlbl(char* lbname); //Generate New Block Label
int poplbl(); //Pull Last Label and Emit on Next Line
void setlbl(); //Emit word as Label on Next Line
int poplbl(); //Pop Last Label and Emit on Next Line
void prslbl(); //Parse Label From Code
void pshlbl(int lbtype, char* lbname); //Push Label onto Stack
void reqlbl(char* lbname); //Require Label
void setblk(int blkflg); //Set Block Flag for Last Label
void setlbl(char *lblset); //Emit word as Label on Next Line
int toplbl(char *rtlbl); //Get Top Label and Return Type

945
parse.c
View File

@ -1,474 +1,471 @@
/*************************************
* 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"
/* Various tests against nxtchr */
int match(char c) {return TF(nxtchr == c);}
int inbtwn(char mn, char mx) {return TF(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 TF(isdec() || inbtwn('A', 'Z'));}
int isbin() {return inbtwn('0', '1');}
int isnl() {return TF(match('\n') || match('\r'));}
int isspc() {return isspace(nxtchr);}
int isnpre() {return TF(isdec() || match('$') || match('%'));}
int isapos() {return match('\'');}
int isbpre() {return TF(isnpre() || isapos());}
int ishash() {return match('#');}
int iscpre() {return TF(isbpre() || ishash());}
int isvpre() {return TF(isalph() || iscpre());}
int isoper() {return TF(strchr("+-&|^", nxtchr));}
int ispopr() {return TF(strchr("+-<>", nxtchr));}
int isxpre() {return TF(isvpre() || match('-'));}
/* Conversion Functions */
char invchr(char c) {return isalpha(c)?(islower(c)?toupper(c):tolower(c)):c;}
/* 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);
if (isspc()) CCMNT(' ');
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 (c == 0) return;
if (look(c)) return;
else {
fprintf(stderr, "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++] = toupper(getnxt());
}
word[wrdlen] = 0;
}
char escape(char c)
{
DEBUG("Escaping character '%c'\n", c);
switch (c) {
case 'r': return 0x0d;
default: return c;
}
}
/* Get String */
void getstr() {
char strdel, tmpchr;
int wrdlen = 0, escnxt = FALSE;
DEBUG("Parsing string\n", 0);
strdel = getnxt(); //Get String Delimiter
CCMNT(strdel);
while(match(strdel) == escnxt) {
CCMNT(nxtchr);
if (escnxt) {
word[wrdlen++] = escape(getnxt());
escnxt = FALSE;
}
else {
if (match('\\'))
escnxt = TRUE;
else
if (invasc) nxtchr = invchr(nxtchr);
word[wrdlen++] = nxtchr;
skpchr();
}
}
skpchr(); //Skip End Delimiter
CCMNT(strdel);
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 '", 0);
if (!match('$'))
expctd("hexadecimal number");
word[wrdlen++] = getnxt();
while (ishexd()) {
DETAIL("%c", nxtchr);
word[wrdlen++] = nxtchr;
if (isdec())
digit = nxtchr - '0';
else
digit = nxtchr - 'A' + 10;
number = number * 16 + digit;
skpchr();
}
DETAIL("'\n", 0);
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);
if (invasc) c = invchr(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 (!isbpre()) expctd("constant value");
switch(nxtchr) {
case '%':
number = prsbin();
break;
case '$':
number = prshex();
break;
case '\'':
number = prschr();
break;
default:
number = prsdec();
}
DEBUG("Parsed number '%s' ", word);
DETAIL("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;
}
int prsbyt()
{
return prsnum(0xFF);
}
void fnddef(char *name)
{
DEBUG("Looking up defined constant '%s'\n", word);
for (defidx=0; defidx<defcnt; defidx++) {
if (strcmp(defnam[defidx], name) == 0)
return;
}
defidx = -1;
}
int prsdef()
{
expect('#');
getwrd(); //Get Constant Name
fnddef(word);
if (defidx < 0) {
ERROR("Undefined constant '%s'\n", word, EXIT_FAILURE);
}
strcpy(value, word);
return defval[defidx];
}
/* Parse numeric constant *
* Args: maxval - maximum allowed value *
* Sets: cnstnt - the constant (as an integer) *
* value - the constant (as asm arg) *
* valtyp - value type (CONSTANT) *
* word - constant (as a string) *
* Note: Value is converted to hexadecimal *
* because DASM uses the format 'c for *
* character arguments instead of 'c' */
void prscon()
{
skpspc();
if (ishash())
cnstnt = prsdef();
else
cnstnt = prsbyt();
valtyp = CONSTANT;
ACMNT(word);
strcpy(word, value); //Patch for DASM
strcpy(value, "#");
strcat(value, word);
DEBUG("Generated constant '%s'\n", value);
}
/* Get Value Type */
int gettyp()
{
if (match('(')) return FUNCTION;
else if (match('[')) return ARRAY;
else return VARIABLE;
}
/* Parse next word as variable or function name *
* Args: alwreg - Allow Register Names *
* Sets: value - Identifier Name *
* valtyp - Identifier Type */
void prsvar(int alwreg)
{
getwrd();
valtyp = gettyp();
if (valtyp != FUNCTION) chksym(alwreg, word);
strcpy(value, word);
DEBUG("Parsed variable '%s'\n", value);
ACMNT(word);
}
/* Parse arithmetic or bitwise operator */
void prsopr()
{
if (!isoper)
expctd("Arithmetic or bitwise operator");
oper = getnxt();
DEBUG("Parsed operator '%c'\n", oper);
CCMNT(oper);
skpspc();
}
void prcidx(char *name, char *index)
{
if (strlen(index)) {
asmlin("LDX", index);
strcat(name,",X");
}
}
void prcpst(char* name, char *index)
{
DEBUG("Processing post operation '%c'\n", oper);
prcidx(name, index);
switch(oper)
{
case '+':
if (strcmp(name, "X")==0)
asmlin("INX", "");
else if (strcmp(name, "Y")==0)
asmlin("INY", "");
else if (strcmp(name, "A")==0)
poperr(); //65C02 supports implicit INC, 6502 does not
else
asmlin("INC", name);
break;
case '-':
if (strcmp(name, "X")==0)
asmlin("DEX", "");
else if (strcmp(name, "Y")==0)
asmlin("DEY", "");
else if (strcmp(name, "A")==0)
poperr(); //65C02 supports implicit DEC, 6502 does not
else
asmlin("DEC", name);
break;
case '<':
if (strcmp(name, "X")==0)
poperr(); //Index Register Shift not Supported
else if (strcmp(name, "Y")==0)
poperr(); //Index Register Shift not Supported
else if (strcmp(name, "A")==0)
asmlin("ASL", "");
else
asmlin("ASL", name);
break;
case '>':
if (strcmp(name, "X")==0)
poperr(); //Index Register Shift not Supported
else if (strcmp(name, "Y")==0)
poperr(); //Index Register Shift not Supported
else if (strcmp(name, "A")==0)
asmlin("LSR", "");
else
asmlin("LSR", name);
break;
default:
fprintf(stderr, "Unrecognized post operator '%c'\n", oper);
exterr(EXIT_FAILURE);
}
}
/* Parse Post Operator */
int prspst(char trmntr, char* name, char* index) {
oper = getnxt();
CCMNT(oper);
DEBUG("Checking for post operation '%c'\n", oper);
if (nxtchr == oper) {
skpchr();
CCMNT(oper);
expect(trmntr);
prcpst(name, index); //Process Post-Op
oper = 0;
}
else {
DEBUG("Not a post operation\n", 0);
}
return oper;
}
/*************************************
* 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 "asm.h"
#include "parse.h"
/* Various tests against nxtchr */
int match(char c) {return TF(nxtchr == c);}
int inbtwn(char mn, char mx) {return TF(nxtchr >= mn && nxtchr <= mx);}
int isalph() {return isalpha(nxtchr);}
int isanum() {return isalnum(nxtchr);}
int isapos() {return match('\'');}
int isbin() {return inbtwn('0', '1');}
int isbpre() {return TF(isnpre() || isapos());}
int iscpre() {return TF(isbpre() || ishash());}
int isdec() {return inbtwn('0', '9');}
int ishash() {return match('#');}
int ishexd() {return TF(isdec() || inbtwn('A', 'Z'));}
int isnl() {return TF(match('\n') || match('\r'));}
int isnpre() {return TF(isdec() || match('$') || match('%'));}
int isoper() {return TF(strchr("+-&|^", nxtchr));}
int ispopr() {return TF(strchr("+-<>", nxtchr));}
int isprnt() {return isprint(nxtchr);}
int isspc() {return isspace(nxtchr);}
int isvpre() {return TF(isalph() || iscpre());}
int isxpre() {return TF(isvpre() || match('-'));}
/* Conversion Functions */
char invchr(char c) {return isalpha(c)?(islower(c)?toupper(c):tolower(c)):c;}
/* 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);
if (isspc()) CCMNT(' ');
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 (c == 0) return;
if (look(c)) return;
else {
fprintf(stderr, "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++] = toupper(getnxt());
}
word[wrdlen] = 0;
}
/* Escape Character */
char escape(char c)
{
DEBUG("Escaping character '%c'\n", c);
switch (c) {
case 'r': return 0x0d;
default: return c;
}
}
/* Get String */
void getstr() {
char strdel, tmpchr;
int wrdlen = 0, escnxt = FALSE;
DEBUG("Parsing string\n", 0);
strdel = getnxt(); //Get String Delimiter
CCMNT(strdel);
while(match(strdel) == escnxt) {
CCMNT(nxtchr);
if (escnxt) {
word[wrdlen++] = escape(getnxt());
escnxt = FALSE;
}
else {
if (match('\\'))
escnxt = TRUE;
else
if (invasc) nxtchr = invchr(nxtchr);
word[wrdlen++] = nxtchr;
skpchr();
}
}
skpchr(); //Skip End Delimiter
CCMNT(strdel);
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 '", 0);
if (!match('$'))
expctd("hexadecimal number");
word[wrdlen++] = getnxt();
while (ishexd()) {
DETAIL("%c", nxtchr);
word[wrdlen++] = nxtchr;
if (isdec())
digit = nxtchr - '0';
else
digit = nxtchr - 'A' + 10;
number = number * 16 + digit;
skpchr();
}
DETAIL("'\n", 0);
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);
if (invasc) c = invchr(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 (!isbpre()) expctd("constant value");
switch(nxtchr) {
case '%':
number = prsbin();
break;
case '$':
number = prshex();
break;
case '\'':
number = prschr();
break;
default:
number = prsdec();
}
DEBUG("Parsed number '%s' ", word);
DETAIL("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 Nuneric Byte Value */
int prsbyt()
{
return prsnum(0xFF);
}
/* Find Defined Constant */
void fnddef(char *name)
{
DEBUG("Looking up defined constant '%s'\n", word);
for (defidx=0; defidx<defcnt; defidx++) {
if (strcmp(defnam[defidx], name) == 0)
return;
}
defidx = -1;
}
/* Parse Definition */
int prsdef()
{
expect('#');
getwrd(); //Get Constant Name
fnddef(word);
if (defidx < 0) {
ERROR("Undefined constant '%s'\n", word, EXIT_FAILURE);
}
strcpy(value, word);
return defval[defidx];
}
/* Parse numeric constant *
* Args: maxval - maximum allowed value *
* Sets: cnstnt - the constant (as an integer) *
* value - the constant (as asm arg) *
* valtyp - value type (CONSTANT) *
* word - constant (as a string) *
* Note: Value is converted to hexadecimal *
* because DASM uses the format 'c for *
* character arguments instead of 'c' */
void prscon()
{
skpspc();
if (ishash())
cnstnt = prsdef();
else
cnstnt = prsbyt();
valtyp = CONSTANT;
ACMNT(word);
strcpy(word, value); //Patch for DASM
strcpy(value, "#");
strcat(value, word);
DEBUG("Generated constant '%s'\n", value);
}
/* Get Value Type */
int gettyp()
{
if (match('(')) return FUNCTION;
else if (match('[')) return ARRAY;
else return VARIABLE;
}
/* Parse arithmetic or bitwise operator */
void prsopr()
{
if (!isoper)
expctd("Arithmetic or bitwise operator");
oper = getnxt();
DEBUG("Parsed operator '%c'\n", oper);
CCMNT(oper);
skpspc();
}
/* Process Array Index */
void prcidx(char *name, char *index)
{
if (strlen(index)) {
asmlin("LDX", index);
strcat(name,",X");
}
}
/* Generate Post-Operation Error */
void poperr(char* name)
{
fprintf(stderr, "Illegal post-operation %c%c on register %s\n", oper, oper, name);
exterr(EXIT_FAILURE);
}
/* Process Post Operator */
void prcpst(char* name, char *index)
{
DEBUG("Processing post operation '%c'\n", oper);
prcidx(name, index);
switch(oper)
{
case '+':
if (strcmp(name, "X")==0)
asmlin("INX", "");
else if (strcmp(name, "Y")==0)
asmlin("INY", "");
else if (strcmp(name, "A")==0)
poperr(name); //65C02 supports implicit INC, 6502 does not
else
asmlin("INC", name);
break;
case '-':
if (strcmp(name, "X")==0)
asmlin("DEX", "");
else if (strcmp(name, "Y")==0)
asmlin("DEY", "");
else if (strcmp(name, "A")==0)
poperr(name); //65C02 supports implicit DEC, 6502 does not
else
asmlin("DEC", name);
break;
case '<':
if (strcmp(name, "X")==0)
poperr(name); //Index Register Shift not Supported
else if (strcmp(name, "Y")==0)
poperr(name); //Index Register Shift not Supported
else if (strcmp(name, "A")==0)
asmlin("ASL", "");
else
asmlin("ASL", name);
break;
case '>':
if (strcmp(name, "X")==0)
poperr(name); //Index Register Shift not Supported
else if (strcmp(name, "Y")==0)
poperr(name); //Index Register Shift not Supported
else if (strcmp(name, "A")==0)
asmlin("LSR", "");
else
asmlin("LSR", name);
break;
default:
fprintf(stderr, "Unrecognized post operator '%c'\n", oper);
exterr(EXIT_FAILURE);
}
}
/* Parse Post Operator */
int prspst(char trmntr, char* name, char* index) {
oper = getnxt();
CCMNT(oper);
DEBUG("Checking for post operation '%c'\n", oper);
if (nxtchr == oper) {
skpchr();
CCMNT(oper);
expect(trmntr);
prcpst(name, index); //Process Post-Op
oper = 0;
}
else {
DEBUG("Not a post operation\n", 0);
}
return oper;
}

133
parse.h
View File

@ -1,61 +1,72 @@
/*************************************
* C02 Input File Parsing Routines *
*************************************/
#define TF(x) (x) ? TRUE : FALSE;
enum stypes {CONSTANT, VARIABLE, ARRAY, FUNCTION}; //Symbol Types
enum etypes {ETDEF, ETMAC}; //Definition Types
char word[LINELEN]; //Word parsed from source file
char uword[LINELEN]; //Word converted too uppercase
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
int cnstnt; //Value of Parsed Constant
char defnam[MAXDEF+1][VARLEN+1]; //Definition Name Table
int defval[MAXDEF+1]; //Definition Value Table
int defcnt; //Number of Definitions Defined
int defidx; //Index into Definition Tables
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 invasc; //Invert ASCII Flag
char invchr(char c); //Invert Character Case
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
int prsdec(); //Get Decimal Number
void prscon(); //Parse a Constant
void prsopr(); //Parse Arithmetic Operator
void prsvar(int alwreg); //Parse Variable
/*************************************
* C02 Input File Parsing Routines *
*************************************/
#define TF(x) (x) ? TRUE : FALSE;
enum stypes {CONSTANT, VARIABLE, ARRAY, FUNCTION}; //Symbol Types
enum etypes {ETDEF, ETMAC}; //Definition Types
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
int cnstnt; //Value of Parsed Constant
char defnam[MAXDEF+1][VARLEN+1]; //Definition Name Table
int defval[MAXDEF+1]; //Definition Value Table
int defcnt; //Number of Definitions Defined
int defidx; //Index into Definition Tables
int invasc; //Invert ASCII Flag
int match(char c); //Does Next Character match c
int inbtwn(char mn, char mx); //Is Next Character in Range ()mn - mx)
int isalph(); //Is Next Character Alphabetic
int isanum(); //Is Next Character AlphaNumeric
int isapos(); //Is Next Character an Apostrophe
int isbin(); //Is Next Character a Binary Digit
int isbpre(); //
int iscpre(); //Is Next Character a Constant
int isdec(); //Is Next Character a Decimal Digit
int ishash(); //Is Next Character a Byte Value
int ishexd(); //Is Next Character a Hexadecimal Digit
int isnl(); //Is Next Character a NewLine
int isnpre(); //Is Next Character a Numeric Prfix
int isoper(); //Is Next Character an Operator
int ispopr(); //Is Next Character a Post-Operator
int isprnt(); //Is Next Character Printable
int isspc(); //Is Next Character a Space
int isvpre(); //Is Next Character a Value Prefix
int isxpre(); //Is Next Character an Expression Prefix
char escape(char c); //Escape Character
void expect(char c); //Look for Character and Exit if not found
void fnddef(char *name); //Find Definition
char getnxt(); //Return Next Character and Advance
void getstr(); //Get String
int gettyp(); //Get Value Type
void getwrd(); //Get Next Word
char invchr(char c); //Invert Character Case
int look(char c); //Look for Character
void prcidx(char *name, char *index); //Process Array Index
void prcpst(char* name, char *index); //Process Post Operator
int prsbin(); //Parse Binary Number
int prsbyt(); //Parse Numeric Byte
int prschr(); //Parse Character Constant
void prscon(); //Parse a Constant
int prsdec(); //Parse Decimal Number
int prsdef(); //Parse Definition
int prshex(); //Parse Hexadecimal Number
int prsnum(int maxval); //Parse Numeric
void prsopr(); //Parse Arithmetic Operator
int prspst(char trmntr, char* name, char* index); //Parse Post Operator
void skpchr(); //Skip Next Character
void skpcmt(); //Skip to End of Comment
void skpeol(); //Skip to End of Line
void skpspc(); //Advance to Next Printable Character
int wordis(char *s); //Does word match s

69
stmnt.c
View File

@ -7,14 +7,45 @@
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include "common.h"
#include "asm.h"
#include "parse.h"
#include "vars.h"
#include "label.h"
#include "vars.h"
#include "cond.h"
#include "expr.h"
#include "stmnt.h"
/* Begin Program Block */
void bgnblk(char blkchr)
{
DEBUG("Begining program block\n", 0);
if (blkchr) {
expect(blkchr);
inblck = TRUE;
}
else
inblck = look('{');
DEBUG("Set inblck to %d\n", inblck);
setblk(inblck);
}
/* End Program Block *
* Args: blkflg: End of Multiline Block */
void endblk(int blkflg)
{
int lbtype;
DEBUG("Ending program block with flag %d\n", blkflg);
expect('}'); //Block End Character
DEBUG("Found inblck set to %d\n", inblck);
if (inblck != blkflg)
ERROR("Encountered '}' without matching '{'\n", 0, EXIT_FAILURE);
lbtype = poplbl();
if (lbtype == LTDO)
pdowhl(); //Parse While at End of Do Loop
}
/* Parse Shortcut If */
void prssif(char trmntr) {
newlbl(cndlbl); //Create Label for "if FALSE" expression
@ -58,12 +89,6 @@ void prcasn(char trmntr)
}
}
void poperr()
{
fprintf(stderr, "Illegal post-operation %c%c on register %s\n", oper, oper, asnvar);
exterr(EXIT_FAILURE);
}
/* Process Variable at Beginning of Statement */
void prcvar(char trmntr)
{
@ -91,20 +116,6 @@ void prcvar(char trmntr)
prcasn(trmntr);
}
/* Begin Program Block */
void bgnblk(char blkchr)
{
DEBUG("Begining program block\n", 0);
if (blkchr) {
expect(blkchr);
inblck = TRUE;
}
else
inblck = look('{');
DEBUG("Set inblck to %d\n", inblck);
setblk(inblck);
}
/* Parse 'asm' String Parameter */
void pasmst(char trmntr)
{
@ -405,21 +416,6 @@ void prssym()
prcvar(';'); //Parse Assignment
}
/* End Program Block *
* Args: blkflg: End of Multiline Block */
void endblk(int blkflg)
{
int lbtype;
DEBUG("Ending program block with flag %d\n", blkflg);
expect('}'); //Block End Character
DEBUG("Found inblck set to %d\n", inblck);
if (inblck != blkflg)
ERROR("Encountered '}' without matching '{'\n", 0, EXIT_FAILURE);
lbtype = poplbl();
if (lbtype == LTDO)
pdowhl(); //Parse While at End of Do Loop
}
/* parse and compile program statement */
void pstmnt()
{
@ -487,4 +483,3 @@ void pstmnt()
pdowhl(); //Parse While at End of Do Loop
}
}

18
stmnt.h
View File

@ -2,11 +2,17 @@
* C02 Statement Compiling Routines *
************************************/
char asnvar[VARLEN+1]; //Assigned Variable Name
char asnidx[VARLEN+1] ; //Assigned Variable Index
int asnivt; //Assigned Index Variable Type
char asnvar[VARLEN+1]; //Assigned Variable Name
char asnidx[VARLEN+1] ; //Assigned Variable Index
int asnivt; //Assigned Index Variable Type
char xstmnt[LINELEN]; //Required Statement
char xstmnt[LINELEN]; //Required Statement
void endblk(); //End Program Block
void pstmnt(); //Parse and Compile Program Statement
void bgnblk(char blkchr); //End Program Block
void endblk(int blkflg); //End Program Block
void pdowhl(); //Parse and Compile WHILE after DO
void prcasn(char trmntr); //Process Assignment
void prcvar(char trmntr); //Process Variable at Beginning of Statement
void prsasn(char trmntr); //Parse and Compile and Assignment
void prssif(char trmntr); //Parse Shortcut If
void pstmnt(); //Parse and Compile Program Statement

541
vars.c
View File

@ -1,309 +1,232 @@
/*************************************
* 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 "label.h"
#include "vars.h"
/* Lookup variable name in variable table *
* Sets: varidx = index into varnam array *
* varcnt if not found *
* Returns: TRUE if found, otherwise FALSE */
int fndvar(char *name)
{
DEBUG("Looking up variable '%s'\n", word);
for (varidx=0; varidx<varcnt; varidx++) {
if (strcmp(varnam[varidx], name) == 0)
return TRUE;
}
return FALSE;
}
/* Check for variable *
* Generates error if variable is undefined *
* Args: alwreg - allow register name *
* name - variable name */
void chksym(int alwreg, char *name)
{
if (strlen(name) == 1 && strchr("AXY", name[0])) {
if (alwreg) return;
else ERROR("Illegal reference to register %s\n", name, EXIT_FAILURE);
}
if (!fndvar(name))
ERROR("Undeclared variable '%s' encountered\n", name, EXIT_FAILURE);
}
/* Parse Variable Name *
* Parameters: alwary - Allow Array Reference *
* Sets: vrname - operand for LDA/STA/LDY/STY */
void reqvar(int alwary)
{
prsvar(FALSE);
if (!alwary)
if (valtyp != VARIABLE)
expctd("Variable");
}
/* Parse Data Array */
void prsdta()
{
dtype = DTARRY;
expect('{');
dlen = 0;
while (TRUE) {
prscon();
dattmp[dlen++] = cnstnt;
if (!look(','))
break;
}
expect('}');
}
/* Parse Data String */
void prsdts()
{
dtype = DTSTR;
getstr();
strcpy(value, word);
DEBUG("Parsed Data String '%s'\n", value);
}
/* Store variable data *
* Uses: value - Data to store *
* Sets: datvar[] - Variable Data *
* datlen[] - Data Length */
void setdat()
{
int i;
if (dtype == DTBYTE) {
DEBUG("Setting variable data to '%d'\n", cnstnt);
dlen = 1;
datvar[dsize++] = cnstnt;
}
else if (dtype == DTARRY) {
DEBUG("Setting variable data to array of length %d\n", dlen);
for (i=0; i<dlen; i++)
datvar[dsize++] = dattmp[i];
}
else {
DEBUG("Setting variable data to '%s'\n", value);
dlen = strlen(value);
for (i=0; i<dlen; i++)
datvar[dsize++] = value[i];
}
datlen[varcnt] = dlen;
dattyp[varcnt] = dtype;
DEBUG("Total data alllocated: %d bytes\n", dsize);
}
/* Parse and store variable data */
void prsdat()
{
DEBUG("Checking for variable data\n", 0);
if (!look('=')) {
datlen[varcnt] = 0;
return;
}
skpspc();
if (iscpre()) {
dtype = DTBYTE;
prscon(); //Parse Data Constant
}
else if (match('"'))
prsdts(); //Parse Data String
else if (match('{'))
prsdta(); //Parse Data Array
else
expctd("numeric or string constant");
setdat(); //Store Data Value
}
/* Add Variable to Variable table *
* Uses: word - variable name *
* value - variable size */
void setvar(int m, int t)
{
DEBUG("Added variable '%s' ", word);
strncpy(varnam[varcnt], vrname, VARLEN);
varmod[varcnt] = m;
vartyp[varcnt] = t;
strncpy(varsiz[varcnt], value, 3);
DETAIL("at index %d\n", varcnt);
}
/* Parse and Compile Variable Declaration *
* Uses: word - variable name */
void addvar(int m, int t)
{
strcpy(vrname, word); //Save Variable Name
if (fndvar(vrname))
ERROR("Duplicate declaration of variable '%s\n", word,EXIT_FAILURE);
if (t == VTVOID)
ERROR("Illegal Variable Type\n", 0, EXIT_FAILURE);
if (m == MTZP) {
setlbl(vrname);
sprintf(word, "$%hhX", zpaddr++);
asmlin(EQUOP, word);
strcpy(value, "*"); //Set Variable Type to Zero Page
}
else {
DEBUG("Checking for array definition\n", 0);
value[0] = 0;
if (match('[')) {
skpchr();
if (alcvar) {
DEBUG("Parsing array size\n", 0);
sprintf(value, "%d", prsnum(0xFF) + 1);
}
expect(']');
}
if (!alcvar) strcpy(value, "*");
setvar(m, t); //Add to Variable Table
}
if (m != MTZP)
prsdat(); //Parse Variable Data
varcnt++; //Increment Variable Counter
}
/* Add Function Definition */
void addfnc()
{
ACMNT(word);
expect('(');
strcpy(fncnam, word); //Save Function Name
prmcnt = 0; //Set Number of Parameters
skpspc(); //Skip Spaces
if (isalph()) { //Parse Parameters
reqvar(FALSE); //Get First Parameter
strcpy(prmtra, value);
prmcnt++;
if (look(',')) {
reqvar(FALSE); //Get Second Parameter
strcpy(prmtry, value);
prmcnt++;
if (look(',')) {
reqvar(FALSE); //Third Parameter
strcpy(prmtrx, value);
prmcnt++;
}
}
}
expect(')');
if (look(';')) //Forward Definition
return;
setlbl(fncnam); //Set Function Entry Point
if (prmcnt > 0)
asmlin("STA", prmtra); //Store First Parameter
if (prmcnt > 1)
asmlin("STY", prmtry); //Store Second Parameter
if (prmcnt > 2)
asmlin("STX", prmtrx); //Store Third Parameter
endlbl[0] = 0; //Create Dummy End Label
pshlbl(LTFUNC, endlbl); //and Push onto Stack
bgnblk('{'); //Start Program Block
}
/* (Check For and) Parse Variable Declaration*/
void pdecl(int m, int t)
{
DEBUG("Processing variable declarations(s) of type %d\n", t);
while(TRUE) {
getwrd();
if (match('(')) {
if (m != MTNONE) {
ERROR("Illegal Modifier %d in Function Definion", m, EXIT_FAILURE);
}
addfnc(); //Add Function Call
return;
}
addvar(m, t);
if (!look(','))
break;
}
expect(';');
DEBUG("Variable Declaration Completed\n", 0);
SCMNT(""); //Clear Assembler Comment
}
/* Check for and Parse Type Keyword */
int ptype(int m)
{
int result = TRUE;
if (wordis("VOID"))
pdecl(m, VTVOID); //Parse 'void' declaration
else if (wordis("CHAR"))
pdecl(m, VTCHAR); //Parse 'char' declaration
else
result = FALSE;
//DEBUG("Returning %d from function ptype\n", result)'
return result;
}
/* Check for and Parse Modifier */
int pmodfr()
{
DEBUG("Parsing modifier '%s'\n", word);
int result = TRUE;
if (wordis("ALIGNED")) {
getwrd();
ptype(MTALGN);
}
else if (wordis("ZEROPAGE")) {
getwrd();
ptype(MTZP);
}
else
result = FALSE;
return result;
}
/* Write Variable Table */
void vartbl()
{
int i, j;
DEBUG("Writing Variable Table", 0);
fprintf(logfil, "\n%-31s %s %s %s\n", "Variable", "Type", "Size", "Data");
dlen = 0;
for (i=0; i<varcnt; i++) {
fprintf(logfil, "%-31s %4d %4s %1d-%d\n", varnam[i], vartyp[i], varsiz[i], dattyp[i], datlen[i]);
strcpy(lblasm, varnam[i]);
DEBUG("Set Label to '%s'\n", lblasm);
if (strcmp(varsiz[i], "*") == 0)
continue;
if (varmod[i] == MTALGN) {
DEBUG("Alligning variable '%s'\n", varnam[i]);
asmlin(ALNOP, "256");
}
if (datlen[i]) {
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, "$%hhX", datvar[dlen++]);
strcat(value, word);
}
if (dattyp[i] == DTSTR) strcat(value, ",$00");
DEBUG("Allocating Data for Variable '%s'\n", varnam[i]);
asmlin(BYTEOP, value);
}
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");
}
}
vrwrtn = TRUE;
}
/*************************************
* 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 "label.h"
#include "vars.h"
/* Lookup variable name in variable table *
* Sets: varidx = index into varnam array *
* varcnt if not found *
* Returns: TRUE if found, otherwise FALSE */
int fndvar(char *name)
{
DEBUG("Looking up variable '%s'\n", word);
for (varidx=0; varidx<varcnt; varidx++) {
if (strcmp(varnam[varidx], name) == 0)
return TRUE;
}
return FALSE;
}
/* Check for variable *
* Generates error if variable is undefined *
* Args: alwreg - allow register name *
* name - variable name */
void chksym(int alwreg, char *name)
{
if (strlen(name) == 1 && strchr("AXY", name[0])) {
if (alwreg) return;
else ERROR("Illegal reference to register %s\n", name, EXIT_FAILURE);
}
if (!fndvar(name))
ERROR("Undeclared variable '%s' encountered\n", name, EXIT_FAILURE);
}
/* Parse next word as variable or function name *
* Args: alwreg - Allow Register Names *
* Sets: value - Identifier Name *
* valtyp - Identifier Type */
void prsvar(int alwreg)
{
getwrd();
valtyp = gettyp();
if (valtyp != FUNCTION) chksym(alwreg, word);
strcpy(value, word);
DEBUG("Parsed variable '%s'\n", value);
ACMNT(word);
}
/* Require and Parse Variable Name *
* Parameters: alwary - Allow Array Reference *
* Sets: vrname - operand for LDA/STA/LDY/STY */
void reqvar(int alwary)
{
prsvar(FALSE);
if (!alwary)
if (valtyp != VARIABLE)
expctd("Variable");
}
/* Parse Data Array */
void prsdta()
{
dtype = DTARRY;
expect('{');
dlen = 0;
while (TRUE) {
prscon();
dattmp[dlen++] = cnstnt;
if (!look(','))
break;
}
expect('}');
}
/* Parse Data String */
void prsdts()
{
dtype = DTSTR;
getstr();
strcpy(value, word);
DEBUG("Parsed Data String '%s'\n", value);
}
/* Store variable data *
* Uses: value - Data to store *
* Sets: datvar[] - Variable Data *
* datlen[] - Data Length */
void setdat()
{
int i;
if (dtype == DTBYTE) {
DEBUG("Setting variable data to '%d'\n", cnstnt);
dlen = 1;
datvar[dsize++] = cnstnt;
}
else if (dtype == DTARRY) {
DEBUG("Setting variable data to array of length %d\n", dlen);
for (i=0; i<dlen; i++)
datvar[dsize++] = dattmp[i];
}
else {
DEBUG("Setting variable data to '%s'\n", value);
dlen = strlen(value);
for (i=0; i<dlen; i++)
datvar[dsize++] = value[i];
}
datlen[varcnt] = dlen;
dattyp[varcnt] = dtype;
DEBUG("Total data alllocated: %d bytes\n", dsize);
}
/* Parse and store variable data */
void prsdat()
{
DEBUG("Checking for variable data\n", 0);
if (!look('=')) {
datlen[varcnt] = 0;
return;
}
skpspc();
if (iscpre()) {
dtype = DTBYTE;
prscon(); //Parse Data Constant
}
else if (match('"'))
prsdts(); //Parse Data String
else if (match('{'))
prsdta(); //Parse Data Array
else
expctd("numeric or string constant");
setdat(); //Store Data Value
}
/* Add Variable to Variable table *
* Uses: word - variable name *
* value - variable size */
void setvar(int m, int t)
{
DEBUG("Added variable '%s' ", word);
strncpy(varnam[varcnt], vrname, VARLEN);
varmod[varcnt] = m;
vartyp[varcnt] = t;
strncpy(varsiz[varcnt], value, 3);
DETAIL("at index %d\n", varcnt);
}
/* Parse and Compile Variable Declaration *
* Uses: word - variable name */
void addvar(int m, int t)
{
strcpy(vrname, word); //Save Variable Name
if (fndvar(vrname))
ERROR("Duplicate declaration of variable '%s\n", word,EXIT_FAILURE);
if (t == VTVOID)
ERROR("Illegal Variable Type\n", 0, EXIT_FAILURE);
if (m == MTZP) {
setlbl(vrname);
sprintf(word, "$%hhX", zpaddr++);
asmlin(EQUOP, word);
strcpy(value, "*"); //Set Variable Type to Zero Page
}
else {
DEBUG("Checking for array definition\n", 0);
value[0] = 0;
if (match('[')) {
skpchr();
if (alcvar) {
DEBUG("Parsing array size\n", 0);
sprintf(value, "%d", prsnum(0xFF) + 1);
}
expect(']');
}
if (!alcvar) strcpy(value, "*");
setvar(m, t); //Add to Variable Table
}
if (m != MTZP)
prsdat(); //Parse Variable Data
varcnt++; //Increment Variable Counter
}
/* Write Variable Table */
void vartbl()
{
int i, j;
DEBUG("Writing Variable Table", 0);
fprintf(logfil, "\n%-31s %s %s %s\n", "Variable", "Type", "Size", "Data");
dlen = 0;
for (i=0; i<varcnt; i++) {
fprintf(logfil, "%-31s %4d %4s %1d-%d\n", varnam[i], vartyp[i], varsiz[i], dattyp[i], datlen[i]);
strcpy(lblasm, varnam[i]);
DEBUG("Set Label to '%s'\n", lblasm);
if (strcmp(varsiz[i], "*") == 0)
continue;
if (varmod[i] == MTALGN) {
DEBUG("Alligning variable '%s'\n", varnam[i]);
asmlin(ALNOP, "256");
}
if (datlen[i]) {
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, "$%hhX", datvar[dlen++]);
strcat(value, word);
}
if (dattyp[i] == DTSTR) strcat(value, ",$00");
DEBUG("Allocating Data for Variable '%s'\n", varnam[i]);
asmlin(BYTEOP, value);
}
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");
}
}
vrwrtn = TRUE;
}

106
vars.h
View File

@ -1,50 +1,56 @@
/*************************************
* C02 Variable Management Routines *
*************************************/
/* Variable Table */
char varnam[MAXVAR+1][VARLEN+1]; //Variable Name Table
char varmod[MAXVAR+1]; //Variable Modifier
char vartyp[MAXVAR+1]; //Variable Type
char varsiz[MAXVAR+1][4]; //Variable Array
int varcnt; //Number of Variables in Table
int varidx; //Index into Variable Tables
char vrname[MAXVAR+1]; //Variable Name
int vrwrtn; //Variables Written Flag
/*
int varidx; //Index into Variable Table
int vrtype; //Variable Type
*/
enum vtypes {VTVOID, VTCHAR}; //Variable Types
char datvar[DATASPC+1]; //Variable Data Storage
char datlen[MAXVAR+1]; //Variable Data Length
char dattyp[MAXVAR+1]; //Variable Data Type
char dattmp[256]; //Variable Temporary Data
int dtype; //Data Type
int dlen; //Length of Variable Data
int dsize; //Total Data Length
enum dtypes {DTBYTE, DTSTR, DTARRY}; //Variable Data Types
enum mtypes {MTNONE, MTALGN, MTZP}; //Variable Modifier Types
int symdef(char *name); //Is Variable defined (TRUE or FALSE)
int zpaddr; //Current Zero-Page Address
char fncnam[VARLEN+1]; //Function Name
char prmtra[VARLEN+1]; //Function Parameter A
char prmtrx[VARLEN+1]; //Function Parameter X
char prmtry[VARLEN+1]; //Function Parameter Y
int prmcnt; //Number of Parameters
void chksym(int alwreg, char *name); //Error if Variable not defined
void prsdts(); //Parse Data String
void setdat(); //Set Variable Data
void setvar(int m, int t); //Set Variable Name and Size
void pdecl(int m, int t); //Parse Variable Declaration
void vartbl(); //Create Variable Table
/*************************************
* C02 Variable Management Routines *
*************************************/
/* Variable Table */
char varnam[MAXVAR+1][VARLEN+1]; //Variable Name Table
char varmod[MAXVAR+1]; //Variable Modifier
char vartyp[MAXVAR+1]; //Variable Type
char varsiz[MAXVAR+1][4]; //Variable Array
int varcnt; //Number of Variables in Table
int varidx; //Index into Variable Tables
char vrname[MAXVAR+1]; //Variable Name
int vrwrtn; //Variables Written Flag
/*
int varidx; //Index into Variable Table
int vrtype; //Variable Type
*/
enum vtypes {VTVOID, VTCHAR}; //Variable Types
char datvar[DATASPC+1]; //Variable Data Storage
char datlen[MAXVAR+1]; //Variable Data Length
char dattyp[MAXVAR+1]; //Variable Data Type
char dattmp[256]; //Variable Temporary Data
int dtype; //Data Type
int dlen; //Length of Variable Data
int dsize; //Total Data Length
enum dtypes {DTBYTE, DTSTR, DTARRY}; //Variable Data Types
enum mtypes {MTNONE, MTALGN, MTZP}; //Variable Modifier Types
int symdef(char *name); //Is Variable defined (TRUE or FALSE)
int zpaddr; //Current Zero-Page Address
char fncnam[VARLEN+1]; //Function Name
char prmtra[VARLEN+1]; //Function Parameter A
char prmtrx[VARLEN+1]; //Function Parameter X
char prmtry[VARLEN+1]; //Function Parameter Y
int prmcnt; //Number of Parameters
void addvar(int m, int t); //Parse and Compile Variable Declaration
void chksym(int alwreg, char *name); //Error if Variable not defined
int fndvar(char *name); //Lookup variable name in variable table
void prsdts(); //Parse Data String
void setdat(); //Set Variable Data
void setvar(int m, int t); //Set Variable Name and Size
void pdecl(int m, int t); //Parse Variable Declaration
void prsdat(); //Parse and store variable data
void prsdta(); //Parse Data Array
void prsdts(); //Parse Data String
void prsvar(int alwreg); //Parse Variable
void reqvar(int alwary); //Require and Parse Variable Name
void setdat(); //Store variable data
void setvar(int m, int t); //Add Variable to Variable table
void vartbl(); //Create Variable Table