mirror of
https://github.com/RevCurtisP/C02.git
synced 2024-11-22 01:31:33 +00:00
Added CPU Type and Numeric Literal String Escapes
This commit is contained in:
parent
0bd11dbaed
commit
2b5f96c7d0
411
src/c02.c
411
src/c02.c
@ -1,203 +1,208 @@
|
||||
/**************************************************************
|
||||
* C02 Compiler - (C) 2013 Curtis F Kaylor *
|
||||
* *
|
||||
* C02 is a simpified C-like language designed for the 6502 *
|
||||
* *
|
||||
* This Compiler generates crasm compatible assembly language *
|
||||
* *
|
||||
**************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "common.h" //Common Code used by all Modules
|
||||
#include "files.h" //Open and Close Files
|
||||
#include "asm.h" //Write out Assembly Language
|
||||
#include "parse.h" //General Code Parsing
|
||||
#include "vars.h" //Variable Parsing, Lookup, and Allocation
|
||||
#include "expr.h" //Expression Parsing
|
||||
#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 */
|
||||
void init(void) {
|
||||
initim(); //Initialize Elapsed Time
|
||||
DEBUG("Initializing Compiler Variables\n",0)
|
||||
concnt = 0; //Number of Constants Defined
|
||||
varcnt = 0; //Number of Variables in Table
|
||||
lblcnt = 0; //Number of Labels in stack
|
||||
padcnt = 0; //Number of Padding Bytes at End
|
||||
curcol = 0; //Current Column in Source Code
|
||||
curlin = 0; //Current Line in Source Code
|
||||
alcvar = TRUE; //Allocate Variables Flag
|
||||
inblck = FALSE; //Multiline Block Flag
|
||||
infunc = FALSE; //Inside Function Definition
|
||||
xstmnt[0] = 0; //Expected Statement
|
||||
nxtwrd[0] = 0; //Next Word (from DEFINE lookup)
|
||||
nxtptr = 0; //Pointer to next character in nxtwrd
|
||||
vrwrtn = FALSE; //Variables Written Flag
|
||||
rambas = 0; //RAM Base Address
|
||||
wrtbas = 0; //Write Base Address
|
||||
zpaddr = 0; //Current Zero-Page Address
|
||||
invasc = FALSE; //Invert ASCII Flag
|
||||
mskasc = FALSE; //Set High Bit Flag
|
||||
fcase = FALSE; //First Case Statement Flag
|
||||
wrtofs[0] = 0; //Write Offset
|
||||
xsnvar[0] = 0; //Assigned X Variable Name
|
||||
ysnvar[0] = 0; //Assigned Y Variable Name
|
||||
subcnt = 0; //Include Subdirectories
|
||||
strcpy(incdir, "../include/");
|
||||
}
|
||||
|
||||
/* Reads and parses the next Word in Source File */
|
||||
void pword(void) {
|
||||
lsrtrn = FALSE; //Clear RETURN flag
|
||||
getwrd();
|
||||
DEBUG("Parsing Word '%s'\n", word)
|
||||
if (xstmnt[0]) {
|
||||
if (wordis(xstmnt)) xstmnt[0] = 0; //Clear xstmnt
|
||||
else ERROR("Expected '%s' statement\n", xstmnt, EXIT_FAILURE)
|
||||
}
|
||||
if (!pmodfr() && !ptype(MTNONE)) pstmnt(); //Parse Statement
|
||||
}
|
||||
|
||||
/* Process a directive */
|
||||
void pdrctv(void) {
|
||||
skpchr(); //skip '#'
|
||||
CCMNT('#');
|
||||
getwrd(); //read directive into word
|
||||
DEBUG("Processing directive '%s'\n", word)
|
||||
if (wordis("DEFINE")) pdefin(); //Parse Define
|
||||
else if (wordis("INCLUDE")) pincfl(); //Parse Include File
|
||||
else if (wordis("ERROR")) ERROR("Error \n", 0, EXIT_FAILURE)
|
||||
else if (wordis("PRAGMA")) pprgma();
|
||||
else ERROR("Illegal directive %s encountered\n", word, EXIT_FAILURE)
|
||||
}
|
||||
|
||||
void prolog(void) {
|
||||
DEBUG("Writing Assembly Prolog\n", 0)
|
||||
asmlin(CPUOP,CPUARG);
|
||||
setcmt("Program ");
|
||||
addcmt(srcnam);
|
||||
cmtlin();
|
||||
}
|
||||
|
||||
void epilog(void) {
|
||||
if (!vrwrtn) wvrtbl(); //Write Variable Table
|
||||
if (padcnt) {
|
||||
SCMNT("PADDING BYTES")
|
||||
sprintf(word, "$%hhX", padcnt);
|
||||
asmlin(STROP, word);
|
||||
}
|
||||
}
|
||||
|
||||
/* Compile Source Code*/
|
||||
void compile(void) {
|
||||
DEBUG("Starting Compilation\n", 0)
|
||||
prolog();
|
||||
phdrfl(); //Process Header File specified on Command Line
|
||||
skpchr();
|
||||
DEBUG("Parsing Code\n", 0)
|
||||
while (TRUE) {
|
||||
skpspc();
|
||||
if (match(EOF)) break; //Stop Parsing (End of File)
|
||||
else if (match('}')) endblk(TRUE); //End Multi-Line Program Block
|
||||
else if (match('#')) pdrctv(); //Parse Directive
|
||||
else if (match('/')) skpcmt(TRUE); //Skip Comment
|
||||
else if (isalph()) pword(); //Parse Word
|
||||
else ERROR("Unexpected character '%c'\n", nxtchr, EXIT_FAILURE)
|
||||
}
|
||||
epilog();
|
||||
}
|
||||
|
||||
/* Display "Usage" text and exit*/
|
||||
void usage(void) {
|
||||
printf("Usage: c02 sourcefile.c02\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Parse Command Line Option */
|
||||
int popt(int arg, int argc, char *argv[]) {
|
||||
char argstr[32]; //Argument String
|
||||
char opt; //Option
|
||||
char optarg[32]; //Option Argument
|
||||
strncpy (argstr, argv[arg], 31);
|
||||
if (strlen(argstr) != 2) ERROR("malformed option %s\n", argstr, EXIT_FAILURE)
|
||||
opt = toupper(argstr[1]);
|
||||
if (strchr("HS", opt)) {
|
||||
if (++arg >= argc) ERROR("Option -%c requires an argument\n", opt, EXIT_FAILURE)
|
||||
strncpy(optarg, argv[arg], 31);
|
||||
}
|
||||
DEBUG("Processing Command Line Option -%c\n", argstr[1])
|
||||
switch (opt) {
|
||||
case 'H':
|
||||
strcpy(hdrnam, optarg);
|
||||
DEBUG("Header Name set to '%s'\n", hdrnam)
|
||||
break;
|
||||
case 'S':
|
||||
strcpy(subdir[subcnt], optarg);
|
||||
DEBUG("subdir[%d] ", subcnt)
|
||||
DEBUG("set to '%s'\n", subdir[subcnt])
|
||||
subcnt++;
|
||||
break;
|
||||
default:
|
||||
ERROR("Illegal option -%c\n", opt, EXIT_FAILURE)
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
/* Parse Command Line Arguments *
|
||||
* Sets: srcnam - Source File Name (from first arg) *
|
||||
* outnam - Output File Name (from optional second arg) */
|
||||
void pargs(int argc, char *argv[]) {
|
||||
int arg;
|
||||
srcnam[0] = 0;
|
||||
outnam[0] = 0;
|
||||
DEBUG("Parsing %d arguments\n", argc)
|
||||
if (argc == 0) usage(); //at least one argument is required
|
||||
for (arg = 1; arg<argc; arg++) {
|
||||
DEBUG("Parsing argument %d\n", arg);
|
||||
if (argv[arg][0] == '-') arg = popt(arg, argc, argv); //Process Command Line Option
|
||||
else if (srcnam[0] == 0) strcpy(srcnam, argv[arg]); //set Source File Name to first arg
|
||||
else if (outnam[0] == 0) strcpy(outnam, argv[arg]); //set Out File Name to second arg
|
||||
else ERROR("Unexpected argument '%s'\n", argv[arg], EXIT_FAILURE)
|
||||
}
|
||||
if (srcnam[0]) DEBUG("srcnam set to '%s'\n", srcnam)
|
||||
else ERROR("Error: Source file not specified\n", 0, EXIT_FAILURE)
|
||||
if (outnam[0]) DEBUG("outnam set to '%s'\n", outnam)
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
debug = TRUE; //Output Debug Info
|
||||
gencmt = TRUE; //Generate Assembly Language Comments
|
||||
|
||||
printf("C02 Compiler (C) 2012 Curtis F Kaylor\n" );
|
||||
|
||||
init(); //Initialize Global Variables
|
||||
|
||||
pargs(argc, argv); //Parse Command Line Arguments
|
||||
|
||||
opnsrc(); //Open Source File
|
||||
opnout(); //Open Output File
|
||||
opnlog(); //Open Log File
|
||||
|
||||
setsrc(); //Set Input to Source File
|
||||
|
||||
compile();
|
||||
|
||||
logstc();
|
||||
logcon();
|
||||
loglab();
|
||||
|
||||
clssrc(); //Close Source File
|
||||
clsout(); //Close Output File
|
||||
clslog(); //Close Log File
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
* C02 Compiler - (C) 2013 Curtis F Kaylor *
|
||||
* *
|
||||
* C02 is a simpified C-like language designed for the 6502 *
|
||||
* *
|
||||
* This Compiler generates crasm compatible assembly language *
|
||||
* *
|
||||
**************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "common.h" //Common Code used by all Modules
|
||||
#include "files.h" //Open and Close Files
|
||||
#include "asm.h" //Write out Assembly Language
|
||||
#include "parse.h" //General Code Parsing
|
||||
#include "vars.h" //Variable Parsing, Lookup, and Allocation
|
||||
#include "expr.h" //Expression Parsing
|
||||
#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 */
|
||||
void init(void) {
|
||||
initim(); //Initialize Elapsed Time
|
||||
DEBUG("Initializing Compiler Variables\n",0)
|
||||
concnt = 0; //Number of Constants Defined
|
||||
varcnt = 0; //Number of Variables in Table
|
||||
lblcnt = 0; //Number of Labels in stack
|
||||
padcnt = 0; //Number of Padding Bytes at End
|
||||
curcol = 0; //Current Column in Source Code
|
||||
curlin = 0; //Current Line in Source Code
|
||||
alcvar = TRUE; //Allocate Variables Flag
|
||||
inblck = FALSE; //Multiline Block Flag
|
||||
infunc = FALSE; //Inside Function Definition
|
||||
xstmnt[0] = 0; //Expected Statement
|
||||
nxtwrd[0] = 0; //Next Word (from DEFINE lookup)
|
||||
nxtptr = 0; //Pointer to next character in nxtwrd
|
||||
vrwrtn = FALSE; //Variables Written Flag
|
||||
rambas = 0; //RAM Base Address
|
||||
wrtbas = 0; //Write Base Address
|
||||
zpaddr = 0; //Current Zero-Page Address
|
||||
invasc = FALSE; //Invert ASCII Flag
|
||||
mskasc = FALSE; //Set High Bit Flag
|
||||
fcase = FALSE; //First Case Statement Flag
|
||||
wrtofs[0] = 0; //Write Offset
|
||||
xsnvar[0] = 0; //Assigned X Variable Name
|
||||
ysnvar[0] = 0; //Assigned Y Variable Name
|
||||
subcnt = 0; //Include Subdirectories
|
||||
strcpy(cputyp, CPUARG); //Set CPU Type to Default Value
|
||||
strcpy(incdir, "../include/");
|
||||
}
|
||||
|
||||
/* Reads and parses the next Word in Source File */
|
||||
void pword(void) {
|
||||
lsrtrn = FALSE; //Clear RETURN flag
|
||||
getwrd();
|
||||
DEBUG("Parsing Word '%s'\n", word)
|
||||
if (xstmnt[0]) {
|
||||
if (wordis(xstmnt)) xstmnt[0] = 0; //Clear xstmnt
|
||||
else ERROR("Expected '%s' statement\n", xstmnt, EXIT_FAILURE)
|
||||
}
|
||||
if (!pmodfr() && !ptype(MTNONE)) pstmnt(); //Parse Statement
|
||||
}
|
||||
|
||||
/* Process a directive */
|
||||
void pdrctv(void) {
|
||||
skpchr(); //skip '#'
|
||||
CCMNT('#');
|
||||
getwrd(); //read directive into word
|
||||
DEBUG("Processing directive '%s'\n", word)
|
||||
if (wordis("DEFINE")) pdefin(); //Parse Define
|
||||
else if (wordis("INCLUDE")) pincfl(); //Parse Include File
|
||||
else if (wordis("ERROR")) ERROR("Error \n", 0, EXIT_FAILURE)
|
||||
else if (wordis("PRAGMA")) pprgma();
|
||||
else ERROR("Illegal directive %s encountered\n", word, EXIT_FAILURE)
|
||||
}
|
||||
|
||||
void prolog(void) {
|
||||
DEBUG("Writing Assembly Prolog\n", 0)
|
||||
asmlin(CPUOP,cputyp);
|
||||
setcmt("Program ");
|
||||
addcmt(srcnam);
|
||||
cmtlin();
|
||||
}
|
||||
|
||||
void epilog(void) {
|
||||
if (!vrwrtn) wvrtbl(); //Write Variable Table
|
||||
if (padcnt) {
|
||||
SCMNT("PADDING BYTES")
|
||||
sprintf(word, "$%hhX", padcnt);
|
||||
asmlin(STROP, word);
|
||||
}
|
||||
}
|
||||
|
||||
/* Compile Source Code*/
|
||||
void compile(void) {
|
||||
DEBUG("Starting Compilation\n", 0)
|
||||
prolog();
|
||||
phdrfl(); //Process Header File specified on Command Line
|
||||
skpchr();
|
||||
DEBUG("Parsing Code\n", 0)
|
||||
while (TRUE) {
|
||||
skpspc();
|
||||
if (match(EOF)) break; //Stop Parsing (End of File)
|
||||
else if (match('}')) endblk(TRUE); //End Multi-Line Program Block
|
||||
else if (match('#')) pdrctv(); //Parse Directive
|
||||
else if (match('/')) skpcmt(TRUE); //Skip Comment
|
||||
else if (isalph()) pword(); //Parse Word
|
||||
else ERROR("Unexpected character '%c'\n", nxtchr, EXIT_FAILURE)
|
||||
}
|
||||
epilog();
|
||||
}
|
||||
|
||||
/* Display "Usage" text and exit*/
|
||||
void usage(void) {
|
||||
printf("Usage: c02 sourcefile.c02\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Parse Command Line Option */
|
||||
int popt(int arg, int argc, char *argv[]) {
|
||||
char argstr[32]; //Argument String
|
||||
char opt; //Option
|
||||
char optarg[32]; //Option Argument
|
||||
strncpy (argstr, argv[arg], 31);
|
||||
if (strlen(argstr) != 2) ERROR("malformed option %s\n", argstr, EXIT_FAILURE)
|
||||
opt = toupper(argstr[1]);
|
||||
if (strchr("CHS", opt)) {
|
||||
if (++arg >= argc) ERROR("Option -%c requires an argument\n", opt, EXIT_FAILURE)
|
||||
strncpy(optarg, argv[arg], 31);
|
||||
}
|
||||
DEBUG("Processing Command Line Option -%c\n", argstr[1])
|
||||
switch (opt) {
|
||||
case 'C':
|
||||
strcpy(cputyp, optarg);
|
||||
DEBUG("CPU Type set to '%s'\n", cputyp)
|
||||
break;
|
||||
case 'H':
|
||||
strcpy(hdrnam, optarg);
|
||||
DEBUG("Header Name set to '%s'\n", hdrnam)
|
||||
break;
|
||||
case 'S':
|
||||
strcpy(subdir[subcnt], optarg);
|
||||
DEBUG("subdir[%d] ", subcnt)
|
||||
DEBUG("set to '%s'\n", subdir[subcnt])
|
||||
subcnt++;
|
||||
break;
|
||||
default:
|
||||
ERROR("Illegal option -%c\n", opt, EXIT_FAILURE)
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
/* Parse Command Line Arguments *
|
||||
* Sets: srcnam - Source File Name (from first arg) *
|
||||
* outnam - Output File Name (from optional second arg) */
|
||||
void pargs(int argc, char *argv[]) {
|
||||
int arg;
|
||||
srcnam[0] = 0;
|
||||
outnam[0] = 0;
|
||||
DEBUG("Parsing %d arguments\n", argc)
|
||||
if (argc == 0) usage(); //at least one argument is required
|
||||
for (arg = 1; arg<argc; arg++) {
|
||||
DEBUG("Parsing argument %d\n", arg);
|
||||
if (argv[arg][0] == '-') arg = popt(arg, argc, argv); //Process Command Line Option
|
||||
else if (srcnam[0] == 0) strcpy(srcnam, argv[arg]); //set Source File Name to first arg
|
||||
else if (outnam[0] == 0) strcpy(outnam, argv[arg]); //set Out File Name to second arg
|
||||
else ERROR("Unexpected argument '%s'\n", argv[arg], EXIT_FAILURE)
|
||||
}
|
||||
if (srcnam[0]) DEBUG("srcnam set to '%s'\n", srcnam)
|
||||
else ERROR("Error: Source file not specified\n", 0, EXIT_FAILURE)
|
||||
if (outnam[0]) DEBUG("outnam set to '%s'\n", outnam)
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
debug = TRUE; //Output Debug Info
|
||||
gencmt = TRUE; //Generate Assembly Language Comments
|
||||
|
||||
printf("C02 Compiler (C) 2012 Curtis F Kaylor\n" );
|
||||
|
||||
init(); //Initialize Global Variables
|
||||
|
||||
pargs(argc, argv); //Parse Command Line Arguments
|
||||
|
||||
opnsrc(); //Open Source File
|
||||
opnout(); //Open Output File
|
||||
opnlog(); //Open Log File
|
||||
|
||||
setsrc(); //Set Input to Source File
|
||||
|
||||
compile();
|
||||
|
||||
logstc();
|
||||
logcon();
|
||||
loglab();
|
||||
|
||||
clssrc(); //Close Source File
|
||||
clsout(); //Close Output File
|
||||
clslog(); //Close Log File
|
||||
}
|
||||
|
||||
|
||||
|
191
src/common.h
191
src/common.h
@ -1,94 +1,97 @@
|
||||
/*************************************
|
||||
* C02 Common Definitions & Routines *
|
||||
*************************************/
|
||||
|
||||
#define FNAMLEN 255 //Maximum File Name Length
|
||||
#define LINELEN 255 //Maximum Input/Output Line Length
|
||||
#define CONLEN 6 //Maximum Constant Name Length
|
||||
#define MAXCON 255 //Maximum Number of Constants
|
||||
#define STCLEN 6 //Maximum Struct Name Length
|
||||
#define MAXSTC 32 //Maximum Number of Stuctures
|
||||
#define STMLEN 6 //Maximum Struct Member Name Length
|
||||
#define MAXSTM 255 //Maximum Number of Stucture Members
|
||||
#define VARLEN 6 //Maximum Variable Name Length
|
||||
#define MAXVAR 255 //Maximum Number of Variables
|
||||
#define MAXTRM 16 //Maximum Terms in Stack
|
||||
#define DATASPC 4096 //Space to Allocate for Variable Data
|
||||
#define SUBMAX 4 //Maximum Number of Sub Directories
|
||||
|
||||
#define LABLEN 6 //Maximum Program Label Length
|
||||
#define MAXLAB 255 //Maximum Number of Program Labels
|
||||
|
||||
#define LBLLEN 6 //Maximum Label Length
|
||||
#define LBLFMT "L_%04d" //Label Format
|
||||
#define LABSFX ":" //Label Suffix
|
||||
#define MAXLBL 15 //Maximum Number of Labels (Nesting Depth)
|
||||
#define LOCPFX "." //Local Variable Prefix
|
||||
|
||||
#define CPUOP "PROCESSOR" //Target CPU Pseudo-Operator
|
||||
#define CPUARG "6502" //Target CPU Operand
|
||||
#define ORGOP "ORG" //Origin Pseudo-Op
|
||||
#define EQUOP "EQU" //Equate Pseudo-Op
|
||||
#define BYTEOP "DC" //Define Byte Pseudo-Op
|
||||
#define STROP "DS" //Define String Pseudo-Op
|
||||
#define ALNOP "ALIGN" //Align Pseudo-Op
|
||||
#define USEGOP "SEG.U" //Uninitalized Segment Pseudo-Op
|
||||
#define LOCOP "SUBROUTINE" //Local Variable Boundary Pseudo-Op
|
||||
|
||||
#define ASMFMT "%-7s %-3s %-12s %s\n" //Assembly Language Line printf Format
|
||||
|
||||
/* Internal defines */
|
||||
#define TRUE -1
|
||||
#define FALSE 0
|
||||
|
||||
void initim(); //Initialize elapsed time counter
|
||||
void prtpos(); //Print current file name and position
|
||||
void prttim(); //Print elapsed time
|
||||
#define DEBUG(fmt, val) {if (debug) {prtpos(); prttim(); printf(fmt, val);}}
|
||||
#define DETAIL(fmt, val) {if (debug) printf(fmt, val);}
|
||||
#define ERROR(fmt, val, err) {fprintf(stderr, fmt, val);exterr(err);}
|
||||
|
||||
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
|
||||
|
||||
int bgntim; //Starting Time
|
||||
|
||||
int nxtchr; //Next Character of Source File to Process
|
||||
int nxtupc; //Next Character Converted to Uppercase
|
||||
int savchr; //Holds nxtchr when switching input files
|
||||
|
||||
int wrdlen; //Length of Parsed Word
|
||||
char word[LINELEN]; //Word parsed from source file
|
||||
char uword[LINELEN]; //Word converted to uppercase
|
||||
char cmtasm[LINELEN]; //Assembly Language Comment Text
|
||||
|
||||
char hdrnam[FNAMLEN]; //Header File Name
|
||||
char incdir[FNAMLEN]; //Include File Directory
|
||||
char inpnam[FNAMLEN]; //Input File Name
|
||||
char subdir[SUBMAX][FNAMLEN]; //Include File SubDirectory
|
||||
int subcnt; //Number of Include Directories
|
||||
int subidx; //Index into subdir[]
|
||||
|
||||
int alcvar; //Allocate Variables Flag
|
||||
int inblck; //Multiline Block Flag
|
||||
int infunc; //Inside Function Definition Flag
|
||||
int lsrtrn; //Last Statement was a Return Flag
|
||||
int fcase; //First Case Statement Flag
|
||||
|
||||
int padcnt; //Number of Padding Bytes at End of Program
|
||||
|
||||
void exterr(int errnum); //Print current file name & position and exit
|
||||
void expctd(char *expected); //Print Expected message and exit
|
||||
|
||||
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);}
|
||||
#define LCMNT(str) if (gencmt) {setcmt(str); cmtlin();}
|
||||
/*************************************
|
||||
* C02 Common Definitions & Routines *
|
||||
*************************************/
|
||||
|
||||
#define FNAMLEN 255 //Maximum File Name Length
|
||||
#define LINELEN 255 //Maximum Input/Output Line Length
|
||||
#define CONLEN 6 //Maximum Constant Name Length
|
||||
#define MAXCON 255 //Maximum Number of Constants
|
||||
#define STCLEN 6 //Maximum Struct Name Length
|
||||
#define MAXSTC 32 //Maximum Number of Stuctures
|
||||
#define STMLEN 6 //Maximum Struct Member Name Length
|
||||
#define MAXSTM 255 //Maximum Number of Stucture Members
|
||||
#define VARLEN 6 //Maximum Variable Name Length
|
||||
#define MAXVAR 255 //Maximum Number of Variables
|
||||
#define MAXTRM 16 //Maximum Terms in Stack
|
||||
#define DATASPC 4096 //Space to Allocate for Variable Data
|
||||
#define SUBMAX 4 //Maximum Number of Sub Directories
|
||||
|
||||
#define LABLEN 6 //Maximum Program Label Length
|
||||
#define MAXLAB 255 //Maximum Number of Program Labels
|
||||
|
||||
#define LBLLEN 6 //Maximum Label Length
|
||||
#define LBLFMT "L_%04d" //Label Format
|
||||
#define LABSFX ":" //Label Suffix
|
||||
#define MAXLBL 15 //Maximum Number of Labels (Nesting Depth)
|
||||
#define LOCPFX "." //Local Variable Prefix
|
||||
|
||||
#define CPUOP "PROCESSOR" //Target CPU Pseudo-Operator
|
||||
#define CPUARG "6502" //Target CPU Operand
|
||||
#define ORGOP "ORG" //Origin Pseudo-Op
|
||||
#define EQUOP "EQU" //Equate Pseudo-Op
|
||||
#define BYTEOP "DC" //Define Byte Pseudo-Op
|
||||
#define STROP "DS" //Define String Pseudo-Op
|
||||
#define ALNOP "ALIGN" //Align Pseudo-Op
|
||||
#define USEGOP "SEG.U" //Uninitalized Segment Pseudo-Op
|
||||
#define LOCOP "SUBROUTINE" //Local Variable Boundary Pseudo-Op
|
||||
|
||||
#define ASMFMT "%-7s %-3s %-12s %s\n" //Assembly Language Line printf Format
|
||||
|
||||
/* Internal defines */
|
||||
#define TRUE -1
|
||||
#define FALSE 0
|
||||
|
||||
void initim(); //Initialize elapsed time counter
|
||||
void prtpos(); //Print current file name and position
|
||||
void prttim(); //Print elapsed time
|
||||
#define DEBUG(fmt, val) {if (debug) {prtpos(); prttim(); printf(fmt, val);}}
|
||||
#define DETAIL(fmt, val) {if (debug) printf(fmt, val);}
|
||||
#define ERROR(fmt, val, err) {fprintf(stderr, fmt, val);exterr(err);}
|
||||
|
||||
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
|
||||
|
||||
int bgntim; //Starting Time
|
||||
|
||||
int nxtchr; //Next Character of Source File to Process
|
||||
int nxtupc; //Next Character Converted to Uppercase
|
||||
int savchr; //Holds nxtchr when switching input files
|
||||
|
||||
int wrdlen; //Length of Parsed Word
|
||||
char word[LINELEN]; //Word parsed from source file
|
||||
char uword[LINELEN]; //Word converted to uppercase
|
||||
int pstlen; //Length of Parsed String
|
||||
char pstrng[LINELEN]; //String parsed fron source file
|
||||
char cmtasm[LINELEN]; //Assembly Language Comment Text
|
||||
char cputyp[LINELEN]; //CPU Type
|
||||
|
||||
char hdrnam[FNAMLEN]; //Header File Name
|
||||
char incdir[FNAMLEN]; //Include File Directory
|
||||
char inpnam[FNAMLEN]; //Input File Name
|
||||
char subdir[SUBMAX][FNAMLEN]; //Include File SubDirectory
|
||||
int subcnt; //Number of Include Directories
|
||||
int subidx; //Index into subdir[]
|
||||
|
||||
int alcvar; //Allocate Variables Flag
|
||||
int inblck; //Multiline Block Flag
|
||||
int infunc; //Inside Function Definition Flag
|
||||
int lsrtrn; //Last Statement was a Return Flag
|
||||
int fcase; //First Case Statement Flag
|
||||
|
||||
int padcnt; //Number of Padding Bytes at End of Program
|
||||
|
||||
void exterr(int errnum); //Print current file name & position and exit
|
||||
void expctd(char *expected); //Print Expected message and exit
|
||||
|
||||
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);}
|
||||
#define LCMNT(str) if (gencmt) {setcmt(str); cmtlin();}
|
||||
|
23
src/parse.c
23
src/parse.c
@ -81,12 +81,15 @@ void skpspc(void) {
|
||||
* otherwise FALSE */
|
||||
int look(char c) {
|
||||
int found;
|
||||
DEBUG("Looking for '%c', ", c);
|
||||
skpspc();
|
||||
found = match(c);
|
||||
if (found) {
|
||||
skpchr();
|
||||
CCMNT(c);
|
||||
DETAIL("Found\n", 0);
|
||||
}
|
||||
else DETAIL("Not found\n", 0);
|
||||
return found;
|
||||
}
|
||||
|
||||
@ -136,6 +139,8 @@ void getwrd(void) {
|
||||
while (isanum()) word[wrdlen++] = toupper(getnxt());
|
||||
word[wrdlen] = 0;
|
||||
ACMNT(word);
|
||||
DEBUG("Read word '%s'", word)
|
||||
DETAIL("Delimited by '%c'\n", nxtchr)
|
||||
}
|
||||
|
||||
/* Escape Character */
|
||||
@ -154,31 +159,41 @@ char escape(char c) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Escape Numeric Literal */
|
||||
char escnum(void) {
|
||||
DEBUG("Escaping numeric literal\n", 0);
|
||||
char c = prsnum(0xff);
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Get String *
|
||||
* Sets: word = parsed string
|
||||
* wrdlen = length of string (including terminator) */
|
||||
void getstr(void) {
|
||||
char strdel;
|
||||
int escnxt = FALSE;
|
||||
wrdlen = 0;
|
||||
pstlen = 0;
|
||||
DEBUG("Parsing string\n", 0)
|
||||
strdel = getnxt(); //Get String Delimiter
|
||||
CCMNT(strdel);
|
||||
while(!match(strdel) || escnxt) {
|
||||
if (isnl()) ERROR("String Not Terminated", 0, EXIT_FAILURE)
|
||||
CCMNT(nxtchr);
|
||||
if (escnxt) {
|
||||
word[wrdlen++] = escape(getnxt());
|
||||
if (isnpre()) pstrng[pstlen++] = escnum();
|
||||
else pstrng[pstlen++] = escape(getnxt());
|
||||
escnxt = FALSE;
|
||||
}
|
||||
else {
|
||||
if (match('\\')) escnxt = TRUE;
|
||||
else word[wrdlen++] = prcchr(nxtchr);
|
||||
else pstrng[pstlen++] = prcchr(nxtchr);
|
||||
skpchr();
|
||||
}
|
||||
}
|
||||
skpchr(); //Skip End Delimiter
|
||||
CCMNT(strdel);
|
||||
word[wrdlen] = 0;
|
||||
pstrng[pstlen] = 0;
|
||||
strcpy(word,pstrng); wrdlen=pstlen;
|
||||
}
|
||||
|
||||
/* Read Binary number from input file *
|
||||
|
Loading…
Reference in New Issue
Block a user