From cc6ef48b85757d27a168ff414990d3b3e76d9cd4 Mon Sep 17 00:00:00 2001 From: Curtis F Kaylor Date: Thu, 8 Mar 2018 14:35:00 -0500 Subject: [PATCH] Added parsing of struct members --- asm6502/asm6502 | Bin 27770 -> 0 bytes asm6502/asm6502.c | 1357 --------------------------------------------- doc/c02.txt | 65 ++- doc/c02vsC.txt | 37 +- py65/structs.c02 | 57 ++ src/expr.c | 6 +- src/parse.c | 1 - src/parse.h | 2 +- src/stmnt.c | 1 + src/vars.c | 75 ++- src/vars.h | 3 +- test/structs.c02 | 34 ++ 12 files changed, 243 insertions(+), 1395 deletions(-) delete mode 100644 asm6502/asm6502 delete mode 100644 asm6502/asm6502.c create mode 100644 py65/structs.c02 create mode 100644 test/structs.c02 diff --git a/asm6502/asm6502 b/asm6502/asm6502 deleted file mode 100644 index 61cb747abbd5cfd4641301527cb8fb77ab919077..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27770 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 Rl$DFXlC9^Vfv~5Z`ad$4i7Eg9 diff --git a/asm6502/asm6502.c b/asm6502/asm6502.c deleted file mode 100644 index f4fae4d..0000000 --- a/asm6502/asm6502.c +++ /dev/null @@ -1,1357 +0,0 @@ -/* Assembler for the MOS Technology 650X series of microprocessors - * Written by J. H. Van Ornum (201) 949-1781 - * AT&T Bell Laboratories - * Holmdel, NJ - * - * - */ - -#include -#include -#include - -#define LAST_CH_POS 132 -#define SFIELD 23 -#define STABSZ 6000 -#define SBOLSZ 20 - -/* - * symbol flags - */ -#define DEFZRO 2 /* defined - page zero address */ -#define MDEF 3 /* multiply defined */ -#define UNDEF 1 /* undefined - may be zero page */ -#define DEFABS 4 /* defined - two byte address */ -#define UNDEFAB 5 /* undefined - two byte address */ - -/* - * operation code flags - */ -#define PSEUDO 0x6000 -#define CLASS1 0x2000 -#define CLASS2 0x4000 -#define IMM1 0x1000 /* opval + 0x00 2 byte */ -#define IMM2 0x0800 /* opval + 0x08 2 byte */ -#define ABS 0x0400 /* opval + 0x0C 3 byte */ -#define ZER 0x0200 /* opval + 0x04 2 byte */ -#define INDX 0x0100 /* opval + 0x00 2 byte */ -#define ABSY2 0x0080 /* opval + 0x1C 3 byte */ -#define INDY 0x0040 /* opval + 0x10 2 byte */ -#define ZERX 0x0020 /* opval + 0x14 2 byte */ -#define ABSX 0x0010 /* opval + 0x1C 3 byte */ -#define ABSY 0x0008 /* opval + 0x18 3 byte */ -#define ACC 0x0004 /* opval + 0x08 1 byte */ -#define IND 0x0002 /* opval + 0x2C 3 byte */ -#define ZERY 0x0001 /* opval + 0x14 2 byte */ - -/* - * pass flags - */ -#define FIRST_PASS 0 -#define LAST_PASS 1 -#define DONE 2 - -FILE *optr; -FILE *iptr; -int dflag; /* debug flag */ -int errcnt; /* error counter */ -int hash_tbl[128]; /* pointers to starting links in symtab */ -char hex[5]; /* hexadecimal character buffer */ -int iflag; /* ignore .nlst flag */ -int lablptr; /* label pointer into symbol table */ -int lflag; /* disable listing flag */ -int loccnt; /* location counter */ -int nflag; /* normal/split address mode */ -int nxt_free; /* next free location in symtab */ -int objcnt; /* object byte counter */ -int oflag; /* object output flag */ -int opflg; /* operation code flags */ -int opval; /* operation code value */ -int pass; /* pass counter */ -char prlnbuf[LAST_CH_POS+1]; /* print line buffer */ -int sflag; /* symbol table output flag */ -int slnum; /* source line number counter */ -char symtab[STABSZ]; /* symbol table */ - /* struct sym_tab */ - /* { char size; */ - /* char chars[size]; */ - /* char flag; */ - /* int value; */ - /* int next_pointer */ - /* } */ -char symbol0[SBOLSZ]; /* temporary symbol storage */ -int udtype; /* undefined symbol type */ -int undef; /* undefined symbol in expression flg */ -int value; /* operand field value */ -char zpref; /* zero page reference flag */ - - -#define A 0x20)+('A'&0x1f)) -#define B 0x20)+('B'&0x1f)) -#define C 0x20)+('C'&0x1f)) -#define D 0x20)+('D'&0x1f)) -#define E 0x20)+('E'&0x1f)) -#define F 0x20)+('F'&0x1f)) -#define G 0x20)+('G'&0x1f)) -#define H 0x20)+('H'&0x1f)) -#define I 0x20)+('I'&0x1f)) -#define J 0x20)+('J'&0x1f)) -#define K 0x20)+('K'&0x1f)) -#define L 0x20)+('L'&0x1f)) -#define M 0x20)+('M'&0x1f)) -#define N 0x20)+('N'&0x1f)) -#define O 0x20)+('O'&0x1f)) -#define P 0x20)+('P'&0x1f)) -#define Q 0x20)+('Q'&0x1f)) -#define R 0x20)+('R'&0x1f)) -#define S 0x20)+('S'&0x1f)) -#define T 0x20)+('T'&0x1f)) -#define U 0x20)+('U'&0x1f)) -#define V 0x20)+('V'&0x1f)) -#define W 0x20)+('W'&0x1f)) -#define X 0x20)+('X'&0x1f)) -#define Y 0x20)+('Y'&0x1f)) -#define Z 0x20)+('Z'&0x1f)) - -#define OPSIZE 63 - -int optab[] = /* nmemonic operation code table */ -{ /* '.' = 31, '*' = 30, '=' = 29 */ - ((0*0x20)+(29)),PSEUDO,1, - ((((0*0x20)+(30))*0x20)+(29)),PSEUDO,3, - ((((((0*A*D*C,IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0x61, - ((((((0*A*N*D,IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0x21, - ((((((0*A*S*L,ABS|ZER|ZERX|ABSX|ACC,0x02, - ((((((0*B*C*C,CLASS2,0x90, - ((((((0*B*C*S,CLASS2,0xb0, - ((((((0*B*E*Q,CLASS2,0xf0, - ((((((0*B*I*T,ABS|ZER,0x20, - ((((((0*B*M*I,CLASS2,0x30, - ((((((0*B*N*E,CLASS2,0xd0, - ((((((0*B*P*L,CLASS2,0x10, - ((((((0*B*R*K,CLASS1,0x00, - ((((((0*B*V*C,CLASS2,0x50, - ((((((0*B*V*S,CLASS2,0x70, - ((((((0*C*L*C,CLASS1,0x18, - ((((((0*C*L*D,CLASS1,0xd8, - ((((((0*C*L*I,CLASS1,0x58, - ((((((0*C*L*V,CLASS1,0xb8, - ((((((0*C*M*P,IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0xc1, - ((((((0*C*P*X,IMM1|ABS|ZER,0xe0, - ((((((0*C*P*Y,IMM1|ABS|ZER,0xc0, - ((((((0*D*E*C,ABS|ZER|ZERX|ABSX,0xc2, - ((((((0*D*E*X,CLASS1,0xca, - ((((((0*D*E*Y,CLASS1,0x88, - ((((((0*E*O*R,IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0x41, - ((((((0*I*N*C,ABS|ZER|ZERX|ABSX,0xe2, - ((((((0*I*N*X,CLASS1,0xe8, - ((((((0*I*N*Y,CLASS1,0xc8, - ((((((0*J*M*P,ABS|IND,0x40, - ((((((0*J*S*R,ABS,0x14, - ((((((0*L*D*A,IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0xa1, - ((((((0*L*D*X,IMM1|ABS|ZER|ABSY2|ZERY,0xa2, - ((((((0*L*D*Y,IMM1|ABS|ZER|ABSX|ZERX,0xa0, - ((((((0*L*S*R,ABS|ZER|ZERX|ABSX|ACC,0x42, - ((((((0*N*O*P,CLASS1,0xea, - ((((((0*O*R*A,IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0x01, - ((((((0*P*H*A,CLASS1,0x48, - ((((((0*P*H*P,CLASS1,0x08, - ((((((0*P*L*A,CLASS1,0x68, - ((((((0*P*L*P,CLASS1,0x28, - ((((((0*R*O*L,ABS|ZER|ZERX|ABSX|ACC,0x22, - ((((((0*R*O*R,ABS|ZER|ZERX|ABSX|ACC,0x62, - ((((((0*R*T*I,CLASS1,0x40, - ((((((0*R*T*S,CLASS1,0x60, - ((((((0*S*B*C,IMM2|ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0xe1, - ((((((0*S*E*C,CLASS1,0x38, - ((((((0*S*E*D,CLASS1,0xf8, - ((((((0*S*E*I,CLASS1,0x78, - ((((((0*S*T*A,ABS|ZER|INDX|INDY|ZERX|ABSX|ABSY,0x81, - ((((((0*S*T*X,ABS|ZER|ZERY,0x82, - ((((((0*S*T*Y,ABS|ZER|ZERX,0x80, - ((((((0*T*A*X,CLASS1,0xaa, - ((((((0*T*A*Y,CLASS1,0xa8, - ((((((0*T*S*X,CLASS1,0xba, - ((((((0*T*X*A,CLASS1,0x8a, - ((((((0*T*X*S,CLASS1,0x9a, - ((((((0*T*Y*A,CLASS1,0x98, - ((((((0*0x20)+(31))*W*O^((((0*R*D,PSEUDO,2, /* 0x7cab */ - ((((((0*0x20)+(31))*B*Y^((((0*T*E,PSEUDO,0, /* 0x7edc */ - ((((((0*0x20)+(31))*D*B^((((0*Y*T,PSEUDO,6, /* 0x7fb6 */ - ((((((0*0x20)+(31))*N*L^((((0*S*T,PSEUDO,5, /* 0x7fb8 */ - ((((((0*0x20)+(31))*L*I^((((0*S*T,PSEUDO,4, /* 0x7ffd */ - 0x7fff,0,0, - 0x7fff,0,0 -}; - -int step[] = -{ - 3*((OPSIZE+1)/2), - 3*((((OPSIZE+1)/2)+1)/2), - 3*((((((OPSIZE+1)/2)+1)/2)+1)/2), - 3*((((((((OPSIZE+1)/2)+1)/2)+1)/2)+1)/2), - 3*(2), - 3*(1), - 0 -}; - - -#define CPMEOF EOF - -/* - * Two changes to version 1.4 have been made to "port" as6502 to CP/M(tm). - * A "tolower()" function call was add to the command line processing - * code to (re)map the command line arguments to lower case (CP/M - * converts all command line arguments to upper case). The readline() - * function has code added to "ignore" the '\r' character (CP/M includes - * the \r character along with \n). - * - * Also, the ability to process multiple files on the command line has been - * added. Now one can do, for example: - * - * as6502 -nisvo header.file source.file data.file ... - * - * George V. Wilder - * IX 1A-360 x1937 - * ihuxp!gvw1 - */ - -/* - * This Macintosh port (1.41) by RTK, Feb. 27, 1995. Added Mac console - * control and removed CP/M checks. - * - */ - -main(argc, argv) - int argc; - char *argv[]; -{ - char c; - int cnt; - int i; - int ac; - char **av; - - while (--argc > 0 && (*++argv)[0] == '-') { - for (i = 1; (c = tolower((*argv)[i])) != '\0'; i++) { - if (c == 'd') /* debug flag */ - dflag++; - if (c == 'i') /* ignore .nlst flag */ - iflag++; - if (c == 'l') /* disable listing flag */ - lflag--; - if (c == 'n') /* normal/split address mode */ - nflag++; - if (c == 'o') /* object output flag */ - oflag++; - if (c == 's') /* list symbol table flag */ - sflag++; - if (c == 'v') /* print assembler version */ - fprintf(stdout, "as6502 - version 4.1b - 11/22/84 - JHV [gvw]\n"); - } - } - ac = argc; - av = argv; - pass = FIRST_PASS; - for (i = 0; i < 128; i++) - hash_tbl[i] = -1; - errcnt = loccnt = slnum = 0; - while (pass != DONE) { - initialize(ac, av, argc); - if(pass == LAST_PASS && ac == argc) - errcnt = loccnt = slnum = 0; - while (readline() != -1) - assemble(); - if (errcnt != 0) { - pass = DONE; - fprintf(stdout, "Terminated with error counter = %d\n", errcnt); - } - switch (pass) { - case FIRST_PASS: - --ac; - ++av; - if(ac == 0) { - pass = LAST_PASS; - if (lflag == 0) - lflag++; - ac = argc; - av = argv; - } - break; - case LAST_PASS: - --ac; - ++av; - if(ac == 0) { - pass = DONE; - if (sflag != 0) - stprnt(); - } - } - wrapup(); - if ((dflag != 0) && (pass == LAST_PASS)) { - fprintf(stdout, "nxt_free = %d\n", nxt_free); - cnt = 0; - for (i = 0; i < 128; i++) - if (hash_tbl[i] == -1) - cnt++; - fprintf(stdout, "%d unused hash table pointers out of 128\n", cnt); - } - } - return(0); -} - -/*****************************************************************************/ - -/* initialize opens files */ - -initialize(ac, av, argc) - int ac; - char *av[]; - int argc; -{ - - if (ac == 0) { - fprintf(stdout, "Invalid argument count (%d).\n", argc); - exit(1); - } - if ((iptr = fopen(*av, "r")) == NULL) { - fprintf(stdout, "Open error for file '%s'.\n", *av); - exit(1); - } - if ((pass == LAST_PASS) && (oflag != 0) && ac == argc) { - if ((optr = fopen("6502.out", "w")) == NULL) { - fprintf(stdout, "Create error for object file 6502.out.\n"); - exit(1); - } - } -} - -/* readline reads and formats an input line */ - -int field[] = -{ - SFIELD, - SFIELD + 8, - SFIELD + 14, - SFIELD + 23, - SFIELD + 43, - SFIELD + 75 -}; - -readline() -{ - int i; /* pointer into prlnbuf */ - int j; /* pointer to current field start */ - int ch; /* current character */ - int cmnt; /* comment line flag */ - int spcnt; /* consecutive space counter */ - int string; /* ASCII string flag */ - int temp1; /* temp used for line number conversion */ - - temp1 = ++slnum; - for (i = 0; i < LAST_CH_POS; i++) - prlnbuf[i] = ' '; - i = 3; - while (temp1 != 0) { /* put source line number into prlnbuf */ - prlnbuf[i--] = temp1 % 10 + '0'; - temp1 /= 10; - } - i = SFIELD; - cmnt = spcnt = string = 0; - j = 1; - while ((ch = getc(iptr)) != '\n') { - prlnbuf[i++] = ch; - if ((ch == ' ') && (string == 0)) { - if (spcnt != 0) - --i; - else if (cmnt == 0) { - ++spcnt; - if (i < field[j]) - i = field[j]; - if (++j > 3) { - spcnt = 0; - ++cmnt; - } - } - } - else if (ch == '\t') { - prlnbuf[i - 1] = ' '; - spcnt = 0; - if (cmnt == 0) { - if (i < field[j]) - i = field[j]; - if (++j > 3) - ++cmnt; - } - else i = (i + 8) & 0x78; - } - else if ((ch == ';') && (string == 0)) { - spcnt = 0; - if (i == SFIELD + 1) - ++cmnt; - else if (prlnbuf[i - 2] != '\'') { - ++cmnt; - prlnbuf[i-1] = ' '; - if (i < field[3]) - i = field[3]; - prlnbuf[i++] = ';'; - } - } - else if (ch == EOF || ch == CPMEOF) - return(-1); - else { - if ((ch == '"') && (cmnt == 0)) - string = string ^ 1; - spcnt = 0; - if (i >= LAST_CH_POS - 1) - --i; - } - } - prlnbuf[i] = 0; - return(0); -} - -/* - * wrapup() closes the source file - */ - -wrapup() -{ - - fclose(iptr); - if ((pass == DONE) && (oflag != 0)) { - fputc('\n', optr); - fclose(optr); - } - return; -} - -/* symbol table print - */ - -stprnt() -{ - int i; - int j; - int k; - - fputc('\014', stdout); - fputc('\n', stdout); - i = 0; - while ((j = symtab[i++]) != 0) { - for (k = j; k > 0; k--) - fputc(symtab[i++], stdout); - for (k = 20 - j; k > 0; k--) - fputc(' ', stdout); - ++i; - j = (symtab[i++] & 0xff); - j += (symtab[i++] << 8); - hexcon(4, j); - fprintf(stdout, "\t%c%c:%c%c\t%c%c%c%c\n", - hex[3], hex[4], hex[1], hex[2], - hex[1], hex[2], hex[3], hex[4]); - i += 2; - } -} - - -int optab[]; -int step[]; - -/* translate source line to machine language */ - -assemble() -{ - int flg; - int i; /* prlnbuf pointer */ - - if ((prlnbuf[SFIELD] == ';') | (prlnbuf[SFIELD] == 0)) { - if (pass == LAST_PASS) - println(); - return; - } - lablptr = -1; - i = SFIELD; - udtype = UNDEF; - if (colsym(&i) != 0 && (lablptr = stlook()) == -1) - return; - while (prlnbuf[++i] == ' '); /* find first non-space */ - if ((flg = oplook(&i)) < 0) { /* collect operation code */ - labldef(loccnt); - if (flg == -1) - error("Invalid operation code"); - if ((flg == -2) && (pass == LAST_PASS)) { - if (lablptr != -1) - loadlc(loccnt, 1, 0); - println(); - } - return; - } - if (opflg == PSEUDO) - pseudo(&i); - else if (labldef(loccnt) == -1) - return; - else { - if (opflg == CLASS1) - class1(); - else if (opflg == CLASS2) - class2(&i); - else class3(&i); - } -} - -/****************************************************************************/ - -/* printline prints the contents of prlnbuf */ - -println() -{ - if (lflag > 0) - fprintf(stdout, "%s\n", prlnbuf); -} - -/* colsym() collects a symbol from prlnbuf into symbol0[], - * leaves prlnbuf pointer at first invalid symbol character, - * returns 0 if no symbol collected - */ - -colsym(ip) - int *ip; -{ - int valid; - int i; - char ch; - - valid = 1; - i = 0; - while (valid == 1) { - ch = prlnbuf[*ip]; - if (ch == '_' || ch == '.'); - else if (ch >= 'a' && ch <= 'z'); - else if (ch >= 'A' && ch <= 'Z'); - else if (i >= 1 && ch >= '0' && ch <= '9'); - else if (i == 1 && ch == '='); - else valid = 0; - if (valid == 1) { - if (i < SBOLSZ - 1) - symbol0[++i] = ch; - (*ip)++; - } - } - if (i == 1) { - switch (symbol0[1]) { - case 'A': case 'a': - case 'X': case 'x': - case 'Y': case 'y': - error("Symbol is reserved (A, X or Y)"); - i = 0; - } - } - symbol0[0] = i; - return(i); -} - -/* symbol table lookup - * if found, return pointer to symbol - * else, install symbol as undefined, and return pointer - */ - -stlook() -{ - int found; - int hptr; - int j; - int nptr; - int pptr; - int ptr; - - hptr = 0; - for (j = 0; j < symbol0[0]; j++) - hptr += symbol0[j]; - hptr %= 128; - ptr = hash_tbl[hptr]; - if (ptr == -1) { /* no entry for this link */ - hash_tbl[hptr] = nxt_free; - return(stinstal()); - } - while (symtab[ptr] != 0) { /* 0 count = end of table */ - found = 1; - for (j = 0; j <= symbol0[0]; j++) { - if (symbol0[j] != symtab[ptr + j]) { - found = 0; - pptr = ptr + symtab[ptr] + 4; - nptr = (symtab[pptr + 1] << 8) + (symtab[pptr] & 0xff); - nptr &= 0xffff; - if (nptr == 0) { - symtab[ptr + symtab[ptr] + 4] = nxt_free & 0xff; - symtab[ptr + symtab[ptr] + 5] = (nxt_free >> 8) & 0xff; - return(stinstal()); - } - ptr = nptr; - break; - } - } - if (found == 1) - return(ptr); - } - error("Symbol not found"); - return(-1); -} - -/* instal symbol into symtab - */ -stinstal() -{ -register int j; -register int ptr1; -register int ptr2; - - ptr1 = ptr2 = nxt_free; - if ((ptr1 + symbol0[0] + 6) >= STABSZ) { - error("Symbol table full"); - return(-1); - } - for (j = 0; j <= symbol0[0]; j++) - symtab[ptr1++] = symbol0[j]; - symtab[ptr1] = udtype; - nxt_free = ptr1 + 5; - return(ptr2); -} - -/* operation code table lookup - * if found, return pointer to symbol, - * else, return -1 - */ - -oplook(ip) - int *ip; -{ -register char ch; -register int i; -register int j; - int k; - int temp[2]; - - i = j = 0; - temp[0] = temp[1] = 0; - while((ch=prlnbuf[*ip])!= ' ' && ch!= 0 && ch!= '\t' && ch!= ';') { - if (ch >= 'A' && ch <= 'Z') - ch &= 0x1f; - else if (ch >= 'a' && ch <= 'z') - ch &= 0x1f; - else if (ch == '.') - ch = 31; - else if (ch == '*') - ch = 30; - else if (ch == '=') - ch = 29; - else return(-1); - temp[j] = (temp[j] * 0x20) + (ch & 0xff); - if (ch == 29) - break; - ++(*ip); - if (++i >= 3) { - i = 0; - if (++j >= 2) { - return(-1); - } - } - } - if ((j = temp[0]^temp[1]) == 0) - return(-2); - k = 0; - i = step[k] - 3; - do { - if (j == optab[i]) { - opflg = optab[++i]; - opval = optab[++i]; - return(i); - } - else if (j < optab[i]) - i -= step[++k]; - else i += step[++k]; - } while (step[k] != 0); - return(-1); -} - -/* error printing routine */ - -error(stptr) - char *stptr; -{ - loadlc(loccnt, 0, 1); - loccnt += 3; - loadv(0,0,0); - loadv(0,1,0); - loadv(0,2,0); - fprintf(stdout, "%s\n", prlnbuf); - fprintf(stdout, "%s\n", stptr); - errcnt++; -} - -/* load 16 bit value in printable form into prlnbuf */ - -loadlc(val, f, outflg) - int val; - int f; - int outflg; -{ - int i; - - i = 6 + 7*f; - hexcon(4, val); - if (nflag == 0) { - prlnbuf[i++] = hex[3]; - prlnbuf[i++] = hex[4]; - prlnbuf[i++] = ':'; - prlnbuf[i++] = hex[1]; - prlnbuf[i] = hex[2]; - } - else { - prlnbuf[i++] = hex[1]; - prlnbuf[i++] = hex[2]; - prlnbuf[i++] = hex[3]; - prlnbuf[i] = hex[4]; - } - if ((pass == LAST_PASS)&&(oflag != 0)&&(objcnt <= 0)&&(outflg != 0)) { - fprintf(optr, "\n;%c%c%c%c", hex[3], hex[4], hex[1], hex[2]); - objcnt = 16; - } -} - - - -/* load value in hex into prlnbuf[contents[i]] */ -/* and output hex characters to obuf if LAST_PASS & oflag == 1 */ - -loadv(val,f,outflg) - int val; - int f; /* contents field subscript */ - int outflg; /* flag to output object bytes */ -{ - - hexcon(2, val); - prlnbuf[13 + 3*f] = hex[1]; - prlnbuf[14 + 3*f] = hex[2]; - if ((pass == LAST_PASS) && (oflag != 0) && (outflg != 0)) { - fputc(hex[1], optr); - fputc(hex[2], optr); - --objcnt; - } -} - -/* convert number supplied as argument to hexadecimal in hex[digit] (lsd) - through hex[1] (msd) */ - -hexcon(digit, num) - int digit; - int num; -{ - - for (; digit > 0; digit--) { - hex[digit] = (num & 0x0f) + '0'; - if (hex[digit] > '9') - hex[digit] += 'A' -'9' - 1; - num >>= 4; - } -} - -/* assign to label pointed to by lablptr, - * checking for valid definition, etc. - */ - -labldef(lval) - int lval; -{ - int i; - - if (lablptr != -1) { - lablptr += symtab[lablptr] + 1; - if (pass == FIRST_PASS) { - if (symtab[lablptr] == UNDEF) { - symtab[lablptr + 1] = lval & 0xff; - i = symtab[lablptr + 2] = (lval >> 8) & 0xff; - if (i == 0) - symtab[lablptr] = DEFZRO; - else symtab[lablptr] = DEFABS; - } - else if (symtab[lablptr] == UNDEFAB) { - symtab[lablptr] = DEFABS; - symtab[lablptr + 1] = lval & 0xff; - symtab[lablptr + 2] = (lval >> 8) & 0xff; - } - else { - symtab[lablptr] = MDEF; - symtab[lablptr + 1] = 0; - symtab[lablptr + 2] = 0; - error("Label multiply defined"); - return(-1); - } - } - else { - i = (symtab[lablptr + 2] << 8) + - (symtab[lablptr+1] & 0xff); - i &= 0xffff; - if (i != lval && pass == LAST_PASS) { - error("Sync error"); - return(-1); - } - } - } - return(0); -} - -/* determine the value of the symbol, - * given pointer to first character of symbol in symtab - */ - -symval(ip) - int *ip; -{ - int ptr; - int svalue; - - svalue = 0; - colsym(ip); - if ((ptr = stlook()) == -1) - undef = 1; /* no room error */ - else if (symtab[ptr + symtab[ptr] + 1] == UNDEF) - undef = 1; - else if (symtab[ptr + symtab[ptr] + 1] == UNDEFAB) - undef = 1; - else svalue = ((symtab[ptr + symtab[ptr] + 3] << 8) + - (symtab[ptr + symtab[ptr] + 2] & 0xff)) & 0xffff; - if (symtab[ptr + symtab[ptr] + 1] == DEFABS) - zpref = 1; - if (undef != 0) - zpref = 1; - return(svalue); -} - - -/* class 1 machine operations processor - 1 byte, no operand field */ - -class1() -{ - if (pass == LAST_PASS) { - loadlc(loccnt, 0, 1); - loadv(opval, 0, 1); - println(); - } - loccnt++; -} - - -/* class 2 machine operations processor - 2 byte, relative addressing */ - -class2(ip) - int *ip; -{ - - if (pass == LAST_PASS) { - loadlc(loccnt, 0, 1); - loadv(opval, 0, 1); - while (prlnbuf[++(*ip)] == ' '); - if (evaluate(ip) != 0) { - loccnt += 2; - return; - } - loccnt += 2; - if ((value -= loccnt) >= -128 && value < 128) { - loadv(value, 1, 1); - println(); - } - else error("Invalid branch address"); - } - else loccnt += 2; -} - - -/* class 3 machine operations processor - various addressing modes */ - -class3(ip) - int *ip; -{ - char ch; - int code; - int flag; - int i; - int ztmask; - - while ((ch = prlnbuf[++(*ip)]) == ' '); - switch(ch) { - case 0: - case ';': - error("Operand field missing"); - return; - case 'A': - case 'a': - if ((ch = prlnbuf[*ip + 1]) == ' ' || ch == 0) { - flag = ACC; - break; - } - default: - switch(ch = prlnbuf[*ip]) { - case '#': case '=': - flag = IMM1 | IMM2; - ++(*ip); - break; - case '(': - flag = IND | INDX | INDY; - ++(*ip); - break; - default: - flag = ABS | ZER | ZERX | ABSX | ABSY | ABSY2 | ZERY; - } - if ((flag & (INDX | INDY | ZER | ZERX | ZERY) & opflg) != 0) - udtype = UNDEFAB; - if (evaluate(ip) != 0) - return; - if (zpref != 0) { - flag &= (ABS | ABSX | ABSY | ABSY2 | IND | IMM1 | IMM2); - ztmask = 0; - } - else ztmask = ZER | ZERX | ZERY; - code = 0; - i = 0; - while (( ch = prlnbuf[(*ip)++]) != ' ' && ch != 0 && i++ < 4) { - code *= 8; - switch(ch) { - case ')': /* ) = 4 */ - ++code; - case ',': /* , = 3 */ - ++code; - case 'X': /* X = 2 */ - case 'x': - ++code; - case 'Y': /* Y = 1 */ - case 'y': - ++code; - break; - default: - flag = 0; - } - } - switch(code) { - case 0: /* no termination characters */ - flag &= (ABS | ZER | IMM1 | IMM2); - break; - case 4: /* termination = ) */ - flag &= IND; - break; - case 25: /* termination = ,Y */ - flag &= (ABSY | ABSY2 | ZERY); - break; - case 26: /* termination = ,X */ - flag &= (ABSX | ZERX); - break; - case 212: /* termination = ,X) */ - flag &= INDX; - break; - case 281: /* termination = ),Y */ - flag &= INDY; - break; - default: - flag = 0; - } - } - if ((opflg &= flag) == 0) { - error("Invalid addressing mode"); - return; - } - if ((opflg & ztmask) != 0) - opflg &= ztmask; - switch(opflg) { - case ACC: /* single byte - class 3 */ - if (pass == LAST_PASS) { - loadlc(loccnt, 0, 1); - loadv(opval + 8, 0, 1); - println(); - } - loccnt++; - return; - case ZERX: case ZERY: /* double byte - class 3 */ - opval += 4; - case INDY: - opval += 8; - case IMM2: - opval += 4; - case ZER: - opval += 4; - case INDX: case IMM1: - if (pass == LAST_PASS) { - loadlc(loccnt, 0, 1); - loadv(opval, 0, 1); - loadv(value, 1, 1); - println(); - } - loccnt += 2; - return; - case IND: /* triple byte - class 3 */ - opval += 16; - case ABSX: - case ABSY2: - opval += 4; - case ABSY: - opval += 12; - case ABS: - if (pass == LAST_PASS) { - opval += 12; - loadlc(loccnt, 0, 1); - loadv(opval, 0, 1); - loadv(value, 1, 1); - loadv(value >> 8, 2, 1); - println(); - } - loccnt += 3; - return; - default: - error("Invalid addressing mode"); - return; - } -} - -/* pseudo operations processor */ - -pseudo(ip) - int *ip; -{ - int count; - int i; - int tvalue; - - switch(opval) { - case 0: /* .byte pseudo */ - labldef(loccnt); - loadlc(loccnt, 0, 1); - while (prlnbuf[++(*ip)] == ' '); /* field */ - count = 0; - do { - if (prlnbuf[*ip] == '"') { - while ((tvalue = prlnbuf[++(*ip)]) != '"') { - if (tvalue == 0) { - error("Unterminated ASCII string"); - return; - } - if (tvalue == '\\') - switch(tvalue = prlnbuf[++(*ip)]) { - case 'n': - tvalue = '\n'; - break; - case 't': - tvalue = '\t'; - break; - } - loccnt++; - if (pass == LAST_PASS) { - loadv(tvalue, count, 1); - if (++count >= 3) { - println(); - for (i = 0; i < SFIELD; i++) - prlnbuf[i] = ' '; - prlnbuf[i] = 0; - count = 0; - loadlc(loccnt, 0, 1); - } - } - } - ++(*ip); - } - else { - if (evaluate(ip) != 0) { - loccnt++; - return; - } - loccnt++; - if (value > 0xff) { - error("Operand field size error"); - return; - } - else if (pass == LAST_PASS) { - loadv(value, count, 1); - if (++count >= 3) { - println(); - for (i = 0; i < SFIELD; i++) - prlnbuf[i] = ' '; - prlnbuf[i] = 0; - count = 0; - loadlc(loccnt, 0, 1); - } - } - } - } while (prlnbuf[(*ip)++] == ','); - if ((pass == LAST_PASS) && (count != 0)) - println(); - return; - case 1: /* = pseudo */ - while (prlnbuf[++(*ip)] == ' '); - if (evaluate(ip) != 0) - return; - labldef(value); - if (pass == LAST_PASS) { - loadlc(value, 1, 0); - println(); - } - return; - case 2: /* .word pseudo */ - labldef(loccnt); - loadlc(loccnt, 0, 1); - while (prlnbuf[++(*ip)] == ' '); - do { - if (evaluate(ip) != 0) { - loccnt += 2; - return; - } - loccnt += 2; - if (pass == LAST_PASS) { - loadv(value, 0, 1); - loadv(value>>8, 1, 1); - println(); - for (i = 0; i < SFIELD; i++) - prlnbuf[i] = ' '; - prlnbuf[i] = 0; - loadlc(loccnt, 0, 1); - } - } while (prlnbuf[(*ip)++] == ','); - return; - case 3: /* *= pseudo */ - while (prlnbuf[++(*ip)] == ' '); - if (prlnbuf[*ip] == '*') { - if (evaluate(ip) != 0) - return; - if (undef != 0) { - error("Undefined symbol in operand field."); - return; - } - tvalue = loccnt; - } - else { - if (evaluate(ip) != 0) - return; - if (undef != 0) { - error("Undefined symbol in operand field."); - return; - } - tvalue = value; - } - loccnt = value; - labldef(tvalue); - if (pass == LAST_PASS) { - objcnt = 0; - loadlc(tvalue, 1, 0); - println(); - } - return; - case 4: /* .list pseudo */ - if (lflag >= 0) - lflag = 1; - return; - case 5: /* .nlst pseudo */ - if (lflag >= 0) - lflag = iflag; - return; - case 6: /* .dbyt pseudo */ - labldef(loccnt); - loadlc(loccnt, 0, 1); - while (prlnbuf[++(*ip)] == ' '); - do { - if (evaluate(ip) != 0) { - loccnt += 2; - return; - } - loccnt += 2; - if (pass == LAST_PASS) { - loadv(value>>8, 0, 1); - loadv(value, 1, 1); - println(); - for (i = 0; i < SFIELD; i++) - prlnbuf[i] = ' '; - prlnbuf[i] = 0; - loadlc(loccnt, 0, 1); - } - } while (prlnbuf[(*ip)++] == ','); - return; - } -} - -/* evaluate expression */ - -evaluate(ip) - int *ip; -{ - int tvalue; - int invalid; - int parflg, value2; - char ch; - char op; - char op2; - - op = '+'; - parflg = zpref = undef = value = invalid = 0; -/* hcj: zpref should reflect the value of the expression, not the value of - the intermediate symbols -*/ - while ((ch=prlnbuf[*ip]) != ' ' && ch != ')' && ch != ',' && ch != ';') { - tvalue = 0; - if (ch == '$' || ch == '@' || ch == '%') - tvalue = colnum(ip); - else if (ch >= '0' && ch <= '9') - tvalue = colnum(ip); - else if (ch >= 'a' && ch <= 'z') - tvalue = symval(ip); - else if (ch >= 'A' && ch <= 'Z') - tvalue = symval(ip); - else if ((ch == '_') || (ch == '.')) - tvalue = symval(ip); - else if (ch == '*') { - tvalue = loccnt; - ++(*ip); - } - else if (ch == '\'') { - ++(*ip); - tvalue = prlnbuf[*ip] & 0xff; - ++(*ip); - } - else if (ch == '[') { - if (parflg == 1) { - error("Too many ['s in expression"); - invalid++; - } - else { - value2 = value; - op2 = op; - value = tvalue = 0; - op = '+'; - parflg = 1; - } - goto next; - } - else if (ch == ']') { - if (parflg == 0) { - error("No matching [ for ] in expression"); - invalid++; - } - else { - parflg = 0; - tvalue = value; - value = value2; - op = op2; - } - ++(*ip); - } - switch(op) { - case '+': - value += tvalue; - break; - case '-': - value -= tvalue; - break; - case '/': - value = (unsigned) value/tvalue; - break; - case '*': - value *= tvalue; - break; - case '%': - value = (unsigned) value%tvalue; - break; - case '^': - value ^= tvalue; - break; - case '~': - value = ~tvalue; - break; - case '&': - value &= tvalue; - break; - case '|': - value |= tvalue; - break; - case '>': - tvalue >>= 8; /* fall through to '<' */ - case '<': - if (value != 0) { - error("High or low byte operator not first in operand field"); - } - value = tvalue & 0xff; - zpref = 0; - break; - default: - invalid++; - } - if ((op=prlnbuf[*ip]) == ' ' - || op == ')' - || op == ',' - || op == ';') - break; - else if (op != ']') -next: ++(*ip); - } - if (parflg == 1) { - error("Missing ] in expression"); - return(1); - } - if (value < 0 || value >= 256) { - zpref = 1; - } - if (undef != 0) { - if (pass != FIRST_PASS) { - error("Undefined symbol in operand field"); - invalid++; - } - value = 0; - } - else if (invalid != 0) - { - error("Invalid operand field"); - } - else { -/* - This is the only way out that may not signal error -*/ - if (value < 0 || value >= 256) { - zpref = 1; - } - else { - zpref = 0; - } - } - return(invalid); -} - -/* collect number operand */ - -colnum(ip) - int *ip; -{ - int mul; - int nval; - char ch; - - nval = 0; - if ((ch = prlnbuf[*ip]) == '$') - mul = 16; - else if (ch >= '1' && ch <= '9') { - mul = 10; - nval = ch - '0'; - } - else if (ch == '@' || ch == '0') - mul = 8; - else if (ch == '%') - mul = 2; - while ((ch = prlnbuf[++(*ip)] - '0') >= 0) { - if (ch > 9) { - ch -= ('A' - '9' - 1); - if (ch > 15) - ch -= ('a' - 'A'); - if (ch > 15) - break; - if (ch < 10) - break; - } - if (ch >= mul) - break; - nval = (nval * mul) + ch; - } - return(nval); -} diff --git a/doc/c02.txt b/doc/c02.txt index e92a7cd..b9c5df2 100644 --- a/doc/c02.txt +++ b/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. diff --git a/doc/c02vsC.txt b/doc/c02vsC.txt index af29934..b43faf1 100644 --- a/doc/c02vsC.txt +++ b/doc/c02vsC.txt @@ -39,7 +39,23 @@ time, so no re-initialization will occur during code execution. 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. +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 @@ -47,6 +63,25 @@ 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 diff --git a/py65/structs.c02 b/py65/structs.c02 new file mode 100644 index 0000000..e9ffc92 --- /dev/null +++ b/py65/structs.c02 @@ -0,0 +1,57 @@ +/********************************************** + * STRINGS - Demonstrate string.h02 functions * + **********************************************/ + +#include +#include +#include +#include +#include +#include + +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(); +} \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index c0df19f..b5d8266 100644 --- a/src/expr.c +++ b/src/expr.c @@ -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); } diff --git a/src/parse.c b/src/parse.c index 93da24a..c296144 100644 --- a/src/parse.c +++ b/src/parse.c @@ -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); diff --git a/src/parse.h b/src/parse.h index 8afee69..724ad6d 100644 --- a/src/parse.h +++ b/src/parse.h @@ -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) diff --git a/src/stmnt.c b/src/stmnt.c index 2096142..1ebccb3 100644 --- a/src/stmnt.c +++ b/src/stmnt.c @@ -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(';')) { diff --git a/src/vars.c b/src/vars.c index be97840..682e17d 100644 --- a/src/vars.c +++ b/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 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; } diff --git a/src/vars.h b/src/vars.h index bcef1ea..5cdf310 100644 --- a/src/vars.h +++ b/src/vars.h @@ -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 diff --git a/test/structs.c02 b/test/structs.c02 new file mode 100644 index 0000000..554774b --- /dev/null +++ b/test/structs.c02 @@ -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];