]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - lexer.c
for the lexer 3 dots now become TOKEN_DOTS
[xonotic/gmqcc.git] / lexer.c
diff --git a/lexer.c b/lexer.c
index d8fcf2e28f0a0257bfa8418ced003b206de70b4d..2798737d200a7b130401ad43ff81804701a28f46 100644 (file)
--- a/lexer.c
+++ b/lexer.c
@@ -9,6 +9,8 @@
 MEM_VEC_FUNCTIONS(token, char, value)
 MEM_VEC_FUNCTIONS(lex_file, frame_macro, frames)
 
+VECTOR_MAKE(char*, lex_filenames);
+
 void lexerror(lex_file *lex, const char *fmt, ...)
 {
     va_list ap;
@@ -144,10 +146,21 @@ lex_file* lex_open(const char *file)
     lex->line = 1; /* we start counting at 1 */
 
     lex->peekpos = 0;
+    lex->eof = false;
+
+    lex_filenames_add(lex->name);
 
     return lex;
 }
 
+void lex_cleanup(void)
+{
+    size_t i;
+    for (i = 0; i < lex_filenames_elements; ++i)
+        mem_d(lex_filenames_data[i]);
+    mem_d(lex_filenames_data);
+}
+
 void lex_close(lex_file *lex)
 {
     size_t i;
@@ -155,11 +168,14 @@ void lex_close(lex_file *lex)
         mem_d(lex->frames[i].name);
     MEM_VECTOR_CLEAR(lex, frames);
 
+    if (lex->modelname)
+        mem_d(lex->modelname);
+
     if (lex->file)
         fclose(lex->file);
     if (lex->tok)
         token_delete(lex->tok);
-    mem_d(lex->name);
+    /* mem_d(lex->name); collected in lex_filenames */
     mem_d(lex);
 }
 
@@ -542,8 +558,13 @@ int lex_do(lex_file *lex)
     lex->tok->ctx.line = lex->sline;
     lex->tok->ctx.file = lex->name;
 
-    if (ch == EOF)
+    if (lex->eof)
+        return (lex->tok->ttype = TOKEN_FATAL);
+
+    if (ch == EOF) {
+        lex->eof = true;
         return (lex->tok->ttype = TOKEN_EOF);
+    }
 
     /* modelgen / spiritgen commands */
     if (ch == '$') {
@@ -753,7 +774,6 @@ int lex_do(lex_file *lex)
             case '^':
             case '~':
             case ',':
-            case '.':
             case '!':
                 if (!lex_tokench(lex, ch) ||
                     !lex_endtoken(lex))
@@ -764,6 +784,37 @@ int lex_do(lex_file *lex)
             default:
                 break;
         }
+
+        if (ch == '.')
+        {
+            if (!lex_tokench(lex, ch))
+                return (lex->tok->ttype = TOKEN_FATAL);
+            /* peak ahead once */
+            nextch = lex_getch(lex);
+            if (nextch != '.') {
+                lex_ungetch(lex, nextch);
+                if (!lex_endtoken(lex))
+                    return (lex->tok->ttype = TOKEN_FATAL);
+                return (lex->tok->ttype = ch);
+            }
+            /* peak ahead again */
+            nextch = lex_getch(lex);
+            if (nextch != '.') {
+                lex_ungetch(lex, nextch);
+                lex_ungetch(lex, nextch);
+                if (!lex_endtoken(lex))
+                    return (lex->tok->ttype = TOKEN_FATAL);
+                return (lex->tok->ttype = ch);
+            }
+            /* fill the token to be "..." */
+            if (!lex_tokench(lex, ch) ||
+                !lex_tokench(lex, ch) ||
+                !lex_endtoken(lex))
+            {
+                return (lex->tok->ttype = TOKEN_FATAL);
+            }
+            return (lex->tok->ttype = TOKEN_DOTS);
+        }
     }
 
     if (ch == ',' || ch == '.') {