mirror of
https://github.com/RevCurtisP/C02.git
synced 2024-06-08 21:29:30 +00:00
Added multiple return values on functions
This commit is contained in:
parent
792c67507f
commit
befddf1077
2
c02.c
2
c02.c
|
@ -45,6 +45,8 @@ void init()
|
||||||
invasc = FALSE;
|
invasc = FALSE;
|
||||||
mskasc = FALSE;
|
mskasc = FALSE;
|
||||||
fcase = FALSE;
|
fcase = FALSE;
|
||||||
|
xsnvar[0] = 0;
|
||||||
|
ysnvar[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reads and parses the next Word in Source File */
|
/* Reads and parses the next Word in Source File */
|
||||||
|
|
35
doc/c02.txt
35
doc/c02.txt
|
@ -1,4 +1,4 @@
|
||||||
INTRODUCTION
|
INTRODUCTION
|
||||||
|
|
||||||
C02 is a simple C-syntax language designed to generate highly optimized
|
C02 is a simple C-syntax language designed to generate highly optimized
|
||||||
code for the 6502 microprocessor. The C02 specification is a highly
|
code for the 6502 microprocessor. The C02 specification is a highly
|
||||||
|
@ -60,7 +60,12 @@ DIRECTIVES
|
||||||
|
|
||||||
Directives are special instructions to the compiler. They do not directy
|
Directives are special instructions to the compiler. They do not directy
|
||||||
generate compiled code. A directive is denoted by a leading # character.
|
generate compiled code. A directive is denoted by a leading # character.
|
||||||
C02 currently supports only one directive.
|
|
||||||
|
DEFINE
|
||||||
|
|
||||||
|
The #define directive creates a named constant.
|
||||||
|
|
||||||
|
INCLUDE
|
||||||
|
|
||||||
The #include directive causes the compiler to read and process and external
|
The #include directive causes the compiler to read and process and external
|
||||||
file. In most cases, #include directives will be used with libraries of
|
file. In most cases, #include directives will be used with libraries of
|
||||||
|
@ -110,7 +115,7 @@ A decimal number consists of one to three decimal digits (0 through 9).
|
||||||
A hexadecimal number consists of a $ followed by two hexadecimal digits
|
A hexadecimal number consists of a $ followed by two hexadecimal digits
|
||||||
(0 through 9 or A through F).
|
(0 through 9 or A through F).
|
||||||
|
|
||||||
A character literals consists of a single character surrounded by ' symbols.
|
A character literal consists of a single character surrounded by ' symbols.
|
||||||
A ' character may be specified by escaping it with a \.
|
A ' character may be specified by escaping it with a \.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
@ -478,6 +483,24 @@ Examples:
|
||||||
Note: An implicit assignment generates an STA opcode with the variable
|
Note: An implicit assignment generates an STA opcode with the variable
|
||||||
as the operand.
|
as the operand.
|
||||||
|
|
||||||
|
PLURAL ASSIGNMENTS
|
||||||
|
|
||||||
|
C02 allows a function to return up to three values by specifying multiple
|
||||||
|
variables, separated by commas, to the left of the assignment operator (=).
|
||||||
|
|
||||||
|
The first and second variables to be assigned may be either simple variables
|
||||||
|
or subscripted array elements. The third variable, if used, may only be a
|
||||||
|
simple variable. Registers are not allowed in plural assignments.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
row, col = scnpos(); //Get current screen position
|
||||||
|
cr, mn, mx = cpmnmx(a, b); //Compare two values, return min and max
|
||||||
|
lwr[i], upr[i] = tolwup(txt[i]); //Convert char to lower and upper case
|
||||||
|
|
||||||
|
Note: When compiled, a plural assignment generates an STX for the third
|
||||||
|
assignment (if specified), an STY for the second assignment and an STA for
|
||||||
|
the first assignment.
|
||||||
|
|
||||||
GOTO STATEMENT
|
GOTO STATEMENT
|
||||||
|
|
||||||
A goto statement unconditionally transfers program execution to the
|
A goto statement unconditionally transfers program execution to the
|
||||||
|
@ -512,9 +535,9 @@ Examples:
|
||||||
Note: In order to optimize the compiled code, the if and else statements
|
Note: In order to optimize the compiled code, the if and else statements
|
||||||
are to 6502 relative branch instructions. This limits the amount of
|
are to 6502 relative branch instructions. This limits the amount of
|
||||||
generated code between the if statement and the end of the if/else block
|
generated code between the if statement and the end of the if/else block
|
||||||
to slightly less than 127 characters. This should be sufficient in most
|
to slightly less than 127 bytes. This should be sufficient in most cases,
|
||||||
cases, but larger code blocks can be accommodated using function calls or
|
but larger code blocks can be accommodated using function calls or goto
|
||||||
goto statements.
|
statements.
|
||||||
|
|
||||||
SELECT, CASE, AND DEFAULT STATEMENTS
|
SELECT, CASE, AND DEFAULT STATEMENTS
|
||||||
|
|
||||||
|
|
15
parse.c
15
parse.c
|
@ -71,7 +71,7 @@ char getnxt()
|
||||||
void skpspc()
|
void skpspc()
|
||||||
{
|
{
|
||||||
//DEBUG("Skipping Spaces\n", 0);
|
//DEBUG("Skipping Spaces\n", 0);
|
||||||
if (isspc()) CCMNT(' ');
|
if (isspc()) CCMNT(' '); //Add only the first space to comments
|
||||||
while (isspc())
|
while (isspc())
|
||||||
getnxt();
|
getnxt();
|
||||||
}
|
}
|
||||||
|
@ -387,14 +387,6 @@ void prsopr()
|
||||||
skpspc();
|
skpspc();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process Array Index */
|
|
||||||
void prcidx(char *name, char *index)
|
|
||||||
{
|
|
||||||
if (strlen(index)) {
|
|
||||||
asmlin("LDX", index);
|
|
||||||
strcat(name,",X");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Generate Post-Operation Error */
|
/* Generate Post-Operation Error */
|
||||||
void poperr(char* name)
|
void poperr(char* name)
|
||||||
|
@ -407,7 +399,10 @@ void poperr(char* name)
|
||||||
void prcpst(char* name, char *index)
|
void prcpst(char* name, char *index)
|
||||||
{
|
{
|
||||||
DEBUG("Processing post operation '%c'\n", oper);
|
DEBUG("Processing post operation '%c'\n", oper);
|
||||||
prcidx(name, index);
|
if (strlen(index)) {
|
||||||
|
asmlin("LDX", index);
|
||||||
|
strcat(name,",X");
|
||||||
|
}
|
||||||
switch(oper)
|
switch(oper)
|
||||||
{
|
{
|
||||||
case '+':
|
case '+':
|
||||||
|
|
2
parse.h
2
parse.h
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
#define TF(x) (x) ? TRUE : FALSE;
|
#define TF(x) (x) ? TRUE : FALSE;
|
||||||
|
|
||||||
enum stypes {CONSTANT, VARIABLE, ARRAY, FUNCTION}; //Symbol Types
|
enum stypes {CONSTANT, VARIABLE, REGISTER, ARRAY, FUNCTION}; //Symbol Types
|
||||||
enum etypes {ETDEF, ETMAC}; //Definition Types
|
enum etypes {ETDEF, ETMAC}; //Definition Types
|
||||||
|
|
||||||
char nxtwrd[LINELEN]; //Next Word (from DEFINE lookup)
|
char nxtwrd[LINELEN]; //Next Word (from DEFINE lookup)
|
||||||
|
|
100
stmnt.c
100
stmnt.c
|
@ -59,61 +59,115 @@ void prssif(char trmntr) {
|
||||||
setlbl(tmplbl); //Emit End of Expression Label
|
setlbl(tmplbl); //Emit End of Expression Label
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Process Array Index */
|
||||||
|
void prcidx(int idxtyp, char *name, char *index)
|
||||||
|
{
|
||||||
|
if (strlen(index)) {
|
||||||
|
if (idxtyp == CONSTANT) {
|
||||||
|
strcat(name, "+");
|
||||||
|
strcat(name, index);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
asmlin("LDX", index);
|
||||||
|
strcat(name,",X");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Process Assignment */
|
/* Process Assignment */
|
||||||
void prcasn(char trmntr)
|
void prcasn(char trmntr)
|
||||||
{
|
{
|
||||||
expect('=');
|
expect('=');
|
||||||
DEBUG("Processing assignment of variable '%s'\n", asnvar);
|
|
||||||
if (look('('))
|
if (look('('))
|
||||||
prssif(trmntr); //Parse Shortcut If
|
prssif(trmntr); //Parse Shortcut If
|
||||||
else
|
else
|
||||||
prsxpr(trmntr); //Parse Expression
|
prsxpr(trmntr); //Parse Expression
|
||||||
|
DEBUG("Processing X assignment variable '%s'\n", xsnvar);
|
||||||
|
if (xsnvar[0]) {
|
||||||
|
asmlin("STX", xsnvar);
|
||||||
|
xsnvar[0] = 0;
|
||||||
|
}
|
||||||
|
DEBUG("Processing Y assignment variable '%s'\n", ysnvar);
|
||||||
|
if (ysnvar[0]) {
|
||||||
|
if (strlen(ysnidx))
|
||||||
|
prcidx(ysnivt, ysnvar, ysnidx);
|
||||||
|
asmlin("STY", ysnvar);
|
||||||
|
ysnvar[0] = 0;
|
||||||
|
}
|
||||||
|
DEBUG("Processing assignment variable '%s'\n", asnvar);
|
||||||
if (strcmp(asnvar, "X")==0)
|
if (strcmp(asnvar, "X")==0)
|
||||||
asmlin("TAX", "");
|
asmlin("TAX", "");
|
||||||
else if (strcmp(asnvar, "Y")==0)
|
else if (strcmp(asnvar, "Y")==0)
|
||||||
asmlin("TAY", "");
|
asmlin("TAY", "");
|
||||||
else if ((strcmp(asnvar, "A")!=0))
|
else if ((strcmp(asnvar, "A")!=0))
|
||||||
{
|
{
|
||||||
if (strlen(asnidx)) {
|
if (strlen(asnidx))
|
||||||
if (asnivt == CONSTANT) {
|
prcidx(asnivt, asnvar, asnidx);
|
||||||
strcat(asnvar, "+");
|
|
||||||
strcat(asnvar, asnidx);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
asmlin("LDX", asnidx);
|
|
||||||
strcat(asnvar,",X");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
asmlin("STA", asnvar);
|
asmlin("STA", asnvar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process Variable at Beginning of Statement */
|
/* Parse and Return Array Index and Type */
|
||||||
|
int getidx(char* idx)
|
||||||
|
{
|
||||||
|
prsidx(); //Parse Array Index
|
||||||
|
if (valtyp == CONSTANT)
|
||||||
|
strncpy(idx, word, VARLEN);
|
||||||
|
else
|
||||||
|
strncpy(idx, value, VARLEN);
|
||||||
|
DEBUG("Set assigned index to %s\n", asnidx);
|
||||||
|
return valtyp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process Assignment Variable(s) */
|
||||||
void prcvar(char trmntr)
|
void prcvar(char trmntr)
|
||||||
{
|
{
|
||||||
chksym(TRUE, word);
|
chksym(TRUE, word);
|
||||||
strcpy(asnvar, word); //sav variable to assign to
|
strcpy(asnvar, word); //save variable to assign to
|
||||||
if (valtyp == VARIABLE && look(';')) {
|
asntyp = valtyp; //Set Assigned Varable Type
|
||||||
|
DEBUG("Set STA variable to %s\n", asnvar);
|
||||||
|
if (asntyp == VARIABLE && look(';')) {
|
||||||
asmlin("STA", asnvar);
|
asmlin("STA", asnvar);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (valtyp == ARRAY) {
|
if (asntyp == ARRAY) {
|
||||||
prsidx(); //Parse Array Index
|
asnivt = getidx(asnidx); //Get Array Index and Type
|
||||||
asnivt = valtyp;
|
DEBUG("Set STA index to %s\n", asnidx);
|
||||||
if (asnivt == CONSTANT)
|
DEBUG("Set STA index type to %d\n", asnivt);
|
||||||
strncpy(asnidx, word, VARLEN);
|
|
||||||
else
|
|
||||||
strncpy(asnidx, value, VARLEN);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
asnidx[0] = 0;
|
asnidx[0] = 0;
|
||||||
if (ispopr()) {
|
if (ispopr()) {
|
||||||
if (prspst(trmntr, asnvar, asnidx)) //Parse Post Operator
|
if (prspst(trmntr, asnvar, asnidx)) //Parse Post Operator
|
||||||
expctd("post operator");
|
expctd("post operator");
|
||||||
|
/*refactor - put a return here and remove followig else*/
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
|
if (look(',')) {
|
||||||
|
if (asntyp == REGISTER) {
|
||||||
|
ERROR("Register %s not allowed in plural assignment\n", asnvar, EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
prsvar(FALSE); //get variable name
|
||||||
|
strcpy(ysnvar, word);
|
||||||
|
DEBUG("Set STY variable to %s\n", ysnvar);
|
||||||
|
if (valtyp == ARRAY) {
|
||||||
|
ysnivt = getidx(ysnidx); //Get Array Index and Type
|
||||||
|
DEBUG("Set STY index to %s\n", ysnidx);
|
||||||
|
DEBUG("Set STY index type to %d\n", ysnivt);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ysnidx[0] = 0;
|
||||||
|
if (look(',')) {
|
||||||
|
prsvar(FALSE); //get variable name
|
||||||
|
strcpy(xsnvar, word);
|
||||||
|
DEBUG("Set STX variable to %s\n", xsnvar);
|
||||||
|
if (valtyp == ARRAY) {
|
||||||
|
ERROR("Array element not allowed in third assignment\n", 0, EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
prcasn(trmntr);
|
prcasn(trmntr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse 'asm' String Parameter */
|
/* Parse 'asm' String Parameter */
|
||||||
|
@ -141,7 +195,7 @@ void pasm()
|
||||||
asmlin(opcode, word);
|
asmlin(opcode, word);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse and Compile and Assignment */
|
/* Parse and Compile an Assignment */
|
||||||
void prsasn(char trmntr)
|
void prsasn(char trmntr)
|
||||||
{
|
{
|
||||||
getwrd(); //Get Variable to be Assigned
|
getwrd(); //Get Variable to be Assigned
|
||||||
|
|
5
stmnt.h
5
stmnt.h
|
@ -3,8 +3,13 @@
|
||||||
************************************/
|
************************************/
|
||||||
|
|
||||||
char asnvar[VARLEN+1]; //Assigned Variable Name
|
char asnvar[VARLEN+1]; //Assigned Variable Name
|
||||||
|
int asntyp; //Assigned Variable Type
|
||||||
char asnidx[VARLEN+1] ; //Assigned Variable Index
|
char asnidx[VARLEN+1] ; //Assigned Variable Index
|
||||||
int asnivt; //Assigned Index Variable Type
|
int asnivt; //Assigned Index Variable Type
|
||||||
|
char ysnvar[VARLEN+1]; //Assigned Y Variable Name
|
||||||
|
char ysnidx[VARLEN+1] ; //Assigned Variable Index
|
||||||
|
int ysnivt; //Assigned Index Variable Type
|
||||||
|
char xsnvar[VARLEN+1]; //Assigned X Variable Name
|
||||||
|
|
||||||
char xstmnt[LINELEN]; //Expected Statement
|
char xstmnt[LINELEN]; //Expected Statement
|
||||||
|
|
||||||
|
|
7
vars.c
7
vars.c
|
@ -36,8 +36,11 @@ int fndvar(char *name)
|
||||||
void chksym(int alwreg, char *name)
|
void chksym(int alwreg, char *name)
|
||||||
{
|
{
|
||||||
if (strlen(name) == 1 && strchr("AXY", name[0])) {
|
if (strlen(name) == 1 && strchr("AXY", name[0])) {
|
||||||
if (alwreg) return;
|
if (alwreg && valtyp != ARRAY) {
|
||||||
else ERROR("Illegal reference to register %s\n", name, EXIT_FAILURE);
|
valtyp = REGISTER;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ERROR("Illegal reference to register %s\n", name, EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (!fndvar(name))
|
if (!fndvar(name))
|
||||||
ERROR("Undeclared variable '%s' encountered\n", name, EXIT_FAILURE);
|
ERROR("Undeclared variable '%s' encountered\n", name, EXIT_FAILURE);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user