1
0
mirror of https://github.com/RevCurtisP/C02.git synced 2024-09-27 14:56:27 +00:00
C02/c02.c

217 lines
5.5 KiB
C
Raw Normal View History

2017-03-28 04:09:18 +00:00
/**************************************************************
* C02 Compiler - (C) 2013 Curtis F Kaylor *
* *
* C02 is a simpified C-like language designed for the 6502 *
2017-03-28 04:09:18 +00:00
* *
* 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
2018-02-13 22:25:57 +00:00
#include "dclrtn.h" //Statement Compiling Code
#include "include.h" //Include File Parsing
2017-03-28 04:09:18 +00:00
/* Initilize Compiler Variables */
void init()
{
DEBUG("Initializing Compiler Variables\n",0);
defcnt = 0;
varcnt = 0;
lblcnt = 0;
curcol = 0;
curlin = 0;
strcpy(incdir, "../include/");
alcvar = TRUE;
2017-05-01 01:17:50 +00:00
inblck = FALSE;
xstmnt[0] = 0;
nxtwrd[0] = 0;
nxtptr = 0;
2017-06-27 00:16:23 +00:00
vrwrtn = FALSE;
zpaddr = 0;
invasc = FALSE;
2018-02-15 04:40:57 +00:00
mskasc = FALSE;
2018-02-13 23:26:57 +00:00
fcase = FALSE;
}
/* Reads and parses the next Word in Source File */
void pword()
{
lsrtrn = FALSE; //Clear RETURN flag
getwrd();
DEBUG("Parsing Word '%s'\n", word);
2018-02-13 23:26:57 +00:00
if (xstmnt[0]) {
if (wordis(xstmnt))
xstmnt[0] = 0; //Clear xstmnt
else
ERROR("Expected '%s' statement\n", xstmnt, EXIT_FAILURE);
2018-02-13 23:26:57 +00:00
}
2017-06-27 00:16:23 +00:00
if (!pmodfr() && !ptype(MTNONE))
pstmnt(); //Parse Statement
}
/* Process a directive */
void pdrctv()
{
skpchr(); //skip '#'
CCMNT('#');
getwrd(); //read directive into word
DEBUG("Processing directive '%s'\n", word);
2017-06-27 00:16:23 +00:00
if (wordis("DEFINE"))
pdefin(); //Parse Define
else if (wordis("INCLUDE"))
pincfl(); //Parse Include File
2017-06-27 00:16:23 +00:00
else if (wordis("ERROR")) {
ERROR("Error \n", 0, EXIT_FAILURE);
2017-06-27 00:16:23 +00:00
}
else if (wordis("PRAGMA"))
pprgma();
else
ERROR("Illegal directive %s encountered\n", word, EXIT_FAILURE);
}
2018-02-13 23:16:23 +00:00
void prolog()
{
DEBUG("Writing Assembly Prolog\n", 0);
asmlin(CPUOP,CPUARG);
setcmt("Program ");
addcmt(srcnam);
cmtlin();
}
void epilog()
{
2017-06-27 00:16:23 +00:00
if (!vrwrtn) vartbl(); //Write Variable Table
}
/* Compile Source Code*/
void compile()
{
DEBUG("Starting Compilation\n", 0);
prolog();
2018-02-17 19:50:43 +00:00
phdrfl(); //Process Header File specified on Command Line
skpchr();
DEBUG("Parsing Code\n", 0);
while (TRUE)
{
skpspc();
//DEBUG("Checking next character '%c'\n", nxtchr);
if (match(EOF))
break;
2017-05-01 01:17:50 +00:00
else if (match('}'))
endblk(TRUE); //End Multi-Line Program Block
else if (match('#'))
2017-05-01 01:17:50 +00:00
pdrctv(); //Parse Directive
else if (match('/'))
2017-05-01 01:17:50 +00:00
skpcmt(); //Skip Comment
else if (isalph())
2017-05-01 01:17:50 +00:00
pword(); //Parse Word
else
2017-05-01 01:17:50 +00:00
ERROR("Unexpected character '%c'\n", nxtchr, EXIT_FAILURE);
}
epilog();
}
/* Display "Usage" text and exit*/
void usage()
{
printf("Usage: c02 sourcefile.c02\n");
exit(EXIT_FAILURE);
}
2018-02-17 19:50:43 +00:00
/* Parse Command Line Option */
2017-06-27 00:16:23 +00:00
int popt(int arg, int argc, char *argv[])
{
2018-02-17 19:50:43 +00:00
char argstr[32]; //Argument String
char opt; //Option
2017-06-27 00:16:23 +00:00
char optarg[32]; //Option Argument
2018-02-17 19:50:43 +00:00
strncpy (argstr, argv[arg], 31);
if (strlen(argstr) != 2)
ERROR("malformed option %s\n", argstr, EXIT_FAILURE);
opt = toupper(argstr[1]);
if (strchr("H", 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;
default:
ERROR("Illegal option -%c\n", opt, EXIT_FAILURE);
}
return arg;
2017-06-27 00:16:23 +00:00
}
/* 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[])
{
2017-06-27 00:16:23 +00:00
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);
}
else if (srcnam[0] == 0) {
strcpy(srcnam, argv[arg]); //set Source File Name to first arg
DEBUG("srcnam set to '%s'\n", srcnam);
}
else if (outnam[0] == 0) {
strcpy(outnam, argv[arg]); //set Out File Name to second arg
DEBUG("outnam set to '%s'\n", outnam);
}
else
ERROR("Unexpected argument '%s'\n", argv[arg], EXIT_FAILURE);
}
}
2017-03-28 04:09:18 +00:00
int main(int argc, char *argv[])
2017-03-28 04:09:18 +00:00
{
debug = TRUE; //Output Debug Info
gencmt = TRUE; //Generate Assembly Language Comments
2017-03-28 04:09:18 +00:00
printf("C02 Compiler (C) 2012 Curtis F Kaylor\n" );
2018-02-17 19:50:43 +00:00
init(); //Initialize Global Variables
2017-03-28 04:09:18 +00:00
pargs(argc, argv); //Parse Command Line Arguments
opnsrc(); //Open Source File
opnout(); //Open Output File
opnlog(); //Open Log File
2017-03-28 04:09:18 +00:00
2018-02-17 19:50:43 +00:00
setsrc(); //Set Input to Source File
2017-03-28 04:09:18 +00:00
compile();
2017-06-27 00:16:23 +00:00
logdef();
2017-03-28 04:09:18 +00:00
clssrc(); //Close Source File
clsout(); //Close Output File
clslog(); //Close Log File
2017-03-28 04:09:18 +00:00
}