|
@@ -88,7 +88,7 @@ static void fReadCommandString(OpenFile* of, char* buffer, int size) {
|
|
files.error("unknown too long command");
|
|
files.error("unknown too long command");
|
|
} else if(isLetter(c)) {
|
|
} else if(isLetter(c)) {
|
|
buffer[index++] = c;
|
|
buffer[index++] = c;
|
|
- } else if(c == ' ') {
|
|
+ } else if(c == ' ' || c == '\n') {
|
|
break;
|
|
break;
|
|
} else {
|
|
} else {
|
|
files.error("unexpected character '%c'", (char)c);
|
|
files.error("unexpected character '%c'", (char)c);
|
|
@@ -98,7 +98,11 @@ static void fReadCommandString(OpenFile* of, char* buffer, int size) {
|
|
buffer[index] = '\0';
|
|
buffer[index] = '\0';
|
|
}
|
|
}
|
|
|
|
|
|
-static void fDefine(OpenFile* of) {
|
|
+static const char* fGetDefineName(Define* d) {
|
|
|
|
+ return files.files[d->name.fileIndex].content + d->name.index;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int fStartDefine(OpenFile* of) {
|
|
if(files.defineIndex >= MAX_INDEX) {
|
|
if(files.defineIndex >= MAX_INDEX) {
|
|
files.error("too many defines");
|
|
files.error("too many defines");
|
|
}
|
|
}
|
|
@@ -113,18 +117,61 @@ static void fDefine(OpenFile* of) {
|
|
d->name.index = of->index;
|
|
d->name.index = of->index;
|
|
fAdd(of, command, strlen(command) + 1);
|
|
fAdd(of, command, strlen(command) + 1);
|
|
|
|
|
|
|
|
+ for(int i = 0; i < files.defineIndex - 1; i++) {
|
|
|
|
+ if(strcmp(command, fGetDefineName(files.defines + i)) == 0) {
|
|
|
|
+ files.error("'%s' is already defined", command);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
d->code.fileIndex = of->arrayIndex;
|
|
d->code.fileIndex = of->arrayIndex;
|
|
d->code.index = of->index;
|
|
d->code.index = 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) {
|
|
|
|
+ int end = fStartDefine(of);
|
|
while(true) {
|
|
while(true) {
|
|
int c = fGet(of);
|
|
int c = fGet(of);
|
|
- if(c == EOF || c == '\n') {
|
|
+ if(c == '#') {
|
|
|
|
+ files.error("# inside define");
|
|
|
|
+ } else if(c == EOF || c == '\n') {
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
fAddChar(of, c);
|
|
fAddChar(of, c);
|
|
}
|
|
}
|
|
- fAddChar(of, '\0');
|
|
+ fFinishDefine(of, end, 1);
|
|
- fSetInt(of, end, of->index);
|
|
+}
|
|
- fAddChar(of, '\n');
|
|
+
|
|
|
|
+static void fStart(OpenFile* of) {
|
|
|
|
+ int end = fStartDefine(of);
|
|
|
|
+ int newLines = 2;
|
|
|
|
+ while(true) {
|
|
|
|
+ int c = fGet(of);
|
|
|
|
+ if(c == '#') {
|
|
|
|
+ char end[64];
|
|
|
|
+ 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 #start");
|
|
|
|
+ }
|
|
|
|
+ if(c == '\n') {
|
|
|
|
+ newLines++;
|
|
|
|
+ c = ' ';
|
|
|
|
+ }
|
|
|
|
+ fAddChar(of, c);
|
|
|
|
+ }
|
|
|
|
+ fFinishDefine(of, end, newLines);
|
|
}
|
|
}
|
|
|
|
|
|
static void fReadCommand(OpenFile* of) {
|
|
static void fReadCommand(OpenFile* of) {
|
|
@@ -132,6 +179,8 @@ static void fReadCommand(OpenFile* of) {
|
|
fReadCommandString(of, command, 64);
|
|
fReadCommandString(of, command, 64);
|
|
if(strcmp(command, "define") == 0) {
|
|
if(strcmp(command, "define") == 0) {
|
|
fDefine(of);
|
|
fDefine(of);
|
|
|
|
+ } else if(strcmp(command, "start") == 0) {
|
|
|
|
+ fStart(of);
|
|
} else {
|
|
} else {
|
|
files.error("invalid command '%s'", command);
|
|
files.error("invalid command '%s'", command);
|
|
}
|
|
}
|
|
@@ -177,7 +226,9 @@ void fOpen(const char* path, FileError fe) {
|
|
|
|
|
|
void fClose() {
|
|
void fClose() {
|
|
for(int i = 0; i < files.fileIndex; i++) {
|
|
for(int i = 0; i < files.fileIndex; i++) {
|
|
- fclose(files.files[i].file);
|
|
+ if(files.files[i].file != NULL) {
|
|
|
|
+ fclose(files.files[i].file);
|
|
|
|
+ }
|
|
free(files.files[i].content);
|
|
free(files.files[i].content);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -190,10 +241,6 @@ static int fReadChar() {
|
|
return currentFile()->content[files.readIndex.index];
|
|
return currentFile()->content[files.readIndex.index];
|
|
}
|
|
}
|
|
|
|
|
|
-static const char* fGetDefineName(Define* d) {
|
|
|
|
- return files.files[d->name.fileIndex].content + d->name.index;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static bool fCompare(const char* a, const char* b, unsigned int bLength) {
|
|
static bool fCompare(const char* a, const char* b, unsigned int bLength) {
|
|
return strncmp(a, b, bLength) == 0 && strlen(a) == bLength;
|
|
return strncmp(a, b, bLength) == 0 && strlen(a) == bLength;
|
|
}
|
|
}
|
|
@@ -206,42 +253,59 @@ static void fEnter(Define* d) {
|
|
files.readIndex = d->code;
|
|
files.readIndex = d->code;
|
|
}
|
|
}
|
|
|
|
|
|
-static void fPrepareChar() {
|
|
+static bool fCheckForReplacement() {
|
|
- int c = fReadChar();
|
|
+ OpenFile* of = currentFile();
|
|
- if(c == '\0') {
|
|
+ int start = files.readIndex.index;
|
|
- if(stackIndex <= 0) {
|
|
+ int index = start;
|
|
- files.error("define stack underflow");
|
|
+ while(index < of->index && isLetter(of->content[index])) {
|
|
- }
|
|
+ index++;
|
|
- files.readIndex = stack[--stackIndex];
|
|
|
|
}
|
|
}
|
|
- if(c == '#') {
|
|
+ for(int i = 0; i < files.defineIndex; i++) {
|
|
- int end = fReadInt(currentFile(), files.readIndex.index + 1);
|
|
+ Define* d = files.defines + i;
|
|
- files.readIndex.index = end;
|
|
+ const char* name = fGetDefineName(d);
|
|
- }
|
|
+ if(fCompare(name, of->content + start, index - start)) {
|
|
- if(isLetter(c) && !isLetter(lastChar)) {
|
|
+ files.readIndex.index = index;
|
|
- OpenFile* of = currentFile();
|
|
+ fEnter(d);
|
|
- int start = files.readIndex.index;
|
|
+ return true;
|
|
- 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;
|
|
+ return false;
|
|
- const char* name = fGetDefineName(d);
|
|
+}
|
|
- if(fCompare(name, of->content + start, index - start)) {
|
|
+
|
|
- files.readIndex.index = index;
|
|
+static void fPrepareChar() {
|
|
- fEnter(d);
|
|
+ while(true) {
|
|
|
|
+ int c = fReadChar();
|
|
|
|
+ if(c == '\0') {
|
|
|
|
+ if(stackIndex <= 0) {
|
|
|
|
+ files.error("define stack underflow");
|
|
}
|
|
}
|
|
|
|
+ files.readIndex = stack[--stackIndex];
|
|
|
|
+ } else if(c == '#') {
|
|
|
|
+ files.readIndex.index =
|
|
|
|
+ fReadInt(currentFile(), files.readIndex.index + 1);
|
|
|
|
+ } else if(isLetter(c) && !isLetter(lastChar)) {
|
|
|
|
+ if(fCheckForReplacement()) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ } else {
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-int fRead() {
|
|
+static int fReadI() {
|
|
fPrepareChar();
|
|
fPrepareChar();
|
|
lastChar = fReadChar();
|
|
lastChar = fReadChar();
|
|
return currentFile()->content[files.readIndex.index++];
|
|
return currentFile()->content[files.readIndex.index++];
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+int fRead() {
|
|
|
|
+ int i = fReadI();
|
|
|
|
+ putchar(i);
|
|
|
|
+ return i;
|
|
|
|
+}
|
|
|
|
+
|
|
int fPeek() {
|
|
int fPeek() {
|
|
fPrepareChar();
|
|
fPrepareChar();
|
|
return fReadChar();
|
|
return fReadChar();
|