diff --git a/asm.c b/asm.c index c90bc64..1956e03 100644 --- a/asm.c +++ b/asm.c @@ -24,13 +24,14 @@ void setcmt(char *s) /* Append string to comment */ void addcmt(char *s) { - strcat(cmtasm, " "); + //strcat(cmtasm, " "); strcat(cmtasm, s); } /* Append character to comment */ void chrcmt(char c) { + if (cmtasm[0] == 0 && c == ' ') return; int i = strlen(cmtasm); cmtasm[i++] = c; cmtasm[i] = 0; diff --git a/asm6502.c b/asm6502.c new file mode 100644 index 0000000..f4fae4d --- /dev/null +++ b/asm6502.c @@ -0,0 +1,1357 @@ +/* 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/c02.c b/c02.c index f76055b..daf5d55 100644 --- a/c02.c +++ b/c02.c @@ -41,8 +41,12 @@ void init() xstmnt[0] = 0; nxtwrd[0] = 0; nxtptr = 0; + vrwrtn = FALSE; + zpaddr = 0; } + + /* Reads and parses the next Word in Source File */ pword() { @@ -55,11 +59,7 @@ pword() xstmnt[0] = 0; else ERROR("Expected '%s' statement\n", xstmnt, EXIT_FAILURE); - if (wordis("void")) - pdecl(VTVOID); //Parse 'void' declaration - else if (wordis("char")) - pdecl(VTCHAR); //Parse 'char' declaration - else + if (!pmodfr() && !ptype(MTNONE)) pstmnt(); //Parse Statement } @@ -69,17 +69,22 @@ void pdrctv() skpchr(); //skip '#' getwrd(); //read directive into word DEBUG("Processing directive '%s'\n", word); - if (wordis("define")) - prsdef(); //Parse Define - if (wordis("include")) + if (wordis("DEFINE")) + pdefin(); //Parse Define + else if (wordis("INCLUDE")) pincfl(); //Parse Include File - else if (wordis("error")) + else if (wordis("ERROR")) { ERROR("Error \n", 0, EXIT_FAILURE); + } + else if (wordis("PRAGMA")) + pprgma(); + else + ERROR("Illegal directive %s encountered\n", word, EXIT_FAILURE); } void epilog() { - vartbl(); //Write Variable Table + if (!vrwrtn) vartbl(); //Write Variable Table } /* Compile Source Code*/ @@ -117,19 +122,44 @@ void usage() exit(EXIT_FAILURE); } +/* Parse Command Line Argument */ +int popt(int arg, int argc, char *argv[]) +{ + char opt; //Option + char optarg[32]; //Option Argument + opt = argv[arg][1]; + //if strchr(opt, "i") { + //if (strlen(argv[arg] > 2) + //} + ERROR("Illegal option -%c\n", opt, EXIT_FAILURE); +} + /* Parse Command Line Arguments * * Sets: srcnam - Source File Name (from first arg) * * outnam - Output File Name (from optional second arg) */ void pargs(int argc, char *argv[]) { - DEBUG("Parsing %d Arguments\n", argc); - if (argc < 2) usage(); //at least one argument is required - strcpy(srcnam, argv[1]); //set Source File Name to first arg - DEBUG("srcnam set to '%s'\n", srcnam); - if (argc > 2) //if second argument exists - strcpy(outnam, argv[2]); //set Out File Name to second arg - else strcpy(outnam, ""); //else set to null string - DEBUG("outnam set to '%s'\n", outnam); + int arg; + srcnam[0] = 0; + outnam[0] = 0; + DEBUG("Parsing %d arguments\n", argc); + if (argc == 0) usage(); //at least one argument is required + for (arg = 1; arg"); strcat(word,symbol); - asmlin("LDY", word); + if (adract == 1) { + asmlin("LDA", word); + asmlin("PHA", ""); + } + else + asmlin("LDY", word); + strcpy(word,"#<"); + strcat(word,symbol); + if (adract == 1) { + asmlin("LDA", word); + asmlin("PHA", ""); + } + else + asmlin("LDX", word); } /* Parse and Compile Address of Operator */ -void prsadr() +void prsadr(int adract) { - prsvar(); - DEBUG("Parsing address of variable '%s'\n", value); - prcadr(value); //Compile Address Reference + DEBUG("Parsing address\n", 0); + if (isnpre()) + prsnum(0xFFFF); + else + prsvar(FALSE); + prcadr(adract, value); //Compile Address Reference } /* Parse and Create Anonymous String */ -void prsstr() +void prsstr(adract) { DEBUG("Parsing anonymous string\n", 0); - newlbl(vrname); //Generate Variable Name - value[0] = 0; //Use Variable Size 0 - setvar(VTCHAR); //Set Variable Name, Type, and Size - prsdts(); //Parse Data String - setdat(); //Set Variable Data - varcnt++; //Increment Variable Counter - prcadr(vrname); //Compile Address Reference + newlbl(vrname); //Generate Variable Name + value[0] = 0; //Use Variable Size 0 + setvar(VTCHAR); //Set Variable Name, Type, and Size + prsdts(); //Parse Data String + setdat(); //Set Variable Data + varcnt++; //Increment Variable Counter + prcadr(adract, vrname); //Compile Address Reference } -/* Parse Additional Function Parameters */ -void prsfnp() +/* Check for and Process Address or String */ +int chkadr(adract) { - if (look(',')) { - if (look('&')) - prsadr(); - else if (match('"')) - prsstr(); - else { - prstrm(); - asmlin("LDY", term); - if (look(',')) { - prsval(); - asmlin("LDX", value); - } - } - } + DEBUG("Checking for Address or String\n", 0); + int result = TRUE; + if (look('&')) + prsadr(adract); + else if (match('"')) + prsstr(adract); + else + result = FALSE; + skpspc(); + return result; } /* Parse function call */ -void prsfnc() +void prsfnc(char trmntr) { DEBUG("Processing Function Call '%s'...\n", term); if (fnscnt >= MAXFNS) @@ -123,15 +151,25 @@ void prsfnc() strcpy(fnstck[fnscnt++], term); skpchr(); //skip open paren CCMNT('('); - if (look('&')) - prsadr(); - else if (match('"')) - prsstr(); - else if (isvpre()) { - prsxpr(0); - prsfnp(); - } + if (!chkadr(0) && isxpre() || match('*')) { + if (!look('*')) prsxpr(0); + if (look(',')) { + if (!chkadr(0)) { + if (!look('*')) { + prstrm(); + asmlin("LDY", term); + } + if (look(',')) { + if (!look('*')) { + prsval(FALSE); + asmlin("LDX", value); + } + } + } + } + } expect(')'); + expect(trmntr); asmlin("JSR", fnstck[--fnscnt]); skpspc(); } @@ -140,20 +178,24 @@ void prsfnc() * First term can include function calls */ void prsftm() { - prsval(); + prsval(TRUE); DEBUG("Processing first term '%s'...\n", value); strcpy(term, value); - trmtxt = valtyp; - if (trmtxt == FUNCTION) { - prsfnc(); //Parse Expression Function + if (valtyp == FUNCTION) { + prsfnc(0); //Parse Expression Function return; } - if (trmtxt == ARRAY) { - prsidx(); - asmlin("LDX", value); - strcat(term, ",X"); + if (wordis("A")) + return; + //if (ispopr()) oper = prspst(0, term); //Check for Post-Operator + if (wordis("X")) + asmlin("TXA", ""); + else if (wordis("Y")) + asmlin("TYA", ""); + else { + chkidx(); //Check for Array Index + asmlin("LDA", term); } - asmlin("LDA", term); } /* Process Arithmetic or Bitwise Operator * @@ -185,6 +227,7 @@ void prcopr() printf("Unrecognized operator '%c'\n", oper); exterr(EXIT_FAILURE); } + oper = 0; } /* Parse and compile expression */ @@ -194,17 +237,17 @@ void prsxpr(char trmntr) skpspc(); if (match('-')) { DEBUG("Processing unary minus", 0); - asmlin("LDA", "#$00"); //Handle Unary Minus + asmlin("LDA", "#$00"); //Handle Unary Minus } else prsftm(); //Parse First Term + skpspc(); while (isoper()) { prsopr(); //Parse Operator prstrm(); //Parse Term prcopr(); //Process Operator } - if (trmntr) - expect(trmntr); + expect(trmntr); } diff --git a/expr.h b/expr.h index 7bfe399..bab1c5e 100644 --- a/expr.h +++ b/expr.h @@ -3,11 +3,12 @@ **********************************/ char term[255]; /*Term parsed from equation*/ -int trmtxt; /*Term Type*/ char fnstck[MAXFNS][VARLEN+1]; //Function Call Stack int fnscnt; //Number of Functions in Stack +int chkpst; //Check for Post-Operator + void prsidx(); //Parse Array Index void prstrm(); //Parse Term in Expression void prsxpr(char trmntr); //Parse Expression diff --git a/include.c b/include.c index afe76d9..396fc9b 100644 --- a/include.c +++ b/include.c @@ -55,14 +55,68 @@ void incasm() { clsinc(); } +/* Process define directive */ +void pdefin() +{ + getwrd(); //get defined identifier + DEBUG("Defining '%s'\n", word); + strncpy(defnam[defcnt], word, VARLEN); + setlbl(word); //Set label Assembler Line + expect('='); + defval[defcnt++] = prsbyt(); //Get Value + asmlin(EQUOP, value); //Write Definition + DEBUG("Defined as '%s'\n", value); +} + +/* Parse Origin Subdirective */ +void porign() +{ + prsnum(0xFFFF); //Get Origin Address + asmlin(ORGOP, value); //Emit Origin Instruction + DEBUG("Set origin to %s\n", value); +} + +/* Parse Origin Subdirective */ +void prszpg() +{ + zpaddr = prsnum(0xFF); //Set Zero Page Address to Constant + DEBUG("Set zero page address to %d\n", zpaddr); +} + +/* Process Vartable Subdirective */ +void pvrtbl() +{ + if (vrwrtn) { + ERROR("Variable table already written", 0, EXIT_FAILURE); + } + vartbl(); //Write Variable Table +} + +/* Parse Pragma Directive */ +void pprgma() +{ + getwrd(); //Get Pragma Subdirective + DEBUG("Parsing pragma directive '%s'\n", word); + if (wordis("ORIGIN")) + porign(); //Parse Origin + else if (wordis("VARTABLE")) + pvrtbl(); //Parse Vartable + else if (wordis("ZEROPAGE")) + prszpg(); //Parse Origin + else + ERROR("Illegal pragma subdirective '%s'\n", word, EXIT_FAILURE); +} + /* Process Include File Directive */ void pincdr() { skpchr(); //skip '#' getwrd(); //read directive into word DEBUG("Processing include file directive '%s'\n", word); - if (wordis("define")) - prsdef(); + if (wordis("DEFINE")) + pdefin(); + if (wordis("PRAGMA")) + pprgma(); else { printf("Unrecognized directive '%s'\n", word); exterr(EXIT_FAILURE); @@ -72,11 +126,7 @@ void pincdr() /* Parse Header Word */ void phdwrd() { getwrd(); - if (wordis("void")) - pdecl(VTVOID); - else if (wordis("char")) - pdecl(VTCHAR); - else { + if (!ptype(MTNONE)) { printf("Unexpected word '%s' in header\n", word); exterr(EXIT_FAILURE); } @@ -151,13 +201,15 @@ void pincfl() printf("Invalid include file name '%sn", incnam); exterr(EXIT_FAILURE); } + if (strcmp(dot, ".a02") == 0) + incasm(); if (strcmp(dot, ".asm") == 0) incasm(); else if (strcmp(dot, ".h") == 0) include_hfil(); else if (strcmp(dot, ".h02") == 0) { inchdr(); //Process Header File - strcpy(dot, ".asm"); + strcpy(dot, ".a02"); incasm(); //Process Assembly File with Same Name } else { @@ -166,3 +218,15 @@ void pincfl() } } +/* Print Definition Table to Log File */ +void logdef() +{ + int i; + fprintf(logfil, "\n%-31s %5s\n", "Definition", "Value"); + for (i=0; i-1; i--) - if (lbltyp[i] == lbtype) break; + DEBUG("Searching for label type %d ", lbtyp1); + DEBUG("and label type %d\n",lbtyp2); + for (i = lblcnt - 1; i>-1; i--) { + if (lbltyp[i] == lbtyp1) break; + if (lbltyp[i] == lbtyp2) break; + } DEBUG("Search produced label index %d\n", i); if (i>=0) strcpy(tmplbl, lblnam[i]); @@ -42,8 +46,10 @@ void setblk(int blkflg) void setlbl(char *lblset) { DEBUG("Setting Label '%s'\n", lblset); - if (strlen(lblasm) > 0) + if (strlen(lblasm) > 0) { + DEBUG("Emitting Label '%s'\n'", lblasm); asmlin("",""); //Emit Block End Label on it's own line + } if (strlen(lblset) > LABLEN) ERROR("Label '%s' exceeds maximum size\n", word, EXIT_FAILURE); strcpy(lblasm, lblset); @@ -53,6 +59,7 @@ void setlbl(char *lblset) void prslbl() { DEBUG("Parsing Label '%s''\n", word); + CCMNT(nxtchr); skpchr(); //skip ':' setlbl(word); } @@ -64,6 +71,22 @@ void newlbl(char* lbname) DEBUG("Generated new label '%s'\n", lbname); } +/* require label * + * if label is already set, returns that label * + * else generates new label and sets it */ +void reqlbl(char* lbname) +{ + if (lblasm[0]) + strcpy(lbname, lblasm); + else { + newlbl(lbname); + setlbl(lbname); + } + +} + + + /* Pop Label from Stack and Emit on Next Line */ int poplbl() { @@ -76,6 +99,9 @@ int poplbl() } else if (lbtype == LTDO) strcpy(loplbl, lblnam[lblcnt]); + else if (lbtype == LTDWHL) + strcpy(endlbl, lblnam[lblcnt]); + //strcpy(cndlbl, lblnam[lblcnt]); else setlbl(lblnam[lblcnt]); inblck = lblblk[lblcnt-1]; diff --git a/label.h b/label.h index af00cde..72be9b2 100644 --- a/label.h +++ b/label.h @@ -18,9 +18,8 @@ int lblcnt; //Number of Labels in stack int lblnxt; //Sequence of next label to be generated char lbltmp[LABLEN+1]; //Label Temporary Storage -enum ltypes {LTIF, LTLOOP, LTEND, LTDO, LTCASE, LTFUNC}; //Label Types +enum ltypes {LTNONE, LTIF, LTLOOP, LTEND, LTDO, LTDWHL, LTFUNC}; //Label Types -int lstlbl(int lbtype); //Find Last Label of Specified Type void prslbl(); //Parse Label From Code void newlbl(char* lbname); //Generate New Block Label int poplbl(); //Pull Last Label and Emit on Next Line diff --git a/parse.c b/parse.c index 1d9713a..81c1425 100644 --- a/parse.c +++ b/parse.c @@ -12,8 +12,6 @@ #include "files.h" #include "parse.h" -char opstr[2]; //Operator as a String - /* Various tests against nxtchr */ int match(char c) {return TF(nxtchr == c);} int inbtwn(char mn, char mx) {return TF(nxtchr >= mn && nxtchr <= mx);} @@ -27,10 +25,13 @@ int isnl() {return TF(match('\n') || match('\r'));} int isspc() {return isspace(nxtchr);} int isnpre() {return TF(isdec() || match('$') || match('%'));} int isapos() {return match('\'');} -int iscpre() {return TF(isnpre() || isapos());} +int isbpre() {return TF(isnpre() || isapos());} +int ishash() {return match('#');} +int iscpre() {return TF(isbpre() || ishash());} int isvpre() {return TF(isalph() || iscpre());} int isoper() {return TF(strchr("+-&|^", nxtchr));} int ispopr() {return TF(strchr("+-<>", nxtchr));} +int isxpre() {return TF(isvpre() || match('-'));} /* if Word is s then return TRUE else return FALSE*/ int wordis(char *s) @@ -61,6 +62,7 @@ char getnxt() void skpspc() { //DEBUG("Skipping Spaces\n", 0); + if (isspc()) CCMNT(' '); while (isspc()) getnxt(); } @@ -84,8 +86,8 @@ int look(char c) /* if next printable character is c then skip, else generate error */ void expect(char c) { - if (look(c)) - return; + if (c == 0) return; + if (look(c)) return; else { printf("Expected Character '%c', but found '%c'\n", c, nxtchr); exterr(EXIT_FAILURE); @@ -131,55 +133,11 @@ void getwrd() if (!isalph()) expctd("Alphabetic Character"); while (isanum()) { - word[wrdlen++] = getnxt(); + word[wrdlen++] = toupper(getnxt()); } word[wrdlen] = 0; } -/* Get Definition Text */ -void getdef() -{ - int wrdlen = 0; - skpspc(); - while (isprnt()) { - word[wrdlen++] = getnxt(); - } - word[wrdlen] = 0; -} - -/* Process define directive */ -void prsdef() -{ - getwrd(); //get defined identifier - DEBUG("Defining '%s'\n", word); - strncpy(defnam[defcnt], word, VARLEN); - getdef(); - DEBUG("Defined as '%s'\n", word); - strncat(deftxt[defcnt], word, DEFLEN); - defcnt++; -} - -/* Check for and Expand DEFINE * - * Sets: nxtwrd, nxtchr, nxtupr * - * if match is found */ -void expdef() -{ - int i; - if (!isalph()) return; - DEBUG("Checking for definition '%s'\n", word); - nxtptr = 0; - for (i=0; i 255) - sprintf(value, "#$%04X", cnstnt); - else - sprintf(value, "#$%02X", cnstnt); - DEBUG("Generated constant '%s'\n", value); - ACMNT(word); + return prsnum(0xFF); } +void fnddef(char *name) +{ + DEBUG("Looking up defined constant '%s'\n", word); + for (defidx=0; defidx': + if (strcmp(name, "X")==0) + poperr(); //Index Register Shift not Supported + else if (strcmp(name, "Y")==0) + poperr(); //Index Register Shift not Supported + else if (strcmp(name, "A")==0) + asmlin("LSR", ""); + else + asmlin("LSR", name); + break; + default: + printf("Unrecognized post operator '%c'\n", oper); + exterr(EXIT_FAILURE); + } +} + +/* Parse Post Operator */ +int prspst(char trmntr, char* name) { + oper = getnxt(); + CCMNT(oper); + DEBUG("Checking for post operation '%c'\n", oper); + if (nxtchr == oper) { + skpchr(); + CCMNT(oper); + expect(trmntr); + prcpst(name); //Process Post-Op + oper = 0; + } + else { + DEBUG("Not a post operation\n", 0); + } + return oper; +} + + diff --git a/parse.h b/parse.h index 74ec8da..41e5bcb 100644 --- a/parse.h +++ b/parse.h @@ -4,20 +4,22 @@ #define TF(x) (x) ? TRUE : FALSE; -enum trmtxts {CONSTANT, VARIABLE, ARRAY, FUNCTION}; -enum etypes {ETDEF, ETMAC}; //Definition Types +enum stypes {CONSTANT, VARIABLE, ARRAY, FUNCTION}; //Symbol Types +enum etypes {ETDEF, ETMAC}; //Definition Types char word[LINELEN]; //Word parsed from source file +char uword[LINELEN]; //Word converted too uppercase char nxtwrd[LINELEN]; //Next Word (from DEFINE lookup) int nxtptr; //Pointer to next character in nxtwrd char value[LINELEN]; //Term parsed from equation int valtyp; //Value Type char oper; //Arithmetic or Bitwise Operator -int cnstnt; //Value of Parsed Constant +int cnstnt; //Value of Parsed Constant char defnam[MAXDEF+1][VARLEN+1]; //Definition Name Table -char deftxt[MAXDEF+1][DEFLEN+1]; //Definition Text Table +int defval[MAXDEF+1]; //Definition Value Table int defcnt; //Number of Definitions Defined +int defidx; //Index into Definition Tables int match(char c); //Does Next Character match c int inbtwn(char mn, char mx); //Is Next Character in Range ()mn - mx) @@ -48,10 +50,9 @@ void skpcmt(); //Skip to End of Comment void getwrd(); //Get Next Word -void expdef(); //Check for and Expand Definition - int prsdec(); //Get Decimal Number -void prscon(int maxval); //Parse a Constant +void prscon(); //Parse a Constant void prsopr(); //Parse Arithmetic Operator -void prsvar(); //Parse Variable +void prsvar(int alwreg); //Parse Variable + diff --git a/stmnt.c b/stmnt.c index 32b17aa..d73b504 100644 --- a/stmnt.c +++ b/stmnt.c @@ -15,80 +15,97 @@ #include "expr.h" #include "stmnt.h" +/* Parse Shortcut If */ +void prssif(char trmntr) { + newlbl(cndlbl); //Create Label for "if FALSE" expression + prscnd(')', FALSE); //Parse Condition + expect('?'); + prsxpr(':'); //Parse "if TRUE" expression + newlbl(tmplbl); //Create End of Expression Label + asmlin("JMP", tmplbl); //Jump over "if FALSE" expression + setlbl(cndlbl); //Emit "if FALSE" label + prsxpr(trmntr); //Parse "if FALSE" expression + setlbl(tmplbl); //Emit End of Expression Label +} + + /* Process Assignment */ void prcasn(char trmntr) { - DEBUG("Processing assignment of variable '%s'\n", asnvar); expect('='); - if (look('(')) { //Parse Shortcut If - newlbl(cndlbl); //Create Label for "if FALSE" expression - prscnd(')', FALSE); //Parse Condition - expect('?'); - prsxpr(':'); //Parse "if TRUE" expression - newlbl(tmplbl); //Create End of Expression Label - asmlin("JMP", tmplbl); //Jump over "if FALSE" expression - setlbl(cndlbl); //Emit "if FALSE" label - prsxpr(trmntr); //Parse "if FALSE" expression - setlbl(tmplbl); //Emit End of Expression Label - } - else - prsxpr(trmntr); - if (strlen(asnidx)) { - asmlin("LDX", asnidx); - strcat(asnvar,",X"); - } - asmlin("STA", asnvar); -} - -void prcpop() { - DEBUG("Processing post operation '%c'\n", oper); - switch(oper) - { - case '+': - asmlin("INC", asnvar); - break; - case '-': - asmlin("DEC", asnvar); - break; - case '<': - asmlin("ASL", asnvar); - break; - case '>': - asmlin("LSR", asnvar); - break; - default: - printf("Unrecognized post operator '%c'\n", oper); - exterr(EXIT_FAILURE); - } -} - -/* Parse Post Operator */ -void prspop(char trmntr) { - oper = getnxt(); - CCMNT(oper); CCMNT(oper); - DEBUG("Checking for post operation '%c'\n", oper); - if (nxtchr == oper) { - skpchr(); - prcpop(); //Process Post-Op + if (strlen(asnvar) == 1 && strchr("XY", asnvar[0])) { + DEBUG("Processing assignment of register '%s'\n", asnvar); + prsval(TRUE); //Get value to assign expect(trmntr); + if (strlen(value) == 1 && strchr("XY", value[0])) { + ERROR("Illegal Reference to Register %s\n", value, EXIT_FAILURE); + } + if (asnvar[0] == 'X') { + if (strcmp(value, "A") == 0) + asmlin("TAX", ""); + else + asmlin("LDX", value); + } + else { + if (strcmp(value, "A") == 0) + asmlin("TAY", ""); + else + asmlin("LDY", value); + } + return; } + DEBUG("Processing assignment of variable '%s'\n", asnvar); + if (look('(')) + prssif(trmntr); //Parse Shortcut If else - expctd("post operator"); + prsxpr(trmntr); //Parse Expression + /* if (strcmp(asnvar, "X")==0) + asmlin("TAX", ""); + else if (strcmp(asnvar, "Y")==0) + asmlin("TAY", ""); + else */ + if ((strcmp(asnvar, "A")!=0)) + { + if (strlen(asnidx)) { + if (asnivt == CONSTANT) { + strcat(asnvar, "+"); + strcat(asnvar, asnidx); + } + else { + asmlin("LDX", asnidx); + strcat(asnvar,",X"); + } + } + asmlin("STA", asnvar); + } +} + +void poperr() +{ + printf("Illegal post-operation %c%c on register %s\n", oper, oper, asnvar); + exterr(EXIT_FAILURE); } /* Process Variable at Beginning of Statement */ void prcvar(char trmntr) { - chksym(word); + chksym(TRUE, word); strcpy(asnvar, word); //sav variable to assign to + if (valtyp == VARIABLE && look(';')) { + asmlin("STA", asnvar); + return; + } if (valtyp == ARRAY) { prsidx(); //Parse Array Index + asnivt = valtyp; strncpy(asnidx, value, VARLEN); } else asnidx[0] = 0; - if (ispopr(nxtchr)) - prspop(trmntr); //Parse Post Operator + if (ispopr()) { + if (prspst(trmntr, asnvar)) //Parse Post Operator + expctd("post operator"); + } else prcasn(trmntr); } @@ -107,6 +124,31 @@ void bgnblk(int blkflg) setblk(inblck); } +/* Parse 'asm' String Parameter */ +void pasmst(char trmntr) +{ + skpspc(); //Skip Spaces + if (!match('"')) + expctd("string"); + getstr(); + skpspc(); + expect(trmntr); +} + +/* Parse and Compile 'asm' statement */ +void pasm() +{ + char opcode[LINELEN]; + expect('('); + pasmst(','); + if (strlen(word)) setlbl(word); + pasmst(','); + strcpy(opcode, word); + pasmst(')'); + expect(';'); + asmlin(opcode, word); +} + /* Parse and Compile and Assignment */ void prsasn(char trmntr) { @@ -116,9 +158,10 @@ void prsasn(char trmntr) } /* parse and compile 'break'/'continue' statement */ -void pbrcnt(int lbtype) { +void pbrcnt(int lbtyp1, int lbtyp2) +{ DEBUG("Parsing BREAK/CONTINUE statement\n", 0); - if (lstlbl(lbtype) < 0) + if (lstlbl(lbtyp1, lbtyp2) < 0) ERROR("Break/continue statement outside of loop\n", 0, EXIT_FAILURE); DEBUG("Found Label '%s'\n", tmplbl); asmlin("JMP", tmplbl); @@ -126,11 +169,15 @@ void pbrcnt(int lbtype) { } /* parse and compile 'do' statement */ -void pdo() { +void pdo() +{ DEBUG("Parsing DO statement '%c'\n", nxtchr); - newlbl(loplbl); //Create Do Loop Label + newlbl(endlbl); //Create End Label + pshlbl(LTDWHL, endlbl); //and Push onto Stack + reqlbl(loplbl); //Get or Create/Set Loop Label + //newlbl(loplbl); //Create Do Loop Label + //setlbl(loplbl); //Set Label to Emit on Next Line pshlbl(LTDO, loplbl); //Push onto Stack - setlbl(loplbl); //Set Label to Emit on Next Line bgnblk(FALSE); //Check For and Begin Block } @@ -139,14 +186,17 @@ void pdowhl() { DEBUG("Parsing WHILE after DO '%c'\n", nxtchr); getwrd(); //Check for While ACMNT(word); - if (!wordis("while")) + if (!wordis("WHILE")) expctd("while statement"); expect('('); - newlbl(cndlbl); //Create Skip Label - prscnd(')', FALSE); //Parse Conditional Expession - asmlin("JMP", loplbl); //Emit Jump to Beginning of Loop - setlbl(cndlbl); //and Set Label to Emit on Next Line - expect(';'); //Check for End of Statement + //poplbl(); //Pop While Conditional Label + strcpy(cndlbl, loplbl); //Set Conditional Label to Loop Label + prscnd(')', TRUE); //Parse Conditional Expession + //asmlin("JMP", loplbl); //Emit Jump to Beginning of Loop + //setlbl(cndlbl); //and Set Label to Emit on Next Line + poplbl(); //Pop While Conditional Label + setlbl(endlbl); //and Set Label to Emit on Next Line + expect(';'); //Check for End of Statement } @@ -198,8 +248,72 @@ void pgoto() { DEBUG("Parsing GOTO statement\n", 0); getwrd(); ACMNT(word); - asmlin("JMP", word); expect(';'); + asmlin("JMP", word); +} + +/* parse and compile inline statement */ +void pinlne() +{ + DEBUG("Parsing INLINE statement\n", 0); + do { + DEBUG("Parsing inline parameter\n", 0); + if (look('&')) { + reqvar(FALSE); //Get Variable Name + strcpy(word, "<"); + strcat(word, value); + strcat(word, ", >"); + strcat(word, value); + asmlin(BYTEOP, word); + } + else if (look('"')) { + value[0] = 0; + while (!match('"')) { + CCMNT(nxtchr); + sprintf(word, "$%hhX,", getnxt()); + strcat(value, word); + } + strcat(value,"0"); + CCMNT(nxtchr); + skpchr(); //Skip Terminating Quote + asmlin(BYTEOP, value); + } + else { + prscon(0xFF); + sprintf(word, "$%hhX", cnstnt); //not needed? + asmlin(BYTEOP, value); + } + } while (look(',')); + expect(';'); +} + +/* parse and compile pop statement */ +void ppop() +{ + DEBUG("Parsing POP statement\n", 0); + do { + asmlin("PLA", ""); //Pop Value off Stack + if (!look('*')) { + reqvar(TRUE); + strcpy(term, value); + chkidx(); + asmlin("STA", term); + } + } while (look(',')); + expect(';'); +} + +/* parse and compile push statement */ +void ppush() +{ + DEBUG("Parsing PUSH statement\n", 0); + do { + if (!chkadr(1)) { + prsxpr(0); //Parse Expression + asmlin("PHA",""); //Push Result on Stack + } + } while (look(',')); + expect(';'); } /* parse and compile return statement */ @@ -211,50 +325,22 @@ void pretrn() { lsrtrn = TRUE; //Set RETURN flag } -/* parse and compile switch statement */ -void pswtch() { - DEBUG("Parsing SWITCH statement\n", 0); - expect('('); - prsxpr(')'); - newlbl(endlbl); - pshlbl(LTEND, endlbl); - bgnblk(TRUE); - strcpy(xstmnt,"case"); -} - -/* parse and compile case statement */ -void pcase() { - DEBUG("Parsing CASE statement\n", 0); - prscon(0xff); //Parse Constant - asmlin("CMP", value); - newlbl(skplbl); - pshlbl(LTCASE, skplbl); - asmlin("BNE", skplbl); - expect(':'); -} - -void pdeflt() { - DEBUG("Parsing DEFAULT statement\n", 0); - expect(':'); - if (poplbl() != LTCASE) - ERROR("Encountered default without case\n", 0, EXIT_FAILURE); - -} - - /* parse and compile while statement */ void pwhile() { DEBUG("Parsing WHILE statement '%c'\n", nxtchr); expect('('); newlbl(endlbl); //Create End Label pshlbl(LTEND, endlbl); //and Push onto Stack - newlbl(loplbl); //create Loop Label - setlbl(loplbl); //Set to Emit on Next Line + reqlbl(loplbl); //Get or Create/Set Loop Label + //newlbl(loplbl); //create Loop Label + //setlbl(loplbl); //Set to Emit on Next Line pshlbl(LTLOOP, loplbl); //Push onto Stack - newlbl(cndlbl); //Create Conditional Skip Label - prscnd(')', TRUE); //Parse Conditional Expession - asmlin("JMP", endlbl); //Emit Jump to End of Loop - setlbl(cndlbl); //and Set Label to Emit on Next Line + if (!look(')')) { + newlbl(cndlbl); //Create Conditional Skip Label + prscnd(')', TRUE); //Parse Conditional Expession + asmlin("JMP", endlbl); //Emit Jump to End of Loop + setlbl(cndlbl); //and Set Label to Emit on Next Line + } bgnblk(FALSE); //Check For and Begin Block } @@ -263,13 +349,11 @@ void punimp() { ERROR("Unimplemented statement '%s' encountered\n", word, EXIT_FAILURE); } - /* Parse Function Call as Statement */ void prsfns() { strcpy(term, word); //Copy Function Name - prsfnc(); //Parse Function Call - expect(';'); + prsfnc(';'); //Parse Function Call return; } @@ -295,8 +379,6 @@ void endblk(int blkflg) if (inblck != blkflg) ERROR("Encountered '}' without matching '{'\n", 0, EXIT_FAILURE); lbtype = poplbl(); - if (lbtype == LTCASE) - ERROR("Ended switch without default\n", 0, EXIT_FAILURE); if (lbtype == LTDO) pdowhl(); //Parse While at End of Do Loop } @@ -305,35 +387,35 @@ void endblk(int blkflg) void pstmnt() { DEBUG("Parsing statement '%s'\n", word); - if (wordis("do")) { + if (wordis("DO")) { pdo(); return; } - if (wordis("else")) { + if (wordis("ELSE")) { pelse(); return; } - if (wordis("for")) { + if (wordis("FOR")) { pfor(); return; } - if (wordis("if")) { + if (wordis("IF")) { pif(); return; } - if (wordis("switch")) { + if (wordis("SWITCH")) { punimp(); return; } - if (wordis("case")) { + if (wordis("CASE")) { punimp(); return; } - if (wordis("default")) { + if (wordis("DEFAULT")) { punimp(); return; } - if (wordis("while")) { + if (wordis("WHILE")) { pwhile(); return; } @@ -341,13 +423,21 @@ void pstmnt() prslbl(); //Parse Label return; } - if (wordis("break")) - pbrcnt(LTEND); - else if (wordis("continue")) - pbrcnt(LTLOOP); - else if (wordis("goto")) + if (wordis("ASM")) + pasm(); + else if (wordis("BREAK")) + pbrcnt(LTEND, LTDWHL); + else if (wordis("CONTINUE")) + pbrcnt(LTLOOP, LTDO); + else if (wordis("GOTO")) pgoto(); - else if (wordis("return")) + else if (wordis("INLINE")) + pinlne(); + else if (wordis("POP")) + ppop(); + else if (wordis("PUSH")) + ppush(); + else if (wordis("RETURN")) pretrn(); else prssym(); diff --git a/stmnt.h b/stmnt.h index d57d6f3..5aaca73 100644 --- a/stmnt.h +++ b/stmnt.h @@ -4,6 +4,7 @@ char asnvar[VARLEN+1]; //Assigned Variable Name char asnidx[VARLEN+1] ; //Assigned Variable Index +int asnivt; //Assigned Index Variable Type char xstmnt[LINELEN]; //Required Statement diff --git a/vars.c b/vars.c index 6faa793..a9179c5 100644 --- a/vars.c +++ b/vars.c @@ -18,7 +18,7 @@ /* Lookup variable name in variable table * * Returns index into varnam array * * FALSE if variable was not found */ -int lookup(char *name) +int fndvar(char *name) { int i; DEBUG("Looking up variable '%s'\n", word); @@ -32,28 +32,36 @@ int lookup(char *name) /* Check if variable has been defined */ int symdef(char *name) { - if (lookup(name) < 0) - return FALSE; - else + if (fndvar(name) > -1) return TRUE; + else + return FALSE; } /* Check for variable * - * Generates error if variable is undefined */ -void chksym(char *name) + * Generates error if variable is undefined * + * Args: alwreg - allow register name * + * name - variable name */ +void chksym(int alwreg, char *name) { + if (strlen(name) == 1 && strchr("AXY", name[0])) { + if (alwreg) return; + else ERROR("Illegal reference to register %s\n", name, EXIT_FAILURE); + } if (!symdef(name)) - ERROR("Undeclared variable '%s' encountered\n", word, EXIT_FAILURE); + ERROR("Undeclared variable '%s' encountered\n", name, EXIT_FAILURE); } -/* Parse Variable Name * - * Generates error if not a simple variable */ -void reqvar() +/* Parse Variable Name * + * Parameters: alwary - Allow Array Reference * + * Sets: vrname - operand for LDA/STA/LDY/STY */ +void reqvar(int alwary) { - prsvar(); - if (valtyp != VARIABLE) - expctd("Variable"); + prsvar(FALSE); + if (!alwary) + if (valtyp != VARIABLE) + expctd("Variable"); } /* Check for Array specifier and get size * @@ -67,7 +75,7 @@ void pvarsz() skpchr(); if (alcvar) { DEBUG("Parsing array size\n", 0); - prsnum(0xFF); + sprintf(value, "%d", prsnum(0xFF) + 1); } expect(']'); } @@ -79,7 +87,22 @@ void pvarsz() void prsdtc() { dtype = DTBYTE; - prscon(0xff); + prscon(); +} + +/* Parse Data Array */ +void prsdta() +{ + dtype = DTARRY; + expect('{'); + dlen = 0; + while (TRUE) { + prscon(); + dattmp[dlen++] = cnstnt; + if (!look(',')) + break; + } + expect('}'); } /* Parse Data String */ @@ -103,6 +126,11 @@ void setdat() dlen = 1; datvar[dsize++] = cnstnt; } + else if (dtype == DTARRY) { + DEBUG("Setting variable data to array of length %d\n", dlen); + for (i=0; i 0) { DEBUG("Allocating array '%s'\n", varnam[i]); @@ -249,6 +319,7 @@ void vartbl() asmlin(BYTEOP, "0"); } } + vrwrtn = TRUE; } /* Print Variable Table to Log File */ diff --git a/vars.h b/vars.h index ea7071d..b8b677b 100644 --- a/vars.h +++ b/vars.h @@ -8,6 +8,7 @@ char vartyp[MAXVAR+1]; //Variable Type char varsiz[MAXVAR+1][4]; //Variable Array int varcnt; //Number of Variables in Table char vrname[MAXVAR+1]; //Variable Name +int vrwrtn; //Variables Written Flag /* int varidx; //Index into Variable Table @@ -18,13 +19,17 @@ enum vtypes {VTVOID, VTCHAR}; //Variable Types char datvar[DATASPC+1]; //Variable Data Storage char datlen[MAXVAR+1]; //Variable Data Length char dattyp[MAXVAR+1]; //Variable Data Type +char dattmp[256]; //Variable Temporary Data int dtype; //Data Type int dlen; //Length of Variable Data int dsize; //Total Data Length -enum dtypes {DTBYTE, DTSTR}; //Variable Data Types +enum dtypes {DTBYTE, DTSTR, DTARRY}; //Variable Data Types + +enum mtypes {MTNONE, MTZP}; //Variable Modifier Types int symdef(char *name); //Is Variable defined (TRUE or FALSE) +int zpaddr; //Current Zero-Page Address char fncnam[VARLEN+1]; //Function Name char prmtra[VARLEN+1]; //Function Parameter A @@ -32,11 +37,11 @@ char prmtrx[VARLEN+1]; //Function Parameter X char prmtry[VARLEN+1]; //Function Parameter Y int prmcnt; //Number of Parameters -void chksym(char *name); //Error if Variable not defined +void chksym(int alwreg, char *name); //Error if Variable not defined void prsdts(); //Parse Data String void setdat(); //Set Variable Data void setvar(int t); //Set Variable Name and Size -void pdecl(int t); //Parse Variable Declaration +void pdecl(int m, int t); //Parse Variable Declaration void vartbl(); //Create Variable Table