mirror of
https://github.com/RevCurtisP/C02.git
synced 2024-09-27 14:56:27 +00:00
Save entire project before changing condition parser to use JMP
This commit is contained in:
parent
91f870bd88
commit
1abb077f09
86
asm.c
Normal file
86
asm.c
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*************************************
|
||||||
|
* 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 "parse.h"
|
||||||
|
#include "asm.h"
|
||||||
|
|
||||||
|
char asmcmt[LINELEN]; //Processed Assembly Language Comment
|
||||||
|
|
||||||
|
/* Set comment to string */
|
||||||
|
void setcmt(char *s)
|
||||||
|
{
|
||||||
|
strcpy(cmtasm, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append string to comment */
|
||||||
|
void addcmt(char *s)
|
||||||
|
{
|
||||||
|
strcat(cmtasm, " ");
|
||||||
|
strcat(cmtasm, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append character to comment */
|
||||||
|
void chrcmt(char c)
|
||||||
|
{
|
||||||
|
int i = strlen(cmtasm);
|
||||||
|
cmtasm[i++] = c;
|
||||||
|
cmtasm[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void prccmt()
|
||||||
|
{
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
DEBUG("Writing Comment Line: %s\n", cmtasm);
|
||||||
|
fprintf(outfil, "; %s\n", cmtasm);
|
||||||
|
setcmt("");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Output a variable definition line *
|
||||||
|
* Uses: word - assembly oprnd */
|
||||||
|
void equlin()
|
||||||
|
{
|
||||||
|
fprintf(outfil, ASMFMT, lblasm, EQUOP, word, "");
|
||||||
|
if (debug) printf(ASMFMT, lblasm, EQUOP, word, "");
|
||||||
|
lblasm[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void prolog()
|
||||||
|
{
|
||||||
|
DEBUG("Writing Assembly Prolog\n", 0);
|
||||||
|
asmlin(CPUOP,CPUARG);
|
||||||
|
strcpy(cmtasm, "Program ");
|
||||||
|
strcat(cmtasm, srcnam);
|
||||||
|
cmtlin();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
17
asm.h
Normal file
17
asm.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/*************************************
|
||||||
|
* C02 Assembly Language Routines *
|
||||||
|
*************************************/
|
||||||
|
|
||||||
|
char cmtasm[LINELEN]; //Assembly Language Comment Text
|
||||||
|
char lblasm[LABLEN+2]; //Label to emit on next asm line
|
||||||
|
|
||||||
|
void setcmt(char *s); //Set Assembly Line Comment to String
|
||||||
|
void addcmt(char *s); //Append String to Assembly Line Comment
|
||||||
|
void chrcmt(char c); //Append Character to Assembly Line Comment
|
||||||
|
|
||||||
|
void asmlin(char *opcode, char *oprnd); //Output a line of assembly code
|
||||||
|
void cmtlin(); //Output a comment lines
|
||||||
|
void equlin(); //Output an equate line
|
||||||
|
|
||||||
|
void prolog(); //Write Assembly Language Initialization Code
|
||||||
|
|
35
common.c
Normal file
35
common.c
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*************************************
|
||||||
|
* C02 Common Definitions & Routines *
|
||||||
|
*************************************/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
/* Error - Print Input File name & position and exit */
|
||||||
|
void exterr(int errnum)
|
||||||
|
{
|
||||||
|
printf("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)
|
||||||
|
{
|
||||||
|
printf("Expected %s, but found '%c'\n", expstr, nxtchr);
|
||||||
|
exterr(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print current position in file */
|
||||||
|
void prtpos()
|
||||||
|
{
|
||||||
|
printf("(%s: %d,%d) ", inpnam, curlin, curcol);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
53
common.h
Normal file
53
common.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*************************************
|
||||||
|
* C02 Common Definitions & Routines *
|
||||||
|
*************************************/
|
||||||
|
|
||||||
|
#define FNAMLEN 255 //Maximum File Name Length
|
||||||
|
#define LINELEN 255 //Maximum Input/Output Line Length
|
||||||
|
#define DEFLEN 9 //Maximum Definition Text Length
|
||||||
|
#define MAXDEF 255 //Maximum Number of Definitions
|
||||||
|
#define VARLEN 6 //Maximum Variable Length
|
||||||
|
#define MAXVAR 255 //Maximum Number of Variables
|
||||||
|
#define DATASPC 2048 //Space to Allocate for
|
||||||
|
#define LABLEN 6 //Maximum Label Length
|
||||||
|
#define LABFMT "L_%04d" //Label Format
|
||||||
|
#define LABSFX ":" //Label Suffix
|
||||||
|
#define MAXLAB 15 //Maximum Number of Labels (Nesting Depth)
|
||||||
|
|
||||||
|
#define CPUOP "PROCESSOR" //Target CPU Pseudo-Operator
|
||||||
|
#define CPUARG "6502" //Target CPU Operand
|
||||||
|
#define EQUOP "EQU" //Equate Pseudo-Op
|
||||||
|
#define BYTEOP "DC" //Define Byte Pseudo-Op
|
||||||
|
#define STROP "DS" //Define String Pseudo-Op
|
||||||
|
|
||||||
|
#define ASMFMT "%-7s %-3s %-12s %s\n" //Assembly Language Line printf Format
|
||||||
|
|
||||||
|
/* Internal defines */
|
||||||
|
#define TRUE -1
|
||||||
|
#define FALSE 0
|
||||||
|
|
||||||
|
#define DEBUG(fmt, val) if (debug) {prtpos(); printf(fmt, val);}
|
||||||
|
#define ERROR(fmt, val, err) if (debug) {printf(fmt, val);exterr(err);}
|
||||||
|
#define SCMNT(str) if (gencmt) {setcmt(str);}
|
||||||
|
#define ACMNT(str) if (gencmt) {addcmt(str);}
|
||||||
|
#define CCMNT(chr) if (gencmt) {chrcmt(chr);}
|
||||||
|
|
||||||
|
int gencmt; //Generate Assembly Language Comments
|
||||||
|
int debug; //Print Debug Info (TRUE or FALSE)
|
||||||
|
|
||||||
|
int curcol, curlin; //Position in Source Code
|
||||||
|
int savcol, savlin; //Save Position in Source Code
|
||||||
|
|
||||||
|
int nxtchr; //Next Character of Source File to Process
|
||||||
|
int nxtupc; //Next Character Converted to Uppercase
|
||||||
|
int savchr; //Holds nxtchr when switching input files
|
||||||
|
|
||||||
|
char inpnam[FNAMLEN]; //Include File Name
|
||||||
|
|
||||||
|
int alcvar; //Allocate Variables Flag
|
||||||
|
|
||||||
|
void exterr(int errnum); //Print current file name & position and exit
|
||||||
|
void expctd(char *expected); //Print Expected message and exit
|
||||||
|
|
||||||
|
void prtpos(); //Print current file name and position
|
||||||
|
|
134
cond.c
Normal file
134
cond.c
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
/************************************
|
||||||
|
* 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
|
||||||
|
|
||||||
|
/* Convert Comparison Operator Character *
|
||||||
|
* Args: Comparison Operator Character *
|
||||||
|
* Returns: Comparison Operator Bit Mask */
|
||||||
|
int enccmp(char c)
|
||||||
|
{
|
||||||
|
int e;
|
||||||
|
switch(c)
|
||||||
|
{
|
||||||
|
case '=': e = 1; break;
|
||||||
|
case '<': e = 2; break;
|
||||||
|
case '>': e = 4; break;
|
||||||
|
default: e = 0;
|
||||||
|
}
|
||||||
|
if (e) {
|
||||||
|
CCMNT(c);
|
||||||
|
skpchr();
|
||||||
|
}
|
||||||
|
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(int cmprtr)
|
||||||
|
{
|
||||||
|
DEBUG("Processing comparison operator %d\n", cmprtr);
|
||||||
|
switch(cmprtr) {
|
||||||
|
case 1: // = or ==
|
||||||
|
asmlin("CMP", term);
|
||||||
|
asmlin("BNE", curlbl);
|
||||||
|
break;
|
||||||
|
case 2: // <
|
||||||
|
if (cmpsgn) {
|
||||||
|
asmlin("CMP", term);
|
||||||
|
asmlin("BPL", curlbl);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
asmlin("CMP", term);
|
||||||
|
asmlin("BCS", curlbl);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3: // <= or =<
|
||||||
|
if (cmpsgn) {
|
||||||
|
asmlin("CMP", term);
|
||||||
|
asmlin("BPL", curlbl);
|
||||||
|
asmlin("BNE", curlbl);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
asmlin("CLC", "");
|
||||||
|
asmlin("SBC", term);
|
||||||
|
asmlin("BCS", curlbl);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4: // >
|
||||||
|
if (cmpsgn) {
|
||||||
|
asmlin("CMP", term);
|
||||||
|
asmlin("BMI", curlbl);
|
||||||
|
asmlin("BEQ", curlbl);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
asmlin("CLC", "");
|
||||||
|
asmlin("SBC", term);
|
||||||
|
asmlin("BCC", curlbl);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 5: // >= or =>
|
||||||
|
if (cmpsgn) {
|
||||||
|
asmlin("CMP", term);
|
||||||
|
asmlin("BMI", curlbl);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
asmlin("CMP", term);
|
||||||
|
asmlin("BCC", curlbl);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 6: // <> or ><
|
||||||
|
asmlin("CMP", term);
|
||||||
|
asmlin("BEQ", curlbl);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Unsupported comparison operator index %d\n", cmprtr);
|
||||||
|
exterr(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse Comparison Operator *
|
||||||
|
* Sets: comparitor - Encoded Comparison Operator */
|
||||||
|
int prscmp()
|
||||||
|
{
|
||||||
|
cmpenc = enccmp(nxtchr); //Encode Comparison Character
|
||||||
|
if (cmpenc == 0)
|
||||||
|
expctd("comparison operator");
|
||||||
|
cmprtr = cmpenc; //Set Encoded Comparator
|
||||||
|
cmpenc = enccmp(nxtchr); //Encode Next Comparison Character
|
||||||
|
if (cmpenc != 0)
|
||||||
|
cmprtr = cmprtr | cmpenc; //Combine Encoded Comparator
|
||||||
|
skpspc();
|
||||||
|
DEBUG("Parsed comparator %d\n", cmprtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse and Compile Conditional Expression *
|
||||||
|
* Condition = <expression> <comparator> <term> */
|
||||||
|
void prscnd(char trmntr)
|
||||||
|
{
|
||||||
|
DEBUG("Parsing condition\n", 0);
|
||||||
|
prsxpr(0);
|
||||||
|
skpspc();
|
||||||
|
prscmp();
|
||||||
|
prstrm();
|
||||||
|
CCMNT(trmntr);
|
||||||
|
prccmp(cmprtr);
|
||||||
|
expect(trmntr);
|
||||||
|
}
|
||||||
|
|
8
cond.h
Normal file
8
cond.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/************************************
|
||||||
|
* C02 Conditional Parsing Routines *
|
||||||
|
************************************/
|
||||||
|
|
||||||
|
int cmpsgn; // Comparison contains signed operands
|
||||||
|
|
||||||
|
void prscnd(char trmntr); //Parse Conditional Expression
|
||||||
|
|
169
expr.c
Normal file
169
expr.c
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
/***********************************
|
||||||
|
* 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 "expr.h"
|
||||||
|
|
||||||
|
/* Parse value (constant or identifier) *
|
||||||
|
* Sets: value - the value (as a string) *
|
||||||
|
* valtyp - value type */
|
||||||
|
void prsval()
|
||||||
|
{
|
||||||
|
DEBUG("Parsing value\n", 0);
|
||||||
|
//expdef(); //Check for and expand define -- BROKEN!
|
||||||
|
if (iscpre())
|
||||||
|
prscon(0xff); //Parse Constant
|
||||||
|
else if (isalph())
|
||||||
|
prsvar(); //Parse Variable
|
||||||
|
else
|
||||||
|
expctd("constant or variable");
|
||||||
|
skpspc();
|
||||||
|
ACMNT(word);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse array index *
|
||||||
|
* Sets: value - array index or *
|
||||||
|
* "" if no index defined */
|
||||||
|
void prsidx()
|
||||||
|
{
|
||||||
|
expect('[');
|
||||||
|
prsval();
|
||||||
|
DEBUG("Parsed array index '%s'\n", value);
|
||||||
|
expect(']');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse term in expression *
|
||||||
|
* Sets: term - the term (as a string) *
|
||||||
|
* trmtxt - type of term */
|
||||||
|
void prstrm()
|
||||||
|
{
|
||||||
|
DEBUG("Parsing term\n", 0);
|
||||||
|
prsval();
|
||||||
|
if (valtyp == FUNCTION) {
|
||||||
|
ERROR("Function call only allowed in first term\n", 0, EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
strcpy(term, value);
|
||||||
|
DEBUG("Parsed term %s\n", term);
|
||||||
|
trmtxt = valtyp;
|
||||||
|
if (trmtxt == ARRAY) {
|
||||||
|
prsidx();
|
||||||
|
asmlin("LDX", value);
|
||||||
|
strcat(term, ",X");
|
||||||
|
}
|
||||||
|
skpspc();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse and Compile Pointer Dereference */
|
||||||
|
void prsadr(char dlmtr)
|
||||||
|
{
|
||||||
|
prsvar();
|
||||||
|
DEBUG("Dereferencing variable '%s'\n", value);
|
||||||
|
ACMNT(value);
|
||||||
|
strcpy(word,"#<");
|
||||||
|
strcat(word,value);
|
||||||
|
asmlin("LDX", word);
|
||||||
|
strcpy(word,"#>");
|
||||||
|
strcat(word,value);
|
||||||
|
asmlin("LDY", word);
|
||||||
|
if (dlmtr) expect(dlmtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Parse function call in first term of expression *
|
||||||
|
* Function call may include term as an argument */
|
||||||
|
void prsxfn()
|
||||||
|
{
|
||||||
|
char fnname[255]; /*Function name*/
|
||||||
|
DEBUG("Processing expression function call '%s'...\n", term);
|
||||||
|
strcpy(fnname, term);
|
||||||
|
skpchr(); //skip open paren
|
||||||
|
CCMNT('(');
|
||||||
|
if (look('&'))
|
||||||
|
prsadr(0);
|
||||||
|
else if (isvpre()) {
|
||||||
|
prstrm();
|
||||||
|
asmlin("LDA", term);
|
||||||
|
}
|
||||||
|
expect(')');
|
||||||
|
asmlin("JSR", fnname);
|
||||||
|
skpspc();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse first term of expession *
|
||||||
|
* First term can include function calls */
|
||||||
|
void prsftm()
|
||||||
|
{
|
||||||
|
prsval();
|
||||||
|
DEBUG("Processing first term '%s'...\n", value);
|
||||||
|
strcpy(term, value);
|
||||||
|
trmtxt = valtyp;
|
||||||
|
if (trmtxt == FUNCTION) {
|
||||||
|
prsxfn(); //Parse Expression Function
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (trmtxt == ARRAY) {
|
||||||
|
prsidx();
|
||||||
|
asmlin("LDX", value);
|
||||||
|
strcat(term, ",X");
|
||||||
|
}
|
||||||
|
asmlin("LDA", term);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process Arithmetic or Bitwise Operator *
|
||||||
|
* and the term that follows it */
|
||||||
|
void prcopr()
|
||||||
|
{
|
||||||
|
DEBUG("Processing operator '%c'\n", oper);
|
||||||
|
switch(oper)
|
||||||
|
{
|
||||||
|
case '+':
|
||||||
|
asmlin("CLC", "");
|
||||||
|
asmlin("ADC", term);
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
asmlin("SEC", "");
|
||||||
|
asmlin("SBC", term);
|
||||||
|
break;
|
||||||
|
case '&':
|
||||||
|
asmlin("AND", term);
|
||||||
|
break;
|
||||||
|
case '|':
|
||||||
|
asmlin("ORA", term);
|
||||||
|
break;
|
||||||
|
case '^':
|
||||||
|
asmlin("EOR", term);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Unrecognized operator '%c'\n", oper);
|
||||||
|
exterr(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse and compile expression */
|
||||||
|
void prsxpr(char trmntr)
|
||||||
|
{
|
||||||
|
DEBUG("Parsing expression\n", 0);
|
||||||
|
skpspc();
|
||||||
|
if (match('-'))
|
||||||
|
asmlin("LDA", "#$00"); //Handle Unary Minus
|
||||||
|
else
|
||||||
|
prsftm(); //Parse First Term
|
||||||
|
while (isoper())
|
||||||
|
{
|
||||||
|
prsopr(); //Parse Operator
|
||||||
|
prstrm(); //Parse Term
|
||||||
|
prcopr(); //Process Operator
|
||||||
|
}
|
||||||
|
if (trmntr)
|
||||||
|
expect(trmntr);
|
||||||
|
}
|
||||||
|
|
11
expr.h
Normal file
11
expr.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/**********************************
|
||||||
|
* C02 Expession Parsing Routines *
|
||||||
|
**********************************/
|
||||||
|
|
||||||
|
char term[255]; /*Term parsed from equation*/
|
||||||
|
int trmtxt; /*Term Type*/
|
||||||
|
|
||||||
|
void prsidx(); //Parse Array Index
|
||||||
|
void prstrm(); //Parse Term in Expression
|
||||||
|
void prsxpr(char trmntr); //Parse Expression
|
||||||
|
|
103
files.c
Normal file
103
files.c
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/******************************
|
||||||
|
* 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()
|
||||||
|
{
|
||||||
|
DEBUG("Processing Source File Name '%s'\n", srcnam);
|
||||||
|
if (strrchr(srcnam, '.') == NULL) //if no extension
|
||||||
|
strcat(srcnam, ".c02"); // 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()
|
||||||
|
{
|
||||||
|
fclose(srcfil);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open Output File *
|
||||||
|
* Uses: outnam - Output File Name *
|
||||||
|
* Sets: outfil - Output File Handle */
|
||||||
|
void opnout()
|
||||||
|
{
|
||||||
|
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) //if no extension
|
||||||
|
strcat(outnam, ".asm"); // 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()
|
||||||
|
{
|
||||||
|
fprintf(outfil, "\n");
|
||||||
|
fclose(outfil);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open Log File *
|
||||||
|
* Uses: srcnam - Source File Name *
|
||||||
|
* Sets: logfil - Log File Handle */
|
||||||
|
void opnlog()
|
||||||
|
{
|
||||||
|
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 ".asm"
|
||||||
|
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() {
|
||||||
|
fclose(logfil);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open Include file *
|
||||||
|
* Uses: incnam - Include File Name *
|
||||||
|
* Sets: incfil - Include File Handle */
|
||||||
|
void opninc()
|
||||||
|
{
|
||||||
|
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() {
|
||||||
|
fclose(incfil);
|
||||||
|
}
|
||||||
|
|
23
files.h
Normal file
23
files.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/******************************
|
||||||
|
* 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
|
||||||
|
|
||||||
|
void opnsrc(); //Open Source File
|
||||||
|
void clssrc(); //Close Source File
|
||||||
|
|
||||||
|
void opnout(); //Open Output File
|
||||||
|
void clsout(); //Close Output File
|
||||||
|
|
||||||
|
void opninc(); //Open Include File
|
||||||
|
void clsinc(); //Close Include File
|
170
include.c
Normal file
170
include.c
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
/*************************************
|
||||||
|
* C02 Include File Parsing Routines *
|
||||||
|
*************************************/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "files.h"
|
||||||
|
#include "asm.h"
|
||||||
|
#include "parse.h"
|
||||||
|
#include "vars.h"
|
||||||
|
#include "include.h"
|
||||||
|
|
||||||
|
/* Reads next include file name from Source File *
|
||||||
|
* Sets: incnam - the include file name */
|
||||||
|
void pincnm()
|
||||||
|
{
|
||||||
|
char dlmtr;
|
||||||
|
int inclen = 0;
|
||||||
|
skpspc();
|
||||||
|
dlmtr = getnxt();
|
||||||
|
if (dlmtr == '<') {
|
||||||
|
strcpy(incnam, "include/");
|
||||||
|
inclen = strlen(incnam);
|
||||||
|
dlmtr = '>';
|
||||||
|
}
|
||||||
|
else if (dlmtr != '"')
|
||||||
|
ERROR("Unexpected character '%c' after include\n", dlmtr, EXIT_FAILURE);
|
||||||
|
while (!match(dlmtr))
|
||||||
|
{
|
||||||
|
incnam[inclen++] = nxtchr;
|
||||||
|
skpchr();
|
||||||
|
}
|
||||||
|
skpchr(); //skip end dlmtr
|
||||||
|
incnam[inclen] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process assembly language include file */
|
||||||
|
void incasm() {
|
||||||
|
opninc();
|
||||||
|
setcmt("======== Assembler File ");
|
||||||
|
addcmt(incnam);
|
||||||
|
addcmt(" =======");
|
||||||
|
cmtlin();
|
||||||
|
while (fgets(line, sizeof line, incfil) != NULL) {
|
||||||
|
DEBUG("Writing line: %s", line);
|
||||||
|
fputs(line, outfil);
|
||||||
|
}
|
||||||
|
setcmt("==========================================");
|
||||||
|
cmtlin();
|
||||||
|
clsinc();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process Include File Directive */
|
||||||
|
void pincdr()
|
||||||
|
{
|
||||||
|
skpchr(); //skip '#'
|
||||||
|
getwrd(); //read directive into word
|
||||||
|
DEBUG("Processing include file directive '%s'\n", word);
|
||||||
|
if (wordis("define"))
|
||||||
|
prsdef();
|
||||||
|
else {
|
||||||
|
printf("Unrecognized directive '%s'\n", word);
|
||||||
|
exterr(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse Header Word */
|
||||||
|
void phdwrd() {
|
||||||
|
getwrd();
|
||||||
|
if (wordis("void"))
|
||||||
|
pdecl(VTVOID);
|
||||||
|
else if (wordis("byte"))
|
||||||
|
pdecl(VTBYTE);
|
||||||
|
else if (wordis("char"))
|
||||||
|
pdecl(VTCHAR);
|
||||||
|
else {
|
||||||
|
printf("Unexpected word '%s' in header\n", word);
|
||||||
|
exterr(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save Source File Information */
|
||||||
|
void savsrc() {
|
||||||
|
savchr = nxtchr;
|
||||||
|
savcol = curcol;
|
||||||
|
savlin = curlin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set Include File Information */
|
||||||
|
void setinc() {
|
||||||
|
curcol = 0;
|
||||||
|
curlin = 0;
|
||||||
|
inpfil = incfil;
|
||||||
|
strcpy(inpnam, incnam);
|
||||||
|
alcvar = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restore Source File Pointer*/
|
||||||
|
void rstsrc() {
|
||||||
|
nxtchr = savchr;
|
||||||
|
nxtupc = toupper(nxtchr);
|
||||||
|
curcol = savcol;
|
||||||
|
curlin = savlin;
|
||||||
|
inpfil = srcfil;
|
||||||
|
strcpy(inpnam, srcnam);
|
||||||
|
alcvar = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process header include file */
|
||||||
|
void inchdr() {
|
||||||
|
savsrc(); //Save Source File Information
|
||||||
|
opninc(); //Open Include File
|
||||||
|
setinc(); //Set Include File Information
|
||||||
|
skpchr();
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
skpspc();
|
||||||
|
if (match(EOF)) break;
|
||||||
|
DEBUG("Checking next character '%c'\n", nxtchr);
|
||||||
|
if (match('#'))
|
||||||
|
pincdr();
|
||||||
|
else if (match('/'))
|
||||||
|
skpcmt();
|
||||||
|
else if (isalph())
|
||||||
|
phdwrd();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Unexpected character '%c'\n", nxtchr);
|
||||||
|
exterr(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clsinc();
|
||||||
|
rstsrc();
|
||||||
|
nxtchr = savchr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process header include file */
|
||||||
|
void include_hfil() {
|
||||||
|
ERROR("Header files with extension .h not supported", 0, EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
/* Process include file */
|
||||||
|
void pincfl()
|
||||||
|
{
|
||||||
|
pincnm(); //Parse Include File Name
|
||||||
|
DEBUG("Processing include file '%s'\n", incnam);
|
||||||
|
char *dot = strrchr(incnam, '.'); //find extension
|
||||||
|
if (dot == NULL) {
|
||||||
|
printf("Invalid include file name '%sn", incnam);
|
||||||
|
exterr(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (strcmp(dot, ".asm") == 0)
|
||||||
|
incasm();
|
||||||
|
else if (strcmp(dot, ".h") == 0)
|
||||||
|
include_hfil();
|
||||||
|
else if (strcmp(dot, ".h02") == 0) {
|
||||||
|
inchdr(); //Process Header File
|
||||||
|
strcpy(dot, ".asm");
|
||||||
|
incasm(); //Process Assembly File with Same Name
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("Unrecognized include file extension '%s'\n'", dot);
|
||||||
|
exterr(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
7
include.h
Normal file
7
include.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
/*************************************
|
||||||
|
* C02 Include File Parsing Routines *
|
||||||
|
*************************************/
|
||||||
|
|
||||||
|
char line[255]; /*Entire line parsed from include file*/
|
||||||
|
|
||||||
|
|
61
label.c
Normal file
61
label.c
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/******************************************************
|
||||||
|
* 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 "asm.h"
|
||||||
|
#include "parse.h"
|
||||||
|
#include "label.h"
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
asmlin("",""); //Emit Block End Label on it's own line
|
||||||
|
if (strlen(word) > LABLEN)
|
||||||
|
ERROR("Label '%s' exceeds maximum size", word, EXIT_FAILURE);
|
||||||
|
strcpy(lblasm, lblset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse label in code */
|
||||||
|
void prslbl()
|
||||||
|
{
|
||||||
|
DEBUG("Parsing Label '%s''\n", word);
|
||||||
|
skpchr(); //skip ':'
|
||||||
|
setlbl(word);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* generate new label */
|
||||||
|
void newlbl(int lbtype)
|
||||||
|
{
|
||||||
|
sprintf(curlbl, LABFMT, lblnxt++);
|
||||||
|
DEBUG("Generated new label '%s'\n", curlbl);
|
||||||
|
strcpy(lblnam[lblcnt++], curlbl);
|
||||||
|
lbltyp[lblcnt] = lbtype;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set label to emit on next line and remove from stack */
|
||||||
|
void lbllin()
|
||||||
|
{
|
||||||
|
int lbtype = lbltyp[--lblcnt];
|
||||||
|
if (lbtype == 1) {
|
||||||
|
DEBUG("Ending Loop at Level %d'\n", lblcnt);
|
||||||
|
strcpy(endlbl, lblnam[lblcnt]); //Save End of Loop Label
|
||||||
|
asmlin("JMP", lblnam[--lblcnt]); //Jump to Beginning of Loop
|
||||||
|
setlbl(endlbl); //Set End of Loop Label
|
||||||
|
}
|
||||||
|
else
|
||||||
|
setlbl(lblnam[lblcnt]);
|
||||||
|
DEBUG("Set label '%s' to emit on next line\n", lblasm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
19
label.h
Normal file
19
label.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/******************************************************
|
||||||
|
* C02 Label Parsing, Generation, and Lookup Routines *
|
||||||
|
******************************************************/
|
||||||
|
|
||||||
|
char curlbl[LABLEN+1]; //Most recently generated label
|
||||||
|
char endlbl[LABLEN+1]; //Label at end of block
|
||||||
|
char lblnam[MAXLAB+1][LABLEN+1]; //Label Name Table
|
||||||
|
int lbltyp[MAXLAB+1]; //Label Type
|
||||||
|
int lblcnt; //Number of Labels in stack
|
||||||
|
int lblnxt; //Sequence of next label to be generated
|
||||||
|
char lbltmp[LABLEN+1]; //Label Temporary Storage
|
||||||
|
|
||||||
|
enum ltypes {LTIF, LTLOOP, LTEND}; //Label Types
|
||||||
|
|
||||||
|
void prslbl(); //Parse Label From Code
|
||||||
|
void newlbl(); //Generate New Block Label
|
||||||
|
void lbllin(); //Pull Last Label and Emit on Next Line
|
||||||
|
void setlbl(); //Emit word as Label on Next Line
|
||||||
|
|
385
parse.c
Normal file
385
parse.c
Normal file
@ -0,0 +1,385 @@
|
|||||||
|
/*************************************
|
||||||
|
* C02 Input File Parsing Routines *
|
||||||
|
*************************************/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "files.h"
|
||||||
|
#include "parse.h"
|
||||||
|
|
||||||
|
char opstr[2]; //Operator as a String
|
||||||
|
|
||||||
|
/* Various tests against nxtchr */
|
||||||
|
int match(char c) {return (nxtchr == c);}
|
||||||
|
int inbtwn(char mn, char mx) {return nxtchr >= mn && nxtchr <= mx;}
|
||||||
|
int isprnt() {return isprint(nxtchr);}
|
||||||
|
int isalph() {return isalpha(nxtchr);}
|
||||||
|
int isanum() {return isalnum(nxtchr);}
|
||||||
|
int isdec() {return inbtwn('0', '9');}
|
||||||
|
int ishexd() {return isdec() || inbtwn('A', 'Z');}
|
||||||
|
int isbin() {return inbtwn('0', '1');}
|
||||||
|
int isnl() {return match('\n') || match('\r');}
|
||||||
|
int isspc() {return isspace(nxtchr);}
|
||||||
|
int isnpre() {return isdec() || match('$') || match('%');}
|
||||||
|
int isapos() {return match('\'');}
|
||||||
|
int iscpre() {return isnpre() || isapos();}
|
||||||
|
int isvpre() {return isalph() || iscpre();}
|
||||||
|
int isoper() {return (strchr("+-&|^", nxtchr)) ? TRUE : FALSE;}
|
||||||
|
int ispopr() {return (strchr("+-<>", nxtchr)) ? TRUE : FALSE;}
|
||||||
|
|
||||||
|
/* if Word is s then return TRUE else return FALSE*/
|
||||||
|
int wordis(char *s)
|
||||||
|
{
|
||||||
|
return strcmp(word, s) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get Next Character from Current Input File *
|
||||||
|
* Uses: inpfil - Input File Handle *
|
||||||
|
* Sets: nxtchr - Next Character in Source File */
|
||||||
|
char getnxt()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int wascr = match('\r');
|
||||||
|
char c = nxtchr;
|
||||||
|
//if (nxtwrd[nxtptr]) //If nxtwrd is set
|
||||||
|
// nxtchr = nxtwrd[nxtptr++]; // Pop First Character from nxtwrd
|
||||||
|
//else
|
||||||
|
nxtchr = fgetc(inpfil);
|
||||||
|
nxtupc = toupper(nxtchr);
|
||||||
|
if (wascr && match('\n')) return c; //Skip NL after CR
|
||||||
|
if (isnl()) curcol=1; else curcol++;
|
||||||
|
if (curcol == 1) curlin++;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Advance Input File to next printable character */
|
||||||
|
void skpspc()
|
||||||
|
{
|
||||||
|
DEBUG("Skipping Spaces\n", 0);
|
||||||
|
while (isspc())
|
||||||
|
getnxt();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the next printable character is c *
|
||||||
|
* and advance past it if it is *
|
||||||
|
* Returns TRUE is character is found, *
|
||||||
|
* otherwise FALSE */
|
||||||
|
int look(char c)
|
||||||
|
{
|
||||||
|
int found;
|
||||||
|
skpspc();
|
||||||
|
found = match(c);
|
||||||
|
if (found) {
|
||||||
|
skpchr();
|
||||||
|
CCMNT(c);
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if next printable character is c then skip, else generate error */
|
||||||
|
void expect(char c)
|
||||||
|
{
|
||||||
|
if (look(c))
|
||||||
|
return;
|
||||||
|
else {
|
||||||
|
printf("Expected Character '%c', but found '%c'\n", c, nxtchr);
|
||||||
|
exterr(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Advance Input File to next printable character */
|
||||||
|
void skpchr() {char skip = getnxt();}
|
||||||
|
|
||||||
|
/* Advance Input File to end of line */
|
||||||
|
void skpeol() {while (!isnl()) getnxt();}
|
||||||
|
|
||||||
|
/* Advance Source File to end of comment *
|
||||||
|
* Recognizes both C and C++ style comments */
|
||||||
|
void skpcmt()
|
||||||
|
{
|
||||||
|
DEBUG("Skipping Comment\n", 0);
|
||||||
|
skpchr(); //skip initial /
|
||||||
|
if (match('/')) //if C style comment
|
||||||
|
skpeol(); // skip rest of line
|
||||||
|
else if (match('*')) //if C++ style comment
|
||||||
|
while (TRUE) // skip to */
|
||||||
|
{
|
||||||
|
skpchr();
|
||||||
|
if (!match('*')) continue;
|
||||||
|
while (match('*')) skpchr();
|
||||||
|
if (!match('/')) continue;
|
||||||
|
skpchr();
|
||||||
|
break;
|
||||||
|
//todo: add code to catch unterminated comment
|
||||||
|
}
|
||||||
|
else //if neither
|
||||||
|
expctd("/ or *"); // error out
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reads next Word in current Input File, where *
|
||||||
|
* a Word is a sequence of AlphaNumeric characters *
|
||||||
|
* Sets: word - the Word read from the source file */
|
||||||
|
void getwrd()
|
||||||
|
{
|
||||||
|
int wrdlen = 0;
|
||||||
|
skpspc();
|
||||||
|
if (!isalph()) expctd("Alphabetic Character");
|
||||||
|
while (isanum())
|
||||||
|
{
|
||||||
|
word[wrdlen++] = getnxt();
|
||||||
|
}
|
||||||
|
word[wrdlen] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get Definition Text */
|
||||||
|
void getdef()
|
||||||
|
{
|
||||||
|
int wrdlen = 0;
|
||||||
|
skpspc();
|
||||||
|
while (isprnt()) {
|
||||||
|
word[wrdlen++] = getnxt();
|
||||||
|
}
|
||||||
|
word[wrdlen] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process define directive */
|
||||||
|
void prsdef()
|
||||||
|
{
|
||||||
|
getwrd(); //get defined identifier
|
||||||
|
DEBUG("Defining '%s'\n", word);
|
||||||
|
strncpy(defnam[defcnt], word, VARLEN);
|
||||||
|
getdef();
|
||||||
|
DEBUG("Defined as '%s'\n", word);
|
||||||
|
strncat(deftxt[defcnt], word, DEFLEN);
|
||||||
|
defcnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for and Expand DEFINE *
|
||||||
|
* Sets: nxtwrd, nxtchr, nxtupr *
|
||||||
|
* if match is found */
|
||||||
|
void expdef()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
if (!isalph()) return;
|
||||||
|
DEBUG("Checking for definition '%s'\n", word);
|
||||||
|
nxtptr = 0;
|
||||||
|
for (i=0; i<defcnt; i++) {
|
||||||
|
if (strcmp(word, defnam[i]) == 0) {
|
||||||
|
strcpy(nxtwrd, deftxt[i]);
|
||||||
|
nxtchr = nxtwrd[0];
|
||||||
|
nxtupc = toupper(nxtchr);
|
||||||
|
DEBUG("Expanded to '%s'\n", word);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
strcpy(nxtwrd, word);
|
||||||
|
}
|
||||||
|
|
||||||
|
char escape(char c)
|
||||||
|
{
|
||||||
|
switch (c) {
|
||||||
|
case 'r': return 0x0d;
|
||||||
|
default: return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_string() {
|
||||||
|
char str_del, tmp_char;
|
||||||
|
int wrdlen = 0, esc_next = FALSE;
|
||||||
|
DEBUG("Parsing string\n", 0);
|
||||||
|
str_del = getnxt();
|
||||||
|
while(!match(str_del)) {
|
||||||
|
if (esc_next)
|
||||||
|
word[wrdlen++] = escape(getnxt());
|
||||||
|
else {
|
||||||
|
if (match('\\'))
|
||||||
|
esc_next = TRUE;
|
||||||
|
else
|
||||||
|
word[wrdlen++] = nxtchr;
|
||||||
|
skpchr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
skpchr();
|
||||||
|
word[wrdlen++] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read Binary number from input file *
|
||||||
|
* a Binary is a series of binary digits (0 or 1) *
|
||||||
|
* prefixed with '%' *
|
||||||
|
* Sets: word - binary number including leading '%' *
|
||||||
|
* Returns: integer value of number */
|
||||||
|
int prsbin()
|
||||||
|
{
|
||||||
|
int wrdlen = 0;
|
||||||
|
int digit;
|
||||||
|
int number = 0;
|
||||||
|
if (!match('%'))
|
||||||
|
expctd("hexadecimal number");
|
||||||
|
word[wrdlen++] = nxtchr;
|
||||||
|
getnxt();
|
||||||
|
while (isbin()) {
|
||||||
|
word[wrdlen++] = nxtchr;
|
||||||
|
digit = nxtchr - '0';
|
||||||
|
number = number * 2 + digit;
|
||||||
|
skpchr();
|
||||||
|
}
|
||||||
|
word[wrdlen] = 0;
|
||||||
|
return (number);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read Decimal number from input file *
|
||||||
|
* a Decimal is a series of digits (0-9) *
|
||||||
|
* Sets: word - number without leading 0's *
|
||||||
|
* Returns: integer value of number */
|
||||||
|
int prsdec()
|
||||||
|
{
|
||||||
|
int wrdlen = 0;
|
||||||
|
int digit;
|
||||||
|
int number = 0;
|
||||||
|
if (!isdec()) expctd("Digit");
|
||||||
|
while (isdec())
|
||||||
|
{
|
||||||
|
if (!match('0') || number != 0) //skip leading zeros
|
||||||
|
word[wrdlen++] = nxtchr;
|
||||||
|
digit = getnxt() - '0';
|
||||||
|
number = number * 10 + digit;
|
||||||
|
}
|
||||||
|
if (number == 0) word[wrdlen++] = '0';
|
||||||
|
word[wrdlen] = 0;
|
||||||
|
return(number);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reads Hexadecimal number from input file *
|
||||||
|
* Sets: word - Hex number including leading '$' *
|
||||||
|
* Returns: integer value of number */
|
||||||
|
int prshex()
|
||||||
|
{
|
||||||
|
int wrdlen = 0;
|
||||||
|
int digit;
|
||||||
|
int number = 0;
|
||||||
|
DEBUG("Parsing hexadecimal constant\n", 0);
|
||||||
|
if (!match('$'))
|
||||||
|
expctd("hexadecimal number");
|
||||||
|
word[wrdlen++] = getnxt();
|
||||||
|
while (ishexd()) {
|
||||||
|
DEBUG("Found hex digit '%c'\n", nxtchr);
|
||||||
|
word[wrdlen++] = nxtchr;
|
||||||
|
if (isdec())
|
||||||
|
digit = nxtchr - '0';
|
||||||
|
else
|
||||||
|
digit = nxtchr - 'A' + 10;
|
||||||
|
number = number * 16 + digit;
|
||||||
|
skpchr();
|
||||||
|
}
|
||||||
|
word[wrdlen] = 0;
|
||||||
|
return (number);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reads Character constant from input file *
|
||||||
|
* Sets: word - Character constant including *
|
||||||
|
* single quotes *
|
||||||
|
* Returns: ASCII value of constant */
|
||||||
|
int prschr()
|
||||||
|
{
|
||||||
|
int wrdlen = 0;
|
||||||
|
char c;
|
||||||
|
DEBUG("Parsing character constant\n", 0);
|
||||||
|
expect('\'');
|
||||||
|
word[wrdlen++] = '\'';
|
||||||
|
if (match('\\'))
|
||||||
|
word[wrdlen++] = getnxt();
|
||||||
|
c = getnxt();
|
||||||
|
DEBUG("Extracted character %c\n", c);
|
||||||
|
word[wrdlen++] = c;
|
||||||
|
expect('\'');
|
||||||
|
word[wrdlen++] = '\'';
|
||||||
|
word[wrdlen] = 0;
|
||||||
|
return (int)c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse numeric value *
|
||||||
|
* Args: maxval - maximum allowed value *
|
||||||
|
* Sets: value - parsed number (as string) *
|
||||||
|
* Returns: parsed number */
|
||||||
|
int prsnum(int maxval)
|
||||||
|
{
|
||||||
|
int number;
|
||||||
|
skpspc();
|
||||||
|
if (!iscpre()) expctd("constant value");
|
||||||
|
switch(nxtchr) {
|
||||||
|
case '%':
|
||||||
|
number = prsbin();
|
||||||
|
break;
|
||||||
|
case '$':
|
||||||
|
number = prshex();
|
||||||
|
break;
|
||||||
|
case '\'':
|
||||||
|
number = prschr();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
number = prsdec();
|
||||||
|
}
|
||||||
|
DEBUG("Parsed number '%s'\n", word);
|
||||||
|
DEBUG("with value '%d'\n", number);
|
||||||
|
|
||||||
|
if (number > maxval) {
|
||||||
|
ERROR("Out of bounds constant '%d';\n", number, EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (maxval > 255)
|
||||||
|
sprintf(value, "$%04X", number);
|
||||||
|
else
|
||||||
|
sprintf(value, "$%02X", number);
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse numeric constant *
|
||||||
|
* Args: maxval - maximum allowed value *
|
||||||
|
* Sets: value - the constant (as a string) *
|
||||||
|
* valtyp - value type (CONSTANT) */
|
||||||
|
void prscon(int maxval)
|
||||||
|
{
|
||||||
|
int constant = prsnum(maxval);
|
||||||
|
valtyp = CONSTANT;
|
||||||
|
if (maxval > 255)
|
||||||
|
sprintf(value, "#$%04X", constant);
|
||||||
|
else
|
||||||
|
sprintf(value, "#$%02X", constant);
|
||||||
|
DEBUG("Generated constant '%s'\n", value);
|
||||||
|
}
|
||||||
|
int get_vartyp()
|
||||||
|
{
|
||||||
|
if (match('(')) return FUNCTION;
|
||||||
|
else if (match('[')) return ARRAY;
|
||||||
|
else return VARIABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse next word as variable or function name *
|
||||||
|
* Sets: value - Identifier Name *
|
||||||
|
* valtyp - Identifier Type */
|
||||||
|
void prsvar()
|
||||||
|
{
|
||||||
|
getwrd();
|
||||||
|
valtyp = get_vartyp();
|
||||||
|
if (valtyp != FUNCTION) chksym(word);
|
||||||
|
strcpy(value, word);
|
||||||
|
DEBUG("Parsed variable '%s'\n", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse arithmetic or bitwise operator */
|
||||||
|
void prsopr()
|
||||||
|
{
|
||||||
|
if (!isoper)
|
||||||
|
expctd("Arithmetic or bitwise operator");
|
||||||
|
oper = getnxt();
|
||||||
|
DEBUG("Parsed operator '%c'\n", oper);
|
||||||
|
opstr[0] = oper;
|
||||||
|
opstr[1] = 0;
|
||||||
|
ACMNT(opstr);
|
||||||
|
skpspc();
|
||||||
|
}
|
||||||
|
|
54
parse.h
Normal file
54
parse.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/*************************************
|
||||||
|
* C02 Input File Parsing Routines *
|
||||||
|
*************************************/
|
||||||
|
|
||||||
|
enum trmtxts {CONSTANT, VARIABLE, ARRAY, FUNCTION};
|
||||||
|
enum etypes {ETDEF, ETMAC}; //Definition Types
|
||||||
|
|
||||||
|
char word[LINELEN]; //Word parsed from source file
|
||||||
|
char nxtwrd[LINELEN]; //Next Word (from DEFINE lookup)
|
||||||
|
int nxtptr; //Pointer to next character in nxtwrd
|
||||||
|
char value[LINELEN]; //Term parsed from equation
|
||||||
|
int valtyp; //Value Type
|
||||||
|
char oper; //Arithmetic or Bitwise Operator
|
||||||
|
|
||||||
|
char defnam[MAXDEF+1][VARLEN+1]; //Definition Name Table
|
||||||
|
char deftxt[MAXDEF+1][DEFLEN+1]; //Definition Text Table
|
||||||
|
int defcnt; //Number of Definitions Defined
|
||||||
|
|
||||||
|
int match(char c); //Does Next Character match c
|
||||||
|
int inbtwn(char mn, char mx); //Is Next Character in Range ()mn - mx)
|
||||||
|
int isprnt(); //Is Next Character Printable
|
||||||
|
int isalpa(); //Is Next Character Alphabetic
|
||||||
|
int isanum(); //Is Next Character AlphaNumeric
|
||||||
|
int isdec(); //Is Next Character a Decimal Digit
|
||||||
|
int ishexd(); //Is Next Character a Hexadecimal Digit
|
||||||
|
int isbin(); //Is Next Character a Binary Digit
|
||||||
|
int isnl(); //Is Next Character a NewLine
|
||||||
|
int isnpre(); //Is Next Character a Numeric Prfix
|
||||||
|
int isspc(); //Is Next Character a Space
|
||||||
|
int isapos(); //Is Next Character an Apostrophe
|
||||||
|
int isvpre(); //Is Next Character a Value Prefix
|
||||||
|
int isoper(); //Is Next Character an Operator
|
||||||
|
int ispopr(); //Is Next Character a Post-Operator
|
||||||
|
|
||||||
|
int wordis(char *s); //Does word match s
|
||||||
|
|
||||||
|
char getnxt(); //Return Next Character and Advance
|
||||||
|
int look(char c); //Look for Character
|
||||||
|
void expect(char c); //Look for Character and Exit if not found
|
||||||
|
|
||||||
|
void skpchr(); //Advance to Next Character
|
||||||
|
void skpeol(); //Skip to End of Line
|
||||||
|
void skpspc(); //Advance to Next Printable Character
|
||||||
|
void skpcmt(); //Skip to End of Comment
|
||||||
|
|
||||||
|
void getwrd(); //Get Next Word
|
||||||
|
|
||||||
|
void expdef(); //Check for and Expand Definition
|
||||||
|
|
||||||
|
int prsdec(); //Get Decimal Number
|
||||||
|
|
||||||
|
void prscon(int maxval); //Parse a Constant
|
||||||
|
void prsopr(); //Parse Arithmetic Operator
|
||||||
|
void prsvar(); //Parse Variable
|
209
stmnt.c
Normal file
209
stmnt.c
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
/************************************
|
||||||
|
* C02 Statement Compiling Routines *
|
||||||
|
************************************/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include "common.h"
|
||||||
|
#include "asm.h"
|
||||||
|
#include "parse.h"
|
||||||
|
#include "vars.h"
|
||||||
|
#include "expr.h"
|
||||||
|
#include "label.h"
|
||||||
|
#include "stmnt.h"
|
||||||
|
|
||||||
|
/* parse and compile if statement */
|
||||||
|
void pif() {
|
||||||
|
DEBUG("Parsing IF statement '%c'\n", nxtchr);
|
||||||
|
expect('(');
|
||||||
|
newlbl(LTIF);
|
||||||
|
prscnd(')'); //Parse Conditional Expession
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse and compile else statement */
|
||||||
|
void pelse() {
|
||||||
|
DEBUG("Parsing ELSE statement '%c'\n", nxtchr);
|
||||||
|
strcpy(lbltmp, lblasm);
|
||||||
|
lblasm[0] = 0;
|
||||||
|
newlbl(LTIF);
|
||||||
|
asmlin("JMP", curlbl);
|
||||||
|
strcpy(lblasm, lbltmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse and compile for statement */
|
||||||
|
void pfor() {
|
||||||
|
ERROR("Unsupported statement FOR encountered",0, EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse and compile if statement */
|
||||||
|
void pgoto() {
|
||||||
|
DEBUG("Parsing GOTO statement\n", 0);
|
||||||
|
getwrd();
|
||||||
|
ACMNT(word);
|
||||||
|
asmlin("JMP", word);
|
||||||
|
expect(';');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse and compile if statement */
|
||||||
|
void pretrn() {
|
||||||
|
DEBUG("Parsing RETURN statement\n", 0);
|
||||||
|
if (!look(';'))
|
||||||
|
prsxpr(';');
|
||||||
|
asmlin("RTS", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse and compile while statement */
|
||||||
|
void pwhile() {
|
||||||
|
DEBUG("Parsing WHILE statement '%c'\n", nxtchr);
|
||||||
|
expect('(');
|
||||||
|
newlbl(LTLOOP); //create Loop Label
|
||||||
|
setlbl(curlbl);
|
||||||
|
newlbl(LTEND); //Create End Label
|
||||||
|
prscnd(')'); //Parse Conditional Expession
|
||||||
|
}
|
||||||
|
|
||||||
|
/* generate unimplemented statement error */
|
||||||
|
void punimp() {
|
||||||
|
ERROR("Unimplemented statement '%s' encountered", word, EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Parse and compile assignment */
|
||||||
|
void prsasn()
|
||||||
|
{
|
||||||
|
DEBUG("Parsing assignment of variable '%s''\n", asnvar);
|
||||||
|
skpchr(); //skip equals sign
|
||||||
|
ACMNT("=");
|
||||||
|
prsxpr(';');
|
||||||
|
if (strlen(asnidx)) {
|
||||||
|
asmlin("LDX", asnidx);
|
||||||
|
strcat(asnvar,",X");
|
||||||
|
}
|
||||||
|
asmlin("STA", asnvar);
|
||||||
|
}
|
||||||
|
|
||||||
|
void prcpop() {
|
||||||
|
DEBUG("Processing post operation '%c'\n", oper);
|
||||||
|
switch(oper)
|
||||||
|
{
|
||||||
|
case '+':
|
||||||
|
asmlin("INC", asnvar);
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
asmlin("DEC", asnvar);
|
||||||
|
break;
|
||||||
|
case '<':
|
||||||
|
asmlin("ASL", asnvar);
|
||||||
|
break;
|
||||||
|
case '>':
|
||||||
|
asmlin("LSR", asnvar);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Unrecognized post operator '%c'\n", oper);
|
||||||
|
exterr(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse Post Operator */
|
||||||
|
void prspop() {
|
||||||
|
oper = getnxt();
|
||||||
|
CCMNT(oper); CCMNT(oper);
|
||||||
|
DEBUG("Checking for post operation '%c'\n", oper);
|
||||||
|
if (nxtchr == oper) {
|
||||||
|
skpchr();
|
||||||
|
prcpop(); //Process Post-Op
|
||||||
|
expect(';');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
expctd("post operator");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse function call in first expression */
|
||||||
|
void prsfnc()
|
||||||
|
{
|
||||||
|
char fnname[255]; /*Function name*/
|
||||||
|
DEBUG("Processing function call '%s'...\n", term);
|
||||||
|
strcpy(fnname, word);
|
||||||
|
skpchr(); //skip open paren
|
||||||
|
CCMNT('(');
|
||||||
|
skpspc();
|
||||||
|
if (match(')')) //if no arguments
|
||||||
|
skpchr(); // skip close paren
|
||||||
|
else { //otherwise
|
||||||
|
if (look('&')) {
|
||||||
|
prsadr(')');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
prsxpr(')'); //parse expression
|
||||||
|
}
|
||||||
|
asmlin("JSR", fnname);
|
||||||
|
expect(';');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse and compile identifier (variable or function call) */
|
||||||
|
void prssym()
|
||||||
|
{
|
||||||
|
DEBUG("Parsing Identifier %s\n", word);
|
||||||
|
valtyp = get_vartyp();
|
||||||
|
if (valtyp == FUNCTION) {
|
||||||
|
prsfnc(); //Parse Function Call
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
chksym(word);
|
||||||
|
strcpy(asnvar, word); //sav variable to assign to
|
||||||
|
if (valtyp == ARRAY) {
|
||||||
|
prsidx(); //Parse Array Index
|
||||||
|
strncpy(asnidx, value, VARLEN);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
asnidx[0] = 0;
|
||||||
|
if (ispopr(nxtchr))
|
||||||
|
prspop(); //Parse Post Operator
|
||||||
|
else
|
||||||
|
{
|
||||||
|
skpspc();
|
||||||
|
if (match('='))
|
||||||
|
prsasn(); //Parse Assignment
|
||||||
|
else
|
||||||
|
expctd("=");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parse and compile program statement */
|
||||||
|
void pstmnt()
|
||||||
|
{
|
||||||
|
DEBUG("Parsing statement '%s'\n", word);
|
||||||
|
if(match(':')) {
|
||||||
|
prslbl(); //Parse Label
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (wordis("if")) {
|
||||||
|
pif();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (wordis("else")) {
|
||||||
|
pelse();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (wordis("while")) {
|
||||||
|
pwhile();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (wordis("for")) {
|
||||||
|
punimp();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (wordis("goto"))
|
||||||
|
pgoto();
|
||||||
|
else if (wordis("return"))
|
||||||
|
pretrn();
|
||||||
|
else
|
||||||
|
prssym();
|
||||||
|
if (lblcnt) {
|
||||||
|
lbllin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
8
stmnt.h
Normal file
8
stmnt.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/************************************
|
||||||
|
* C02 Statement Compiling Routines *
|
||||||
|
************************************/
|
||||||
|
|
||||||
|
char asnvar[VARLEN+1]; /*Assigned Variable Name*/
|
||||||
|
char asnidx[VARLEN+1] ; /*Assigned Variable Index*/
|
||||||
|
|
||||||
|
|
201
vars.c
Normal file
201
vars.c
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
/*************************************
|
||||||
|
* C02 Variable Management Routines *
|
||||||
|
*************************************/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "files.h"
|
||||||
|
#include "asm.h"
|
||||||
|
#include "parse.h"
|
||||||
|
#include "vars.h"
|
||||||
|
|
||||||
|
/* Lookup variable name in variable table *
|
||||||
|
* Returns index into varnam array *
|
||||||
|
* FALSE if variable was not found */
|
||||||
|
int lookup(char *name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
DEBUG("Looking up variable '%s'\n", word);
|
||||||
|
for (i=0; i<varcnt; i++) {
|
||||||
|
if (strcmp(varnam[i], name) == 0)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if variable has been defined */
|
||||||
|
int symdef(char *name)
|
||||||
|
{
|
||||||
|
if (lookup(name) < 0)
|
||||||
|
return FALSE;
|
||||||
|
else
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for variable *
|
||||||
|
* Generates error if variable is undefined */
|
||||||
|
void chksym(char *name)
|
||||||
|
{
|
||||||
|
if (!symdef(name))
|
||||||
|
ERROR("Undeclared variable '%s' encountered\n", word, EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Check for Array specifier and get size *
|
||||||
|
* Sets: value - array size (as string) *
|
||||||
|
* "" if not an array */
|
||||||
|
void pvarsz()
|
||||||
|
{
|
||||||
|
DEBUG("Checking for array definition\n", 0);
|
||||||
|
value[0] = 0;
|
||||||
|
if (match('[')) {
|
||||||
|
skpchr();
|
||||||
|
if (alcvar) {
|
||||||
|
DEBUG("Parsing array size\n", 0);
|
||||||
|
prsnum(0xFF);
|
||||||
|
}
|
||||||
|
expect(']');
|
||||||
|
}
|
||||||
|
if (!alcvar)
|
||||||
|
strcpy(value, "*");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse Data Constant */
|
||||||
|
void prsdtc()
|
||||||
|
{
|
||||||
|
dtype = DTBYTE;
|
||||||
|
prscon(0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse Data String */
|
||||||
|
void prsdts()
|
||||||
|
{
|
||||||
|
dtype = DTSTR;
|
||||||
|
get_string();
|
||||||
|
strcpy(value, word);
|
||||||
|
DEBUG("Parsed Data String '%s'\n", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse and store variable data *
|
||||||
|
* Sets: datvar[] - Variable Data *
|
||||||
|
* datlen[] - Data Length */
|
||||||
|
void prsdat()
|
||||||
|
{
|
||||||
|
DEBUG("Checking for variable data\n", 0);
|
||||||
|
int i;
|
||||||
|
if (!look('=')) {
|
||||||
|
datlen[varcnt] = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
skpspc();
|
||||||
|
if (isnpre())
|
||||||
|
prsdtc(0xff);
|
||||||
|
else if (match('"'))
|
||||||
|
prsdts();
|
||||||
|
dlen = strlen(value);
|
||||||
|
datlen[varcnt] = dlen;
|
||||||
|
dattyp[varcnt] = dtype;
|
||||||
|
DEBUG("Setting variable data to '%s'\n", value);
|
||||||
|
for (i=0; i<dlen; i++)
|
||||||
|
datvar[dsize++] = value[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add Variable to Variable table *
|
||||||
|
* Uses: word - variable name */
|
||||||
|
void addvar(int t)
|
||||||
|
{
|
||||||
|
if (symdef(word))
|
||||||
|
ERROR("Duplicate declaration of variable '%s\n", word,EXIT_FAILURE);
|
||||||
|
if (t == VTVOID)
|
||||||
|
ERROR("Illegal Variable Type\n", 0, EXIT_FAILURE);
|
||||||
|
DEBUG("Adding variable '%s'\n", word);
|
||||||
|
strncpy(varnam[varcnt], word, VARLEN);
|
||||||
|
vartyp[varcnt] = t;
|
||||||
|
pvarsz();
|
||||||
|
strncpy(varsiz[varcnt], value, 3);
|
||||||
|
DEBUG("Added at index %d\n", varcnt);
|
||||||
|
prsdat(); //Parse Variable Data
|
||||||
|
varcnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addfnc()
|
||||||
|
{
|
||||||
|
expect(')');
|
||||||
|
if (alcvar)
|
||||||
|
setlbl(word);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (Check For and) Parse Variable Declaration*/
|
||||||
|
void pdecl(int t)
|
||||||
|
{
|
||||||
|
DEBUG("Processing variable declarations(s) of type %d\n", t);
|
||||||
|
while(TRUE) {
|
||||||
|
getwrd();
|
||||||
|
if (look('(')) {
|
||||||
|
addfnc();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
addvar(t);
|
||||||
|
if (!look(','))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
expect(';');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write Variable Data */
|
||||||
|
void vardat(int i)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
DEBUG("Building Data for Variable '%s'\n", varnam[i]);
|
||||||
|
value[0] = 0;
|
||||||
|
for (j=0; j<datlen[i]; j++) {
|
||||||
|
if (j) strcat(value,",");
|
||||||
|
sprintf(word, "$%02X", datvar[dlen++]);
|
||||||
|
strcat(value, word);
|
||||||
|
}
|
||||||
|
if (dattyp[i] == DTSTR) strcat(value, ",$00");
|
||||||
|
DEBUG("Allocating Data for Variable '%s'\n", varnam[i]);
|
||||||
|
asmlin(BYTEOP, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write Variable Table */
|
||||||
|
void vartbl()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
DEBUG("Writing Variable Table", 0);
|
||||||
|
dlen = 0;
|
||||||
|
for (i=0; i<varcnt; i++) {
|
||||||
|
strcpy(lblasm, varnam[i]);
|
||||||
|
DEBUG("Set Label to '%s'\n", lblasm);
|
||||||
|
if (strcmp(varsiz[i], "*") == 0)
|
||||||
|
continue;
|
||||||
|
else if (datlen[i])
|
||||||
|
vardat(i); //Write Variable Data
|
||||||
|
else if (strlen(varsiz[i]) > 0) {
|
||||||
|
DEBUG("Allocating array '%s'\n", varnam[i]);
|
||||||
|
asmlin(STROP, varsiz[i]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DEBUG("Allocating variable '%s'\n", varnam[i]);
|
||||||
|
asmlin(BYTEOP, "0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print Variable Table to Log File */
|
||||||
|
void logvar()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
fprintf(logfil, "\n%-31s %s %s\n", "Variable", "Type", "Size");
|
||||||
|
for (i=0; i<varcnt; i++)
|
||||||
|
{
|
||||||
|
fprintf(logfil, "%-31s %4d %s\n", varnam[i], vartyp[i], varsiz[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
27
vars.h
Normal file
27
vars.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*************************************
|
||||||
|
* C02 Variable Management Routines *
|
||||||
|
*************************************/
|
||||||
|
|
||||||
|
/* Variable Table */
|
||||||
|
char varnam[MAXVAR+1][VARLEN+1]; //Variable Name
|
||||||
|
char vartyp[MAXVAR+1]; //Variable Type
|
||||||
|
char varsiz[MAXVAR+1][4]; //Variable Array
|
||||||
|
int varcnt; //Number of Variables in Table
|
||||||
|
|
||||||
|
enum vtypes {VTVOID, VTBYTE, VTCHAR}; //Variable Types
|
||||||
|
|
||||||
|
char datvar[DATASPC+1]; //Variable Data Storage
|
||||||
|
char datlen[MAXVAR+1]; //Variable Data Length
|
||||||
|
char dattyp[MAXVAR+1]; //Variable Data Type
|
||||||
|
int dtype; //Data Type
|
||||||
|
int dlen; //Length of Variable Data
|
||||||
|
int dsize; //Total Data Length
|
||||||
|
|
||||||
|
enum dtypes {DTBYTE, DTSTR}; //Variable Data Types
|
||||||
|
|
||||||
|
int symdef(char *name); //Is Variable defined (TRUE or FALSE)
|
||||||
|
void chksym(char *name); //Error if Variable not defined
|
||||||
|
|
||||||
|
void pdecl(int t); //Parse Variable Declaration
|
||||||
|
|
||||||
|
void vartbl(); //Create Variable Table
|
Loading…
Reference in New Issue
Block a user