1
0
mirror of https://github.com/RevCurtisP/C02.git synced 2024-11-22 01:31:33 +00:00

Added parsing of struct members

This commit is contained in:
Curtis F Kaylor 2018-03-08 14:35:00 -05:00
parent f7f23059fe
commit cc6ef48b85
12 changed files with 243 additions and 1395 deletions

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -264,7 +264,7 @@ are suffixed with a ; character.
A simple variable declaration may include an initial value definition in
the form of an = character and literal after the variable name.
A variable array may be declares in one of two ways: the variable name
A variable array may be declared in one of two ways: the variable name
suffixed with a [ character, a literal specifying the upper bound of
the array, and a ] character; or a variable name followed by an = character
and string literal or series of literals separated by , characters and
@ -309,6 +309,40 @@ statement with an explicit expression will simply process that expression
statement without an expression (including an implicit return) will, by
default, return the value of the last processed expression.
STRUCTS
A struct is a special type of variable which is composed of one or more
unique variables called members. Each member may be either a simple
variable or an array. However, the total size of the struct may not
exceed 256 characters.
Member names are local to a struct: each member within a struct must have
a unique name, but the same member name can be used in different structs
and may also have the same name as a global variable.
The struct keyword is used for both defining the members of a struct type
as well as declaring struct type variables.
When defining a struct type, the struct keyword is followed by the name of
the struct type, the { character, the member definitions separated by
commas, and the } character. The struct definition is terminated with a
semicolon. Each member definition is composed of the optional char keyword,
and the member name. If the member is an array, the member name is suffixed
the [ character, the upper bound of the array, and the ] character. Each
member definition is terminated with a semicolon.
When declaring a struct variable, the struct keyword is followed by the struct
type name, and the name of the struct variable. The struct declaration is
terminated with a semicolon.
Examples:
struct record {char name[8]; char index; data[128];};
struct record rec;
Note: Unlike simple and array variable, the members of a struct variable
may not be initialized during declaration.
EXPRESSIONS
An expression is a series of one or more terms separated by operators.
@ -408,6 +442,25 @@ Note: After a subscripted array reference, the 6502 X register will contain
the value of the index (unless the register Y was used as the index, in
which X register is not changed).
STRUCTS
Individual members of a struct variable are specified using the struct
variable name, a period, and the member name. If a member is an array,
it's elements are accessed using the same syntax as an array variable.
A struct variable can also be treated like an array variable, with each
byte of the variable accessed as an array index.
Examples:
i = rec.index; //Get Struct Member
rec.data[i] = i; //Set Struct Member Element
arr[i] = rec[i]; //Copy Struct Byte into Array
Note: Unlike standard C, structs may not be assigned using an equals
sign. One struct variable may be copied to another byte by byte or
through a function call.
FUNCTION CALLS
A function call may be used as a stand-alone statement, or as the first
@ -426,9 +479,10 @@ The third argument may only be a simple variable or constant.
If the first or second argument is an address or string, then no more
arguments may be passed.
To pass the address of a variable or array into a function, precede the
variable name with the address-of operator &. To pass a string, simply
specify the string as the argument.
When passing the address of a variable, array, struct, or struct member
into a function, the variable specification is prefixed with the
address-of operator &. Wjen passing a string, the string is simply
specified as the argument with.
Examples:
c = getc(); //Get character from keyboard
@ -438,6 +492,9 @@ Examples:
p = strchr(c, &s); //Return position of character c in string s
putc(getc()); //Echo typed characters to screen
puts("Hello World"); //Write "Hello World" to screen
memdst(&dstrec); //Set struct variable as destination
memcpy(140, &srcrec); //Copy struct variable to destination struct
puts(&rec.name); //Write struct membet to screen
Note: This particular argument passing convention has been chosen because
of the 6502's limited number of registers and stack processing instructions.

View File

@ -41,12 +41,47 @@ Array declarations using bracket syntax specify the upper bound, rather
than the array size. Therefore, the array will be allocated with one more
element than the specified number.
Only one-dimensional arrays of type char are allowed and are limited to
a total of 256 elements. Multi-dimensional arrays, arrays of arrays, and
arrays of structs are not supported.
Struct definition and syntax is similar to standard C. When defining a
struct, the char keyword is optional, since char the char type is implied.
Struct members may only be simple variables or arrays. The maximum total
size of a struct is 256 bytes. Initialization of members during declaration
of a struct variable is not supported.
REGISTERS
The 6502 registers may be explicitly referenced by name, i.e. A, X, and Y.
These may only be used in specific places due to the nature of the compiled
code a well as the limitations of the 6502 instruction set.
EXPRESSIONS
C02 supports the addition, subtraction, bitwise-and, bitwise-or, and
exclusive-or operators. The multiplication, division, and binary shift
operators are not supported. These can be implemented through functions.
FUNCTIONS
Parameter passing uses the 6502's A, Y, and X registers. This limits
function calls to a maximum of three char variables or address reference
plus and optional char variable. However this also allows the return
of up to three char variables (see assignments below). However, the
non-standard push and pop statements allow explicit parameter passing
via the stack, and the inline keyword has been re-purposed to allow
explicit passing of inline parameters.
ASSIGNMENTS
Unlike standard C, struct contents may not be copied via simple assignment.
Struct variables may be copied byte by byte or using memory move functions.
Up to three comma-separated variables may be specified on the left side of
the = assignment operator. This is generally only useful when the expression
contains a function with multiple return values.
STATEMENTS
Instead of the switch statement, C02 uses the select statement. The

