#include #include #include #include #include "bindings.h" #include "gcl.h" #define null ((void*) 0) /*----------------------------------------------------------------------+ | Definitions | +----------------------------------------------------------------------*/ typedef enum { endType, openType, closeType, wordType, condType, loopType } WordType_t; // Disected word struct word { char prefix; // optional char *name; // null in case of a number int number; // length in case of a name char operator[3]; // or a conditional }; /*----------------------------------------------------------------------+ | Variables | +----------------------------------------------------------------------*/ char *cursor; char *compileError; int blockDepth; int base, offset, size; unsigned char page[256]; /*----------------------------------------------------------------------+ | Internal functions | +----------------------------------------------------------------------*/ /* * Get the next word skipping whitespace and nested comments. * Classify the word according to its structure. * Generate an error message if malformed. * Most work is done here already. */ static WordType_t nextWord(struct word *word) { #define hasMore\ (isprint(*cursor) && !strchr("[{", *cursor)) #define error(s)\ ((compileError = (s)), -1) memset(word, 0, sizeof *word); // Whitespace while (1) { // Spaces or newlines if (strchr(" \n", *cursor) || strncmp("\r\n", cursor, 2)==0) { cursor++; continue; } // Comments if (*cursor == '{') { cursor++; int depth = 1; do { if (*cursor == 0) return error("Comment without end"); if (!isprint(*cursor)) return error("Invalid byte"); if (*cursor == '{') depth++; if (*cursor == '}') depth--; cursor++; } while (depth > 0); continue; } break; } // End of file/line if (*cursor == 0) return endType; // Blocks if (*cursor == '[') return cursor++, openType; if (*cursor == ']') return cursor++, closeType; // Prefix if (strchr("<>\\%", *cursor)) word->prefix = *cursor++; // Word or number char *s = strchr("-+", *cursor); char sign = s ? *cursor++ : 0; if (isdigit(*cursor)) { // Decimal number (ignore overflows) int n = 0; do { n = 10 * n + (*cursor - '0'); cursor++; } while (isdigit(*cursor)); word->number = (sign == '-') ? -n : n; } else if (*cursor == '$') { // Hexadecimal number (ignore overflows) int n = 0; s = ++cursor; while (1) { if (isdigit(*cursor)) n = 16 * n + (*cursor - '0'); else if ('a' <= *cursor && *cursor <= 'f') n = 16 * n + (*cursor - 'a'); else if ('A' <= *cursor && *cursor <= 'F') n = 16 * n + (*cursor - 'A'); else break; cursor++; } if (cursor == s) return error("Missing hex"); word->number = (sign == '-') ? -n : n; } else if (sign) return error("Sign without number"); else if (isalpha(*cursor)) { // Name word->name = cursor++; while (isalnum(*cursor) || *cursor == '_') cursor++; word->number = cursor - word->name; } else return error("Invalid word"); // Conditionals if (strncmp("if", word->name, 2)==0 && word->number == 2 && !word->prefix && !sign) { int i = 0; if (*cursor == '<') word->operator[i++] = *cursor++; if (*cursor == '>') word->operator[i++] = *cursor++; if (*cursor == '=' && i<2) word->operator[i++] = *cursor++; if (i > 0 && *cursor++ == '0') { if (strncmp(cursor, "loop", 4)==0) cursor += 4; if (!hasMore) return condType; } return error("Invalid conditional"); } // Operator s = strchr("+-&|^=.,:;?!<", *cursor); if (s) { word->operator[0] = *cursor++; if (cursor[-1] == cursor[0] && strchr("+-<", *cursor)) word->operator[1] = *cursor++; // ++ -- << } if (hasMore) return error("Invalid word"); return wordType; } static int compileWord(struct word *w) { return 0; } static void emit(int byte) { if (offset < size) page[offset] = byte; offset++; } static int emitIf(int cond) { emit(BCC); emit(cond); return 0; } static int emitIfLoop(int cond) { emit(BCC); emit(cond); return 0; } static int compileCond(struct word *w) { if (strcmp(w->operator, "<")==0) return emitIf(GE); if (strcmp(w->operator, ">")==0) return emitIf(LE); if (strcmp(w->operator, "=")==0) return emitIf(NE); if (strcmp(w->operator, "<>")==0) return emitIf(EQ); if (strcmp(w->operator, "<=")==0) return emitIf(GT); if (strcmp(w->operator, ">=")==0) return emitIf(LT); return -1; } static int compileLoop(struct word *w) { if (strcmp(w->operator, "<")==0) return emitIfLoop(LT); if (strcmp(w->operator, ">")==0) return emitIfLoop(GT); if (strcmp(w->operator, "=")==0) return emitIfLoop(EQ); if (strcmp(w->operator, "<>")==0) return emitIfLoop(NE); if (strcmp(w->operator, "<=")==0) return emitIfLoop(LE); if (strcmp(w->operator, ">=")==0) return emitIfLoop(GE); return -1; } /*----------------------------------------------------------------------+ | External functions | +----------------------------------------------------------------------*/ void compileBegin(void) { compileError = null; blockDepth = 0; base = 0x0200; offset = 0; size = 250; } int compileLine(char *line) { cursor = line; struct word w; while (1) { switch (nextWord(&w)) { case endType: break; case openType: blockDepth++; continue; case closeType: if (blockDepth <= 0) return error("Close block without open"); blockDepth--; continue; case wordType: if (compileWord(&w)) return -1; continue; case condType: if (compileCond(&w)) return -1; continue; case loopType: if (compileLoop(&w)) return -1; continue; default: return -1; } break; } return 0; } int compileEnd(void) { if (blockDepth > 0) return error("Open block without close"); return 0; } /*----------------------------------------------------------------------+ | | +----------------------------------------------------------------------*/