|
@@ -1,684 +0,0 @@
|
|
-#include <errno.h>
|
|
|
|
-#include <stdio.h>
|
|
|
|
-#include <stdlib.h>
|
|
|
|
-#include <string.h>
|
|
|
|
-
|
|
|
|
-#include "tokenizer/FileReader.h"
|
|
|
|
-
|
|
|
|
-typedef char String[64];
|
|
|
|
-#define STRING_LENGTH ((int)sizeof(String))
|
|
|
|
-
|
|
|
|
-#define END_IF "#endif"
|
|
|
|
-#define END_IF_LENGTH ((int)sizeof(END_IF) - 1)
|
|
|
|
-
|
|
|
|
-static Error* error;
|
|
|
|
-
|
|
|
|
-typedef struct {
|
|
|
|
- String name;
|
|
|
|
-} Define;
|
|
|
|
-
|
|
|
|
-#define DEFINES 256
|
|
|
|
-static Define defines[DEFINES];
|
|
|
|
-static int defineIndex = 0;
|
|
|
|
-
|
|
|
|
-static bool frHasError() {
|
|
|
|
- return error->message[0] != '\0';
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static bool frStringCompare(const String a, const char* b) {
|
|
|
|
- return strcmp(a, b) == 0;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void frInitFileReader(FileReader* fr, const char* path) {
|
|
|
|
- fr->data = NULL;
|
|
|
|
- fr->path = path;
|
|
|
|
- fr->length = 0;
|
|
|
|
- fr->readIndex = 0;
|
|
|
|
- fr->line = 1;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void frSystemError(const char* msg, FileReader* fr) {
|
|
|
|
- eInitError(error, fr->line, "%s '%s': %s", msg, fr->path, strerror(errno));
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void frFullRead(FILE* file, FileReader* fr) {
|
|
|
|
- if(fseek(file, 0, SEEK_END)) {
|
|
|
|
- frSystemError("cannot seek end of file", fr);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- long length = ftell(file);
|
|
|
|
- if(length < 0) {
|
|
|
|
- frSystemError("cannot tell end of file", fr);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- rewind(file);
|
|
|
|
- fr->data = malloc(length + 1);
|
|
|
|
- fr->length = length;
|
|
|
|
- int readValues = fread(fr->data, 1, length, file);
|
|
|
|
- if(readValues != length) {
|
|
|
|
- frSystemError("cannot read file", fr);
|
|
|
|
- fr->data[0] = '\0';
|
|
|
|
- fr->length = 0;
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- fr->data[length] = '\0';
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void frFullReadFile(FileReader* fr) {
|
|
|
|
- FILE* file = fopen(fr->path, "r");
|
|
|
|
- if(file == NULL) {
|
|
|
|
- frSystemError("cannot open file", fr);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- frFullRead(file, fr);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static int frReadUntil(int from, char end, String s, FileReader* fr) {
|
|
|
|
- int index = 0;
|
|
|
|
- while(from < fr->length && index < STRING_LENGTH - 1 &&
|
|
|
|
- fr->data[from] != end) {
|
|
|
|
- s[index++] = fr->data[from];
|
|
|
|
- from++;
|
|
|
|
- }
|
|
|
|
- s[index] = '\0';
|
|
|
|
- return index;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static int frReadUntilOrLine(int from, char end, String s, FileReader* fr) {
|
|
|
|
- int index = 0;
|
|
|
|
- while(from < fr->length && index < STRING_LENGTH - 1 &&
|
|
|
|
- fr->data[from] != end && fr->data[from] != '\n') {
|
|
|
|
- s[index++] = fr->data[from];
|
|
|
|
- from++;
|
|
|
|
- }
|
|
|
|
- s[index] = '\0';
|
|
|
|
- return index;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void frMakePath(String fullPath, const char* parent, String name) {
|
|
|
|
- int i = 0;
|
|
|
|
- int lastSlash = 0;
|
|
|
|
- while(i < STRING_LENGTH - 1 && parent[i] != '\0') {
|
|
|
|
- fullPath[i] = parent[i];
|
|
|
|
- lastSlash = parent[i] == '/' ? i : lastSlash;
|
|
|
|
- i++;
|
|
|
|
- }
|
|
|
|
- i = lastSlash + 1;
|
|
|
|
- int nameI = 0;
|
|
|
|
- while(i < STRING_LENGTH - 1 && name[nameI] != '\0') {
|
|
|
|
- fullPath[i] = name[nameI];
|
|
|
|
- i++;
|
|
|
|
- nameI++;
|
|
|
|
- }
|
|
|
|
- fullPath[i] = '\0';
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void frReplace(int from, int to, FileReader* fr,
|
|
|
|
- FileReader* replacement) {
|
|
|
|
- int replaceLength = replacement->length - 1;
|
|
|
|
- replaceLength = replaceLength < 0 ? 0 : replaceLength;
|
|
|
|
- int newLength = fr->length + replaceLength - (to - from);
|
|
|
|
- unsigned char* newData = malloc(newLength + 1);
|
|
|
|
- memcpy(newData, fr->data, from);
|
|
|
|
- memcpy(newData + from, replacement->data, replaceLength);
|
|
|
|
- memcpy(newData + from + replaceLength, fr->data + to, fr->length - to);
|
|
|
|
- newData[newLength] = '\0';
|
|
|
|
-
|
|
|
|
- free(fr->data);
|
|
|
|
- fr->data = newData;
|
|
|
|
- fr->length = newLength;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static int skipSpaces(int index, FileReader* fr) {
|
|
|
|
- while(index < fr->length && fr->data[index] == ' ') {
|
|
|
|
- index++;
|
|
|
|
- }
|
|
|
|
- return index;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void frHandleInclude(int from, int length, FileReader* fr) {
|
|
|
|
- int index = from + length;
|
|
|
|
- index = skipSpaces(index, fr);
|
|
|
|
- if(index >= fr->length || fr->data[index] != '"') {
|
|
|
|
- eInitError(error, fr->line, "expected '\"' and not '%c' in '%s'",
|
|
|
|
- fr->data[index], fr->path);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- index++;
|
|
|
|
- String s;
|
|
|
|
- int pathLength = frReadUntil(index, '"', s, fr) + 1;
|
|
|
|
-
|
|
|
|
- String fullPath;
|
|
|
|
- frMakePath(fullPath, fr->path, s);
|
|
|
|
-
|
|
|
|
- FileReader include;
|
|
|
|
- frInitFileReader(&include, fullPath);
|
|
|
|
- frFullReadFile(&include);
|
|
|
|
- if(frHasError()) {
|
|
|
|
- frDelete(&include);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- frReplace(from, index + pathLength, fr, &include);
|
|
|
|
- frDelete(&include);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static int frReadWord(String s, int from, FileReader* fr) {
|
|
|
|
- int index = skipSpaces(from, fr);
|
|
|
|
- int wordLength = frReadUntilOrLine(index, ' ', s, fr);
|
|
|
|
- return index + wordLength;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static bool frIsDefined(String s) {
|
|
|
|
- for(int i = 0; i < defineIndex; i++) {
|
|
|
|
- if(frStringCompare(defines[i].name, s)) {
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return false;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static bool frIsMatching(int from, FileReader* fr, const char* s) {
|
|
|
|
- int i = 0;
|
|
|
|
- while(true) {
|
|
|
|
- if(s[i] == '\0') {
|
|
|
|
- return true;
|
|
|
|
- } else if(from >= fr->length || fr->data[from] != s[i]) {
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
- from++;
|
|
|
|
- i++;
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static int frFindEndIf(int from, FileReader* fr) {
|
|
|
|
- int layer = 0;
|
|
|
|
- for(int i = from; i < fr->length; i++) {
|
|
|
|
- if(frIsMatching(i, fr, END_IF)) {
|
|
|
|
- if(layer == 0) {
|
|
|
|
- return i;
|
|
|
|
- }
|
|
|
|
- layer--;
|
|
|
|
- } else if(frIsMatching(i, fr, "#ifndef")) {
|
|
|
|
- layer++;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return -1;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void frHandleIfNotDefined(int from, int length, FileReader* fr) {
|
|
|
|
- String s;
|
|
|
|
- int end = frReadWord(s, from + length, fr);
|
|
|
|
- int endIf = frFindEndIf(end, fr);
|
|
|
|
- if(endIf == -1) {
|
|
|
|
- eInitError(error, fr->line, "cannot find #endif in '%s'", fr->path);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- if(frIsDefined(s)) {
|
|
|
|
- memset(fr->data + from, ' ', endIf - from + END_IF_LENGTH);
|
|
|
|
- } else {
|
|
|
|
- memset(fr->data + from, ' ', end - from);
|
|
|
|
- memset(fr->data + endIf, ' ', END_IF_LENGTH);
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void frHandleDefine(int from, int length, FileReader* fr) {
|
|
|
|
- if(defineIndex >= DEFINES) {
|
|
|
|
- eInitError(error, fr->line, "too much defines in '%s'", fr->path);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- String s;
|
|
|
|
- int end = frReadWord(s, from + length, fr);
|
|
|
|
- if(frIsDefined(s)) {
|
|
|
|
- puts("already defined");
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- strncpy(defines[defineIndex].name, s, STRING_LENGTH);
|
|
|
|
- defineIndex++;
|
|
|
|
- printf("defined '%s'\n", s);
|
|
|
|
- memset(fr->data + from, ' ', end - from);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void frParseInstruction(int from, FileReader* fr) {
|
|
|
|
- String s;
|
|
|
|
- int length = frReadUntil(from, ' ', s, fr);
|
|
|
|
- if(frStringCompare(s, "#include")) {
|
|
|
|
- frHandleInclude(from, length, fr);
|
|
|
|
- } else if(frStringCompare(s, "#ifndef")) {
|
|
|
|
- frHandleIfNotDefined(from, length, fr);
|
|
|
|
- } else if(frStringCompare(s, "#define")) {
|
|
|
|
- frHandleDefine(from, length, fr);
|
|
|
|
- } else {
|
|
|
|
- eInitError(error, fr->line, "unknown preprocessor token '%s' in '%s'",
|
|
|
|
- s, fr->path);
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void frSearchInstruction(FileReader* fr) {
|
|
|
|
- if(fr->data == NULL) {
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- for(int i = 0; i < fr->length && !frHasError(); i++) {
|
|
|
|
- unsigned char c = fr->data[i];
|
|
|
|
- if(c == '#') {
|
|
|
|
- frParseInstruction(i, fr);
|
|
|
|
- i--;
|
|
|
|
- } else if(c == '\n') {
|
|
|
|
- fr->line++;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-void frInit(const char* path, FileReader* fr, Error* e) {
|
|
|
|
- defineIndex = 0;
|
|
|
|
- error = e;
|
|
|
|
- eInitSuccess(error);
|
|
|
|
- frInitFileReader(fr, path);
|
|
|
|
- frFullReadFile(fr);
|
|
|
|
- frSearchInstruction(fr);
|
|
|
|
- if(fr->data != NULL) {
|
|
|
|
- printf((char*)fr->data);
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-void frDelete(FileReader* fr) {
|
|
|
|
- free(fr->data);
|
|
|
|
- fr->data = NULL;
|
|
|
|
- fr->path = NULL;
|
|
|
|
- fr->length = 0;
|
|
|
|
- fr->readIndex = 0;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-int frRead(FileReader* fr) {
|
|
|
|
- if(fr->readIndex < fr->length) {
|
|
|
|
- return fr->data[fr->readIndex++];
|
|
|
|
- }
|
|
|
|
- return -1;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-int frPeek(FileReader* fr) {
|
|
|
|
- if(fr->readIndex < fr->length) {
|
|
|
|
- return fr->data[fr->readIndex];
|
|
|
|
- }
|
|
|
|
- return -1;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-bool frReadIf(FileReader* fr, int c) {
|
|
|
|
- if(frPeek(fr) == c) {
|
|
|
|
- frRead(fr);
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- return false;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-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();
|
|
|
|
-
|
|
|
|
- return i;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-int fPeek() {
|
|
|
|
- fPrepareChar();
|
|
|
|
- return fReadChar();
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-bool fReadIf(int c) {
|
|
|
|
- if(fPeek() == c) {
|
|
|
|
- fRead();
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- return false;
|
|
|
|
-}*/
|
|
|