123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684 |
- #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;
- }
- /*#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;
- }*/
|