123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "tokenizer/File.h"
- #include "utils/SnuviUtils.h"
- #define MAX_INDEX 50
- typedef struct {
- char* content;
- int size;
- int index;
- int arrayIndex;
- bool newLines;
- char* path;
- FILE* file;
- } OpenFile;
- typedef struct {
- int fileIndex;
- int index;
- } FilePointer;
- typedef struct {
- FilePointer name;
- FilePointer code;
- } Define;
- typedef struct {
- int fileIndex;
- int defineIndex;
- OpenFile files[MAX_INDEX];
- Define defines[MAX_INDEX];
- FilePointer readIndex;
- FileError error;
- } OpenFiles;
- static OpenFiles files;
- static int lastChar = 0;
- static int stackIndex = 0;
- static FilePointer stack[MAX_INDEX];
- static void fAdd(OpenFile* of, const void* data, int size) {
- while(of->index + size > of->size) {
- of->size *= 2;
- of->content = realloc(of->content, of->size);
- }
- memcpy(of->content + of->index, data, size);
- of->index += size;
- }
- static void fAddChar(OpenFile* of, int ic) {
- char c = ic;
- fAdd(of, &c, 1);
- }
- static int fReserverInt(OpenFile* of) {
- int address = of->index;
- int empty = 0;
- fAdd(of, &empty, sizeof(int));
- return address;
- }
- static void fSetInt(OpenFile* of, int address, int i) {
- memcpy(of->content + address, &i, sizeof(int));
- }
- static int fReadInt(OpenFile* of, int address) {
- int i = 0;
- memcpy(&i, of->content + address, sizeof(int));
- of->index += sizeof(int);
- return i;
- }
- static int fGet(OpenFile* of) {
- int c = fgetc(of->file);
- if(!of->newLines && c == '\n') {
- return ' ';
- }
- return c;
- }
- static bool fReadCommandString(OpenFile* of, char* buffer, int size) {
- int index = 0;
- int c = fGet(of);
- while(c == ' ') {
- c = fGet(of);
- }
- int text = 0;
- while(true) {
- if(c == EOF) {
- files.error("unexpected end of file");
- } else if(index >= size - 1) {
- files.error("unknown too long command");
- } else if(c == '"' && text < 2) {
- text++;
- buffer[index++] = c;
- } else if((isLetter(c) || text == 1) && text < 2) {
- buffer[index++] = c;
- } else if(c == ' ' || c == '\n') {
- buffer[index] = '\0';
- return c == '\n';
- } else {
- files.error("unexpected character '%c'", (char)c);
- }
- c = fGet(of);
- }
- }
- static const char* fGetDefineName(Define* d) {
- return files.files[d->name.fileIndex].content + d->name.index;
- }
- static int fStartDefine(OpenFile* of, bool* newLine) {
- fAddChar(of, '#');
- int end = fReserverInt(of);
- int nameFileIndex = fReserverInt(of);
- int nameIndex = fReserverInt(of);
- int codeFileIndex = fReserverInt(of);
- int codeIndex = fReserverInt(of);
- char command[64];
- *newLine = fReadCommandString(of, command, 64);
- fSetInt(of, nameFileIndex, of->arrayIndex);
- fSetInt(of, nameIndex, of->index);
- fAdd(of, command, strlen(command) + 1);
- fSetInt(of, codeFileIndex, of->arrayIndex);
- fSetInt(of, codeIndex, of->index);
- return end;
- }
- static void fFinishDefine(OpenFile* of, int end, int newLines) {
- fAddChar(of, '\0');
- fSetInt(of, end, of->index);
- for(int i = 0; i < newLines; i++) {
- fAddChar(of, '\n');
- }
- }
- static void fDefine(OpenFile* of) {
- bool newLine = false;
- int end = fStartDefine(of, &newLine);
- int newLines = newLine;
- while(true) {
- int c = fGet(of);
- if(c == '#') {
- char end[64];
- newLines += fReadCommandString(of, end, 64);
- if(strcmp(end, "end") == 0) {
- break;
- }
- files.error("invalid command '%s' inside define region", end);
- } else if(c == EOF) {
- files.error("unclosed #define");
- }
- if(c == '\n') {
- newLines++;
- c = ' ';
- }
- fAddChar(of, c);
- }
- fFinishDefine(of, end, newLines);
- }
- static void fReadFile(const char* path, bool newLines);
- static void fEnter(FilePointer* fp);
- static int fConcat(char* buffer, int size, const char* s) {
- int l = strlen(s) + 1;
- if(l > size) {
- files.error("too long include path");
- }
- memcpy(buffer, s, l);
- return l;
- }
- static void fInclude(OpenFile* of) {
- char path[64];
- if(fReadCommandString(of, path, 64)) {
- fAddChar(of, '\n');
- }
- int l = strlen(path);
- if(l < 2 || path[0] != '"' || path[l - 1] != '"') {
- files.error("invalid include path '%s'", path);
- }
- path[l - 1] = '\0';
- const char* cutPath = path + 1;
- char fullName[256];
- int index = fConcat(fullName, 256, of->path);
- while(index > 0 && fullName[index - 1] != '/') {
- index--;
- }
- fConcat(fullName + index, 256 - index, cutPath);
- FilePointer fp = {files.fileIndex, 0};
- fEnter(&fp);
- fReadFile(fullName, false);
- }
- static void fReadCommand(OpenFile* of) {
- char command[64];
- fReadCommandString(of, command, 64);
- if(strcmp(command, "define") == 0) {
- fDefine(of);
- } else if(strcmp(command, "include") == 0) {
- fInclude(of);
- } else {
- files.error("invalid command '%s'", command);
- }
- }
- static void fReadFile(const char* path, bool newLines) {
- if(files.fileIndex >= MAX_INDEX) {
- files.error("cannot read file '%s': too many open files", path);
- }
- OpenFile* of = files.files + files.fileIndex;
- of->arrayIndex = files.fileIndex++;
- of->index = 0;
- of->size = 16;
- of->newLines = newLines;
- of->content = malloc(of->size);
- of->file = fopen(path, "r");
- of->path = strdup(path);
- if(of->file == NULL) {
- files.error("cannot read file '%s'", path);
- }
- while(true) {
- int c = fGet(of);
- if(c == '#') {
- fReadCommand(of);
- continue;
- }
- fAddChar(of, c);
- if(c == EOF) {
- break;
- }
- }
- fAddChar(of, '\0');
- }
- void fOpen(const char* path, FileError fe) {
- files.fileIndex = 0;
- files.defineIndex = 0;
- files.readIndex.fileIndex = 0;
- files.readIndex.index = 0;
- files.error = fe;
- lastChar = 0;
- stackIndex = 0;
- fReadFile(path, true);
- }
- void fClose() {
- for(int i = 0; i < files.fileIndex; i++) {
- if(files.files[i].file != NULL) {
- fclose(files.files[i].file);
- }
- free(files.files[i].path);
- free(files.files[i].content);
- }
- }
- static OpenFile* currentFile() {
- return files.files + files.readIndex.fileIndex;
- }
- static int fReadChar() {
- return currentFile()->content[files.readIndex.index];
- }
- static bool fCompare(const char* a, const char* b, unsigned int bLength) {
- return strncmp(a, b, bLength) == 0 && strlen(a) == bLength;
- }
- static void fEnter(FilePointer* fp) {
- if(stackIndex >= MAX_INDEX) {
- files.error("define stack overflow");
- }
- stack[stackIndex++] = files.readIndex;
- files.readIndex = *fp;
- }
- static bool fCheckForReplacement() {
- OpenFile* of = currentFile();
- int start = files.readIndex.index;
- int index = start;
- while(index < of->index && isLetter(of->content[index])) {
- index++;
- }
- for(int i = 0; i < files.defineIndex; i++) {
- Define* d = files.defines + i;
- const char* name = fGetDefineName(d);
- if(fCompare(name, of->content + start, index - start)) {
- files.readIndex.index = index;
- fEnter(&d->code);
- return true;
- }
- }
- return false;
- }
- static void fReadDefine() {
- int base = files.readIndex.index + 1;
- int end = fReadInt(currentFile(), base);
- int nameFileIndex = fReadInt(currentFile(), base + sizeof(int));
- int nameIndex = fReadInt(currentFile(), base + sizeof(int) * 2);
- int codeFileIndex = fReadInt(currentFile(), base + sizeof(int) * 3);
- int codeIndex = fReadInt(currentFile(), base + sizeof(int) * 4);
- const char* name = files.files[nameFileIndex].content + nameIndex;
- if(files.defineIndex >= MAX_INDEX) {
- files.error("too many defines");
- }
- Define* d = files.defines + files.defineIndex++;
- for(int i = 0; i < files.defineIndex - 1; i++) {
- if(strcmp(name, fGetDefineName(files.defines + i)) == 0) {
- d = files.defines + i;
- files.defineIndex--;
- break;
- }
- }
- d->name.fileIndex = nameFileIndex;
- d->name.index = nameIndex;
- d->code.fileIndex = codeFileIndex;
- d->code.index = codeIndex;
- files.readIndex.index = end;
- }
- static void fPrepareChar() {
- while(true) {
- int c = fReadChar();
- if(c == '\0') {
- if(stackIndex <= 0) {
- files.error("define stack underflow");
- }
- files.readIndex = stack[--stackIndex];
- } else if(c == EOF && stackIndex > 0) {
- files.readIndex = stack[--stackIndex];
- } else if(c == '#') {
- fReadDefine();
- } else if(isLetter(c) && !isLetter(lastChar)) {
- if(fCheckForReplacement()) {
- continue;
- }
- break;
- } else {
- break;
- }
- }
- }
- static int fReadI() {
- fPrepareChar();
- lastChar = fReadChar();
- return currentFile()->content[files.readIndex.index++];
- }
- int fRead() {
- int i = fReadI();
- // putchar(i);
- return i;
- }
- int fPeek() {
- fPrepareChar();
- return fReadChar();
- }
- bool fReadIf(int c) {
- if(fPeek() == c) {
- fRead();
- return true;
- }
- return false;
- }
|