1
0
mirror of https://github.com/RevCurtisP/C02.git synced 2024-06-15 22:29:27 +00:00

Allow int members in structs

This commit is contained in:
Curtis F Kaylor 2019-05-12 23:34:47 -04:00
parent 2530f3ed1e
commit b6cec4d75a
16 changed files with 397 additions and 212 deletions

View File

@ -28,8 +28,8 @@ LIB = $(PellesCDir)\Lib\Win64;$(PellesCDir)\Lib#
# Build c02.exe.
#
c02.exe: \
output\c02.obj \
output\asm.obj \
output\c02.obj \
output\common.obj \
output\cond.obj \
output\dclrtn.obj \
@ -165,6 +165,7 @@ output\parse.obj: \
src\asm.h \
src\common.h \
src\files.h \
src\label.h \
src\parse.h
$(CC) $(CCFLAGS) "$!" -Fo"$@"
@ -190,6 +191,7 @@ output\vars.obj: \
src\vars.c \
src\asm.h \
src\common.h \
src\dclrtn.h \
src\files.h \
src\label.h \
src\parse.h \
@ -197,3 +199,5 @@ output\vars.obj: \
$(CC) $(CCFLAGS) "$!" -Fo"$@"
.SILENT:
.EXCLUDEDFILES:

View File

