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:
parent
f7f23059fe
commit
cc6ef48b85
BIN
asm6502/asm6502
BIN
asm6502/asm6502
Binary file not shown.
1357
asm6502/asm6502.c
1357
asm6502/asm6502.c
File diff suppressed because it is too large
Load Diff
65
doc/c02.txt
65
doc/c02.txt
@ -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.
|
||||
|
@ -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
57
py65/structs.c02
Normal 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();
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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(';')) {
|
||||
|
75
src/vars.c
75
src/vars.c
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
34
test/structs.c02
Normal 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];
|
Loading…
Reference in New Issue
Block a user