mirror of
https://github.com/RevCurtisP/C02.git
synced 2024-11-23 23:33:03 +00:00
Updated x16/include .a02 files to use 65C02 opcodes
This commit is contained in:
parent
7f4e98826c
commit
cf56e15c01
BIN
src/.vscode/ipch/771b4d3d25e434c7/C02.ipch
vendored
Normal file
BIN
src/.vscode/ipch/771b4d3d25e434c7/C02.ipch
vendored
Normal file
Binary file not shown.
BIN
src/.vscode/ipch/771b4d3d25e434c7/mmap_address.bin
vendored
Normal file
BIN
src/.vscode/ipch/771b4d3d25e434c7/mmap_address.bin
vendored
Normal file
Binary file not shown.
19
src/.vscode/launch.json
vendored
Normal file
19
src/.vscode/launch.json
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "(Windows) Launch",
|
||||
"type": "cppvsdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/c02.exe",
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}",
|
||||
"environment": [],
|
||||
"externalConsole": true
|
||||
}
|
||||
]
|
||||
}
|
72
src/asm.c
72
src/asm.c
@ -1,36 +1,36 @@
|
||||
/*************************************
|
||||
* C02 Assembly Language Routines *
|
||||
*************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "files.h"
|
||||
#include "asm.h"
|
||||
|
||||
/* Process comment */
|
||||
void prccmt(void) {
|
||||
if (strlen(cmtasm)) { strcpy(asmcmt, ";"); strcat(asmcmt, cmtasm); }
|
||||
else asmcmt[0] = 0;
|
||||
setcmt("");
|
||||
}
|
||||
|
||||
/* output a single line of assembly code */
|
||||
void asmlin(char *opcode, char *oprnd) {
|
||||
if (strlen(lblasm)) strcat(lblasm, LABSFX);
|
||||
prccmt();
|
||||
fprintf(outfil, ASMFMT, lblasm, opcode, oprnd, asmcmt);
|
||||
if (debug) printf(ASMFMT, lblasm, opcode, oprnd, asmcmt);
|
||||
lblasm[0] = 0;
|
||||
}
|
||||
|
||||
/* output a single comment line */
|
||||
void cmtlin(void) {
|
||||
DEBUG("Writing Comment Line: %s\n", cmtasm)
|
||||
fprintf(outfil, "; %s\n", cmtasm);
|
||||
setcmt("");
|
||||
}
|
||||
/*************************************
|
||||
* C02 Assembly Language Routines *
|
||||
*************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "files.h"
|
||||
#include "asm.h"
|
||||
|
||||
/* Process comment */
|
||||
void prccmt(void) {
|
||||
if (strlen(cmtasm)) { strcpy(asmcmt, ";"); strcat(asmcmt, cmtasm); }
|
||||
else asmcmt[0] = 0;
|
||||
setcmt("");
|
||||
}
|
||||
|
||||
/* output a single line of assembly code */
|
||||
void asmlin(char *opcode, char *oprnd) {
|
||||
if (strlen(lblasm)) strcat(lblasm, LABSFX);
|
||||
prccmt();
|
||||
fprintf(outfil, ASMFMT, lblasm, opcode, oprnd, asmcmt);
|
||||
if (debug) printf(ASMFMT, lblasm, opcode, oprnd, asmcmt);
|
||||
lblasm[0] = 0;
|
||||
}
|
||||
|
||||
/* output a single comment line */
|
||||
void cmtlin(void) {
|
||||
DEBUG("Writing Comment Line: %s\n", cmtasm)
|
||||
fprintf(outfil, "; %s\n", cmtasm);
|
||||
setcmt("");
|
||||
}
|
||||
|
18
src/asm.h
18
src/asm.h
@ -1,9 +1,9 @@
|
||||
/*************************************
|
||||
* C02 Assembly Language Routines *
|
||||
*************************************/
|
||||
|
||||
char lblasm[LBLLEN+2]; //Label to emit on next asm line
|
||||
|
||||
void asmlin(char *opcode, char *oprnd); //Output a line of assembly code
|
||||
void cmtlin(); //Output a comment lines
|
||||
void prccmt(); //Process comment
|
||||
/*************************************
|
||||
* C02 Assembly Language Routines *
|
||||
*************************************/
|
||||
|
||||
char lblasm[LBLLEN+2]; //Label to emit on next asm line
|
||||
|
||||
void asmlin(char *opcode, char *oprnd); //Output a line of assembly code
|
||||
void cmtlin(); //Output a comment lines
|
||||
void prccmt(); //Process comment
|
||||
|
430
src/c02.c
430
src/c02.c
@ -1,203 +1,227 @@
|
||||
/**************************************************************
|
||||
* 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/");
|
||||
}
|
||||
|
||||
/* Parse Pointer Dereference Assignment */
|
||||
void ppntr(void) {
|
||||
lsrtrn = FALSE; //Clear RETURN flag
|
||||
if (xstmnt[0]) ERROR("Expected '%s' statement\n", xstmnt, EXIT_FAILURE)
|
||||
prcasp(';');
|
||||
}
|
||||
|
||||
/* 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 (match('*')) ppntr(); //Parse Pointer
|
||||
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)
|
||||
}
|
||||
|
||||
/* Validate CPU Type *
|
||||
* Uses: cputype *
|
||||
* Sets: cmos */
|
||||
void chkcpu(void) {
|
||||
if (strcmp(cputyp, "6502") == 0) cmos = FALSE;
|
||||
else if (strcmp(cputyp, "65C02") == 0) cmos = TRUE;
|
||||
else ERROR("Invalid CPU Type %s\n", cputyp, EXIT_FAILURE)
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
chkcpu(); //Validate CPU Type
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
|
120
src/common.c
120
src/common.c
@ -1,60 +1,60 @@
|
||||
/*************************************
|
||||
* C02 Common Definitions & Routines *
|
||||
*************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include "common.h"
|
||||
|
||||
struct timespec curtim; //Current Time
|
||||
|
||||
/* Error - Print Input File name & position and exit */
|
||||
void exterr(int errnum) {
|
||||
fprintf(stderr, "Line %d Column %d of File %s\n", curlin, curcol, inpnam);
|
||||
exit(errnum);
|
||||
}
|
||||
|
||||
/* Error - print "Expected" error message *
|
||||
and exit with general failure code *
|
||||
Args: expected - Description of what was expected */
|
||||
void expctd(char *expstr) {
|
||||
fprintf(stderr, "Expected %s, but found '%c'\n", expstr, nxtchr);
|
||||
exterr(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Print current position in file */
|
||||
void prtpos(void) { if (inpnam[0]) printf("(%s: %d,%d) ", inpnam, curlin, curcol); }
|
||||
|
||||
/* Initialize elapsed time counter */
|
||||
void initim(void) {
|
||||
timespec_get (&curtim, TIME_UTC);
|
||||
bgntim = curtim.tv_sec;
|
||||
}
|
||||
|
||||
/* Print elapsed time */
|
||||
void prttim(void) {
|
||||
timespec_get (&curtim, TIME_UTC);
|
||||
printf("[%d", curtim.tv_sec - bgntim);
|
||||
printf(".%06d]",curtim.tv_nsec/1000);
|
||||
}
|
||||
|
||||
/* Set comment to string */
|
||||
void setcmt(char *s) { strcpy(cmtasm, s); }
|
||||
|
||||
/* Append string to comment */
|
||||
void addcmt(char *s) {
|
||||
if (strlen(cmtasm)+strlen(s)<73) strcat(cmtasm, s);
|
||||
}
|
||||
|
||||
/* Append character to comment */
|
||||
void chrcmt(char c) {
|
||||
if (strlen(cmtasm)>72) return;
|
||||
if (cmtasm[0] == 0 && c == ' ') return;
|
||||
int i = strlen(cmtasm);
|
||||
cmtasm[i++] = c;
|
||||
cmtasm[i] = 0;
|
||||
}
|
||||
/*************************************
|
||||
* C02 Common Definitions & Routines *
|
||||
*************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include "common.h"
|
||||
|
||||
struct timespec curtim; //Current Time
|
||||
|
||||
/* Error - Print Input File name & position and exit */
|
||||
void exterr(int errnum) {
|
||||
fprintf(stderr, "Line %d Column %d of File %s\n", curlin, curcol, inpnam);
|
||||
exit(errnum);
|
||||
}
|
||||
|
||||
/* Error - print "Expected" error message *
|
||||
and exit with general failure code *
|
||||
Args: expected - Description of what was expected */
|
||||
void expctd(char *expstr) {
|
||||
fprintf(stderr, "Expected %s, but found '%c'\n", expstr, nxtchr);
|
||||
exterr(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Print current position in file */
|
||||
void prtpos(void) { if (inpnam[0]) printf("(%s: %d,%d) ", inpnam, curlin, curcol); }
|
||||
|
||||
/* Initialize elapsed time counter */
|
||||
void initim(void) {
|
||||
timespec_get (&curtim, TIME_UTC);
|
||||
bgntim = curtim.tv_sec;
|
||||
}
|
||||
|
||||
/* Print elapsed time */
|
||||
void prttim(void) {
|
||||
timespec_get (&curtim, TIME_UTC);
|
||||
printf("[%d", curtim.tv_sec - bgntim);
|
||||
printf(".%06d]",curtim.tv_nsec/1000);
|
||||
}
|
||||
|
||||
/* Set comment to string */
|
||||
void setcmt(char *s) { strcpy(cmtasm, s); }
|
||||
|
||||
/* Append string to comment */
|
||||
void addcmt(char *s) {
|
||||
if (strlen(cmtasm)+strlen(s)<73) strcat(cmtasm, s);
|
||||
}
|
||||
|
||||
/* Append character to comment */
|
||||
void chrcmt(char c) {
|
||||
if (strlen(cmtasm)>72) return;
|
||||
if (cmtasm[0] == 0 && c == ' ') return;
|
||||
int i = strlen(cmtasm);
|
||||
cmtasm[i++] = c;
|
||||
cmtasm[i] = 0;
|
||||
}
|
||||
|
192
src/common.h
192
src/common.h
@ -1,94 +1,98 @@
|
||||
/*************************************
|
||||
* 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 "BYTE" //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 cmos; //Flag: Use 65C02 Instruction Set
|
||||
|
||||
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();}
|
||||
|
276
src/cond.c
276
src/cond.c
@ -1,138 +1,138 @@
|
||||
/************************************
|
||||
* C02 Conditional Parsing Routines *
|
||||
************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "common.h"
|
||||
#include "asm.h"
|
||||
#include "parse.h"
|
||||
#include "vars.h"
|
||||
#include "expr.h"
|
||||
#include "label.h"
|
||||
#include "cond.h"
|
||||
|
||||
int cmprtr; //Encoded Comparison Operator
|
||||
int cmpenc; //Encoded Comparator Character
|
||||
|
||||
/* Encode Comparison Operator Character *
|
||||
* Args: Comparison Operator Character *
|
||||
* Returns: Comparison Operator Bit Mask */
|
||||
int enccmp(char c) {
|
||||
int e;
|
||||
DEBUG("Encoding Comparison Character '%c'", c)
|
||||
switch(c) {
|
||||
case '=': e = 1; break;
|
||||
case '<': e = 2; break;
|
||||
case '>': e = 4; break;
|
||||
default: e = 0;
|
||||
}
|
||||
if (e) { CCMNT(c); skpchr(); }
|
||||
DETAIL(", encoded as %d\n", e);
|
||||
return e;
|
||||
}
|
||||
|
||||
/* Process and Compile Comparison Operator and *
|
||||
* Args: comparator - Encoded Comparison Operator *
|
||||
* Uses: term - Term Being Compared Against *
|
||||
* label - Branch Target if Comparison is FALSE */
|
||||
void prccmp(void) {
|
||||
DEBUG("Processing comparator %d", cmprtr) DETAIL(" with REVCMP=%d\n", revcmp)
|
||||
if (cmprtr > 7) { //Process Flag
|
||||
cmprtr = (cmprtr ^ revcmp) & 1; //Apply Reversal
|
||||
if (cmprtr) asmlin("BPL", cmplbl);
|
||||
else asmlin("BMI", cmplbl);
|
||||
return;
|
||||
}
|
||||
cmprtr = (cmprtr ^ revcmp) & 7; //Apply reversal
|
||||
switch(cmprtr) {
|
||||
case 0: // Raw Expression (Skip)
|
||||
asmlin("BEQ", cmplbl); break;
|
||||
case 1: // = or ==
|
||||
asmlin("CMP", term); asmlin("BNE", cmplbl); break;
|
||||
case 2: // <
|
||||
asmlin("CMP", term); asmlin("BCS", cmplbl); break;
|
||||
case 3: // <= or =<
|
||||
asmlin("CLC", ""); asmlin("SBC", term); asmlin("BCS", cmplbl); break;
|
||||
case 4: // >
|
||||
asmlin("CLC", ""); asmlin("SBC", term); asmlin("BCC", cmplbl); break;
|
||||
case 5: // >= or =>
|
||||
asmlin("CMP", term); asmlin("BCC", cmplbl); break;
|
||||
case 6: // <> or ><
|
||||
asmlin("CMP", term); asmlin("BEQ", cmplbl); break;
|
||||
case 7: // Raw Expression (Normal)
|
||||
asmlin("BNE", cmplbl); break;
|
||||
default:
|
||||
ERROR("Unsupported comparison operator index %d\n", cmprtr, EXIT_FAILURE)
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse Comparison */
|
||||
void prscmp(int revrse) {
|
||||
skpspc();
|
||||
cmpenc = enccmp(nxtchr); //Encode Comparison Character
|
||||
cmprtr = cmpenc; //Set Encoded Comparator
|
||||
if (cmprtr) {
|
||||
cmpenc = enccmp(nxtchr); //Encode Next Comparison Character
|
||||
if (cmpenc != 0) cmprtr = cmprtr | cmpenc; //Combine Encoded Comparator
|
||||
}
|
||||
skpspc();
|
||||
if (cmprtr) prstrm(FALSE);
|
||||
//prccmp(); - Do after check for logical operator
|
||||
DEBUG("Parsed comparator %d\n", cmprtr)
|
||||
}
|
||||
|
||||
/* Parse Flag Operator */
|
||||
void prsflg(int revrse) {
|
||||
DEBUG("Parsing Flag Operator '%c'\n", nxtchr)
|
||||
if (match('+')) cmprtr = 8; //Bit 0 = 0
|
||||
else if (match('-')) cmprtr = 9; //Bit 1 = 1
|
||||
else expctd("Flag operator");
|
||||
skpchr();
|
||||
}
|
||||
|
||||
/* Parse Logical Operator *
|
||||
* Sets: logops */
|
||||
void prslop(void) {
|
||||
DEBUG("Checking for Logical Operator\n", 0)
|
||||
logopr = LOPNONE;
|
||||
skpspc();
|
||||
if (isalph()) {
|
||||
getwrd(); //Get Logical Operator
|
||||
DEBUG("Parsing Logical Operator %s\n", word)
|
||||
if (wordis("AND")) logopr = LOPAND;
|
||||
else if (wordis("OR")) logopr = LOPOR;
|
||||
else ERROR("Encountered invalid token \"%s\"\n", word, EXIT_FAILURE)
|
||||
}
|
||||
DEBUG("Set LOGOPR to %d\n", logopr)
|
||||
}
|
||||
|
||||
/* Parse and Compile Conditional Expression *
|
||||
* Condition = <expression> <comparator> <term> */
|
||||
void prscnd(char trmntr, int revrse) {
|
||||
DEBUG("Parsing condition with REVRSE=%d\n", revrse)
|
||||
tmplbl[0] = 0;
|
||||
do {
|
||||
strcpy(cmplbl, cndlbl); DEBUG("Set CMPLBL to \"%s\"\n", cmplbl);
|
||||
revcmp = revrse;
|
||||
if (look('!')) revcmp = (revcmp) ? FALSE: TRUE;
|
||||
DEBUG("Set REVCMP to %d\n", revcmp)
|
||||
if (!look('.')) prsxpr(0);
|
||||
if (look(':')) prsflg(revcmp); //Parse Flag Operator
|
||||
else prscmp(revcmp); //Parse Comparison Operator
|
||||
prslop(); //Parse Logical Operator
|
||||
if (logopr == LOPOR) {
|
||||
revcmp = (revcmp) ? FALSE: TRUE;
|
||||
DEBUG("Set REVCMP to %d\n", revcmp)
|
||||
}
|
||||
if (logopr && revcmp) {
|
||||
if (!tmplbl[0]) newlbl(tmplbl);
|
||||
strcpy(cmplbl, tmplbl); DEBUG("Set CMPLBL to \"%s\"\n", cmplbl);
|
||||
}
|
||||
prccmp(); //Process Comparison/Flag Operator
|
||||
} while (logopr);
|
||||
if (tmplbl[0]) setlbl(tmplbl);
|
||||
expect(trmntr);
|
||||
}
|
||||
/************************************
|
||||
* C02 Conditional Parsing Routines *
|
||||
************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "common.h"
|
||||
#include "asm.h"
|
||||
#include "parse.h"
|
||||
#include "vars.h"
|
||||
#include "expr.h"
|
||||
#include "label.h"
|
||||
#include "cond.h"
|
||||
|
||||
int cmprtr; //Encoded Comparison Operator
|
||||
int cmpenc; //Encoded Comparator Character
|
||||
|
||||
/* Encode Comparison Operator Character *
|
||||
* Args: Comparison Operator Character *
|
||||
* Returns: Comparison Operator Bit Mask */
|
||||
int enccmp(char c) {
|
||||
int e;
|
||||
DEBUG("Encoding Comparison Character '%c'", c)
|
||||
switch(c) {
|
||||
case '=': e = 1; break;
|
||||
case '<': e = 2; break;
|
||||
case '>': e = 4; break;
|
||||
default: e = 0;
|
||||
}
|
||||
if (e) { CCMNT(c); skpchr(); }
|
||||
DETAIL(", encoded as %d\n", e);
|
||||
return e;
|
||||
}
|
||||
|
||||
/* Process and Compile Comparison Operator and *
|
||||
* Args: comparator - Encoded Comparison Operator *
|
||||
* Uses: term - Term Being Compared Against *
|
||||
* label - Branch Target if Comparison is FALSE */
|
||||
void prccmp(void) {
|
||||
DEBUG("Processing comparator %d", cmprtr) DETAIL(" with REVCMP=%d\n", revcmp)
|
||||
if (cmprtr > 7) { //Process Flag
|
||||
cmprtr = (cmprtr ^ revcmp) & 1; //Apply Reversal
|
||||
if (cmprtr) asmlin("BPL", cmplbl);
|
||||
else asmlin("BMI", cmplbl);
|
||||
return;
|
||||
}
|
||||
cmprtr = (cmprtr ^ revcmp) & 7; //Apply reversal
|
||||
switch(cmprtr) {
|
||||
case 0: // Raw Expression (Skip)
|
||||
asmlin("BEQ", cmplbl); break;
|
||||
case 1: // = or ==
|
||||
asmlin("CMP", term); asmlin("BNE", cmplbl); break;
|
||||
case 2: // <
|
||||
asmlin("CMP", term); asmlin("BCS", cmplbl); break;
|
||||
case 3: // <= or =<
|
||||
asmlin("CLC", ""); asmlin("SBC", term); asmlin("BCS", cmplbl); break;
|
||||
case 4: // >
|
||||
asmlin("CLC", ""); asmlin("SBC", term); asmlin("BCC", cmplbl); break;
|
||||
case 5: // >= or =>
|
||||
asmlin("CMP", term); asmlin("BCC", cmplbl); break;
|
||||
case 6: // <> or ><
|
||||
asmlin("CMP", term); asmlin("BEQ", cmplbl); break;
|
||||
case 7: // Raw Expression (Normal)
|
||||
asmlin("BNE", cmplbl); break;
|
||||
default:
|
||||
ERROR("Unsupported comparison operator index %d\n", cmprtr, EXIT_FAILURE)
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse Comparison */
|
||||
void prscmp(int revrse) {
|
||||
skpspc();
|
||||
cmpenc = enccmp(nxtchr); //Encode Comparison Character
|
||||
cmprtr = cmpenc; //Set Encoded Comparator
|
||||
if (cmprtr) {
|
||||
cmpenc = enccmp(nxtchr); //Encode Next Comparison Character
|
||||
if (cmpenc != 0) cmprtr = cmprtr | cmpenc; //Combine Encoded Comparator
|
||||
}
|
||||
skpspc();
|
||||
if (cmprtr) prstrm(FALSE);
|
||||
//prccmp(); - Do after check for logical operator
|
||||
DEBUG("Parsed comparator %d\n", cmprtr)
|
||||
}
|
||||
|
||||
/* Parse Flag Operator */
|
||||
void prsflg(int revrse) {
|
||||
DEBUG("Parsing Flag Operator '%c'\n", nxtchr)
|
||||
if (match('+')) cmprtr = 8; //Bit 0 = 0
|
||||
else if (match('-')) cmprtr = 9; //Bit 1 = 1
|
||||
else expctd("Flag operator");
|
||||
skpchr();
|
||||
}
|
||||
|
||||
/* Parse Logical Operator *
|
||||
* Sets: logops */
|
||||
void prslop(void) {
|
||||
DEBUG("Checking for Logical Operator\n", 0)
|
||||
logopr = LOPNONE;
|
||||
skpspc();
|
||||
if (isalph()) {
|
||||
getwrd(); //Get Logical Operator
|
||||
DEBUG("Parsing Logical Operator %s\n", word)
|
||||
if (wordis("AND")) logopr = LOPAND;
|
||||
else if (wordis("OR")) logopr = LOPOR;
|
||||
else ERROR("Encountered invalid token \"%s\"\n", word, EXIT_FAILURE)
|
||||
}
|
||||
DEBUG("Set LOGOPR to %d\n", logopr)
|
||||
}
|
||||
|
||||
/* Parse and Compile Conditional Expression *
|
||||
* Condition = <expression> <comparator> <term> */
|
||||
void prscnd(char trmntr, int revrse) {
|
||||
DEBUG("Parsing condition with REVRSE=%d\n", revrse)
|
||||
tmplbl[0] = 0;
|
||||
do {
|
||||
strcpy(cmplbl, cndlbl); DEBUG("Set CMPLBL to \"%s\"\n", cmplbl);
|
||||
revcmp = revrse;
|
||||
if (look('!')) revcmp = (revcmp) ? FALSE: TRUE;
|
||||
DEBUG("Set REVCMP to %d\n", revcmp)
|
||||
if (!look('.')) prsxpr(0);
|
||||
if (look(':')) prsflg(revcmp); //Parse Flag Operator
|
||||
else prscmp(revcmp); //Parse Comparison Operator
|
||||
prslop(); //Parse Logical Operator
|
||||
if (logopr == LOPOR) {
|
||||
revcmp = (revcmp) ? FALSE: TRUE;
|
||||
DEBUG("Set REVCMP to %d\n", revcmp)
|
||||
}
|
||||
if (logopr && revcmp) {
|
||||
if (!tmplbl[0]) newlbl(tmplbl);
|
||||
strcpy(cmplbl, tmplbl); DEBUG("Set CMPLBL to \"%s\"\n", cmplbl);
|
||||
}
|
||||
prccmp(); //Process Comparison/Flag Operator
|
||||
} while (logopr);
|
||||
if (tmplbl[0]) setlbl(tmplbl);
|
||||
expect(trmntr);
|
||||
}
|
||||
|
20
src/cond.h
20
src/cond.h
@ -1,10 +1,10 @@
|
||||
/************************************
|
||||
* C02 Conditional Parsing Routines *
|
||||
************************************/
|
||||
|
||||
enum LOGOPS {LOPNONE, LOPAND, LOPOR};
|
||||
|
||||
int revcmp; //Reverse Comparison
|
||||
int logopr; //Logical Operator (set to LOGOPS)
|
||||
|
||||
void prscnd(char trmntr, int revrse); //Parse Conditional Expression
|
||||
/************************************
|
||||
* C02 Conditional Parsing Routines *
|
||||
************************************/
|
||||
|
||||
enum LOGOPS {LOPNONE, LOPAND, LOPOR};
|
||||
|
||||
int revcmp; //Reverse Comparison
|
||||
int logopr; //Logical Operator (set to LOGOPS)
|
||||
|
||||
void prscnd(char trmntr, int revrse); //Parse Conditional Expression
|
||||
|
@ -53,6 +53,7 @@ void addfnc(void) {
|
||||
infunc = TRUE; //Set Inside Function Definition Flag
|
||||
DEBUG("Set infunc to %d\n", infunc)
|
||||
setlbl(fncnam); //Set Function Entry Point
|
||||
asmlin(LOCOP, ""); //Set Local Variables Boundary
|
||||
if (prmtra[0]) asmlin("STA", prmtra); //Store First Parameter
|
||||
if (prmtry[0]) asmlin("STY", prmtry); //Store Second Parameter
|
||||
if (prmtrx[0]) asmlin("STX", prmtrx); //Store Third Parameter
|
||||
|
34
src/dclrtn.h
34
src/dclrtn.h
@ -1,17 +1,17 @@
|
||||
/************************************
|
||||
* C02 Declaration Compiling Routines *
|
||||
************************************/
|
||||
|
||||
char fncnam[VARLEN+1]; //Function Name
|
||||
char prmtra[VARLEN+1]; //Function Parameter A
|
||||
char prmtrx[VARLEN+1]; //Function Parameter X
|
||||
char prmtry[VARLEN+3]; //Function Parameter Y
|
||||
int prmcnt; //Number of Parameters
|
||||
//int lpemtd; //Location Prefix Emitted
|
||||
|
||||
void addcon(int numval); //Add Constant
|
||||
int pmodfr(); //Check for and Parse Modifier
|
||||
int ctype(int reqtyp); //Check for Type Keyword
|
||||
int ptype(int m); //Check for and Parse Type Keyword
|
||||
|
||||
enum types {TNONE, TVOID, TENUM, TBITMASK,TCHAR, TINT, TSTRUCT};
|
||||
/************************************
|
||||
* C02 Declaration Compiling Routines *
|
||||
************************************/
|
||||
|
||||
char fncnam[VARLEN+1]; //Function Name
|
||||
char prmtra[VARLEN+1]; //Function Parameter A
|
||||
char prmtrx[VARLEN+1]; //Function Parameter X
|
||||
char prmtry[VARLEN+3]; //Function Parameter Y
|
||||
int prmcnt; //Number of Parameters
|
||||
//int lpemtd; //Location Prefix Emitted
|
||||
|
||||
void addcon(int numval); //Add Constant
|
||||
int pmodfr(); //Check for and Parse Modifier
|
||||
int ctype(int reqtyp); //Check for Type Keyword
|
||||
int ptype(int m); //Check for and Parse Type Keyword
|
||||
|
||||
enum types {TNONE, TVOID, TENUM, TBITMASK,TCHAR, TINT, TSTRUCT};
|
||||
|
826
src/expr.c
826
src/expr.c
@ -1,372 +1,454 @@
|
||||
/***********************************
|
||||
* C02 Expression Parsing Routines *
|
||||
***********************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "common.h"
|
||||
#include "asm.h"
|
||||
#include "parse.h"
|
||||
#include "vars.h"
|
||||
#include "label.h"
|
||||
#include "expr.h"
|
||||
|
||||
/* Push Term and Operator onto Stack */
|
||||
void pshtrm(void) {
|
||||
if (trmidx >= MAXTRM) ERROR("Maximum Function Call/Array Index Depth Exceeded", 0, EXIT_FAILURE)
|
||||
oprstk[trmidx] = oper; //Put Current Operator on Stack
|
||||
strcpy(trmstk[trmidx], term); //Put Current Term on Stack
|
||||
trmidx++; //Increment Stack Pointer
|
||||
}
|
||||
|
||||
/* Pop Term and Operator off Stack */
|
||||
void poptrm(void) {
|
||||
trmidx--; //Decrement Stack Pointer
|
||||
strcpy(term, trmstk[trmidx]); //Restore Current Term from Stack
|
||||
oper = oprstk[trmidx]; //Restore Current Operator from Stack
|
||||
}
|
||||
|
||||
/* Parse value (literal or identifier) *
|
||||
* Args: alwreg - allow registers *
|
||||
8 alwcon - allow constants *
|
||||
* Sets: value - the value (as a string) *
|
||||
* valtyp - value type */
|
||||
void prsval(int alwreg, int alwcon) {
|
||||
DEBUG("Parsing value\n", 0)
|
||||
skpspc();
|
||||
if (islpre()) prslit(); //Parse Literal
|
||||
else if (isalph()) prsvar(alwreg, alwcon); //Parse Variable
|
||||
else if (isbtop()) prsbop(); //Parse Byte Operator
|
||||
else expctd("literal or variable");
|
||||
DEBUG("Parsed value of type %d\n", valtyp)
|
||||
skpspc();
|
||||
}
|
||||
|
||||
/* Process Unary Minus */
|
||||
void prcmns(void) {
|
||||
DEBUG("Processing unary minus", 0)
|
||||
asmlin("LDA", "#$00"); //Handle Unary Minus
|
||||
}
|
||||
|
||||
/* Parse array index *
|
||||
* Args: clbrkt - require closing bracket *
|
||||
* Sets: value - array index or *
|
||||
* "" if no index defined */
|
||||
void prsidx(int clbrkt) {
|
||||
expect('[');
|
||||
prsval(TRUE, TRUE); //Parse Value, Allow Registers & Constants
|
||||
DEBUG("Parsed array index '%s'\n", value)
|
||||
if (clbrkt) expect(']');
|
||||
}
|
||||
|
||||
/* Process Simple Array Index *
|
||||
* Uses: term - array variable name *
|
||||
* valtyp - array index value type *
|
||||
* value - array index as string *
|
||||
* word - array index raw string *
|
||||
* Sets: term - modified variable name */
|
||||
void prcsix(void) {
|
||||
if (valtyp == LITERAL) {
|
||||
strcat(term, "+");
|
||||
strcat(term, word);
|
||||
}
|
||||
else if (strcmp(value, "Y")==0)
|
||||
strcat(term, ",Y");
|
||||
else {
|
||||
if (strcmp(value, "A")==0) asmlin("TAX", "");
|
||||
else if (strcmp(value, "X")!=0) asmlin("LDX", value);
|
||||
strcat(term, ",X");
|
||||
}
|
||||
}
|
||||
|
||||
/* Process Expression Array Index */
|
||||
void prcxix(void) {
|
||||
pshtrm(); //Push Array Variable onto Term Stack
|
||||
if (trmcnt) asmlin("PHA", ""); //Save Accumulator if not first term
|
||||
prcftm(FALSE); //Process First Term of Expression
|
||||
prsrxp(']'); //Parse Rest of Expression
|
||||
asmlin("TAX", ""); //Transfer Result of Expression to Index Register
|
||||
if (trmcnt) asmlin("PLA", ""); //Restore Accumator if not first term
|
||||
poptrm(); //Pop Array Variable off Term Stack
|
||||
strcat(term, ",X");
|
||||
}
|
||||
|
||||
/* Check for, Parse, and Process Index */
|
||||
void chkidx(void) {
|
||||
//DEBUG("Checking for Array Index with valtyp=%d\n", valtyp)
|
||||
if (valtyp == ARRAY) {
|
||||
if (look('-')) {
|
||||
prcmns();
|
||||
prcxix();
|
||||
}
|
||||
else {
|
||||
prsidx(FALSE);
|
||||
if (valtyp > REGISTER) prcxix();
|
||||
else if (look(']')) prcsix();
|
||||
else prcxix();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse Term in Expression *
|
||||
* Sets: term - the term (as a string) */
|
||||
int prstrm(int alwint) {
|
||||
DEBUG("Parsing term\n", 0)
|
||||
prsval(FALSE, TRUE); //Parse Value - Disallow Registers, Allow Constants
|
||||
if (valtyp == FUNCTION) ERROR("Function call only allowed in first term\n", 0, EXIT_FAILURE)
|
||||
strcpy(term, value);
|
||||
if (valtyp == VARIABLE && prcvar(alwint)) return TRUE;
|
||||
DEBUG("Parsed term %s\n", term)
|
||||
chkidx(); //Check for Array Index
|
||||
skpspc();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Process Address Reference
|
||||
* Args: adract = Address Action (adacts) *
|
||||
* symbol = Symbol to Process */
|
||||
void prcadr(int adract, char* symbol) {
|
||||
DEBUG("Processing address '%s'\n", word)
|
||||
strcpy(word,"#>(");
|
||||
strcat(word,symbol);
|
||||
strcat(word,")");
|
||||
if (adract == ADPUSH) { asmlin("LDA", word); asmlin("PHA", ""); }
|
||||
else asmlin("LDY", word);
|
||||
strcpy(word,"#<(");
|
||||
strcat(word,symbol);
|
||||
strcat(word,")");
|
||||
if (adract == ADPUSH) { asmlin("LDA", word); asmlin("PHA", ""); }
|
||||
else asmlin("LDX", word);
|
||||
}
|
||||
|
||||
/* Parse and Compile Address of Operator *
|
||||
* Args: adract = Address Action */
|
||||
void prsadr(int adract) {
|
||||
DEBUG("Parsing address\n", 0)
|
||||
if (isnpre()) prsnum(0xFFFF);
|
||||
else {
|
||||
getwrd();
|
||||
if (fndlab(word)) strcpy(value, word);
|
||||
else prsvrw(FALSE, TRUE);
|
||||
}
|
||||
if (adract) prcadr(adract, value); //Compile Address Reference
|
||||
else strcpy(word, value); //Save for Calling Routine
|
||||
}
|
||||
|
||||
/* Parse and Create Anonymous String *
|
||||
* Args: adract = Address Action *
|
||||
* alwstr = Allow String */
|
||||
void prsstr(int adract, int alwstr) {
|
||||
if (!alwstr) ERROR("Illegal String Reference", 0, EXIT_FAILURE)
|
||||
DEBUG("Parsing anonymous string\n", 0)
|
||||
newlbl(vrname); //Generate Variable Name
|
||||
value[0] = 0; //Use Variable Size 0
|
||||
setvar(MTNONE, VTCHAR); //Set Variable Name, Type, and Size
|
||||
prsdts(); //Parse Data String
|
||||
setdat(); //Set Variable Data
|
||||
varcnt++; //Increment Variable Counter
|
||||
if (adract) prcadr(adract, vrname); //Compile Address Reference
|
||||
else strcpy(word, vrname); //Save for Calling Routine
|
||||
}
|
||||
|
||||
/* Check for and Process Address or String *
|
||||
* Args: adract = Address Action *
|
||||
* alwstr = Allow String */
|
||||
int chkadr(int adract, int alwstr) {
|
||||
DEBUG("Checking for Address or String\n", 0)
|
||||
int result = TRUE;
|
||||
if (look('&')) prsadr(adract);
|
||||
else if (match('"')) prsstr(adract, alwstr);
|
||||
else result = FALSE;
|
||||
skpspc();
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Parse Byte Operator */
|
||||
void prsbop(void) {
|
||||
char byteop = getnxt();
|
||||
CCMNT(byteop);
|
||||
DEBUG("Parsing byte operator '%c'\n", byteop)
|
||||
if (chkadr(FALSE, FALSE)) {
|
||||
sprintf(value, "%c(%s)", byteop, word);
|
||||
valtyp = LITERAL;
|
||||
} else {
|
||||
reqvar(FALSE);
|
||||
if (vartyp != VTINT) ERROR("Integer Value Expected\n", 0, EXIT_FAILURE)
|
||||
if (byteop == '>') strcat(value, "+1");
|
||||
vartyp = VTCHAR;
|
||||
}
|
||||
DEBUG("Set value to \"%s\"\n", value)
|
||||
}
|
||||
|
||||
/* Parse Function Argument or Return Values */
|
||||
void prsfpr(char trmntr) {
|
||||
if (!chkadr(ADLDYX, TRUE) && isxpre() || match('.')) {
|
||||
if (!look('.')) {if (prsxpf(0)) goto prsfne;}
|
||||
if (look(',') && !chkadr(ADLDYX, TRUE)) {
|
||||
if (!look('.')) {
|
||||
if (prstrm(TRUE)) goto prsfne;
|
||||
asmlin("LDY", term);
|
||||
}
|
||||
if (look(',')) {
|
||||
prsval(FALSE, TRUE); //Parse Value - Disallow Registers, Allow Constants
|
||||
if (valtyp > VARIABLE) ERROR("Illegal Value Function Argument\n", 0, EXIT_FAILURE);
|
||||
if (valtyp == VARIABLE && vartyp != VTCHAR) ERROR("Illegal Variable Type\n", 0, EXIT_FAILURE);
|
||||
asmlin("LDX", value); }
|
||||
}
|
||||
}
|
||||
prsfne:
|
||||
expect(trmntr);
|
||||
}
|
||||
|
||||
/* Parse function call */
|
||||
void prsfnc(char trmntr) {
|
||||
DEBUG("Processing Function Call '%s'\n", term)
|
||||
//int argexp = FALSE; //Expression(s) in second and third argument
|
||||
pshtrm(); //Push Function Name onto Term Stack
|
||||
skpchr(); //skip open paren
|
||||
CCMNT('(');
|
||||
prsfpr(')'); //Parse Function Parameters
|
||||
expect(trmntr);
|
||||
poptrm(); //Pop Function Name off Term Stack
|
||||
asmlin("JSR", term);
|
||||
skpspc();
|
||||
}
|
||||
|
||||
/* Process Integer Variable */
|
||||
void prcvri(void) {
|
||||
DEBUG("Processing Integer Variable '%s'\n", value)
|
||||
asmlin("LDX", value);
|
||||
strcat(value, "+1");
|
||||
asmlin("LDY", value);
|
||||
}
|
||||
|
||||
/* Process Variable in Term */
|
||||
int prcvar(int alwint) {
|
||||
switch (vartyp) {
|
||||
case VTINT:
|
||||
if (!alwint) ERROR("Illegal Use of Integer Variable %s\n", word, EXIT_FAILURE)
|
||||
prcvri();
|
||||
return TRUE;
|
||||
case VTARRAY:
|
||||
if (!alwint) ERROR("Illegal Reference to Array %s\n", word, EXIT_FAILURE)
|
||||
prcadr(ADNONE, term);
|
||||
return TRUE;
|
||||
case VTSTRUCT:
|
||||
if (!alwint) ERROR("Illegal Reference to Struct %s\n", word, EXIT_FAILURE)
|
||||
prcadr(ADNONE, term);
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Process first term of expression */
|
||||
int prcftm(int alwint) {
|
||||
DEBUG("Processing first term '%s'\n", value)
|
||||
strcpy(term, value);
|
||||
if (valtyp == VARIABLE && prcvar(alwint)) return TRUE;
|
||||
if (valtyp == FUNCTION) prsfnc(0); //Parse Expression Function
|
||||
else if (wordis("A")) return FALSE;
|
||||
else if (wordis("X")) asmlin("TXA", "");
|
||||
else if (wordis("Y")) asmlin("TYA", "");
|
||||
else { chkidx(); asmlin("LDA", term); }
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Parse first term of expession *
|
||||
* First term can include function calls */
|
||||
int prsftm(int alwint) {
|
||||
prsval(TRUE, TRUE); //Parse Value, Allow Registers & Constants
|
||||
return prcftm(alwint);
|
||||
}
|
||||
|
||||
/* Process Arithmetic or Bitwise Operator *
|
||||
* and the term that follows it */
|
||||
void prcopr(void) {
|
||||
DEBUG("Processing operator '%c'\n", oper)
|
||||
switch(oper) {
|
||||
case '+': asmlin("CLC", ""); asmlin("ADC", term); break; //Addition
|
||||
case '-': asmlin("SEC", ""); asmlin("SBC", term); break; //Subtraction
|
||||
case '&': asmlin("AND", term); break; //Bitwise AND
|
||||
case '!': //For systems that don't have pipe in character set
|
||||
case '|': asmlin("ORA", term); break; //Bitwise OR
|
||||
case '^': asmlin("EOR", term); break; //Bitwise XOR
|
||||
default: ERROR("Unrecognized operator '%c'\n", oper, EXIT_FAILURE)
|
||||
}
|
||||
oper = 0;
|
||||
}
|
||||
|
||||
/* Parse Remainder of Expression */
|
||||
void prsrxp(char trmntr) {
|
||||
skpspc();
|
||||
while (isoper()) {
|
||||
trmcnt++; //Increment Expression Depth
|
||||
prsopr(); //Parse Operator
|
||||
prstrm(FALSE); //Parse Term
|
||||
prcopr(); //Process Operator
|
||||
trmcnt--; //Decrement Expression Depth
|
||||
}
|
||||
expect(trmntr);
|
||||
}
|
||||
|
||||
int prsxpp(char trmntr, int alwint) {
|
||||
DEBUG("Parsing expression\n", 0)
|
||||
skpspc();
|
||||
trmcnt = 0; //Initialize Expression Depth
|
||||
if (match('-')) prcmns(); //Process Unary Minus
|
||||
else if (prsftm(alwint)) return TRUE; //Parse First Term
|
||||
prsrxp(trmntr); //Parse Remainder of Express
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Parse and compile expression */
|
||||
void prsxpr(char trmntr) {
|
||||
prsxpp(trmntr, FALSE);
|
||||
}
|
||||
|
||||
/* Parse and compile function parameter expression *
|
||||
* Returns: TRUE if Integer Expression */
|
||||
int prsxpf(char trmntr) {
|
||||
return prsxpp(trmntr, TRUE);
|
||||
}
|
||||
|
||||
/* Parse and Compile Integer Expression *
|
||||
* (Address, Integer Literal, Variable, *
|
||||
* Struct Member, or Function) *
|
||||
* Args: trmntr - expression terminator *
|
||||
* asmxpr - assemble expression *
|
||||
* Sets: value - Parsed Value or Symbol */
|
||||
void prsxpi(char trmntr, int asmxpr) {
|
||||
skpspc();
|
||||
DEBUG("Parsing integer expression\n", 0)
|
||||
if (!chkadr(TRUE, FALSE)) {
|
||||
if (isnpre()) {
|
||||
DEBUG("Parsing Integer Literal\n", 0)
|
||||
int number = prsnum(0xFFFF); //Parse Number into value
|
||||
if (asmxpr) {
|
||||
sprintf(value, "#%d", number & 0xFF); asmlin("LDX", value);
|
||||
sprintf(value, "#%d", number >> 8); asmlin("LDY", value);
|
||||
}
|
||||
} else if (isalph()) {
|
||||
prsvar(FALSE, TRUE);
|
||||
if (valtyp == FUNCTION) {
|
||||
strcpy(term, value);
|
||||
prsfnc(0); //Parse Expression Function
|
||||
} else if (valtyp == STRUCTURE) {
|
||||
prsmbr(value);
|
||||
if (vartyp != VTINT) ERROR("Illegal Member %s In Integer Expression", value, EXIT_FAILURE)
|
||||
} else if (valtyp == VARIABLE && vartyp == VTINT) {
|
||||
if (asmxpr) prcvri(); //Process Integer Variable
|
||||
} else {
|
||||
ERROR("Illegal Variable %s In Integer Expression", value, EXIT_FAILURE)
|
||||
}
|
||||
} else {
|
||||
ERROR("Expected Integer Value or Function\n", 0, EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
expect(trmntr);
|
||||
}
|
||||
/***********************************
|
||||
* C02 Expression Parsing Routines *
|
||||
***********************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "common.h"
|
||||
#include "asm.h"
|
||||
#include "parse.h"
|
||||
#include "vars.h"
|
||||
#include "label.h"
|
||||
#include "expr.h"
|
||||
|
||||
/* Push Term and Operator onto Stack */
|
||||
void pshtrm(void) {
|
||||
if (trmidx >= MAXTRM) ERROR("Maximum Function Call/Array Index Depth Exceeded", 0, EXIT_FAILURE)
|
||||
oprstk[trmidx] = oper; //Put Current Operator on Stack
|
||||
strcpy(trmstk[trmidx], term); //Put Current Term on Stack
|
||||
trmidx++; //Increment Stack Pointer
|
||||
DEBUG("expr.pshtrm: Pushed term %s ", term)
|
||||
DETAIL("and operator '%onto stack'\n", oper)
|
||||
}
|
||||
|
||||
/* Pop Term and Operator off Stack */
|
||||
void poptrm(void) {
|
||||
trmidx--; //Decrement Stack Pointer
|
||||
strcpy(term, trmstk[trmidx]); //Restore Current Term from Stack
|
||||
oper = oprstk[trmidx]; //Restore Current Operator from Stack
|
||||
DEBUG("expr.pshtrm: Popped term %s ", term)
|
||||
DETAIL("and operator '%c' off stack\n", oper)
|
||||
}
|
||||
|
||||
/* Parse value (literal or identifier) *
|
||||
* Args: alwreg - allow registers *
|
||||
8 alwcon - allow constants *
|
||||
* Sets: value - the value (as a string) *
|
||||
* valtyp - value type */
|
||||
void prsval(int alwreg, int alwcon) {
|
||||
DEBUG("expr.prsval: Parsing value\n", 0)
|
||||
skpspc();
|
||||
if (islpre()) prslit(); //Parse Literal
|
||||
else if (isalph()) prsvar(alwreg, alwcon); //Parse Variable
|
||||
else if (isbtop()) prsbop(); //Parse Byte Operator
|
||||
else expctd("literal or variable");
|
||||
DEBUG("expr.prsval: Parsed value %s ", value)
|
||||
DETAIL("of type %d\n", valtyp)
|
||||
skpspc();
|
||||
}
|
||||
|
||||
/* Process Unary Minus */
|
||||
void prcmns(void) {
|
||||
DEBUG("Processing unary minus", 0)
|
||||
asmlin("LDA", "#$00"); //Handle Unary Minus
|
||||
}
|
||||
|
||||
/* Parse array index *
|
||||
* Args: clbrkt - require closing bracket *
|
||||
* Sets: value - array index or *
|
||||
* "" if no index defined */
|
||||
void prsidx(int clbrkt) {
|
||||
expect('[');
|
||||
prsval(TRUE, TRUE); //Parse Value, Allow Registers & Constants
|
||||
DEBUG("expr.prsidx: Parsed array index '%s'\n", value)
|
||||
if (clbrkt) expect(']');
|
||||
}
|
||||
|
||||
/* Process Simple Array Index *
|
||||
* Uses: term - array variable name *
|
||||
* valtyp - array index value type *
|
||||
* value - array index as string *
|
||||
* word - array index raw string *
|
||||
* Sets: term - modified variable name */
|
||||
void prcsix(void) {
|
||||
DEBUG("expr.prcsix: Processing simple array index %s\n", word);
|
||||
if (valtyp == LITERAL) {
|
||||
strcat(term, "+");
|
||||
strcat(term, word);
|
||||
}
|
||||
else if (strcmp(value, "Y")==0)
|
||||
strcat(term, ",Y");
|
||||
else {
|
||||
if (strcmp(value, "A")==0) asmlin("TAX", "");
|
||||
else if (strcmp(value, "X")!=0) asmlin("LDX", value);
|
||||
strcat(term, ",X");
|
||||
}
|
||||
DEBUG("expr.prcsix: Set term to %s\n", term);
|
||||
}
|
||||
|
||||
/* Process Expression Array Index */
|
||||
void prcxix(void) {
|
||||
DEBUG("expr.prcxix: Processing Expression Array Index", 0)
|
||||
pshtrm(); //Push Array Variable onto Term Stack
|
||||
if (trmcnt) asmlin("PHA", ""); //Save Accumulator if not first term
|
||||
prcftm(FALSE); //Process First Term of Expression
|
||||
prsrxp(']'); //Parse Rest of Expression
|
||||
asmlin("TAX", ""); //Transfer Result of Expression to Index Register
|
||||
if (trmcnt) asmlin("PLA", ""); //Restore Accumator if not first term
|
||||
poptrm(); //Pop Array Variable off Term Stack
|
||||
strcat(term, ",X");
|
||||
DEBUG("expr.prcxix: Set term to %s\n", term);
|
||||
}
|
||||
|
||||
/* Check for, Parse, and Process Index */
|
||||
void chkidx(void) {
|
||||
//DEBUG("Checking for Array Index with valtyp=%d\n", valtyp)
|
||||
if (valtyp == ARRAY) {
|
||||
if (look('-')) {
|
||||
prcmns();
|
||||
prcxix();
|
||||
}
|
||||
else {
|
||||
prsidx(FALSE);
|
||||
if (valtyp > REGISTER) prcxix();
|
||||
else if (look(']')) prcsix();
|
||||
else prcxix();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse Pointer *
|
||||
* Sets: term - Compiled Pointer */
|
||||
void prsptr(void) {
|
||||
DEBUG("Parsing pointer\n", 0)
|
||||
expect('*'); //Pointer Dereference Operator
|
||||
prsvar(FALSE,FALSE); //Parse Variable to Dereference
|
||||
strcpy(term, value);
|
||||
if (varble.modifr != MTZP) ERROR("Illegal dereference of non-pointer variable %s.\n", value, EXIT_FAILURE)
|
||||
DEBUG("expr.prsptr: Set term to %s\n", term);
|
||||
}
|
||||
|
||||
/* Process Pointer Index *
|
||||
* Sets: term - Compiled Pointer */
|
||||
void prcptx(char *index) {
|
||||
DEBUG("expr.prcptx: Processing Dereferenced Pointer %s ", term)
|
||||
DETAIL("index [%s]\n", index)
|
||||
if (strcmp(index,"X")==0) ERROR("Illegal use of register X\n", 0, EXIT_FAILURE);
|
||||
if (strcmp(index,"A")==0) asmlin("TAY", "");
|
||||
else if (strcmp(index,"Y") != 0) asmlin("LDY", index);
|
||||
}
|
||||
|
||||
/* Process Pointer *
|
||||
* Sets: term - Compiled Pointer */
|
||||
int prcptr(void) {
|
||||
prsptr();
|
||||
DEBUG("expr.prcptr: Dereferencing Pointer %s\n", value);
|
||||
if (valtyp == ARRAY) {
|
||||
prsidx(TRUE);
|
||||
prcptx(value);
|
||||
sprintf(word, "(%s),Y", term);
|
||||
} else if (cmos) {
|
||||
sprintf(word, "(%s)", term);
|
||||
} else {
|
||||
asmlin("LDY","0");
|
||||
sprintf(word, "(%s),Y", term);
|
||||
}
|
||||
strcpy(term, word);
|
||||
DEBUG("expr.prcptr: Set term to %s\n", term);
|
||||
return FALSE; //Return Value Not an Integer
|
||||
}
|
||||
|
||||
/* Parse Term in Expression *
|
||||
* Sets: term - the term (as a string) *
|
||||
* Returns: TRUE if term is an integer */
|
||||
int prstrm(int alwint) {
|
||||
DEBUG("Parsing term\n", 0)
|
||||
if (match('*')) return prcptr(); //Parse and Deference Pointer
|
||||
prsval(FALSE, TRUE); //Parse Value - Disallow Registers, Allow Constants
|
||||
if (valtyp == FUNCTION) ERROR("Function call only allowed in first term\n", 0, EXIT_FAILURE)
|
||||
strcpy(term, value);
|
||||
if (valtyp == VARIABLE && prcivr(alwint)) return TRUE;
|
||||
DEBUG("expr.prstrm: Parsed term %s\n", term)
|
||||
chkidx(); //Check for Array Index
|
||||
skpspc();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Process Address Reference
|
||||
* Args: adract = Address Action (adacts) *
|
||||
* symbol = Symbol to Process */
|
||||
void prcadr(int adract, char* symbol) {
|
||||
DEBUG("Processing address '%s'\n", word)
|
||||
strcpy(word,"#>(");
|
||||
strcat(word,symbol);
|
||||
strcat(word,")");
|
||||
if (adract == ADPUSH) { asmlin("LDA", word); asmlin("PHA", ""); }
|
||||
else asmlin("LDY", word);
|
||||
strcpy(word,"#<(");
|
||||
strcat(word,symbol);
|
||||
strcat(word,")");
|
||||
if (adract == ADPUSH) { asmlin("LDA", word); asmlin("PHA", ""); }
|
||||
else asmlin("LDX", word);
|
||||
}
|
||||
|
||||
/* Parse and Compile Address of Operator *
|
||||
* Args: adract = Address Action */
|
||||
void prsadr(int adract) {
|
||||
DEBUG("Parsing address\n", 0)
|
||||
if (isnpre()) prsnum(0xFFFF);
|
||||
else {
|
||||
getwrd();
|
||||
if (fndlab(word)) strcpy(value, word);
|
||||
else prsvrw(FALSE, TRUE);
|
||||
}
|
||||
if (adract) prcadr(adract, value); //Compile Address Reference
|
||||
else strcpy(word, value); //Save for Calling Routine
|
||||
}
|
||||
|
||||
/* Parse and Create Anonymous String *
|
||||
* Args: adract = Address Action *
|
||||
* alwstr = Allow String */
|
||||
void prsstr(int adract, int alwstr) {
|
||||
if (!alwstr) ERROR("Illegal String Reference", 0, EXIT_FAILURE)
|
||||
DEBUG("Parsing anonymous string\n", 0)
|
||||
newlbl(vrname); //Generate Variable Name
|
||||
value[0] = 0; //Use Variable Size 0
|
||||
setvar(MTNONE, VTCHAR); //Set Variable Name, Type, and Size
|
||||
prsdts(); //Parse Data String
|
||||
setdat(); //Set Variable Data
|
||||
varcnt++; //Increment Variable Counter
|
||||
if (adract) prcadr(adract, vrname); //Compile Address Reference
|
||||
else strcpy(word, vrname); //Save for Calling Routine
|
||||
}
|
||||
|
||||
/* Check for and Process Address or String *
|
||||
* Args: adract = Address Action *
|
||||
* alwstr = Allow String */
|
||||
int chkadr(int adract, int alwstr) {
|
||||
DEBUG("Checking for Address or String\n", 0)
|
||||
int result = TRUE;
|
||||
if (look('&')) prsadr(adract);
|
||||
else if (match('"')) prsstr(adract, alwstr);
|
||||
else result = FALSE;
|
||||
skpspc();
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Parse Byte Operator */
|
||||
void prsbop(void) {
|
||||
char byteop = getnxt();
|
||||
CCMNT(byteop);
|
||||
DEBUG("Parsing byte operator '%c'\n", byteop)
|
||||
if (chkadr(FALSE, FALSE)) {
|
||||
sprintf(value, "%c(%s)", byteop, word);
|
||||
valtyp = LITERAL;
|
||||
} else {
|
||||
reqvar(FALSE);
|
||||
if (vartyp != VTINT) ERROR("Integer Value Expected\n", 0, EXIT_FAILURE)
|
||||
if (byteop == '>') strcat(value, "+1");
|
||||
vartyp = VTCHAR;
|
||||
}
|
||||
DEBUG("Set value to \"%s\"\n", value)
|
||||
}
|
||||
|
||||
/* Parse Function Argument or Return Values */
|
||||
void prsfpr(char trmntr) {
|
||||
int pusha = 0; int pushy = 0; //A and Y Arguments Pushed
|
||||
if (!chkadr(ADLDYX, TRUE) && isxpre() || match('.')) {
|
||||
if (look('.')) pusha = 255;
|
||||
else {if (prsxpf(0)) goto prsfne;}
|
||||
if (look(',') && !chkadr(ADLDYX, TRUE)) {
|
||||
if (look('.')) {
|
||||
pushy = -1;
|
||||
}
|
||||
else {
|
||||
if (look('(')) {
|
||||
if (pusha==0) {pusha = 1; asmlin("PHA","");} //Save A on Stack
|
||||
prsxpr(')'); asmlin("TAY", ""); //Evaluate Expression, and Copy to Y
|
||||
}
|
||||
else {
|
||||
if (prstrm(TRUE)) goto prsfne;
|
||||
asmlin("LDY", term);
|
||||
}
|
||||
}
|
||||
if (look(',')) {
|
||||
if (look('(')) {
|
||||
if (pusha==0) {pusha = 1; asmlin("PHA","");} //Save A on Stack
|
||||
if (pushy==0) {pushy = 1; asmlin("PHA",""); asmlin("PHY","");} //Save Y on Stack
|
||||
prsxpr(')'); asmlin("TAX", ""); //Evaluate Expression, and Copy to X
|
||||
}
|
||||
else {
|
||||
prsval(FALSE, TRUE); //Parse Value - Disallow Registers, Allow Constants
|
||||
if (valtyp > VARIABLE) ERROR("Illegal Value Function Argument\n", 0, EXIT_FAILURE);
|
||||
if (valtyp == VARIABLE && vartyp != VTCHAR) ERROR("Illegal Variable Type\n", 0, EXIT_FAILURE);
|
||||
asmlin("LDX", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
prsfne:
|
||||
if (pushy==1) {asmlin("PLA",""); asmlin("TAY","");} //Pull Y Off Stack
|
||||
if (pusha==1) asmlin("PLA",""); //Pull A Off Stack
|
||||
expect(trmntr);
|
||||
}
|
||||
|
||||
/* Parse function call */
|
||||
void prsfnc(char trmntr) {
|
||||
DEBUG("Processing Function Call '%s'\n", term)
|
||||
//int argexp = FALSE; //Expression(s) in second and third argument
|
||||
pshtrm(); //Push Function Name onto Term Stack
|
||||
skpchr(); //skip open paren
|
||||
CCMNT('(');
|
||||
prsfpr(')'); //Parse Function Parameters
|
||||
expect(trmntr);
|
||||
poptrm(); //Pop Function Name off Term Stack
|
||||
asmlin("JSR", term);
|
||||
skpspc();
|
||||
}
|
||||
|
||||
/* Process Integer Variable */
|
||||
void prcvri(void) {
|
||||
DEBUG("Processing Integer Variable '%s'\n", value)
|
||||
asmlin("LDX", value);
|
||||
strcat(value, "+1");
|
||||
asmlin("LDY", value);
|
||||
}
|
||||
|
||||
/* Process Integer Variable in Term *
|
||||
* Args: alwint = Allow Integer-Like Variable *
|
||||
* Returns: Integer-Like Variable Processed - TRUE/FALSE */
|
||||
int prcivr(int alwint) {
|
||||
switch (vartyp) {
|
||||
case VTINT:
|
||||
if (!alwint) ERROR("Illegal Use of Integer Variable %s\n", word, EXIT_FAILURE)
|
||||
prcvri();
|
||||
return TRUE;
|
||||
case VTARRAY:
|
||||
if (!alwint) ERROR("Illegal Reference to Array %s\n", word, EXIT_FAILURE)
|
||||
prcadr(ADNONE, term);
|
||||
return TRUE;
|
||||
case VTSTRUCT:
|
||||
if (!alwint) ERROR("Illegal Reference to Struct %s\n", word, EXIT_FAILURE)
|
||||
prcadr(ADNONE, term);
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Process first term of expression */
|
||||
int prcftm(int alwint) {
|
||||
DEBUG("Processing first term '%s'\n", value)
|
||||
strcpy(term, value);
|
||||
if (valtyp == VARIABLE && prcivr(alwint)) return TRUE;
|
||||
if (valtyp == FUNCTION) prsfnc(0); //Parse Expression Function
|
||||
else if (wordis("A")) return FALSE;
|
||||
else if (wordis("X")) asmlin("TXA", "");
|
||||
else if (wordis("Y")) asmlin("TYA", "");
|
||||
else { chkidx(); asmlin("LDA", term); }
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Parse first term of expession *
|
||||
* First term can include function calls */
|
||||
int prsftm(int alwint) {
|
||||
DEBUG("Parsing first term\n", 0)
|
||||
if (match('*')) {
|
||||
prcptr(); //Parse and Deference Pointer
|
||||
asmlin("LDA", term);
|
||||
return FALSE;
|
||||
}
|
||||
prsval(TRUE, TRUE); //Parse Value, Allow Registers & Constants
|
||||
return prcftm(alwint);
|
||||
}
|
||||
|
||||
/* Process Arithmetic or Bitwise Operator *
|
||||
* and the term that follows it */
|
||||
void prcopr(void) {
|
||||
DEBUG("Processing operator '%c'\n", oper)
|
||||
switch(oper) {
|
||||
case '+': asmlin("CLC", ""); asmlin("ADC", term); break; //Addition
|
||||
case '-': asmlin("SEC", ""); asmlin("SBC", term); break; //Subtraction
|
||||
case '&': asmlin("AND", term); break; //Bitwise AND
|
||||
case '!': //For systems that don't have pipe in character set
|
||||
case '|': asmlin("ORA", term); break; //Bitwise OR
|
||||
case '^': asmlin("EOR", term); break; //Bitwise XOR
|
||||
default: ERROR("Unrecognized operator '%c'\n", oper, EXIT_FAILURE)
|
||||
}
|
||||
oper = 0;
|
||||
}
|
||||
|
||||
/* Parse Remainder of Expression */
|
||||
void prsrxp(char trmntr) {
|
||||
skpspc();
|
||||
while (isoper()) {
|
||||
trmcnt++; //Increment Expression Depth
|
||||
prsopr(); //Parse Operator
|
||||
prstrm(FALSE); //Parse Term
|
||||
prcopr(); //Process Operator
|
||||
trmcnt--; //Decrement Expression Depth
|
||||
}
|
||||
expect(trmntr);
|
||||
}
|
||||
|
||||
int prsxpp(char trmntr, int alwint) {
|
||||
DEBUG("Parsing expression\n", 0)
|
||||
skpspc();
|
||||
trmcnt = 0; //Initialize Expression Depth
|
||||
if (match('-')) prcmns(); //Process Unary Minus
|
||||
else if (prsftm(alwint)) return TRUE; //Parse First Term
|
||||
prsrxp(trmntr); //Parse Remainder of Express
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Parse and compile expression */
|
||||
void prsxpr(char trmntr) {
|
||||
prsxpp(trmntr, FALSE);
|
||||
}
|
||||
|
||||
/* Parse and compile function parameter expression *
|
||||
* Returns: TRUE if Integer Expression */
|
||||
int prsxpf(char trmntr) {
|
||||
return prsxpp(trmntr, TRUE);
|
||||
}
|
||||
|
||||
/* Parse and Compile Integer Expression *
|
||||
* (Address, Integer Literal, Variable, *
|
||||
* Struct Member, or Function) *
|
||||
* Args: trmntr - expression terminator *
|
||||
* asmxpr - assemble expression *
|
||||
* Sets: value - Parsed Value or Symbol */
|
||||
void prsxpi(char trmntr, int asmxpr) {
|
||||
skpspc();
|
||||
DEBUG("Parsing integer expression\n", 0)
|
||||
if (!chkadr(TRUE, FALSE)) {
|
||||
if (isnpre()) {
|
||||
DEBUG("Parsing Integer Literal\n", 0)
|
||||
int number = prsnum(0xFFFF); //Parse Number into value
|
||||
if (asmxpr) {
|
||||
sprintf(value, "#%d", number & 0xFF); asmlin("LDX", value);
|
||||
sprintf(value, "#%d", number >> 8); asmlin("LDY", value);
|
||||
}
|
||||
} else if (isalph()) {
|
||||
prsvar(FALSE, TRUE);
|
||||
if (valtyp == FUNCTION) {
|
||||
strcpy(term, value);
|
||||
DEBUG("expr.prsxpi: Set term to %s\n", term)
|
||||
prsfnc(0); //Parse Expression Function
|
||||
} else if (valtyp == STRUCTURE) {
|
||||
prsmbr(value);
|
||||
if (vartyp != VTINT) ERROR("Illegal Member %s In Integer Expression", value, EXIT_FAILURE)
|
||||
} else if (valtyp == VARIABLE && vartyp == VTINT) {
|
||||
if (asmxpr) prcvri(); //Process Integer Variable
|
||||
} else {
|
||||
ERROR("Illegal Variable %s In Integer Expression", value, EXIT_FAILURE)
|
||||
}
|
||||
} else {
|
||||
ERROR("Expected Integer Value or Function\n", 0, EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
expect(trmntr);
|
||||
}
|
||||
|
62
src/expr.h
62
src/expr.h
@ -1,30 +1,32 @@
|
||||
/**********************************
|
||||
* C02 Expession Parsing Routines *
|
||||
**********************************/
|
||||
|
||||
enum adacts {ADNONE, ADLDYX, ADPUSH};
|
||||
|
||||
char term[255]; //Term parsed from equation
|
||||
|
||||
char oprstk[MAXTRM]; //Operator Stack
|
||||
char trmstk[MAXTRM][VARLEN+1]; //Function/Index Terms Stack
|
||||
int trmidx; //Next Index in Stack
|
||||
|
||||
int trmcnt; //Number of total terms in current expression
|
||||
|
||||
int chkadr(int adract, int alwstr); //Check for and Process Address or String
|
||||
void chkidx(); //Check for, Parse, and Process Index
|
||||
int prcftm(int alwint); //Process First Term
|
||||
void prcvri(void); //Process Integer Variable
|
||||
int prcvar(int alwint); //Process Variable in Term
|
||||
void prsadr(int adract); //Parse and Compile Address of Operator
|
||||
void prsbop(void); //Parse Byte Operator
|
||||
void prsval(int alwreg, int alwcon); //Parse Value
|
||||
void prsfnc(char trmntr); //Parse function call
|
||||
void prsfpr(char trmntr); //Parse Function Paraeters or Return
|
||||
void prsidx(); //Parse Array Index
|
||||
int prstrm(int alwint); //Parse Term in Expression
|
||||
void prsrxp(char trmntr); //Parse Rest of Expression
|
||||
int prsxpf(char trmntr); //Parse Expression in Function Call
|
||||
void prsxpr(char trmntr); //Parse Expression
|
||||
void prsxpi(char trmntr, int asmxpr); //Parse Integer Expression
|
||||
/**********************************
|
||||
* C02 Expession Parsing Routines *
|
||||
**********************************/
|
||||
|
||||
enum adacts {ADNONE, ADLDYX, ADPUSH};
|
||||
|
||||
char term[255]; //Term parsed from equation
|
||||
|
||||
char oprstk[MAXTRM]; //Operator Stack
|
||||
char trmstk[MAXTRM][VARLEN+1]; //Function/Index Terms Stack
|
||||
int trmidx; //Next Index in Stack
|
||||
|
||||
int trmcnt; //Number of total terms in current expression
|
||||
|
||||
int chkadr(int adract, int alwstr); //Check for and Process Address or String
|
||||
void chkidx(); //Check for, Parse, and Process Index
|
||||
int prcftm(int alwint); //Process First Term
|
||||
void prcptx(char *index); //Process Pointer Index
|
||||
void prcvri(void); //Process Integer Variable
|
||||
int prcivr(int alwint); //Process Integer Variable in Term
|
||||
void prsadr(int adract); //Parse and Compile Address of Operator
|
||||
void prsbop(void); //Parse Byte Operator
|
||||
void prsval(int alwreg, int alwcon); //Parse Value
|
||||
void prsfnc(char trmntr); //Parse function call
|
||||
void prsfpr(char trmntr); //Parse Function Paraeters or Return
|
||||
void prsidx(); //Parse Array Index
|
||||
void prsptr(void); //Parse Pointer
|
||||
int prstrm(int alwint); //Parse Term in Expression
|
||||
void prsrxp(char trmntr); //Parse Rest of Expression
|
||||
int prsxpf(char trmntr); //Parse Expression in Function Call
|
||||
void prsxpr(char trmntr); //Parse Expression
|
||||
void prsxpi(char trmntr, int asmxpr); //Parse Integer Expression
|
||||
|
204
src/files.c
204
src/files.c
@ -1,102 +1,102 @@
|
||||
/******************************
|
||||
* C02 File Handling Routines *
|
||||
******************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "files.h"
|
||||
|
||||
/* Error - Print textual description of system error *
|
||||
* and exit with system error code */
|
||||
void extsys(char *s) {
|
||||
perror(s);
|
||||
exterr(errno);
|
||||
}
|
||||
|
||||
/* Open Source File *
|
||||
* Uses: srcnam - Source File Name *
|
||||
* Sets: srcfil - Source File Handle */
|
||||
void opnsrc(void) {
|
||||
DEBUG("Processing Source File Name '%s'\n", srcnam)
|
||||
if (strrchr(srcnam, '.') == NULL) strcat(srcnam, ".c02"); //if no extension. add ".c02"
|
||||
DEBUG("opening Source File '%s'\n", srcnam)
|
||||
srcfil = fopen(srcnam, "r"); //open file
|
||||
if (srcfil == NULL) extsys(srcnam);
|
||||
}
|
||||
|
||||
/* Close Source File */
|
||||
void clssrc(void) { fclose(srcfil); }
|
||||
|
||||
/* Open Output File *
|
||||
* Uses: outnam - Output File Name *
|
||||
* Sets: outfil - Output File Handle */
|
||||
void opnout(void) {
|
||||
DEBUG("Processing Output File Name '%s'\n", outnam)
|
||||
if (strlen(outnam) == 0) //if Output File not specified
|
||||
{
|
||||
strcpy(outnam, srcnam); //copy Source Name to Ouput Name
|
||||
char *dot = strrchr(outnam, '.'); //find extension
|
||||
if (dot != NULL) *dot = 0; //and remove it
|
||||
DEBUG("Set Output File Name to '%s'\n", outnam)
|
||||
}
|
||||
if (strrchr(outnam, '.') == NULL) strcat(outnam, ".asm"); //if no extension, add ".asm"
|
||||
DEBUG("Opening Output File '%s'\n", outnam)
|
||||
outfil = fopen(outnam, "w"); //open file
|
||||
if (outfil == NULL) extsys(outnam);
|
||||
}
|
||||
|
||||
/* Close Output File */
|
||||
void clsout(void) {
|
||||
fprintf(outfil, "\n");
|
||||
fclose(outfil);
|
||||
}
|
||||
|
||||
/* Open Log File *
|
||||
* Uses: srcnam - Source File Name *
|
||||
* Sets: logfil - Log File Handle */
|
||||
void opnlog(void) {
|
||||
strcpy(lognam, srcnam); //set Log File Name to Source File Name
|
||||
char *dot = strrchr(lognam, '.'); //find file extension
|
||||
if (dot != NULL) *dot = 0; //and remove it
|
||||
strcat(lognam, ".log"); //add extension ".log"
|
||||
DEBUG("Opening Log File '%s'\n", lognam)
|
||||
logfil = fopen(lognam, "w");
|
||||
if (logfil == NULL) extsys(lognam);
|
||||
}
|
||||
|
||||
/* Close Log File *
|
||||
* Uses: logfil - Log File Handle */
|
||||
void clslog(void) { fclose(logfil); }
|
||||
|
||||
/* Open Include file *
|
||||
* Uses: incnam - Include File Name *
|
||||
* subnam - Include File Name (Subdirectory) *
|
||||
* Sets: incfil - Include File Handle */
|
||||
void opninc(int chksub)
|
||||
{
|
||||
if (chksub) {
|
||||
for (subidx=0; subidx<subcnt; subidx++) {
|
||||
DEBUG("Attempting to open include file '%s'\n", subnam[subidx])
|
||||
incfil = fopen(subnam[subidx], "r");
|
||||
if (incfil == NULL) DEBUG("Open failed\n", 0)
|
||||
else {
|
||||
strcpy(incnam, subnam[subidx]);
|
||||
DEBUG("INCNAM set to '%s'\n", incnam);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG("Opening include file '%s'\n", incnam)
|
||||
incfil = fopen(incnam, "r");
|
||||
if (incfil == NULL) extsys(incnam);
|
||||
}
|
||||
|
||||
/* Close Include File *
|
||||
* Uses: incfil - Include File Handle */
|
||||
void clsinc(void) { fclose(incfil); }
|
||||
/******************************
|
||||
* C02 File Handling Routines *
|
||||
******************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "files.h"
|
||||
|
||||
/* Error - Print textual description of system error *
|
||||
* and exit with system error code */
|
||||
void extsys(char *s) {
|
||||
perror(s);
|
||||
exterr(errno);
|
||||
}
|
||||
|
||||
/* Open Source File *
|
||||
* Uses: srcnam - Source File Name *
|
||||
* Sets: srcfil - Source File Handle */
|
||||
void opnsrc(void) {
|
||||
DEBUG("Processing Source File Name '%s'\n", srcnam)
|
||||
if (strrchr(srcnam, '.') == NULL) strcat(srcnam, ".c02"); //if no extension. add ".c02"
|
||||
DEBUG("opening Source File '%s'\n", srcnam)
|
||||
srcfil = fopen(srcnam, "r"); //open file
|
||||
if (srcfil == NULL) extsys(srcnam);
|
||||
}
|
||||
|
||||
/* Close Source File */
|
||||
void clssrc(void) { fclose(srcfil); }
|
||||
|
||||
/* Open Output File *
|
||||
* Uses: outnam - Output File Name *
|
||||
* Sets: outfil - Output File Handle */
|
||||
void opnout(void) {
|
||||
DEBUG("Processing Output File Name '%s'\n", outnam)
|
||||
if (strlen(outnam) == 0) //if Output File not specified
|
||||
{
|
||||
strcpy(outnam, srcnam); //copy Source Name to Ouput Name
|
||||
char *dot = strrchr(outnam, '.'); //find extension
|
||||
if (dot != NULL) *dot = 0; //and remove it
|
||||
DEBUG("Set Output File Name to '%s'\n", outnam)
|
||||
}
|
||||
if (strrchr(outnam, '.') == NULL) strcat(outnam, ".asm"); //if no extension, add ".asm"
|
||||
DEBUG("Opening Output File '%s'\n", outnam)
|
||||
outfil = fopen(outnam, "w"); //open file
|
||||
if (outfil == NULL) extsys(outnam);
|
||||
}
|
||||
|
||||
/* Close Output File */
|
||||
void clsout(void) {
|
||||
fprintf(outfil, "\n");
|
||||
fclose(outfil);
|
||||
}
|
||||
|
||||
/* Open Log File *
|
||||
* Uses: srcnam - Source File Name *
|
||||
* Sets: logfil - Log File Handle */
|
||||
void opnlog(void) {
|
||||
strcpy(lognam, srcnam); //set Log File Name to Source File Name
|
||||
char *dot = strrchr(lognam, '.'); //find file extension
|
||||
if (dot != NULL) *dot = 0; //and remove it
|
||||
strcat(lognam, ".log"); //add extension ".log"
|
||||
DEBUG("Opening Log File '%s'\n", lognam)
|
||||
logfil = fopen(lognam, "w");
|
||||
if (logfil == NULL) extsys(lognam);
|
||||
}
|
||||
|
||||
/* Close Log File *
|
||||
* Uses: logfil - Log File Handle */
|
||||
void clslog(void) { fclose(logfil); }
|
||||
|
||||
/* Open Include file *
|
||||
* Uses: incnam - Include File Name *
|
||||
* subnam - Include File Name (Subdirectory) *
|
||||
* Sets: incfil - Include File Handle */
|
||||
void opninc(int chksub)
|
||||
{
|
||||
if (chksub) {
|
||||
for (subidx=0; subidx<subcnt; subidx++) {
|
||||
DEBUG("Attempting to open include file '%s'\n", subnam[subidx])
|
||||
incfil = fopen(subnam[subidx], "r");
|
||||
if (incfil == NULL) DEBUG("Open failed\n", 0)
|
||||
else {
|
||||
strcpy(incnam, subnam[subidx]);
|
||||
DEBUG("INCNAM set to '%s'\n", incnam);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG("Opening include file '%s'\n", incnam)
|
||||
incfil = fopen(incnam, "r");
|
||||
if (incfil == NULL) extsys(incnam);
|
||||
}
|
||||
|
||||
/* Close Include File *
|
||||
* Uses: incfil - Include File Handle */
|
||||
void clsinc(void) { fclose(incfil); }
|
||||
|
54
src/files.h
54
src/files.h
@ -1,27 +1,27 @@
|
||||
/******************************
|
||||
* C02 File Handling Routines *
|
||||
******************************/
|
||||
|
||||
FILE *srcfil; //Source File (Input)
|
||||
FILE *outfil; //Assembler File (Output)
|
||||
FILE *logfil; //Log File (Output)
|
||||
FILE *incfil; //Include File Handle
|
||||
FILE *inpfil; //Current Input File
|
||||
|
||||
char srcnam[FNAMLEN]; //Source File Name
|
||||
char outnam[FNAMLEN]; //Assembler File Name
|
||||
char lognam[FNAMLEN]; //Log File Name
|
||||
char incnam[FNAMLEN]; //Include File Name
|
||||
char subnam[SUBMAX][FNAMLEN]; //Include File Name (Subdirectory)
|
||||
|
||||
void opnsrc(); //Open Source File
|
||||
void clssrc(); //Close Source File
|
||||
|
||||
void opnout(); //Open Output File
|
||||
void clsout(); //Close Output File
|
||||
|
||||
void opnlog(); //Open Log File
|
||||
void clslog(); //Close Log File
|
||||
|
||||
void opninc(int chksub); //Open Include File
|
||||
void clsinc(); //Close Include File
|
||||
/******************************
|
||||
* C02 File Handling Routines *
|
||||
******************************/
|
||||
|
||||
FILE *srcfil; //Source File (Input)
|
||||
FILE *outfil; //Assembler File (Output)
|
||||
FILE *logfil; //Log File (Output)
|
||||
FILE *incfil; //Include File Handle
|
||||
FILE *inpfil; //Current Input File
|
||||
|
||||
char srcnam[FNAMLEN]; //Source File Name
|
||||
char outnam[FNAMLEN]; //Assembler File Name
|
||||
char lognam[FNAMLEN]; //Log File Name
|
||||
char incnam[FNAMLEN]; //Include File Name
|
||||
char subnam[SUBMAX][FNAMLEN]; //Include File Name (Subdirectory)
|
||||
|
||||
void opnsrc(); //Open Source File
|
||||
void clssrc(); //Close Source File
|
||||
|
||||
void opnout(); //Open Output File
|
||||
void clsout(); //Close Output File
|
||||
|
||||
void opnlog(); //Open Log File
|
||||
void clslog(); //Close Log File
|
||||
|
||||
void opninc(int chksub); //Open Include File
|
||||
void clsinc(); //Close Include File
|
||||
|
@ -37,8 +37,8 @@ void pincnm(void) {
|
||||
sublen[subidx] = strlen(subnam[subidx]);
|
||||
subnam[subidx][sublen[subidx]++] = '/';
|
||||
}
|
||||
dlmtr = '>';
|
||||
}
|
||||
dlmtr = '>';
|
||||
}
|
||||
else if (dlmtr != '"')
|
||||
ERROR("Unexpected character '%c' after include\n", dlmtr, EXIT_FAILURE)
|
||||
@ -86,7 +86,7 @@ void pdefin(void) {
|
||||
|
||||
/* Parse ASCII Subdirective */
|
||||
void pascii(void) {
|
||||
getwrd(); //Get Pragma Subdirective
|
||||
getwrd(); //Get Subdirective Argument
|
||||
DEBUG("Parsing subdirective '%s'\n", word)
|
||||
if (wordis("INVERT"))
|
||||
invasc = TRUE;
|
||||
@ -146,7 +146,7 @@ void pprgma(void) {
|
||||
else if (wordis("ORIGIN"))
|
||||
porign(); //Parse Origin
|
||||
else if (wordis("PADDING"))
|
||||
ppddng(); //Parse Origin
|
||||
ppddng(); //Parse Padding
|
||||
else if (wordis("RAMBASE"))
|
||||
prambs(); //Parse RamBase
|
||||
else if (wordis("VARTABLE"))
|
||||
|
@ -1,14 +1,14 @@
|
||||
/*************************************
|
||||
* C02 Include File Parsing Routines *
|
||||
*************************************/
|
||||
|
||||
char line[255]; /*Entire line parsed from include file*/
|
||||
|
||||
void logcon(); //Print Constant Table to Log File
|
||||
void pdefin(); //Process define directive
|
||||
void pdefin(); //Process define directive
|
||||
void penumd(); //Process enum directive
|
||||
void phdrfl(); //Process command line header file
|
||||
void pincfl(); //Process include file
|
||||
void pprgma(); //Parse Pragma Directive
|
||||
void setsrc(); ///Set Input to Source File
|
||||
/*************************************
|
||||
* C02 Include File Parsing Routines *
|
||||
*************************************/
|
||||
|
||||
char line[255]; /*Entire line parsed from include file*/
|
||||
|
||||
void logcon(); //Print Constant Table to Log File
|
||||
void pdefin(); //Process define directive
|
||||
void pdefin(); //Process define directive
|
||||
void penumd(); //Process enum directive
|
||||
void phdrfl(); //Process command line header file
|
||||
void pincfl(); //Process include file
|
||||
void pprgma(); //Parse Pragma Directive
|
||||
void setsrc(); ///Set Input to Source File
|
||||
|
306
src/label.c
306
src/label.c
@ -1,153 +1,153 @@
|
||||
/******************************************************
|
||||
* C02 Label Parsing, Generation, and Lookup Routines *
|
||||
******************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "files.h"
|
||||
#include "asm.h"
|
||||
#include "parse.h"
|
||||
#include "label.h"
|
||||
#include "vars.h"
|
||||
|
||||
/* Add New Program Label */
|
||||
void addlab(char *name) {
|
||||
if (fndvar(name)) ERROR("Label %s conflicts with variable with same name", name, EXIT_FAILURE)
|
||||
if (fndlab(name)) ERROR("Duplicate program label %s\n", name, EXIT_FAILURE)
|
||||
DEBUG("Adding Program Label %s ", name) DEBUG("at index %d\n", labcnt)
|
||||
strcpy(labnam[labcnt++], name);
|
||||
}
|
||||
|
||||
int fndlab(char *name) {
|
||||
DEBUG("Looking for Program Label %s\n", name)
|
||||
for (labidx=0; labidx<labcnt; labidx++)
|
||||
if (strcmp(labnam[labidx], name) == 0) return TRUE;
|
||||
DEBUG("Label %s Not Found\n", name)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Print Program Label Table to Log File */
|
||||
void loglab(void) {
|
||||
int i;
|
||||
fprintf(logfil, "\n%-10s\n", "Label");
|
||||
for (i=0; i<labcnt; i++) {
|
||||
fprintf(logfil, "%-10s\n", labnam[i]);
|
||||
}
|
||||
}
|
||||
|
||||
const char lblflg[] = {LFNONE, LFNONE, LFNONE, LFBGN, LFEND, LFBGN, LFEND, LFEND, LFNONE, LFNONE}; //Label Type Flags
|
||||
// enum ltypes {LTNONE, LTIF, LTELSE, LTLOOP, LTEND, LTDO, LTDWHL, LTSLCT, LTCASE, LTFUNC}; //Label Types
|
||||
|
||||
/* Find Last Label of Specified Types *
|
||||
* Args: lbtyp1: First label type *
|
||||
* lbtyp2: Second label type *
|
||||
* Sets: tmplbl - Label name *
|
||||
* Returns: Index into label table *
|
||||
* (-1 if not found) */
|
||||
int lstlbl(int lbflag) {
|
||||
int i;
|
||||
DEBUG("Searching for label flag %d\n", lbflag)
|
||||
for (i = lblcnt - 1; i>-1; i--)
|
||||
if (lblflg[lbltyp[i]] == lbflag) break;
|
||||
DEBUG("Search produced label index %d\n", i)
|
||||
if (i>=0) strcpy(tmplbl, lblnam[i]);
|
||||
return i;
|
||||
}
|
||||
|
||||
/* Set Block Flag for Last Label */
|
||||
void setblk(int blkflg) { lblblk[lblcnt-1] = blkflg; }
|
||||
|
||||
/* Set label for next line of *
|
||||
* Assembly Language Code *
|
||||
* to word */
|
||||
void setlbl(char *lblset) {
|
||||
DEBUG("Setting Label '%s'\n", lblset)
|
||||
if (strlen(lblasm) > 0) {
|
||||
DEBUG("Emitting Label '%s'\n'", lblasm);
|
||||
asmlin("",""); //Emit Block End Label on it's own line
|
||||
}
|
||||
if (strlen(lblset) > LBLLEN) ERROR("Label '%s' exceeds maximum size\n", word, EXIT_FAILURE)
|
||||
strcpy(lblasm, lblset);
|
||||
}
|
||||
|
||||
/* Parse Program Label */
|
||||
void prslab(void) {
|
||||
DEBUG("Parsing Label '%s''\n", word)
|
||||
addlab(word);
|
||||
CCMNT(nxtchr);
|
||||
skpchr(); //skip ':'
|
||||
}
|
||||
|
||||
/* generate new label */
|
||||
void newlbl(char* lbname) {
|
||||
sprintf(lbname, LBLFMT, lblnxt++);
|
||||
DEBUG("Generated new label '%s'\n", lbname)
|
||||
}
|
||||
|
||||
/* Check Label Contents *
|
||||
* If lbname is blank, generate new *
|
||||
* label and copy into lbname */
|
||||
void chklbl(char* lbname) {
|
||||
if (lbname[0]) return;
|
||||
newlbl(lbname);
|
||||
}
|
||||
|
||||
/* Request Label *
|
||||
* if label is already set, returns that label *
|
||||
* else generates new label and sets it */
|
||||
void reqlbl(char* lbname) {
|
||||
DEBUG("Requesting Label\n",0)
|
||||
if (lblasm[0] == 0) {newlbl(lbname); setlbl(lbname);}
|
||||
else {strcpy(lbname,lblasm); DEBUG("Found lblasm set to \"%s\"\n", lblasm)}
|
||||
}
|
||||
|
||||
/* End Function Block */
|
||||
void endfnc(void) {
|
||||
DEBUG("Ending function definition with lsrtrn set to %d\n", lsrtrn)
|
||||
if (!lsrtrn) asmlin("RTS", "");
|
||||
infunc = FALSE;
|
||||
DEBUG("Set infunc to %d\n", infunc)
|
||||
}
|
||||
|
||||
/* Pop Label from Stack and Emit on Next Line */
|
||||
int poplbl(void) {
|
||||
int lbtype = lbltyp[--lblcnt];
|
||||
DEBUG("Popped label type %d\n", lbtype)
|
||||
switch (lbtype) {
|
||||
case LTFUNC: endfnc(); break; //Return From Subroutine
|
||||
case LTDO: strcpy(loplbl, lblnam[lblcnt]); break;
|
||||
case LTDWHL: strcpy(endlbl, lblnam[lblcnt]); break;
|
||||
case LTCASE: strcpy(cndlbl, lblnam[lblcnt]); break;
|
||||
case LTLOOP: asmlin("JMP", lblnam[lblcnt--]); //Jump to Beginning of Loop
|
||||
default: setlbl(lblnam[lblcnt]); //Emit End of Loop Label
|
||||
}
|
||||
if (lbtype != LTCASE) inblck = lblblk[lblcnt-1];
|
||||
return lbtype;
|
||||
}
|
||||
|
||||
/* Get Top Label and Return Type */
|
||||
int toplbl(char *rtlbl) {
|
||||
if (lblcnt) {
|
||||
strcpy(rtlbl, lblnam[lblcnt-1]);
|
||||
DEBUG("Found top label %s\n", rtlbl)
|
||||
return lbltyp[lblcnt-1];
|
||||
}
|
||||
rtlbl[0] = 0; //Clear Label
|
||||
return LTNONE;
|
||||
}
|
||||
|
||||
/* Push Label onto Stack *
|
||||
* Args: lbltyp - Label type *
|
||||
* Uses: curlbl - Label to push */
|
||||
void pshlbl(int lbtype, char* lbname) {
|
||||
DEBUG("Pushing label type %d\n", lbtype)
|
||||
strcpy(lblnam[lblcnt], lbname);
|
||||
lbltyp[lblcnt] = lbtype;
|
||||
lblblk[lblcnt++] = FALSE;
|
||||
DEBUG("Pushed label '%s' onto stack\n", lbname)
|
||||
}
|
||||
/******************************************************
|
||||
* C02 Label Parsing, Generation, and Lookup Routines *
|
||||
******************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "files.h"
|
||||
#include "asm.h"
|
||||
#include "parse.h"
|
||||
#include "label.h"
|
||||
#include "vars.h"
|
||||
|
||||
/* Add New Program Label */
|
||||
void addlab(char *name) {
|
||||
if (fndvar(name)) ERROR("Label %s conflicts with variable with same name", name, EXIT_FAILURE)
|
||||
if (fndlab(name)) ERROR("Duplicate program label %s\n", name, EXIT_FAILURE)
|
||||
DEBUG("Adding Program Label %s ", name) DEBUG("at index %d\n", labcnt)
|
||||
strcpy(labnam[labcnt++], name);
|
||||
}
|
||||
|
||||
int fndlab(char *name) {
|
||||
DEBUG("Looking for Program Label %s\n", name)
|
||||
for (labidx=0; labidx<labcnt; labidx++)
|
||||
if (strcmp(labnam[labidx], name) == 0) return TRUE;
|
||||
DEBUG("Label %s Not Found\n", name)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Print Program Label Table to Log File */
|
||||
void loglab(void) {
|
||||
int i;
|
||||
fprintf(logfil, "\n%-10s\n", "Label");
|
||||
for (i=0; i<labcnt; i++) {
|
||||
fprintf(logfil, "%-10s\n", labnam[i]);
|
||||
}
|
||||
}
|
||||
|
||||
const char lblflg[] = {LFNONE, LFNONE, LFNONE, LFBGN, LFEND, LFBGN, LFEND, LFEND, LFNONE, LFNONE}; //Label Type Flags
|
||||
// enum ltypes {LTNONE, LTIF, LTELSE, LTLOOP, LTEND, LTDO, LTDWHL, LTSLCT, LTCASE, LTFUNC}; //Label Types
|
||||
|
||||
/* Find Last Label of Specified Types *
|
||||
* Args: lbtyp1: First label type *
|
||||
* lbtyp2: Second label type *
|
||||
* Sets: tmplbl - Label name *
|
||||
* Returns: Index into label table *
|
||||
* (-1 if not found) */
|
||||
int lstlbl(int lbflag) {
|
||||
int i;
|
||||
DEBUG("Searching for label flag %d\n", lbflag)
|
||||
for (i = lblcnt - 1; i>-1; i--)
|
||||
if (lblflg[lbltyp[i]] == lbflag) break;
|
||||
DEBUG("Search produced label index %d\n", i)
|
||||
if (i>=0) strcpy(tmplbl, lblnam[i]);
|
||||
return i;
|
||||
}
|
||||
|
||||
/* Set Block Flag for Last Label */
|
||||
void setblk(int blkflg) { lblblk[lblcnt-1] = blkflg; }
|
||||
|
||||
/* Set label for next line of *
|
||||
* Assembly Language Code *
|
||||
* to word */
|
||||
void setlbl(char *lblset) {
|
||||
DEBUG("Setting Label '%s'\n", lblset)
|
||||
if (strlen(lblasm) > 0) {
|
||||
DEBUG("Emitting Label '%s'\n'", lblasm);
|
||||
asmlin("",""); //Emit Block End Label on it's own line
|
||||
}
|
||||
if (strlen(lblset) > LBLLEN) ERROR("Label '%s' exceeds maximum size\n", word, EXIT_FAILURE)
|
||||
strcpy(lblasm, lblset);
|
||||
}
|
||||
|
||||
/* Parse Program Label */
|
||||
void prslab(void) {
|
||||
DEBUG("Parsing Label '%s''\n", word)
|
||||
addlab(word);
|
||||
CCMNT(nxtchr);
|
||||
skpchr(); //skip ':'
|
||||
}
|
||||
|
||||
/* generate new label */
|
||||
void newlbl(char* lbname) {
|
||||
sprintf(lbname, LBLFMT, lblnxt++);
|
||||
DEBUG("Generated new label '%s'\n", lbname)
|
||||
}
|
||||
|
||||
/* Check Label Contents *
|
||||
* If lbname is blank, generate new *
|
||||
* label and copy into lbname */
|
||||
void chklbl(char* lbname) {
|
||||
if (lbname[0]) return;
|
||||
newlbl(lbname);
|
||||
}
|
||||
|
||||
/* Request Label *
|
||||
* if label is already set, returns that label *
|
||||
* else generates new label and sets it */
|
||||
void reqlbl(char* lbname) {
|
||||
DEBUG("Requesting Label\n",0)
|
||||
if (lblasm[0] == 0) {newlbl(lbname); setlbl(lbname);}
|
||||
else {strcpy(lbname,lblasm); DEBUG("Found lblasm set to \"%s\"\n", lblasm)}
|
||||
}
|
||||
|
||||
/* End Function Block */
|
||||
void endfnc(void) {
|
||||
DEBUG("Ending function definition with lsrtrn set to %d\n", lsrtrn)
|
||||
if (!lsrtrn) asmlin("RTS", "");
|
||||
infunc = FALSE;
|
||||
DEBUG("Set infunc to %d\n", infunc)
|
||||
}
|
||||
|
||||
/* Pop Label from Stack and Emit on Next Line */
|
||||
int poplbl(void) {
|
||||
int lbtype = lbltyp[--lblcnt];
|
||||
DEBUG("Popped label type %d\n", lbtype)
|
||||
switch (lbtype) {
|
||||
case LTFUNC: endfnc(); break; //Return From Subroutine
|
||||
case LTDO: strcpy(loplbl, lblnam[lblcnt]); break;
|
||||
case LTDWHL: strcpy(endlbl, lblnam[lblcnt]); break;
|
||||
case LTCASE: strcpy(cndlbl, lblnam[lblcnt]); break;
|
||||
case LTLOOP: asmlin("JMP", lblnam[lblcnt--]); //Jump to Beginning of Loop
|
||||
default: setlbl(lblnam[lblcnt]); //Emit End of Loop Label
|
||||
}
|
||||
if (lbtype != LTCASE) inblck = lblblk[lblcnt-1];
|
||||
return lbtype;
|
||||
}
|
||||
|
||||
/* Get Top Label and Return Type */
|
||||
int toplbl(char *rtlbl) {
|
||||
if (lblcnt) {
|
||||
strcpy(rtlbl, lblnam[lblcnt-1]);
|
||||
DEBUG("Found top label %s\n", rtlbl)
|
||||
return lbltyp[lblcnt-1];
|
||||
}
|
||||
rtlbl[0] = 0; //Clear Label
|
||||
return LTNONE;
|
||||
}
|
||||
|
||||
/* Push Label onto Stack *
|
||||
* Args: lbltyp - Label type *
|
||||
* Uses: curlbl - Label to push */
|
||||
void pshlbl(int lbtype, char* lbname) {
|
||||
DEBUG("Pushing label type %d\n", lbtype)
|
||||
strcpy(lblnam[lblcnt], lbname);
|
||||
lbltyp[lblcnt] = lbtype;
|
||||
lblblk[lblcnt++] = FALSE;
|
||||
DEBUG("Pushed label '%s' onto stack\n", lbname)
|
||||
}
|
||||
|
82
src/label.h
82
src/label.h
@ -1,41 +1,41 @@
|
||||
/******************************************************
|
||||
* C02 Label Parsing, Generation, and Lookup Routines *
|
||||
******************************************************/
|
||||
|
||||
char labnam[MAXLAB+1][LABLEN+1]; //Program Label Names
|
||||
int labcnt; //Number of Program Labels
|
||||
int labidx; //Index into labnam[]
|
||||
|
||||
char curlbl[LBLLEN+1]; //Most recently generated label
|
||||
char cmplbl[LBLLEN+1]; //Label for Comparison
|
||||
char cndlbl[LBLLEN+1]; //Label for Conditional Code
|
||||
char endlbl[LBLLEN+1]; //End Label
|
||||
char forlbl[LBLLEN+1]; //For Loop Label
|
||||
char loplbl[LBLLEN+1]; //Skip Increment Label
|
||||
char skplbl[LBLLEN+1]; //Skip Increment Label
|
||||
char tmplbl[LBLLEN+1]; //Temporary Label
|
||||
char lblnam[MAXLBL+1][LBLLEN+1]; //Label Name Table
|
||||
int lbltyp[MAXLBL+1]; //Label Type
|
||||
int lblblk[MAXLBL+1]; //Label Ends Program Block
|
||||
int lblcnt; //Number of Labels in stack
|
||||
int lblnxt; //Sequence of next label to be generated
|
||||
char lbltmp[LBLLEN+1]; //Label Temporary Storage
|
||||
|
||||
enum ltypes {LTNONE, LTIF, LTELSE, LTLOOP, LTEND, LTDO, LTDWHL, LTSLCT, LTCASE, LTFUNC}; //Label Types
|
||||
enum lflags {LFNONE, LFBGN, LFEND}; //Label Flag Types
|
||||
|
||||
void addlab(char *name); //Add Program Label
|
||||
int fndlab(char *name); //Find Program Label
|
||||
void prslab(); //Parse Program Label
|
||||
void loglab(void); //Print Program Label Table
|
||||
|
||||
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(); //Pop Last Label and Emit on Next Line
|
||||
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
|
||||
|
||||
/******************************************************
|
||||
* C02 Label Parsing, Generation, and Lookup Routines *
|
||||
******************************************************/
|
||||
|
||||
char labnam[MAXLAB+1][LABLEN+1]; //Program Label Names
|
||||
int labcnt; //Number of Program Labels
|
||||
int labidx; //Index into labnam[]
|
||||
|
||||
char curlbl[LBLLEN+1]; //Most recently generated label
|
||||
char cmplbl[LBLLEN+1]; //Label for Comparison
|
||||
char cndlbl[LBLLEN+1]; //Label for Conditional Code
|
||||
char endlbl[LBLLEN+1]; //End Label
|
||||
char forlbl[LBLLEN+1]; //For Loop Label
|
||||
char loplbl[LBLLEN+1]; //Skip Increment Label
|
||||
char skplbl[LBLLEN+1]; //Skip Increment Label
|
||||
char tmplbl[LBLLEN+1]; //Temporary Label
|
||||
char lblnam[MAXLBL+1][LBLLEN+1]; //Label Name Table
|
||||
int lbltyp[MAXLBL+1]; //Label Type
|
||||
int lblblk[MAXLBL+1]; //Label Ends Program Block
|
||||
int lblcnt; //Number of Labels in stack
|
||||
int lblnxt; //Sequence of next label to be generated
|
||||
char lbltmp[LBLLEN+1]; //Label Temporary Storage
|
||||
|
||||
enum ltypes {LTNONE, LTIF, LTELSE, LTLOOP, LTEND, LTDO, LTDWHL, LTSLCT, LTCASE, LTFUNC}; //Label Types
|
||||
enum lflags {LFNONE, LFBGN, LFEND}; //Label Flag Types
|
||||
|
||||
void addlab(char *name); //Add Program Label
|
||||
int fndlab(char *name); //Find Program Label
|
||||
void prslab(); //Parse Program Label
|
||||
void loglab(void); //Print Program Label Table
|
||||
|
||||
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(); //Pop Last Label and Emit on Next Line
|
||||
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
|
||||
|
||||
|
48
src/parse.c
48
src/parse.c
@ -13,6 +13,8 @@
|
||||
#include "asm.h"
|
||||
#include "parse.h"
|
||||
#include "label.h"
|
||||
#include "expr.h"
|
||||
#include "stmnt.h"
|
||||
|
||||
/* Various tests against nxtchr */
|
||||
int match(char c) {return TF(nxtchr == c);}
|
||||
@ -81,12 +83,15 @@ void skpspc(void) {
|
||||
* otherwise FALSE */
|
||||
int look(char c) {
|
||||
int found;
|
||||
DEBUG("parse.look: 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 +141,8 @@ void getwrd(void) {
|
||||
while (isanum()) word[wrdlen++] = toupper(getnxt());
|
||||
word[wrdlen] = 0;
|
||||
ACMNT(word);
|
||||
DEBUG("parse.getwrd: Read word '%s' ", word)
|
||||
DETAIL("delimited by '%c'\n", nxtchr)
|
||||
}
|
||||
|
||||
/* Escape Character */
|
||||
@ -154,31 +161,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 *
|
||||
@ -357,21 +374,24 @@ void poperr(char* name) {
|
||||
}
|
||||
|
||||
/* Process Post Operator */
|
||||
void prcpst(int isint, char* name, char *index) {
|
||||
DEBUG("Processing post operation '%c'\n", oper)
|
||||
void prcpst(int isint, char* name, char *index, char indtyp, char ispntr) {
|
||||
DEBUG("parse.prcpst: Processing post operation '%c'\n", oper)
|
||||
if (ispntr) ERROR("Post Operation on dereferenced pointer %s not supported\n", name, EXIT_FAILURE)
|
||||
//sprintf(word,"(%s),Y", name); strcpy(name, word); }
|
||||
char name1[VARLEN+3];
|
||||
strcpy(name1, name); strcat(name1, "+1");
|
||||
if (strlen(index)) {
|
||||
asmlin("LDX", index);
|
||||
strcat(name,",X");
|
||||
if (ispntr) prcptx(index); //Process Pointer Index
|
||||
else prcidx(indtyp, name, index); //Process Index
|
||||
}
|
||||
else if (ispntr) asmlin("LDY","0");
|
||||
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 if (strcmp(name, "A")==0 && !cmos) poperr(name); //65C02 supports implicit INC, 6502 does not
|
||||
else {
|
||||
asmlin("INC", name);
|
||||
asmlin("INC", word);
|
||||
if (isint) {
|
||||
newlbl(skplbl);
|
||||
asmlin("BNE", skplbl);
|
||||
@ -383,7 +403,7 @@ void prcpst(int isint, char* name, char *index) {
|
||||
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 if (strcmp(name, "A")==0 && !cmos) poperr(name); //65C02 supports implicit DEC, 6502 does not
|
||||
else {
|
||||
if (isint) {
|
||||
newlbl(skplbl);
|
||||
@ -392,7 +412,7 @@ void prcpst(int isint, char* name, char *index) {
|
||||
asmlin("DEC", name1);
|
||||
setlbl(skplbl);
|
||||
}
|
||||
asmlin("DEC", name);
|
||||
asmlin("DEC", name);
|
||||
}
|
||||
break;
|
||||
case '<':
|
||||
@ -419,7 +439,7 @@ void prcpst(int isint, char* name, char *index) {
|
||||
}
|
||||
|
||||
/* Parse Post Operator */
|
||||
int prspst(char trmntr, int isint, char* name, char* index) {
|
||||
int prspst(char trmntr, int isint, char* name, char* index, char indtyp, char ispntr) {
|
||||
oper = getnxt();
|
||||
CCMNT(oper);
|
||||
DEBUG("Checking for post operation '%c'\n", oper)
|
||||
@ -427,7 +447,7 @@ int prspst(char trmntr, int isint, char* name, char* index) {
|
||||
skpchr();
|
||||
CCMNT(oper);
|
||||
expect(trmntr);
|
||||
prcpst(isint, name, index); //Process Post-Op
|
||||
prcpst(isint, name, index, indtyp, ispntr); //Process Post-Op
|
||||
return 0;
|
||||
}
|
||||
DEBUG("Not a post operation\n", 0)
|
||||
|
@ -55,7 +55,7 @@ int prsbyt(); //Parse Numeric Byte
|
||||
void prslit(); //Parse Literal
|
||||
int prsnum(int maxval); //Parse Numeric
|
||||
void prsopr(); //Parse Arithmetic Operator
|
||||
int prspst(char trmntr, int isint, char* name, char* index); //Parse Post Operator
|
||||
int prspst(char trmntr, int isint, char* name, char* index, char indtyp, char ispntr); //Parse Post Operator
|
||||
int psizof(void); //Parse SizeOf Operator
|
||||
int pidxof(void); //Parse SizeOf Operator
|
||||
void skpchr(); //Skip Next Character
|
||||
|
1115
src/stmnt.c
1115
src/stmnt.c
File diff suppressed because it is too large
Load Diff
44
src/stmnt.h
44
src/stmnt.h
@ -1,21 +1,23 @@
|
||||
/************************************
|
||||
* C02 Statement Compiling Routines *
|
||||
************************************/
|
||||
|
||||
char asnvar[VARLEN+1]; //Assigned Variable Name
|
||||
int asntyp; //Assigned Variable Type
|
||||
char asnidx[VARLEN+1] ; //Assigned Variable Index
|
||||
int asnivt; //Assigned Index Variable Type
|
||||
char ysnvar[VARLEN+1]; //Assigned Y Variable Name
|
||||
char ysnidx[VARLEN+1] ; //Assigned Y Variable Index
|
||||
int ysnivt; //Assigned Y Index Variable Type
|
||||
char xsnvar[VARLEN+1]; //Assigned X Variable Name
|
||||
char xsnidx[VARLEN+1] ; //Assigned X Variable Index
|
||||
int xsnivt; //Assigned X Index Variable Type
|
||||
|
||||
char xstmnt[LINELEN]; //Expected Statement
|
||||
|
||||
void bgnblk(char blkchr); //End Program Block
|
||||
void endblk(int blkflg); //End Program Block
|
||||
void pdowhl(); //Parse and Compile WHILE after DO
|
||||
void pstmnt(); //Parse and Compile Program Statement
|
||||
/************************************
|
||||
* C02 Statement Compiling Routines *
|
||||
************************************/
|
||||
|
||||
char asnvar[VARLEN+1]; //Assigned Variable Name
|
||||
int asntyp; //Assigned Variable Type
|
||||
char asnidx[VARLEN+1] ; //Assigned Variable Index
|
||||
int asnivt; //Assigned Index Variable Type
|
||||
char ysnvar[VARLEN+1]; //Assigned Y Variable Name
|
||||
char ysnidx[VARLEN+1] ; //Assigned Y Variable Index
|
||||
int ysnivt; //Assigned Y Index Variable Type
|
||||
char xsnvar[VARLEN+1]; //Assigned X Variable Name
|
||||
char xsnidx[VARLEN+1] ; //Assigned X Variable Index
|
||||
int xsnivt; //Assigned X Index Variable Type
|
||||
|
||||
char xstmnt[LINELEN]; //Expected Statement
|
||||
|
||||
void bgnblk(char blkchr); //End Program Block
|
||||
void endblk(int blkflg); //End Program Block
|
||||
void prcasp(char trmntr); //Process Pointer Assignment
|
||||
void prcidx(int idxtyp, char *name, char *index);
|
||||
void pdowhl(); //Parse and Compile WHILE after DO
|
||||
void pstmnt(); //Parse and Compile Program Statement
|
||||
|
38
src/vars.c
38
src/vars.c
@ -21,7 +21,7 @@
|
||||
* varcnt if not found *
|
||||
* Returns: TRUE if found, otherwise FALSE */
|
||||
int fndvar(char *name) {
|
||||
DEBUG("Looking up variable '%s'\n", name)
|
||||
DEBUG("vars,fndvar: Looking up variable '%s'\n", name)
|
||||
for (varidx=0; varidx<varcnt; varidx++) {
|
||||
if (strcmp(vartbl[varidx].name, name) == 0) {
|
||||
memcpy(&varble, &vartbl[varidx], sizeof(varble));
|
||||
@ -37,7 +37,7 @@ int fndvar(char *name) {
|
||||
* sctcnt if not found *
|
||||
* Returns: TRUE if found, otherwise FALSE */
|
||||
int fndstc(char *name) {
|
||||
DEBUG("Looking up struct '%s'\n", name)
|
||||
DEBUG("vars.fndstc: Looking up struct '%s'\n", name)
|
||||
for (stcidx=0; stcidx<stccnt; stcidx++)
|
||||
if (strcmp(strcts[stcidx].name, name) == 0) return TRUE;
|
||||
return FALSE;
|
||||
@ -48,7 +48,7 @@ int fndstc(char *name) {
|
||||
* stmcnt if not found *
|
||||
* Returns: TRUE if found, otherwise FALSE */
|
||||
int fndmbr(int idx, char *name) {
|
||||
DEBUG("Looking up member '%s'\n", word)
|
||||
DEBUG("vars.fndmbr: Looking up member '%s'\n", word)
|
||||
for (mbridx=0; mbridx<mbrcnt; mbridx++) {
|
||||
if (membrs[mbridx].strcti != idx) continue;
|
||||
if (strcmp(membrs[mbridx].name, name) == 0) {
|
||||
@ -88,7 +88,7 @@ void prcmbr(char* name) {
|
||||
getwrd(); //Get Member Name
|
||||
valtyp = gettyp(); //Determine Variable Type
|
||||
if (valtyp == FUNCTION) ERROR("Illegal Function Reference\n", 0, EXIT_FAILURE)
|
||||
DEBUG("Checking for member %s", word) DETAIL(" with struct index %d\n", stcidx)
|
||||
DEBUG("vars.prcmbr: Checking for member %s", word) DETAIL(" with struct index %d\n", stcidx)
|
||||
if (!fndmbr(stcidx, word)) ERROR("Struct does Not Contain Member %s\n", word, EXIT_FAILURE)
|
||||
mbrofs += membr.offset; //Get Member Offet in Struct
|
||||
}
|
||||
@ -117,7 +117,7 @@ void prsvrw(int alwreg, int alwcon) {
|
||||
valtyp = gettyp(); //Determine Variable Type
|
||||
if (valtyp != FUNCTION) chksym(alwreg, alwcon, word);
|
||||
strcpy(value, word);
|
||||
DEBUG("Parsed variable '%s'\n", value)
|
||||
DEBUG("vars.prsvrw: Parsed variable '%s'\n", value)
|
||||
if (valtyp == STRUCTURE) prsmbr(value);
|
||||
}
|
||||
|
||||
@ -143,7 +143,7 @@ void reqvar(int alwary) {
|
||||
* Returns: variable size (as integer */
|
||||
int pidxof(void) {
|
||||
expect('?'); //Check for and Skip SizeOf Operator
|
||||
DEBUG("Parsing IndexOf operator", 0);
|
||||
DEBUG("vars.pidxof: Parsing IndexOf operator", 0);
|
||||
mbridx = -1; //Set Member Index to None
|
||||
reqvar(FALSE); //Parse Variable Name to get Size Of
|
||||
if (mbridx > -1) {
|
||||
@ -159,7 +159,7 @@ int pidxof(void) {
|
||||
* Returns: variable size (as integer */
|
||||
int psizof(void) {
|
||||
expect('@'); //Check for and Skip SizeOf Operator
|
||||
DEBUG("Parsing SizeOf operator", 0);
|
||||
DEBUG("vars.pdizof: Parsing SizeOf operator", 0);
|
||||
mbridx = -1; //Set Member Index to None
|
||||
reqvar(FALSE); //Parse Variable Name to get Size Of
|
||||
if (mbridx > -1) {
|
||||
@ -181,7 +181,7 @@ int psizof(void) {
|
||||
|
||||
/* Parse Data Array */
|
||||
void prsdta(void) {
|
||||
DEBUG("Parsing Array Data\n", 0)
|
||||
DEBUG("vars.prsdta: Parsing Array Data\n", 0)
|
||||
int i;
|
||||
dtype = DTARRY;
|
||||
expect('{');
|
||||
@ -202,7 +202,7 @@ void prsdts(void) {
|
||||
dtype = DTSTR;
|
||||
getstr();
|
||||
strcpy(value, word);
|
||||
DEBUG("Parsed Data String '%s'\n", value)
|
||||
DEBUG("vars.prsdts: Parsed Data String '%s'\n", value)
|
||||
}
|
||||
|
||||
/* Store variable data *
|
||||
@ -212,34 +212,34 @@ void prsdts(void) {
|
||||
void setdat(void) {
|
||||
int i;
|
||||
if (dtype == DTBYTE) {
|
||||
DEBUG("Setting variable data to '%d'\n", litval)
|
||||
DEBUG("vars.setdat: Setting variable data to '%d'\n", litval)
|
||||
dlen = 1;
|
||||
datvar[dsize++] = litval;
|
||||
}
|
||||
else if (dtype == DTINT) {
|
||||
DEBUG("Setting variable data to '%d'\n", litval)
|
||||
DEBUG("vars.setdat: Setting variable data to '%d'\n", litval)
|
||||
dlen = 2;
|
||||
datvar[dsize++] = litval & 0xFF;
|
||||
datvar[dsize++] = litval >> 8;
|
||||
}
|
||||
else if (dtype == DTARRY) {
|
||||
DEBUG("Setting variable data to array of length %d\n", dlen)
|
||||
DEBUG("vars.setdat: 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)
|
||||
DEBUG("vars.setdat: 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 allocated: %d bytes\n", dsize)
|
||||
DEBUG("vars.setdat: Total data allocated: %d bytes\n", dsize)
|
||||
}
|
||||
|
||||
/* Parse and store variable data */
|
||||
void prsdat(int m, int t) {
|
||||
if ((m & MTCONST) == 0) ERROR("Initialization allowed only on variables declared CONST\n", 0, EXIT_FAILURE);
|
||||
DEBUG("Parsing variable data\n", 0)
|
||||
DEBUG("vars.prsdat: Parsing variable data\n", 0)
|
||||
skpspc();
|
||||
if (t == VTINT) {dtype = DTINT; litval = prsnum(0xFFFF); } //Parse Integer
|
||||
else if (islpre()) {dtype = DTBYTE; prslit(); } //Parse Data Literal
|
||||
@ -253,7 +253,7 @@ void prsdat(int m, int t) {
|
||||
* Uses: vrname - variable name *
|
||||
* value - variable size */
|
||||
void setvar(int m, int t) {
|
||||
DEBUG("Added variable '%s' ", vrname);
|
||||
DEBUG("vars.setvar: Added variable '%s' ", vrname);
|
||||
strncpy(vartbl[varcnt].name, vrname, VARLEN);
|
||||
vartbl[varcnt].modifr = m;
|
||||
vartbl[varcnt].type = t;
|
||||
@ -294,17 +294,17 @@ void addvar(int m, int t) {
|
||||
}
|
||||
else {
|
||||
if (t == VTSTRUCT) {
|
||||
DEBUG("Setting variable size to %d\n", strct.size)
|
||||
DEBUG("vars.addvar: Setting variable size to %d\n", strct.size)
|
||||
sprintf(value, "%d", strct.size);
|
||||
} else if (t == VTINT) {
|
||||
DEBUG("Setting variable size to %d\n", 2)
|
||||
DEBUG("vars.addvar: Setting variable size to %d\n", 2)
|
||||
sprintf(value, "%d", 2);
|
||||
} else if (match('[')) {
|
||||
t = VTARRAY; //Set Type to Array
|
||||
CCMNT('[')
|
||||
skpchr();
|
||||
if (alcvar) {
|
||||
DEBUG("Parsing array size\n", 0)
|
||||
DEBUG("vars.addvar: Parsing array size\n", 0)
|
||||
sprintf(value, "%d", prsnum(0xFF) + 1);
|
||||
}
|
||||
expect(']');
|
||||
|
@ -25,7 +25,7 @@ RGBCLR: LSR ;Divide Red Value by 16
|
||||
LSR
|
||||
ORA TEMP0 ;Combine with Green
|
||||
TAX ;and Return as LSB
|
||||
.DC $7A ;PLY Return Red as MSB
|
||||
PLY ;Return Red as MSB
|
||||
RTS
|
||||
|
||||
;clrrgb(c) - Convert Palette Color to RGB Values
|
||||
@ -34,7 +34,7 @@ RGBCLR: LSR ;Divide Red Value by 16
|
||||
;Returns: A = Red Value (0-255)
|
||||
; Y = Green Value (0-255)
|
||||
; X = Blue Value (0-255)
|
||||
CLRRGB: .DC $5A ;PHY Save MSB
|
||||
CLRRGB: PHY ;Save MSB
|
||||
TXA ;Copy LSB into Accumulator
|
||||
AND #$F0 ;Isolate Green Value
|
||||
TAY ;and Return in Y
|
||||
@ -73,7 +73,7 @@ GETCLN: LDX $9F25 ;Get Current Data Port
|
||||
; Y = Green Value (0-255)
|
||||
; X = Blue Value (0-255)
|
||||
GETRGB: JSR GETCLN ;Get Next Color Entry
|
||||
JMP CLRRGB ;Convert to RGB and Return
|
||||
BRA CLRRGB ;Convert to RGB and Return
|
||||
|
||||
;setclr(idx) - Set Color Entry idx in Palette
|
||||
;Args: A = Color Entry Index
|
||||
@ -106,7 +106,7 @@ SETCLN: TXA ;Copy LSB to Accumulator
|
||||
;Destroys: TEMP0
|
||||
;Affects: A,Y,X
|
||||
SETRGB: JSR RGBCLR ;Convert RGB to Vera Color Value
|
||||
JMP SETCLN ;and Write to Next Palette Entry
|
||||
BRA SETCLN ;and Write to Next Palette Entry
|
||||
|
||||
;setidy(idx) - Set Palette Index and Entry Count
|
||||
;Args: A = Palette Index
|
||||
|
@ -86,7 +86,7 @@ GETVIM: .DC $04 ;Chroma Disable Bit Mask
|
||||
GETVSP: LDA #7 ;Set Reg Offset to Vertical Stop
|
||||
JSR GETHVS ;Read Registers
|
||||
LSR ;Shift Left One Bit
|
||||
JMP GETVSS ;Then Four More Bits and Mask
|
||||
BRA GETVSS ;Then Four More Bits and Mask
|
||||
|
||||
;getvsr() - Get Vertical Start
|
||||
;Affects: A
|
||||
@ -108,7 +108,7 @@ GETHSP: LDA #5 ;Set Lookup Index to Horizontal Start
|
||||
JSR GETHVS ;Read Registers
|
||||
LSR ;Shift Left Two Bits
|
||||
LSR
|
||||
JMP GETHSS ;then Mask and Return
|
||||
BRA GETHSS ;then Mask and Return
|
||||
|
||||
;gethsr() - Get Horizontal Start
|
||||
;Affects: A
|
||||
@ -127,9 +127,9 @@ GETHSS: AND #$03 ;Isolate Bit 0
|
||||
GETHVS: JSR GETDCB ;Read LSB from Register
|
||||
PHA ;and Save It
|
||||
LDA #8 ;Load Register Offset for High Bits
|
||||
STA $9F20 ;Set As Address LSB
|
||||
STA $9F20 ;Set As Address LSB
|
||||
LDA $9F23,X ;and Read High Bits into A
|
||||
.DC $FA ;PLX ;Restore LSB into X
|
||||
PLX ;Restore LSB into X
|
||||
RTS
|
||||
|
||||
;setbdr() - Set Border Color
|
||||
|
@ -263,7 +263,7 @@ SETLRM: AND TEMP1 ;Apply Mask
|
||||
;Returns: A = Contents of Register
|
||||
; X = Current Data Port
|
||||
SETLRR: ;.dc $ff
|
||||
.DC $5A ;PHY Save Value to Write
|
||||
PHY ;Save Value to Write
|
||||
JSR GETLRP ;Get Layer Page in Y
|
||||
PLA ;Restore Value to Write
|
||||
JMP SETREG ;and Write to Register
|
||||
@ -278,7 +278,7 @@ SETLRR: ;.dc $ff
|
||||
SETLRS: ;.dc $ff
|
||||
JSR SAVREG ;Save Layer, Value, and Mask
|
||||
JSR GETLRS ;Get Layer Size Register
|
||||
JMP SETLRM ;Mask in Value and Write Back
|
||||
BRA SETLRM ;Mask in Value and Write Back
|
||||
|
||||
;setmod() - Set Layer 0/1 Mode
|
||||
;Args: A = Layer (0/1)
|
||||
|
@ -24,7 +24,7 @@ ASLADR: ASL TEMP1 ;Shift LSB Left
|
||||
ROL TEMP0 ;Rotate Carry Left into LSB
|
||||
DEX ;Decrement Shift Count
|
||||
BNE ASLADR ;and Loop if Not Zero
|
||||
JMP RESREG ;Return Bank, MSB, LSB
|
||||
BRA RESREG ;Return Bank, MSB, LSB
|
||||
|
||||
;chkadr(opts,addr) - Check Vera Address
|
||||
;Args: A = Bank + Auto-Increment
|
||||
@ -163,7 +163,7 @@ SETVRB: STA TEMP1 ;Save Bit Pattern
|
||||
JSR GETVRG ;Read Register
|
||||
AND TEMP0 ;Mask Result
|
||||
ORA TEMP1 ;Set Bits
|
||||
JMP SETBYN ;Write Back to Register
|
||||
BRA SETBYN ;Write Back to Register
|
||||
|
||||
;setreg(addr) - Set Register
|
||||
;Args: A = Value to Write
|
||||
|
@ -28,7 +28,7 @@ MAXSPR EQU 128 ;Maximum Sprite Index
|
||||
ADDSPD: JSR SAVREG ;Save Sprite Index, Addend
|
||||
JSR GETSPD ;Read Sprite Address Register
|
||||
JSR ADDTXY ;Add Number to Address
|
||||
JMP SETSTD ;Write Sprite (TEMP0) Address Register
|
||||
BRA SETSTD ;Write Sprite (TEMP0) Address Register
|
||||
|
||||
;subspd(index,number) - Decrement Sprite Address Register
|
||||
;Args: A = Sprite Index
|
||||
@ -37,7 +37,7 @@ ADDSPD: JSR SAVREG ;Save Sprite Index, Addend
|
||||
SUBSPD: JSR SAVREG ;Save Sprite Index, Addend
|
||||
JSR GETSPD ;Read Sprite Address Register
|
||||
JSR ADDTXY ;Add Number to Address
|
||||
JMP SETSTD ;Write Sprite (TEMP0) Address Register
|
||||
BRA SETSTD ;Write Sprite (TEMP0) Address Register
|
||||
|
||||
;clrspr(index) - Set Sprite Attributes
|
||||
;Args: A = Sprite Index
|
||||
@ -133,7 +133,7 @@ GETSXF: RTS
|
||||
GETSPW: JSR GETSPS ;Get Sprite Size Register
|
||||
ASL ;Shift Left 2 Bits
|
||||
ASL
|
||||
JMP GETSP6 ;Then Right 6 Bits
|
||||
BRA GETSP6 ;Then Right 6 Bits
|
||||
|
||||
;getsph(index) - Get Sprite Height Specifier
|
||||
;Args: A = Sprite Index
|
||||
@ -327,7 +327,7 @@ SETSPZ: PHA ;Save Sprite Depth
|
||||
SETSP2: ASL ;Move to Bits 2 and 3
|
||||
ASL
|
||||
STX TEMP1 ;Save Bit Mask
|
||||
JMP SETSP6 ;Set Bits in Control Register
|
||||
BRA SETSP6 ;Set Bits in Control Register
|
||||
|
||||
;getspu(index) - Get Sprite Width, Height, and Mode
|
||||
;Args: A = Sprite Index
|
||||
@ -344,7 +344,7 @@ GETSPU: STA TEMP0 ;Save Sprite Index
|
||||
LDA TEMP0 ;Retrieve Sprite Index
|
||||
JSR GETSPP ;Get Mode
|
||||
TAX ;Return Mode in X
|
||||
.DC $7A ;PLY Height in Y
|
||||
PLY ;Height in Y
|
||||
PLA ;and Width in A
|
||||
RTS
|
||||
|
||||
@ -364,7 +364,7 @@ GETSPL: JSR GETSPU ;Get Width, Height, Mode and Execute GETSCL
|
||||
;Affects: A
|
||||
;Returns: Y,X = Data Size in Bytes
|
||||
GETSCL: ;.DC $FF ;Debug
|
||||
.DC $DA ;PHX Save Mode
|
||||
PHX ;Save Mode
|
||||
PHA ;Save Width
|
||||
TYA ;Copy Height to Accumulator
|
||||
JSR GETSCS ;Calculate Height in Pixles
|
||||
@ -376,7 +376,7 @@ GETSLK: ASL TEMP1 ;Multiply LSB
|
||||
ROL ;and MSB by 2
|
||||
DEY ;Decrement Counter
|
||||
BNE GETSLK ;and Loop if Not Zero
|
||||
.DC $FA ;PLX Retrieve Mode
|
||||
PLX ;Retrieve Mode
|
||||
BNE GETSSK ;If 0 (4 Bits Per Pixel)
|
||||
LSR ; Divide MSB
|
||||
ROR TEMP1 ; snd LSB by 2
|
||||
@ -444,7 +444,7 @@ SETSPW: PHA ;Save Sprite Index
|
||||
LDX #$CF ;Set Bit Mask
|
||||
TYA ;Copy Specifier to Accumulator
|
||||
AND #$03 ;Isolate Bits 0 and 1
|
||||
JMP SETSP4 ;Shift Left Four Bits and Write Masked
|
||||
BRA SETSP4 ;Shift Left Four Bits and Write Masked
|
||||
|
||||
;setsph(index) - Set Sprite Height Specifier
|
||||
;Args: A = Sprite Index
|
||||
@ -458,7 +458,7 @@ SETSP4: ASL
|
||||
ASL
|
||||
ASL
|
||||
ASL
|
||||
JMP SETSP7 ;Write Masked to Size Register
|
||||
BRA SETSP7 ;Write Masked to Size Register
|
||||
|
||||
;setspp(index) - Set Sprite Palette Offset
|
||||
;Args: A = Sprite Index
|
||||
@ -471,7 +471,7 @@ SETSP7: STA TEMP0 ;Save Value
|
||||
STX TEMP1 ;Save Bit Mask
|
||||
PLA ;Retrieve Sprite Index
|
||||
JSR GETSPS ;Get Sprite Size Register
|
||||
JMP SETSP8 ;Apply Mask, Set Bits, and Write
|
||||
BRA SETSP8 ;Apply Mask, Set Bits, and Write
|
||||
|
||||
;setsps(index,value) - Set Sprite Attribute Size Register
|
||||
;Args: A = Sprite Index
|
||||
|
@ -9,7 +9,8 @@ ECHO Compiling File %1.c02 for Commander X16
|
||||
..\c02.exe -h x16 -s x16 -s cbm %1 >%1.dbg
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO EOF
|
||||
ECHO Assembling File %1.asm
|
||||
C:\Programs\dasm %1.asm -f1 -o%1.prg -l%1.lst -s%1.sym
|
||||
..\a02.exe -p %1.asm %1.asm %1.lst >%1.out
|
||||
REM C:\Programs\dasm %1.asm -f1 -o%1.prg -l%1.lst -s%1.sym
|
||||
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO EOF
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user