@ -287,13 +287,13 @@ generate sets of related but distinct values.
An enumeration is defined using an enum statement. When using the enum
keyword, it is followed by a { character, one or more constant names
separated by commas, and a } character. An asterisk may be used in place
of a constant name, in which case the sequence will be skipped. The enum
statement is terminated with a semicolon.
separated by commas, and a } character. A period may be used in place
of a constant name, in which case the sequence will be skipped. The
enum statement is terminated with a semicolon.
Examples:
enum {BLACK, WHITE, RED, CYAN, PURPLE, GREEN, BLUE, YELLOW};
enum {*, FIRST, SECOND, THIRD};
enum {., FIRST, SECOND, THIRD};
enum {ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN};
Note: Values are automatically assigned to the constants in an enumeration.
@ -308,13 +308,13 @@ combined into a single char variable.
An enumeration is defined using a bitmask statement. When using the bitmask
keyword, it is followed by a { character, one to eight constant names
separated by commas, and a } character. An asterisk may be used in place
of a constant name, in which case the bit value will be skipped. The
bitmask statement is terminated with a semicolon.
separated by commas, and a } character. A period may be used in place of a
constant name, in which case the bit value will be skipped. The bitmask
statement is terminated with a semicolon.
Examples:
bitmask {BLUE, GREEN, RED, BRIGHT, INVERT, BLINK, FLIP, BKGRND};
bitmask {RD, RTS, DTR, RI, CD, *, CTS, DSR};
bitmask {RD, RTS, DTR, RI, CD, ., CTS, DSR};
Note: Values are automatically assigned to the constants in a bitmask,
each of which is a sequential power of two. The first constant in the
@ -323,43 +323,72 @@ the third is assigned the value 4, and so on.
DECLARATIONS
A declaration statement consists of type keyword (char or void) followed
by one or more variable names and optional definitions, or a single
function name and optional function block.
A declaration statement consists of type a keyword (char, int, or void)
followed one or more variable names (and optional definitions) or a single
function name and optional function block, or the struct keyword followed
by a structure name and either a definition or a variable name.
Variables may only be of type char and all variable declaration statements
are suffixed with a ; character.
Variables may only be of type char or int, and all variable declaration
statements are suffixed with a ; character. Variables of type char may be
delared as arrays, by appending the variable name with the [ character,
the upper bound of the array (0 to 255), and the ] character.
Examples:
char c; //Defines variable c
char i, j; //Defines variables i and j
char r[7]; //Defines 8 byte array r
char c; //Defines 8-bit variable c
char hi,lo; //Defines 8-bit variables hi and lo
char r[7]; //Defines 8 byte array r
int addr; //Defines 16-bit variable addr
int i, j; //Defines 16-bit variables i and j
A function declaration consists of the function name suffixed with a (
character, followed zero to three comma separated simple variables and
a ) character. A function declaration terminated with a ; character is
called a forward declaration and does not generate any code, while one
followed by a program block creates the specified function. Functions of
type char explicitly return a value (using a return statement), while
functions of type void do not.
character, followed by an optional parameter set and a ) character.
The parameter set, if specified, may be either one to three simple
char variables, a single int variable, or a char variable followed
by an int variable.
A function declaration terminated with a ; character is called a forward
declaration and does not generate any code, while one followed by a
program block creates the specified function.
Functions of type char and int explicitly return one or more values
(using a return statement), while functions of type void return no
explicit value.
The return statement causes the function to exit, after which control
returns to the statement immediately following the function call. If
the last statement before the closing } of the function body is not
a return, then an implicit return is assumed.
A return statement may be followed by an list of one to three variables
following the same rules as function arguments (see FUNCTION CALLS,
below), in which case those values are returned by the function call,
otherwise the function call will not return any explicit values.
Examples:
void myfunc(); //Forward declaration of function myfunc
char not(tmp) {tmp = tmp ^ $FF;}
char max(tmp1, tmp2) {if (tmp1 > tmp2) return tmp1; else return tmp2;}
char min(tmp1, tmp2) {if (tmp1 < tmp2) return tmp1; else return tmp2;}
char test(b,c,d) {if (b:-) return min(c,d); else return max(c,d);}
int swap(*,msb,lsb) {return *,lsb,msb;} //Swap bytes in integer
int incdec(m,i) {if (m:-) i--; else i++; return i}; //inc/dec integer
Note: Like all variables, function parameters are global. They must be
declared prior to the function decaration, and retain there values after
declared prior to the function declaration, and retain there values after
the function call. Although functions may be called recursively, they are
not re-entrant. Allocation of variables and functions is implementation
dependent, they could be placed in any part of memory and in any order.
The default behavior is to place variables directly after the program code,
including them as part of the generated object file.
The return value of a function is passed through the A register. A return
statement with an explicit expression will simply process that expression
(which leaves the result in the A register) before returning. A return
statement without an expression (including an implicit return) will, by
default, return the value of the last processed expression.
Function arguments and return values are passed through the 6502 registers.
Char type values are passed by loading A, Y, and X respectively, while int
type values are passed by loading Y with the most significant byte and
X with the least significant bit.
A return statement without explicit return values will return whatever
happens to be in the registers at that time.
STRUCTS
@ -378,19 +407,29 @@ 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.
semicolon. Each member definition is composed of a type keyword (char, int,
or struct) and one or more member names, separated with commas. If a 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. Any number of comments may appear before the first member, between
members, and after the last member.
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.
Member names are limited to six alphanumeric characters, the first of which
must be alphabetic. Any names are allowed including reserved words, as well
as A, X, and Y (which in this case, do not refer to registers).
When declaring a struct variable, the struct keyword is followed by the
struct type name, and one or more variable names, separated with commas.
The struct declaration is terminated with a semicolon.
Examples:
struct record {char name[8]; char index; data[128];};
struct record {char name[8]; char index; int addr, char data[128];};
struct record rec;
struct record srcrec, dstrec;
struct point {char x, y;}
struct point pnt;
struct line {struct pnt bgnpnt, endpnt;}
Note: Unlike simple and array variable, the members of a struct variable
may not be initialized during declaration.
@ -412,12 +451,13 @@ a page variable. This is used to ensure that accessing an array element will
not cross a page boundary, which requires extra CPU cycles to execute.
The const modifier specifies that a variable or array should not be changed
by program code. The const modifier may be preceded by the aligned modifier.
by program code. The const modifier may be preceded by an` aligned or
zeropage modifier.
A const variable declaration may include an initial value definition in
the form of an = character and literal after the variable name.
A const array may be declared in one of two ways: the variable name
A const array is 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 atring and/or numeric literals separated by
@ -437,20 +477,22 @@ Examples:
const char n = {1,2,3}; //Defines 3 byte array m containing 1, 2, and 3
const char m = {"abc", 123); //Defines 5 byte array containing string and byte
const char t = {"ab", "cd"); //Defines 6 byte array of two strings
aligned const char fbncci[] = {0, 1, 1, 2, 3, 5, 8, 13, 21, 34};
aligned const char fbncci = {0, 1, 1, 2, 3, 5, 8, 13, 21, 34};
zeropage char ptr, tmp; //Defines zero page variables
EXPRESSIONS
An expression is a series of one or more terms separated by operators.
The first term in an expression may be a function call, subscripted array
element, simple variable, literal, or register (A, X, or Y). An expression
may be preceded with a - character, in which case the first term is assumed
to be a literal 0.
Each term in an expression may be any of the following:
function call (first term only)
subscripted array element
char type variable, struct member, constant, or literal
byte operation
register (A, X, or Y).
Additional terms are limited to subscripted array elements, simple variables,
literals, and constants.
An expression may be preceded with a - character, in which case the first
term is assumed to be a literal 0.
Operators:
+ — Add the following value.
@ -471,10 +513,28 @@ result.
Note: Function calls are allowed in the first term of an expression
because upon return from the function the return value will be in the
Accumulator. However, due to the 6502 having only one Accumulatorm which
Accumulator. However, due to the 6502 having only one Accumulator, which
is used for all operations between two bytes, there is no simple system
agnostic method for allowing function calls in subsequent terms.
BYTE OPERATIONS
Byte operation allows the the bytes in an integer value to be accessed
as individual character values. A byte operation consists of a byte
operator prefixed to an integer value.
Byte Operators:
< - Get Least Significant Byte
> - Get Most Significant Byte
The integer value may be an integer literal, an address, or an int type
variable or struct member.
Examples:
hi = >&r; lo = <&r; //Set hi, lo to MSB, LSB of address of array R
page = >53281; //Set page to MSB of the integer literal 53281
lsb = <count; //Set lsb to low byte of integer variable count
CONTENTIONS
An contention is a construct which generates either TRUE or FALSE condition,
@ -624,7 +684,7 @@ a variable length.
INDEX-OF OPERATOR
The index-of operator ? generates a literal value equal to the offset in bytes
of a specified stucture member. It is allowed anywhere a literal would be and
of a specified structure member. It is allowed anywhere a literal would be and
should be used anytime the offset of the member of a struct is required.
When using the size-of operator, it is prefixed to the member specification.
@ -634,7 +694,7 @@ Examples:
blkmem(?rec.data, &s); //Search block for segment where data contains s
memcpy(?rec.data, &t); //Copy bytes of rec up to member data into t
Note: The idex-of operator is evaluated at compile time and generates two
Note: The index-of operator is evaluated at compile time and generates two
bytes of machine language code. It is the most efficient method of specifying
a the offset of a struct member.
@ -645,21 +705,21 @@ term in an expression. A function call consists of the function name
appended with a ( character, followed by zero to three arguments separated
with commas, and a closing ) character.
The first argument of a function call may be an expression, address, or
string (see below).
The first argument of a function call may be an expression, integer,
address, or string (see below).
The second argument may be a term (subscripted array element, simple
variable, or constant), address, or string,
variable, or constant), integer, address, or string,
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.
If the first or second argument is an integer address or string, then
no more arguments may be passed.
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 &. When passing a string, the string is simply
specified as the argument with.
address-of operator &. When passing a literal string, it is simply
specified as is.
Examples:
c = getc(); //Get character from keyboard
@ -671,7 +731,7 @@ Examples:
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
puts(&rec.name); //Write struct member to screen
Note: This particular argument passing convention has been chosen because
of the 6502's limited number of registers and stack processing instructions.
@ -698,14 +758,14 @@ The pop statement is likewise used to pop arguments off of the machine
stack after a function call. When using a pop statement, it is followed
with one or more simple variables or subscripted array elements , separated
by commas, and terminated with a semicolon. If any of the arguments are to
be discarded, an asterisk can be specified instead of a variable name.
be discarded, a period may be specified instead of a variable name.
The number of arguments pushed and popped may or may not be the same,
depending on how the machine language routine manipulates the stack pointer.
Examples:
push d,r; mult(); pop p; //multiply d times r and store in p
push x1,y1,x2,y2; rect(); pop *,*,*,*; //draw rectangle from x1,y1 to x2,y2
push x1,y1,x2,y2; rect(); pop .,.,.,.; //draw rectangle from x1,y1 to x2,y2
push &s, "tail"; strcat(); //concatenate "tail" onto string s
push x[i],y[i]; rotate(d); pop x[i],y[i]; //rotate point x[1],y[i] by d
@ -845,8 +905,10 @@ of code to be executed if the conditional was false.
Examples:
if (c = 27) goto end;
if (n) q = div(n,d) else puts("Division by 0!");
if (r[j]<r[i]) {t=r[i],r[i]=r[j],r[j]=t)}
if (n) q = div(n,d) else putln("Division by 0!");
if (r[q]<r[p]) {t=r[p],r[p]=r[q],r[q]=t)}
if (!>i | <i) puts("i is zero.");
if (>i > >j || >i = >j && <i > <j) k = i; else k = j;
Note: In order to optimize the compiled code, the if and else statements
are to 6502 relative branch instructions. This limits the amount of
@ -958,6 +1020,7 @@ if it is true, the code block is repeated.
Examples:
do c = rdkey(); while (c=0); //Wait for keypress
do (c = getchr(); putchr(c); while (c<>13) //Echo line to screen
i=0; do {i++;} while (>i <= >j && <i < <j); //Count from 0 to J
Note: Unlike the other loop structures do/while statements do not use
6502 JMP instructions. This optimizes the compiled code, but limits
@ -1021,10 +1084,11 @@ The #define directive allows the definition of constants but not macros.
The #if, #else, and #endif directives are not recognized at all by the
compiler. They may be added in the future.
The only type recognized by the compiler is char. Since the 6502 is an
8-bit processor, multi-byte types would generate over-complicated code.
In addition, the signed and unsigned keywords are unrecognized, due to the
6502's limited signed comparison functionality.
The only types recognized by the compiler are char and int. Int values
may only be used in limited contexts. Since the 6502 is an 8-bit processor,
multi-byte types would generate over-complicated code. In addition, the
signed and unsigned keywords are unrecognized, due to the 6502's limited
signed comparison functionality.
Because of the 6502's peculiar indirect addressing modes, pointers are not
currently implemented. Limited pointer operations may be implemented using

View File

@ -1,34 +1,34 @@
Character Symbols Recognized by the C02 Compiler
Symbol Prefix Operator Comparator Delimiter
! Bitwise Or Logical Not
" String Literal
Symbol Prefix/Suffix Operator Contention Other
! Bitwise Or Logical Not
" String Literal
# Constant
$ Hexadecimal
% Binary
& Address Of Bitwise And
' Character Literal
( Comparison
) Comparison
* (pointer)
+ Addition
, Declarations
- Subtraction
. Struct Members
& Address Of Bitwise And
' Character Literal
( Contention
) Contention
* (pointer)
+ Addition
, Argument Separator
- Subtraction
. Null Placeholder Struct Member Separator
/ Comment
: Status Flag Shortcut Else
; Statement
< Less Than
= Equal To Assignment
> Greater Than
? Index Of Shortcut If
: Status Flag Shortcut Else
; Statement
< Integer LSB Less Than
= Equal To Assignment
> Integer MSB Greater Than
? Index Of Shortcut If
@ Length Of
[ Array Element
\
] Array Element
^ (pointer)
[ Array Element
\
] Array Element
^ (pointer)
_
{ Block Start
| Bitwise Or
} Block End
{ Block Start
| Bitwise Or
} Block End
~

View File

@ -119,7 +119,7 @@ void prscnd(char trmntr, int revrse) {
revcmp = revrse;
if (look('!')) revcmp = (revcmp) ? FALSE: TRUE;
DEBUG("Set REVCMP to %d\n", revcmp)
if (!look('?')) prsxpr(0);
if (!look('.')) prsxpr(0);
if (look(':')) prsflg(revcmp); //Parse Flag Operator
else prscmp(revcmp); //Parse Comparison Operator
prslop(); //Parse Logical Operator

View File

@ -19,7 +19,7 @@
int addprm(char* prmtr) {
reqvar(FALSE); //Get Variable Name
if (varble.type == VTINT) {
if (vartyp == VTINT) {
strcpy(prmtrx, value);
strcpy(prmtry, value);
strcat(prmtry, "+1");
@ -38,8 +38,8 @@ void addfnc(void) {
prmtry[0] = 0;
prmtrx[0] = 0;
skpspc(); //Skip Spaces
if (isalph() || match('?')) { //Parse Parameters
if (!look('?')) {if (addprm(prmtra)) goto addfne;} //Get First Parameter
if (isalph() || match('.')) { //Parse Parameters
if (!look('.')) {if (addprm(prmtra)) goto addfne;} //Get First Parameter
if (look(',')) { //Look for Comma
if (addprm(prmtry)) goto addfne; //Get Second Parameter
if (look(',')) { //Look for Comma
@ -85,7 +85,7 @@ void penum(int m, int bitmsk) {
expect('{');
do {
if (enmval > 0xFF) ERROR("Maximum ENUM or BITMASK value exceeded\n", 0, EXIT_FAILURE)
if (look('?'))
if (look('.'))
DEBUG("Skipping sequence %d\n", enmval)
else {
getwrd(); //get defined identifier
@ -129,18 +129,33 @@ void pdecl(int m, int t) {
cmtlin(); //Write out declaration comment
}
/* Check for and Parse Type Keyword *
* Returns: Type (enum types) */
int ctype(int reqtyp) {
if (wordis("BITMASK")) return TBITMASK;
else if (wordis("STRUCT")) return TSTRUCT;
else if (wordis("ENUM")) return TENUM;
else if (wordis("CHAR")) return TCHAR;
else if (wordis("INT")) return TINT;
else if (wordis("VOID")) return TVOID;
else if (reqtyp) ERROR("Type Declaration Expected\n", 0, EXIT_FAILURE)
return TNONE;
}
/* Check for and Parse Type Keyword *
* Args: m - Modifier Type */
int ptype(int m) {
int reslt = TRUE;
if (wordis("STRUCT")) pstrct(m); //Parse 'struct' declaration
else if (wordis("ENUM")) penum(m, FALSE); //Parse 'enum' declaration
else if (wordis("BITMASK")) penum(m, TRUE); //Parse 'enum' declaration
else if (wordis("CHAR")) pdecl(m, VTCHAR); //Parse 'char' declaration
else if (wordis("INT")) pdecl(m, VTINT); //Parse 'int' declaration
else if (wordis("VOID")) pdecl(m, VTVOID); //Parse 'void' declaration
else reslt = FALSE;
return reslt;
int type = ctype(FALSE);
switch (type) {
case TSTRUCT: pstrct(m); break; //Parse 'struct' declaration
case TENUM: penum(m, FALSE); break; //Parse 'enum' declaration
case TBITMASK: penum(m, TRUE); break; //Parse 'enum' declaration
case TCHAR: pdecl(m, VTCHAR); break; //Parse 'char' declaration
case TINT: pdecl(m, VTINT); break; //Parse 'int' declaration
case TVOID: pdecl(m, VTVOID); break; //Parse 'void' declaration
default: return FALSE;
}
return TRUE;
}
int pmtype(int m) {

View File

@ -11,4 +11,7 @@ int prmcnt; //Number of Parameters
void addcon(int numval); //Add Constant
int pmodfr(); //Check for and Parse Modifier
int ctype(int reqtyp); //Check for Type Keyword
int ptype(int m); //Check for and Parse Type Keyword
enum types {TNONE, TVOID, TENUM, TBITMASK,TCHAR, TINT, TSTRUCT};

View File

@ -37,8 +37,9 @@ void poptrm(void) {
void prsval(int alwreg, int alwcon) {
DEBUG("Parsing value\n", 0)
skpspc();
if (islpre()) prslit(); //Parse Literal
if (islpre()) prslit(); //Parse Literal
else if (isalph()) prsvar(alwreg, alwcon); //Parse Variable
else if (isbtop()) prsbop(); //Parse Byte Operator
else expctd("literal or variable");
DEBUG("Parsed value of type %d\n", valtyp)
skpspc();
@ -56,7 +57,7 @@ void prcmns(void) {
* "" if no index defined */
void prsidx(int clbrkt) {
expect('[');
prsval(TRUE, TRUE); //Parse Value, Allowing Registers
prsval(TRUE, TRUE); //Parse Value, Allow Registers & Constants
DEBUG("Parsed array index '%s'\n", value)
if (clbrkt) expect(']');
}
@ -114,7 +115,7 @@ void chkidx(void) {
* Sets: term - the term (as a string) */
int prstrm(int alwint) {
DEBUG("Parsing term\n", 0)
prsval(FALSE, TRUE); //Parse Term - Disallow Registers
prsval(FALSE, TRUE); //Parse Value - Disallow Registers, Allow Constants
if (valtyp == FUNCTION) ERROR("Function call only allowed in first term\n", 0, EXIT_FAILURE)
strcpy(term, value);
if (valtyp == VARIABLE && prcvar(alwint)) return TRUE;
@ -180,19 +181,36 @@ int chkadr(int adract, int alwstr) {
return result;
}
/* Parse Byte Operator */
void prsbop(void) {
char byteop = getnxt();
CCMNT(byteop);
DEBUG("Parsing byte operator '%c'\n", byteop)
if (chkadr(FALSE, FALSE)) {
sprintf(value, "%c(%s)", byteop, word);
valtyp = LITERAL;
} else {
reqvar(FALSE);
if (vartyp != VTINT) ERROR("Integer Value Expected\n", 0, EXIT_FAILURE)
if (byteop == '>') strcat(value, "+1");
vartyp = VTCHAR;
}
DEBUG("Set value to \"%s\"\n", value)
}
/* Parse Function Argument or Return Values */
void prsfpr(char trmntr) {
if (!chkadr(ADLDYX, TRUE) && isxpre() || match('?')) {
if (!look('?')) {if (prsxpf(0)) goto prsfne;}
if (!chkadr(ADLDYX, TRUE) && isxpre() || match('.')) {
if (!look('.')) {if (prsxpf(0)) goto prsfne;}
if (look(',') && !chkadr(ADLDYX, TRUE)) {
if (!look('?')) {
if (!look('.')) {
if (prstrm(TRUE)) goto prsfne;
asmlin("LDY", term);
}
if (look(',')) {
prsval(FALSE, TRUE);
prsval(FALSE, TRUE); //Parse Value - Disallow Registers, Allow Constants
if (valtyp > VARIABLE) ERROR("Illegal Value Function Argument\n", 0, EXIT_FAILURE);
if (valtyp == VARIABLE && varble.type != VTCHAR) ERROR("Illegal Variable Type\n", 0, EXIT_FAILURE);
if (valtyp == VARIABLE && vartyp != VTCHAR) ERROR("Illegal Variable Type\n", 0, EXIT_FAILURE);
asmlin("LDX", value); }
}
}
@ -224,7 +242,7 @@ void prcvri(void) {
/* Process Variable in Term */
int prcvar(int alwint) {
switch (varble.type) {
switch (vartyp) {
case VTINT:
if (!alwint) ERROR("Illegal Use of Integer Variable %s\n", word, EXIT_FAILURE)
prcvri();
@ -258,7 +276,7 @@ int prcftm(int alwint) {
/* Parse first term of expession *
* First term can include function calls */
int prsftm(int alwint) {
prsval(TRUE, TRUE); //Parse Value, Allowing Registers
prsval(TRUE, TRUE); //Parse Value, Allow Registers & Constants
return prcftm(alwint);
}
@ -326,7 +344,10 @@ void prsxpi(char trmntr) {
if (valtyp == FUNCTION) {
strcpy(term, value);
prsfnc(0); //Parse Expression Function
} else if (valtyp == VARIABLE && varble.type == VTINT) {
} else if (valtyp == STRUCTURE) {
prsmbr(value);
if (vartyp != VTINT) ERROR("Illegal Member %s In Integer Expression", value, EXIT_FAILURE)
} else if (valtyp == VARIABLE && vartyp == VTINT) {
prcvri(); //Process Integer Variable
} else {
ERROR("Illegal Variable %s In Integer Expression", value, EXIT_FAILURE)

View File

@ -18,6 +18,7 @@ int prcftm(int alwint); //Process First Term
void prcvri(void); //Process Integer Variable
int prcvar(int alwint); //Process Variable in Term
void prsadr(int adract); //Parse and Compile Address of Operator
void prsbop(void); //Parse Byte Operator
void prsval(int alwreg, int alwcon); //Parse Value
void prsfnc(char trmntr); //Parse function call
void prsfpr(char trmntr); //Parse Function Paraeters or Return

View File

@ -22,6 +22,7 @@ int isanum(void) {return isalnum(nxtchr);}
int isapos(void) {return match('\'');}
int isbin(void) {return inbtwn('0', '1');}
int isbpre(void) {return TF(isnpre() || isapos());}
int isbtop(void) {return TF(match('<') || match('>'));}
int isdec(void) {return inbtwn('0', '9');}
int iscpre(void) {return match('#');}
int ishexd(void) {return TF(isdec() || inbtwn('A', 'Z'));}

View File

@ -29,6 +29,7 @@ int isanum(); //Is Next Character AlphaNumeric
int isapos(); //Is Next Character an Apostrophe
int isbin(); //Is Next Character a Binary Digit
int isbpre(); //Is Next Character a Binary Prefix
int isbtop(); //Is Next Character a Byte Operator
int isdec(); //Is Next Character a Decimal Digit
int iscpre(); //Is Next Character a Constant Prefix
int ishexd(); //Is Next Character a Hexadecimal Digit

View File

@ -126,8 +126,8 @@ void prcasn(char trmntr) {
void prcasi(char trmntr) {
DEBUG("Processing Integer Assignment\n", 0);
expect('=');
strcpy(xsnvar, word); //Set Assignment LSB
strcpy(ysnvar, word); strcat(ysnvar, "+1"); //Set Assignment MSB
strcpy(xsnvar, vrname); //Set Assignment LSB
strcpy(ysnvar, vrname); strcat(ysnvar, "+1"); //Set Assignment MSB
ysnidx[0] = 0; //No Y Index
prsxpi(trmntr);
prcaxy();
@ -145,13 +145,15 @@ int getidx(char* idx) {
/* Process Assignment Variable(s) */
void prcavr(char trmntr) {
chksym(TRUE, FALSE, word);
if (varble.type == VTINT) {
if (ispopr()) {if (prspst(trmntr, TRUE, word, "")) expctd("post operator");}
DEBUG("Processing assignment of variable %s\n", word);
strcpy(vrname, word); //save variable to assign to
if (valtyp == STRUCTURE) prsmbr(vrname); //Updates word and vartyp
if (vartyp == VTINT) {
if (ispopr()) {if (prspst(trmntr, TRUE, vrname, "")) expctd("post operator");}
else prcasi(trmntr); //Process Integer Assignment
return;
}
strcpy(asnvar, word); //save variable to assign to
if (valtyp == STRUCTURE) prsmbr(asnvar);
strcpy(asnvar, vrname);
asntyp = valtyp; //Set Assigned Variable Type
DEBUG("Set STA variable to %s\n", asnvar)
if (asntyp == VARIABLE && look(';')) {
@ -210,6 +212,7 @@ void pasm(void) {
/* Parse and Compile an Assignment */
void prsasn(char trmntr) {
getwrd(); //Get Variable to be Assigned
DEBUG("Parsing assignment of word %s\n", word)
prcavr(trmntr);
}
@ -343,7 +346,7 @@ void pinlne(void) {
void ppop(void) {
DEBUG("Parsing POP statement\n", 0)
do {
if (look('?')) term[0]=0;
if (look('.')) term[0]=0;
else {
reqvar(TRUE);
strcpy(term, value);

View File

@ -14,6 +14,7 @@
#include "parse.h"
#include "label.h"
#include "vars.h"
#include "dclrtn.h"
/* Lookup variable name in variable table *
* Sets: varidx = index into vartbl array *
@ -24,6 +25,7 @@ int fndvar(char *name) {
for (varidx=0; varidx<varcnt; varidx++) {
if (strcmp(vartbl[varidx].name, name) == 0) {
memcpy(&varble, &vartbl[varidx], sizeof(varble));
vartyp = varble.type;
return TRUE;
}
}
@ -49,7 +51,11 @@ 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;
if (strcmp(membrs[mbridx].name, name) == 0) {
memcpy(&membr, &membrs[mbridx], sizeof(membr));
vartyp = membr.vartyp;
return TRUE;
}
}
return FALSE;
}
@ -84,7 +90,7 @@ void prcmbr(char* name) {
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)
mbrofs += membrs[mbridx].offset; //Get Member Offet in Struct
mbrofs += membr.offset; //Get Member Offet in Struct
}
/* Parse next word as struct member *
@ -95,9 +101,9 @@ void prsmbr(char* name) {
mbrofs = 0;
stcidx = varble.stcidx; //Get Struct Index
prcmbr(name);
while (membrs[mbridx].stype == STRUCTURE && nxtchr == '.') {
stcidx = membrs[mbridx].symidx;
prcmbr(membrs[mbridx].name);
while (membr.vartyp == VTSTRUCT && nxtchr == '.') {
stcidx = membr.symidx;
prcmbr(membr.name);
}
sprintf(word, "+$%hhX", mbrofs); //Get Member Offet in Struct
strcat(name, word); //Add Offset to Struct
@ -133,8 +139,8 @@ int pidxof(void) {
mbridx = -1; //Set Member Index to None
reqvar(FALSE); //Parse Variable Name to get Size Of
if (mbridx > -1) {
sprintf(value, "$%hhX", membrs[mbridx].offset);
return membrs[mbridx].offset;
sprintf(value, "$%hhX", membr.offset);
return membr.offset;
}
ERROR("IndexOf operator requires a struct member\n", 0, EXIT_FAILURE);
return 0; //Suppress Warning
@ -149,8 +155,8 @@ int psizof(void) {
mbridx = -1; //Set Member Index to None
reqvar(FALSE); //Parse Variable Name to get Size Of
if (mbridx > -1) {
sprintf(value, "$%hhX", membrs[mbridx].size);
return membrs[mbridx].size;
sprintf(value, "$%hhX", membr.size);
return membr.size;
}
if (datlen[varidx]) {
sprintf(value, "$%hhX", datlen[varidx]);
@ -270,7 +276,7 @@ void addvar(int m, int t) {
prsnum(0xFFFF);
else {
prsvar(FALSE, FALSE);
if (t == VTINT && varble.type != t)
if (t == VTINT && vartyp != t)
ERROR("ALIAS Type Mismatch\n", 0, EXIT_FAILURE)
if (t > VTINT) ERROR("Type may not be ALIASed\n", 0, EXIT_FAILURE)
}
@ -370,8 +376,10 @@ void wvrtbl(void) {
void addstc(void) {
if (!fndstc(word)) ERROR("Undefined Struct '%s\n", word,EXIT_FAILURE)
strct = strcts[stcidx]; //Retrieve Structure
getwrd(); //Get Variable Name
addvar(MTNONE, VTSTRUCT);
do {
getwrd(); //Get Variable Name
addvar(MTNONE, VTSTRUCT);
} while (look(','));
expect(';');
}
@ -380,46 +388,63 @@ void addstc(void) {
void defstc(void) {
DEBUG("Parsing struct definition\n", 0)
if (fndstc(word)) ERROR("Duplicate Declaration of Struct '%s\n", word,EXIT_FAILURE)
int type;
int prnidx = stcidx;
strncpy(strct.name, word, STCLEN);
DEBUG("Set struct name to '%s'\n", word);
strct.size = 0; //Initialize Struct Length
while (look('/')) skpcmt(FALSE); //Skip Comments
do {
getwrd(); //Get Member Name
if (wordis("STRUCT")) {
getwrd(); //Get Structure Name
if (!fndstc(word)) ERROR("Structure '%s' Not Defined\n", word, EXIT_FAILURE)
membr.stype = STRUCTURE;
membr.size = strcts[stcidx].size;
membr.symidx = stcidx;
getwrd(); //Get Member Name
} else {
if (wordis("CHAR")) getwrd(); //Skip Optional Type Declaration
membr.stype = VARIABLE;
membr.size = 1;
membr.symidx = -1;
getwrd(); //Get Next word
type = ctype(TRUE); //Check if word is a type declaration
switch (type) {
case TSTRUCT:
vartyp = VTSTRUCT;
getwrd(); //Get Structure Name
if (!fndstc(word)) ERROR("Structure '%s' Not Defined\n", word, EXIT_FAILURE)
mbrsiz = strcts[stcidx].size;
break;
case TINT:
vartyp = VTINT;
mbrsiz = 2;
stcidx = -1;
break;
case TCHAR:
vartyp = VTCHAR;
mbrsiz = 1;
stcidx = -1;
break;
default:
ERROR("Invalid Type %s in Struct Definition\n", word, EXIT_FAILURE)
}
if (fndmbr(stccnt, word)) ERROR("Duplicate Declaration of Struct Member '%s\n", word,EXIT_FAILURE)
DEBUG("Parsing member %s\n", word)
strncpy(membr.name, word, STMLEN); //Set Member Name
membr.strcti = prnidx; //Set Parent Struct Index
membr.offset = strct.size; //Set Offset into Struct
if (membr.stype == VARIABLE) {
DEBUG("Checking for array definition\n", 0)
if (match('[')) {
CCMNT('[');
skpchr();
membr.stype = ARRAY;
DEBUG("Parsing array size\n", 0)
membr.size = prsnum(0xFF) + 1;
expect(']');
DEBUG("Parsing members of type %s\n", word)
do {
getwrd(); //Get Member Name
DEBUG("Parsing member %s\n", word)
if (fndmbr(stccnt, word)) ERROR("Duplicate Declaration of Struct Member '%s\n", word,EXIT_FAILURE)
if (strlen(word) > STMLEN) ERROR("Member Name %s too long\n", word, EXIT_FAILURE)
strcpy(membr.name, word); //Set Member Name
membr.strcti = prnidx; //Set Parent Struct Index
membr.vartyp = vartyp; //Set Member Variable Type
membr.symidx = stcidx; //Set Member Symbol Index
membr.offset = strct.size; //Set Offset into Struct
membr.size = mbrsiz; //Set Member Size
if (membr.vartyp == VTCHAR) {
DEBUG("Checking member for array definition\n", 0)
if (match('[')) {
CCMNT('[');
skpchr();
membr.vartyp = VTARRAY;
DEBUG("Parsing member array size\n", 0)
membr.size = prsnum(0xFF) + 1;
expect(']');
}
}
}
DEBUG("Set member type to %d", membr.stype) DETAIL(" and size to %d\n", membr.size);
DEBUG("Adding member at index %d\n", mbrcnt);
membrs[mbrcnt++] = membr;
strct.size += membr.size;
DEBUG("Set member type to %d", membr.vartyp) DETAIL(" and size to %d\n", membr.size);
DEBUG("Adding member at index %d\n", mbrcnt);
membrs[mbrcnt++] = membr;
strct.size += membr.size;
} while (look(','));
expect(';');
while (look('/')) skpcmt(FALSE); //Skip Comments
} while (!look('}'));
@ -440,7 +465,7 @@ void logstc(void) {
for (mbridx=0; mbridx<mbrcnt; mbridx++) {
membr = membrs[mbridx];
fprintf(logfil, "%-8s %-8s", strcts[membr.strcti].name, membr.name);
fprintf(logfil, " %5d %5d %6d %5d\n", membr.stype, membr.symidx, membr.offset, membr.size);
fprintf(logfil, " %5d %5d %6d %5d\n", membr.vartyp, membr.symidx, membr.offset, membr.size);
}
}

View File

@ -17,6 +17,7 @@ struct varrec varble; //Variable Table Entry
int varcnt; //Number of Variables in Table
int varidx; //Index into Variable Tables
char vrname[MAXVAR+1]; //Variable Name
int vartyp; //Variable/Member Type
int vrwrtn; //Variables Written Flag
struct strctd { //Struct Definition
@ -32,7 +33,7 @@ int stcidx; //Index into Struct Tables
struct membrd { //Struct Membetr Definition
char name[STMLEN+1]; //Member Name
int strcti; //Parent Struct Index
int stype; //Member Symbol Type
int vartyp; //Member Symbol Type
int symidx; //Member Symbol Index
int offset; //Offset into Struct
int size; //Member Size
@ -43,6 +44,7 @@ struct membrd membr; //Defined Member
int mbrcnt; //Number of Struct Members Defined
int mbridx; //Index into Struct Member Tables
int mbrofs; //Member Offset
int mbrsiz; //Member Size
enum vtypes {VTVOID, VTREG, VTCHAR, VTINT, VTARRAY, VTSTRUCT}; //Variable Types

View File

@ -1,6 +1,6 @@
/**********************************************
* STRINGS - Demonstrate string.h02 functions *
**********************************************/
/*********************************
* STRUCTS - Test C02 structures *
*********************************/
//Specify System Header using -H option
#include <stddef.h02>
@ -16,60 +16,64 @@ int yx;
//Define Structure
struct record { /* Sample Record */
char name[8]; //Name
char index; //Index
data[128]; //Data
char name[8]; //Name
char index; //Index
int addr; //Address
char data[128]; //Data
};
//Declare Structure Variable
struct record srcrec;
struct record dstrec;
//Struct Containing Structs
struct point { char xpos; char ypos; };
//Structs Containing Structs
struct point {char x, y; };
struct point pnt;
struct rect {struct point toplft; struct point btmrgt; };
struct rect {struct point toplft, btmrgt; };
struct rect box;
struct frame {struct rect outer; struct rect inner; };
struct frame {struct rect outer, inner; };
struct frame fram;
main:
//Set Structure Members
strdst(&srcrec.name); strcpy("RECNAME");
strdst(srcrec.name); strcpy("RECNAME");
srcrec.index = 1;
srcrec.addr = &srcrec;
for (i = 0; i<=@srcrec.data; i++)
srcrec.data[i] = i;
//Clear Destination Record
memclr(@dstrec,&dstrec);
memclr(@dstrec, dstrec);
prtdst();
//Copy Source Record into Destination Record
memdst(&dstrec);
memcpy(@srcrec, &srcrec);
memdst(dstrec);
memcpy(@srcrec, srcrec);
prtdst();
//Clear Box
memclr(@box, &box); //Clear Box Members
prtbox(); //Print Box Members
memclr(@box, box); //Clear Box Members
prtbox(""); //Print Box Members
//Set Box Members
box.toplft.xpos=1; box.toplft.ypos=2;
box.btmrgt.xpos=8; box.btmrgt.ypos=9;
prtbox();
box.toplft.x=1; box.toplft.y=2;
box.btmrgt.x=8; box.btmrgt.y=9;
prtbox("");
newlin();
//Clear Frame
memclr(@fram, &fram); //Clear Frame Members
memclr(@fram, fram); //Clear Frame Members
prtfrm(); //Print Frame Members
//Set Frame Members
fram.outer.toplft.xpos=10; fram.outer.toplft.ypos=11;
fram.outer.btmrgt.xpos=98; fram.outer.btmrgt.ypos=99;
fram.inner.toplft.xpos=22; fram.inner.toplft.ypos=23;
fram.inner.btmrgt.xpos=86; fram.inner.btmrgt.ypos=87;
fram.outer.toplft.x=10; fram.outer.toplft.y=11;
fram.outer.btmrgt.x=98; fram.outer.btmrgt.y=99;
fram.inner.toplft.x=22; fram.inner.toplft.y=23;
fram.inner.btmrgt.x=86; fram.inner.btmrgt.y=87;
prtfrm();
newlin();
@ -77,8 +81,9 @@ goto exit;
//Print Destination Record
void prtdst() {
setdst(&dstrec.name); printf("REC.NAME=\"%s\"%n");
setdst(dstrec.name); printf("REC.NAME=\"%s\"%n");
printf(dstrec.index, "REC.INDEX=%d%n");
setdst(dstrec.addr); printf("REC.ADDR=$%w%n");
puts("REC.DATA=[");
for (i = 0; i<@dstrec.data; i++) {
if (i) putc(',');
@ -90,26 +95,26 @@ void prtdst() {
//Print Frame
void prtfrm() {
putln("OUTER."); cpybox(&fram.outer); prtbox();
putln("INNER."); cpybox(&fram.inner); prtbox();
cpybox(fram.outer); prtbox("OUTER.");
cpybox(fram.inner); prtbox("INNER.");
anykey();
}
void cpybox() {
savrxy(); setdst(&box);
savrxy(); setdst(box);
resrxy(); memcpy(@box);
}
//Print Box
void prtbox() {
puts(" TOPLFT."); prtpnt(&box.toplft);
puts(" BTMRGT."); prtpnt(&box.btmrgt);
void prtbox(yx) {
puts(yx); puts("TOPLFT."); prtpnt(box.toplft);
puts(yx); puts("BTMRGT."); prtpnt(box.btmrgt);
}
//Print Point
void prtpnt() {
savrxy(); setdst(&pnt);
savrxy(); setdst(pnt);
resrxy(); memcpy(@pnt);
printf(pnt.xpos,"XPOS=%d,");
printf(pnt.ypos,"YPOS=%d%n");
printf(pnt.x,"X=%d,");
printf(pnt.y,"Y=%d%n");
}

View File

@ -4,6 +4,7 @@
#pragma zeropage $80
char b,d;
char hi,lo;
char s[128];
char aa,yy,xx;
@ -15,6 +16,9 @@ int i,j;
int m,n;
int yx;
hi = >c; lo = <c;
hi = >&c; lo = <&c;
i<<;
j>>;
m++;
@ -31,13 +35,13 @@ d = fnd(b,c);
i = fni(c);
j = fnj(b,c);
int fnb(?,yy,xx) {
return ?,xx,yy;
int fnb(.,yy,xx) {
return .,xx,yy;
}
int fnd(aa,yy,xx) {
if (aa) return ?,xx,yy;
else return ?,yy,xx;
if (aa) return .,xx,yy;
else return .,yy,xx;
}
int fni(yx) {

View File

@ -3,41 +3,77 @@
#pragma origin 1000
char d, i;
char lo, hi;
char index, name[8], data[128];
int addr;
//Define Structure
struct record {
char name[8];
char index;
char data[128];
//Define Structures
struct point {
char x, y;
};
//Declare Structure Variable
struct line {
struct point bgnpnt, endpnt;
};
struct record {
/* This is a Record */ //Extra Comment
char name[8]; //Name
char index; //Index
int addr; //Address
struct point pnt; //Point
char data[128]; //Data
};
//Declare Structure Variables
struct point pnt;
struct point bgnpnt, endpnt;
struct line lin;
struct record rec;
//Display Structure Info
printf(?pnt.x,"?pnt.x=%d\t");
printf(@pnt.x,"@pnt.x=%d\n");
printf(?pnt.y,"?pnt.y=%d\t");
printf(@pnt.y,"@pnt.y=%d\n");
printf(@rec,"@rec=%d\n");
printf(?rec.name,"?rec.name=%d\t");
printf(@rec.name,"@rec.name=%d\n");
printf(?rec.index,"?rec.index=%d\t");
printf(@rec.index,"@rec.index=%d\n");
printf(?rec.addr,"?rec.addr=%d\t");
printf(@rec.addr,"@rec.addr=%d\n");
printf(?rec.pnt,"?rec.pnt=%d\t");
printf(@rec.pnt,"@rec.pnt=%d\n");
printf(?rec.data,"?rec.data=%d\t");
printf(@rec.data,"@rec.data=%d\n");
//Get Member LSB & MSB
hi = >rec.addr; lo = <rec.addr;
hi = >&rec.data; lo = <&rec.data;
//Set Structure Members
strdst(&rec.name); strcpy(name);
rec.index = index;
rec.addr = $ABCD;
rec.pnt.x = 33;
rec.pnt.y = 44;
for (i = 0; i<=128; i++)
rec.data[i] = d;
//Pass Entire Structure into Function
blkput(@rec, &rec);
//Print Structure Members
setdst(rec.name); putln("rec.name=\"%s\"");
//Copy Struct Member
memdst(&data); memcpy(@rec.data, &rec.data);
//Get Structure Members
index = rec.index;
addr = rec.addr;
for (i = 0; i<129; i++)
d = rec.data[i];