From d5d4d79929c8f12fc530afb67b9a177d24b6be44 Mon Sep 17 00:00:00 2001 From: Curtis F Kaylor Date: Thu, 8 Mar 2018 20:07:31 -0500 Subject: [PATCH] Added size-of operator --- doc/c02.txt | 19 +++++++++++++++++++ doc/c02vsC.txt | 4 ++++ py65/structs.c02 | 6 +++--- src/dclrtn.c | 4 ++-- src/parse.c | 20 +++++++++++--------- src/parse.h | 9 +++++---- src/vars.c | 33 ++++++++++++++++++++++++++++++--- src/vars.h | 3 ++- test/structs.c02 | 5 ++++- 9 files changed, 80 insertions(+), 23 deletions(-) diff --git a/doc/c02.txt b/doc/c02.txt index b9c5df2..b3470f2 100644 --- a/doc/c02.txt +++ b/doc/c02.txt @@ -461,6 +461,25 @@ 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. +SIZE-OF OPERATOR + +The size-of operator @ generates a literal value equal to the size in bytes +of a specified variable. It is allowed anywhere a literal would be and +should be used anytime the size of an array, struct, or member is required. + +When using the size-of operator, it is prefixed to the variable name or +member specification. + +Examples: + + for (i=0; i<=@z; i++) z[i] = r[i]; //Copy elements from r[] to z[] + blkput(@rec ,&rec); //Copy struct rec to next block segment + memcpy(@rec.data, &rec.data); //Copy member data to destination array + +Note: The size-of operator is evaluated at compile time and generates two +bytes of machine language code. It is the most efficient method of specifying +a variable length. + FUNCTION CALLS A function call may be used as a stand-alone statement, or as the first diff --git a/doc/c02vsC.txt b/doc/c02vsC.txt index b43faf1..a79347e 100644 --- a/doc/c02vsC.txt +++ b/doc/c02vsC.txt @@ -63,6 +63,9 @@ 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. +The sizeof operator in C02 is the at sign @. It may only be used with +declared variables and struct members, not types. + FUNCTIONS Parameter passing uses the 6502's A, Y, and X registers. This limits @@ -82,6 +85,7 @@ 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 diff --git a/py65/structs.c02 b/py65/structs.c02 index e9ffc92..f0bd295 100644 --- a/py65/structs.c02 +++ b/py65/structs.c02 @@ -27,7 +27,7 @@ main: //Set Structure Members strdst(&srcrec.name); strcpy("RECNAME"); srcrec.index = 1; -for (i = 0; i<129; i++) +for (i = 0; i<=@srcrec.data; i++) srcrec.data[i] = i; //Clear Destination Record @@ -37,7 +37,7 @@ prtdst(); //Copy Source Record into Destination Record memdst(&dstrec); -memcpy(129, &srcrec); +memcpy(@srcrec, &srcrec); prtdst(); @@ -48,7 +48,7 @@ void prtdst() { puts("REC.NAME="); putln(&dstrec.name); puts("REC.INDEX="); putdec(dstrec.index); newlin(); puts("REC.DATA={"); - for (i = 0; i<129; i++) { + for (i = 0; i<@dstrec.data; i++) { if (i) putc(','); putdec(dstrec.data[i]); } diff --git a/src/dclrtn.c b/src/dclrtn.c index 27ac86a..8957511 100644 --- a/src/dclrtn.c +++ b/src/dclrtn.c @@ -98,7 +98,7 @@ void pstrct(int m) { getwrd(); //Parse Structure Name if (look('{')) defstc(); //Parse Struct Definition else addstc(); //Parse and Compile Struct Declaration - SCMNT(""); //Clear Assembler Comment + cmtlin(); //Write out declaration comment } /* Parse Variable/Function Declaration*/ @@ -115,7 +115,7 @@ void pdecl(int m, int t) { } while (look(',')); expect(';'); DEBUG("Variable Declaration Completed\n", 0) - SCMNT(""); //Clear Assembler Comment + cmtlin(); //Write out declaration comment } /* Check for and Parse Type Keyword */ diff --git a/src/parse.c b/src/parse.c index c296144..a0a6ba6 100644 --- a/src/parse.c +++ b/src/parse.c @@ -21,16 +21,17 @@ 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 islpre(void) {return TF(isbpre() || ishash());} int isdec(void) {return inbtwn('0', '9');} -int ishash(void) {return match('#');} +int iscpre(void) {return match('#');} int ishexd(void) {return TF(isdec() || inbtwn('A', 'Z'));} +int islpre(void) {return TF(isbpre() || iscpre() || isszop());} int isnl(void) {return TF(match('\n') || match('\r'));} int isnpre(void) {return TF(isdec() || match('$') || match('%'));} int isoper(void) {return TF(strchr("+-&|^", nxtchr));} int ispopr(void) {return TF(strchr("+-<>", nxtchr));} int isprnt(void) {return isprint(nxtchr);} int isspc(void) {return isspace(nxtchr);} +int isszop(void) {return match('@');} int isvpre(void) {return TF(isalph() || islpre());} int isxpre(void) {return TF(isvpre() || match('-'));} @@ -241,14 +242,13 @@ int prschr(void) { int wrdlen = 0; char c; DEBUG("Parsing character literal\n", 0) - expect('\''); - word[wrdlen++] = '\''; + word[wrdlen++] = getnxt(); //Initial Single Quote if (match('\\')) word[wrdlen++] = getnxt(); c = getnxt(); DEBUG("Extracted character %c\n", c) word[wrdlen++] = prcchr(c); - expect('\''); - word[wrdlen++] = '\''; + if (!match('\'')) expctd("character delimiter"); + word[wrdlen++] = getnxt(); word[wrdlen] = 0; return (int)c; } @@ -256,7 +256,7 @@ int prschr(void) { /* Parse numeric value * * Args: maxval - maximum allowed value * * Sets: value - parsed number (as string) * - * word - parses text of value * + * word - parsed text of value * * Returns: parsed number */ int prsnum(int maxval) { int number; @@ -273,6 +273,7 @@ int prsnum(int maxval) { if (number > maxval) ERROR("Out of bounds literal '%d';\n", number, EXIT_FAILURE) if (maxval > 255) sprintf(value, "$%04X", number); else sprintf(value, "$%02X", number); + ACMNT(word) return number; } @@ -308,8 +309,9 @@ int prscon(void) { * character arguments instead of 'c' */ void prslit(void) { skpspc(); - if (ishash()) litval = prscon(); //Parse Constant - else litval = prsbyt(); //Parse Byte Value + if (iscpre()) litval = prscon(); //Parse Constant + else if (isszop()) litval = psizof(); //Parese SizeOf Operator + else litval = prsbyt(); //Parse Byte Value valtyp = LITERAL; strcpy(word, value); //Patch for DASM strcpy(value, "#"); diff --git a/src/parse.h b/src/parse.h index 724ad6d..9a64f50 100644 --- a/src/parse.h +++ b/src/parse.h @@ -27,10 +27,10 @@ int isalph(); //Is Next Character Alphabetic int isanum(); //Is Next Character AlphaNumeric int isapos(); //Is Next Character an Apostrophe int isbin(); //Is Next Character a Binary Digit -int isbpre(); // -int islpre(); //Is Next Character a Constant +int isbpre(); //Is Next Character a Binary Prefix +int islpre(); //Is Next Character a Literal Prefix int isdec(); //Is Next Character a Decimal Digit -int ishash(); //Is Next Character a Byte Value +int iscpre(); //Is Next Character a Constant Prefix int ishexd(); //Is Next Character a Hexadecimal Digit int isnl(); //Is Next Character a NewLine int isnpre(); //Is Next Character a Numeric Prfix @@ -38,6 +38,7 @@ int isoper(); //Is Next Character an Operator int ispopr(); //Is Next Character a Post-Operator int isprnt(); //Is Next Character Printable int isspc(); //Is Next Character a Space +int isszop(); //Is Next Character the SizeOf Operator int isvpre(); //Is Next Character a Value Prefix int isxpre(); //Is Next Character an Expression Prefix @@ -52,8 +53,8 @@ void prslit(); //Parse Literal int prsnum(int maxval); //Parse Numeric void prsopr(); //Parse Arithmetic Operator int prspst(char trmntr, char* name, char* index); //Parse Post Operator +int psizof(void); //Parse SizeOf Operator void skpchr(); //Skip Next Character void skpcmt(); //Skip to End of Comment void skpspc(); //Advance to Next Printable Character int wordis(char *s); //Does word match s - diff --git a/src/vars.c b/src/vars.c index 682e17d..90afbb7 100644 --- a/src/vars.c +++ b/src/vars.c @@ -74,13 +74,13 @@ 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 + getwrd(); //Get Member 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 + strcat(name, word); //Add Offset to Struct } /* Parse next word as variable or function name * @@ -104,6 +104,31 @@ void reqvar(int alwary) { if (!alwary && valtyp != VARIABLE) expctd("Variable"); } +/* Parse SizeOf Operator * + * Sets: value - variable size (as string) * + * Returns: variable size (as integer */ +int psizof(void) { + expect('@'); //Check for and Skip SizeOf Operator + DEBUG("Parsing sizeof operator", 0); + mbridx = -1; //Set Member Index to None + reqvar(FALSE); //Parse Variable Name to get Size Of + if (mbridx > 0) { + sprintf(value, "$%hhX", membrs[mbridx].size); + return membrs[mbridx].size; + } + if (datlen[varidx]) { + sprintf(value, "$%hhX", datlen[varidx]); + return datlen[varidx]; + } + if (strlen(varsiz[varidx]) == 0) { + strcpy(value,"1"); + return 1; + } + strcpy(value, varsiz[varidx]); + if (strcmp(value, "*") == 0) ERROR("Unable to Determine Size of Variable %s\n", vrname, EXIT_FAILURE); + return atoi(value); +} + /* Parse Data Array */ void prsdta(void) { dtype = DTARRY; @@ -191,6 +216,7 @@ void addvar(int m, int t) { DEBUG("Setting variable size to %d\n", strct.size) sprintf(value, "%d", strct.size); } else if (match('[')) { + CCMNT('[') skpchr(); if (alcvar) { DEBUG("Parsing array size\n", 0) @@ -272,7 +298,8 @@ void defstc(void) { membr.offset = strct.size; //Set Offset into Struct DEBUG("Checking for array definition\n", 0) if (match('[')) { - skpchr(); + CCMNT('['); + skpchr(); membr.stype = ARRAY; DEBUG("Parsing array size\n", 0) membr.size = prsnum(0xFF) + 1; diff --git a/src/vars.h b/src/vars.h index 5cdf310..3f22da2 100644 --- a/src/vars.h +++ b/src/vars.h @@ -68,7 +68,8 @@ 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 prsmbr(char* name); //Parse Struct Member +int psizof(void); //Parse SizeOf Operator 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 diff --git a/test/structs.c02 b/test/structs.c02 index 554774b..3c149f9 100644 --- a/test/structs.c02 +++ b/test/structs.c02 @@ -22,7 +22,10 @@ for (i = 0; i<=128; i++) rec.data[i] = d; //Pass Entire Structure into Function -blkadd(&rec); +blkput(@rec, &rec); + +//Copy Struct Member +memdst(&data); memcpy(@rec.data, &rec.data); //Get Structure Members index = rec.index;