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:
parent
44410ce0ce
commit
2edb6da3cb
2
Makefile
2
Makefile
|
@ -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
28
asm.c
|
@ -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
19
asm.h
|
@ -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
1
c02.c
|
@ -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 */
|
||||
|
|
19
common.c
19
common.c
|
@ -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;
|
||||
}
|
||||
|
|
32
common.h
32
common.h
|
@ -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
3
cond.c
|
@ -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
5
cond.h
|
@ -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
110
dclrtn.c
Normal 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
6
dclrtn.h
Normal 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
11
expr.c
|
@ -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
19
expr.h
|
@ -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
|
||||
|
||||
|
||||
|
|
9
files.h
9
files.h
|
@ -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
|
||||
|
|
16
include.c
16
include.c
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
17
include.h
17
include.h
|
@ -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
|
||||
|
|
7
label.c
7
label.c
|
@ -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
14
label.h
|
@ -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
945
parse.c
|
@ -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
133
parse.h
|
@ -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
69
stmnt.c
|
@ -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
18
stmnt.h
|
@ -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
541
vars.c
|
@ -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
106
vars.h
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user