57
py65/structs.c02 Normal file
View File

@ -0,0 +1,57 @@
/**********************************************
* STRINGS - Demonstrate string.h02 functions *
**********************************************/
#include <py65.h02>
#include <stdio.h02>
#include <stdiox.h02>
#include <stdlib.h02>
#include <memory.h02>
#include <string.h02>
char d, i;
//Define Structure
struct record {
char name[8];
char index;
data[128];
};
//Declare Structure Variable
struct record srcrec;
struct record dstrec;
main:
//Set Structure Members
strdst(&srcrec.name); strcpy("RECNAME");
srcrec.index = 1;
for (i = 0; i<129; i++)
srcrec.data[i] = i;
//Clear Destination Record
for (i=0; i<140; i++)
dstrec[i] = 0;
prtdst();
//Copy Source Record into Destination Record
memdst(&dstrec);
memcpy(129, &srcrec);
prtdst();
goto exit;
//Print Destination Record
void prtdst() {
puts("REC.NAME="); putln(&dstrec.name);
puts("REC.INDEX="); putdec(dstrec.index); newlin();
puts("REC.DATA={");
for (i = 0; i<129; i++) {
if (i) putc(',');
putdec(dstrec.data[i]);
}
putln("}");
newlin();
}

View File

@ -71,12 +71,14 @@ void prstrm(void) {
/* Process Address Reference */
void prcadr(int adract, char* symbol) {
DEBUG("Processing address '%s'\n", word)
strcpy(word,"#>");
strcpy(word,"#>(");
strcat(word,symbol);
strcat(word,")");
if (adract == 1) { asmlin("LDA", word); asmlin("PHA", ""); }
else asmlin("LDY", word);
strcpy(word,"#<");
strcpy(word,"#<(");
strcat(word,symbol);
strcat(word,")");
if (adract == 1) { asmlin("LDA", word); asmlin("PHA", ""); }
else asmlin("LDX", word);
}

View File

@ -333,7 +333,6 @@ void prsopr(void) {
skpspc();
}
/* Generate Post-Operation Error */
void poperr(char* name) {
fprintf(stderr, "Illegal post-operation %c%c on register %s\n", oper, oper, name);

View File

@ -4,7 +4,7 @@
#define TF(x) (x) ? TRUE : FALSE;
enum stypes {LITERAL, VARIABLE, REGISTER, ARRAY, STRUCT, FUNCTION}; //Symbol Types
enum stypes {LITERAL, VARIABLE, REGISTER, ARRAY, FUNCTION}; //Symbol Types
enum etypes {ETDEF, ETMAC}; //Definition Types
char nxtwrd[LINELEN]; //Next Word (from DEFINE lookup)

View File

@ -108,6 +108,7 @@ int getidx(char* idx) {
void prcvar(char trmntr) {
chksym(TRUE, word);
strcpy(asnvar, word); //save variable to assign to
if (valtyp == VARIABLE && match('.')) prsmbr(asnvar);
asntyp = valtyp; //Set Assigned Varable Type
DEBUG("Set STA variable to %s\n", asnvar)
if (asntyp == VARIABLE && look(';')) {

View File

@ -26,6 +26,30 @@ int fndvar(char *name) {
return FALSE;
}
/* Lookup structure name in struct table *
* Sets: sctidx = index into sctnam array *
* sctcnt if not found *
* Returns: TRUE if found, otherwise FALSE */
int fndstc(char *name) {
DEBUG("Looking up struct '%s'\n", name)
for (stcidx=0; stcidx<stccnt; stcidx++)
if (strcmp(strcts[stcidx].name, name) == 0) return TRUE;
return FALSE;
}
/* Lookup structure member name in table *
* Sets: stmidx = index into stmnam array *
* stmcnt if not found *
* Returns: TRUE if found, otherwise FALSE */
int fndmbr(int idx, char *name) {
DEBUG("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) return TRUE;
}
return FALSE;
}
/* Check for variable *
* Generates error if variable is undefined *
* Args: alwreg - allow register name *
@ -42,16 +66,34 @@ void chksym(int alwreg, char *name) {
ERROR("Undeclared variable '%s' encountered\n", name, EXIT_FAILURE)
}
/* Parse next word as struct member *
* Args: name - Struct Variable *
* Sets: name - Variable + Offset *
* valtyp - Member Type */
void prsmbr(char* name) {
expect('.'); //Check for and Skip Period
stcidx = varstc[varidx]; //Get Struct Index
if (stcidx < 0) ERROR("Variable %s is Not a Structure\n", value, EXIT_FAILURE)
getwrd(); //Get Membert 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)
if (!fndmbr(stcidx, word)) ERROR("Struct does Not Contain Member %s\n", word, EXIT_FAILURE)
sprintf(word, "+$%hhX", membrs[mbridx].offset); //Get Member Offet in Struct
strcat(name, word); //Add Offset to Struct
}
/* Parse next word as variable or function name *
* Args: alwreg - Allow Register Names *
* Sets: value - Identifier Name *
* valtyp - Identifier Type */
void prsvar(int alwreg) {
getwrd();
valtyp = gettyp();
getwrd(); //Get Variable Name
valtyp = gettyp(); //Determine Variable Type
if (valtyp != FUNCTION) chksym(alwreg, word);
strcpy(value, word);
DEBUG("Parsed variable '%s'\n", value)
if (valtyp == VARIABLE && match('.')) prsmbr(value);
}
/* Require and Parse Variable Name *
@ -168,10 +210,10 @@ void addvar(int m, int t) {
void vartbl(void) {
int i, j;
DEBUG("Writing Variable Table", 0)
fprintf(logfil, "\n%-31s %s %s %s\n", "Variable", "Type", "Size", "Data");
fprintf(logfil, "\n%-31s %s %s %s %s\n", "Variable", "Type", "Size", "Struct", "Data");
dlen = 0;
for (i=0; i<varcnt; i++) {
fprintf(logfil, "%-31s %4d %4s %1d-%d\n", varnam[i], vartyp[i], varsiz[i], dattyp[i], datlen[i]);
fprintf(logfil, "%-31s %4d %4s %6d %1d-%d\n", varnam[i], vartyp[i], varsiz[i], varstc[i], dattyp[i], datlen[i]);
strcpy(lblasm, varnam[i]);
DEBUG("Set Label to '%s'\n", lblasm)
if (strcmp(varsiz[i], "*") == 0) continue;
@ -203,29 +245,6 @@ void vartbl(void) {
vrwrtn = TRUE;
}
/* Lookup structure name in struct table *
* Sets: sctidx = index into sctnam array *
* sctcnt if not found *
* Returns: TRUE if found, otherwise FALSE */
int fndstc(char *name) {
DEBUG("Looking up struct '%s'\n", name)
for (stcidx=0; stcidx<stccnt; stcidx++)
if (strcmp(strcts[stcidx].name, name) == 0) return TRUE;
return FALSE;
}
/* Lookup structure member name in table *
* Sets: stmidx = index into stmnam array *
* stmcnt if not found *
* Returns: TRUE if found, otherwise FALSE */
int fndmbr(int stcidx, char *name) {
DEBUG("Looking up member '%s'\n", word)
for (mbridx=0; mbridx<mbrcnt; mbridx++)
if (membrs[mbridx].strcti != stcidx) continue;
if (strcmp(membrs[mbridx].name, name) == 0) return TRUE;
return FALSE;
}
/* Parse and Compile Struct Declaration */
void addstc(void) {
if (!fndstc(word)) ERROR("Undefined Struct '%s\n", word,EXIT_FAILURE)
@ -271,7 +290,7 @@ void defstc(void) {
} while (!look('}'));
expect(';');
if (strct.size > 256) ERROR("Structure Size %d Exceeds Limit of 256 bytes.\n", strct.size, EXIT_FAILURE);
DEBUG("Adding struct with size %d\n", strct.size) DETAIL("at index %d\n", stccnt);
DEBUG("Adding struct with size %d", strct.size) DETAIL("at index %d\n", stccnt);
strcts[stccnt++] = strct;
}

View File

@ -7,7 +7,7 @@ char varnam[MAXVAR+1][VARLEN+1]; //Variable Name Table
char varmod[MAXVAR+1]; //Variable Modifier
char vartyp[MAXVAR+1]; //Variable Type
char varsiz[MAXVAR+1][4]; //Variable Array Size
char varstc[MAXVAR+1]; //Variable Struct Type
char varstc[MAXVAR+1]; //Variable Struct Index
int varcnt; //Number of Variables in Table
int varidx; //Index into Variable Tables
char vrname[MAXVAR+1]; //Variable Name
@ -68,6 +68,7 @@ void setdat(); //Set Variable Data
void setvar(int m, int t); //Set Variable Name and Size
void prsdts(); //Parse Data String
void prsvar(int alwreg); //Parse Variable
void prsmbr(char* name); //Parse Variable
void reqvar(int alwary); //Require and Parse Variable Name
void setdat(); //Store variable data
void setvar(int m, int t); //Add Variable to Variable table

34
test/structs.c02 Normal file
View File

@ -0,0 +1,34 @@
/* Test C02 define directive */
#pragma origin 1000
char d, i;
char index, name[8], data[128];
//Define Structure
struct record {
char name[8];
char index;
char data[128];
};
//Declare Structure Variable
struct record rec;
//Set Structure Members
strdst(&rec.name); strcpy(name);
rec.index = index;
for (i = 0; i<=128; i++)
rec.data[i] = d;
//Pass Entire Structure into Function
blkadd(&rec);
//Get Structure Members
index = rec.index;
for (i = 0; i<129; i++)
d = rec.data[i];
//Treat Structure Like and Array
for (i = 0; i<140; i++)
d = rec[i];