From b6cec4d75adb2b67fa66f40426877717d27c77d8 Mon Sep 17 00:00:00 2001 From: Curtis F Kaylor Date: Sun, 12 May 2019 23:34:47 -0400 Subject: [PATCH] Allow int members in structs --- c02.ppj | 6 +- doc/c02.txt | 192 +++++++++++++++++++++++++++++++---------------- doc/symbols.txt | 50 ++++++------ src/cond.c | 2 +- src/dclrtn.c | 41 ++++++---- src/dclrtn.h | 3 + src/expr.c | 43 ++++++++--- src/expr.h | 1 + src/parse.c | 1 + src/parse.h | 1 + src/stmnt.c | 17 +++-- src/vars.c | 115 +++++++++++++++++----------- src/vars.h | 4 +- test/structs.c02 | 73 +++++++++--------- work/ints.c02 | 12 ++- work/structs.c02 | 48 ++++++++++-- 16 files changed, 397 insertions(+), 212 deletions(-) diff --git a/c02.ppj b/c02.ppj index 518be17..f45d1dd 100644 --- a/c02.ppj +++ b/c02.ppj @@ -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: diff --git a/doc/c02.txt b/doc/c02.txt index 85672f9..a898bda 100644 --- a/doc/c02.txt +++ b/doc/c02.txt @@ -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 = i | i > >j || >i = >j && 13) //Echo line to screen + i=0; do {i++;} while (>i <= >j && 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 ~ diff --git a/src/cond.c b/src/cond.c index b06fa06..54fd01e 100644 --- a/src/cond.c +++ b/src/cond.c @@ -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 diff --git a/src/dclrtn.c b/src/dclrtn.c index d911545..445257e 100644 --- a/src/dclrtn.c +++ b/src/dclrtn.c @@ -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) { diff --git a/src/dclrtn.h b/src/dclrtn.h index 2992551..98486f3 100644 --- a/src/dclrtn.h +++ b/src/dclrtn.h @@ -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}; diff --git a/src/expr.c b/src/expr.c index 112f8d3..c34d8c6 100644 --- a/src/expr.c +++ b/src/expr.c @@ -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) diff --git a/src/expr.h b/src/expr.h index 8626094..8963cd8 100644 --- a/src/expr.h +++ b/src/expr.h @@ -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 diff --git a/src/parse.c b/src/parse.c index 2c8418d..c7474c5 100644 --- a/src/parse.c +++ b/src/parse.c @@ -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'));} diff --git a/src/parse.h b/src/parse.h index d9f92c3..6e8c5b2 100644 --- a/src/parse.h +++ b/src/parse.h @@ -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 diff --git a/src/stmnt.c b/src/stmnt.c index 05b7a49..24c617f 100644 --- a/src/stmnt.c +++ b/src/stmnt.c @@ -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); diff --git a/src/vars.c b/src/vars.c index 0664abe..533261b 100644 --- a/src/vars.c +++ b/src/vars.c @@ -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 -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 @@ -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"); } diff --git a/work/ints.c02 b/work/ints.c02 index e851156..1b43501 100644 --- a/work/ints.c02 +++ b/work/ints.c02 @@ -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; 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) { diff --git a/work/structs.c02 b/work/structs.c02 index c6ff89d..b4186c6 100644 --- a/work/structs.c02 +++ b/work/structs.c02 @@ -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.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];