]> de.git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - lexer.c
Replaced it all...
[xonotic/gmqcc.git] / lexer.c
diff --git a/lexer.c b/lexer.c
index 08a63d624bb7cfc258c9e654aadae2cefb95ed05..094c6efc2841e4c0cd4640e55ee6218a50986b1d 100644 (file)
--- a/lexer.c
+++ b/lexer.c
@@ -9,14 +9,14 @@
 MEM_VEC_FUNCTIONS(token, char, value)
 MEM_VEC_FUNCTIONS(lex_file, frame_macro, frames)
 
-VECTOR_MAKE(char*, lex_filenames);
+char* *lex_filenames;
 
 void lexerror(lex_file *lex, const char *fmt, ...)
 {
        va_list ap;
 
        va_start(ap, fmt);
-    vprintmsg(LVL_ERROR, lex->name, lex->sline, "parse error", fmt, ap);
+    con_vprintmsg(LVL_ERROR, lex->name, lex->sline, "parse error", fmt, ap);
        va_end(ap);
 }
 
@@ -32,7 +32,7 @@ bool lexwarn(lex_file *lex, int warntype, const char *fmt, ...)
            lvl = LVL_ERROR;
 
        va_start(ap, fmt);
-    vprintmsg(lvl, lex->name, lex->sline, "warning", fmt, ap);
+    con_vprintmsg(lvl, lex->name, lex->sline, "warning", fmt, ap);
        va_end(ap);
 
        return opts_werror;
@@ -157,7 +157,34 @@ lex_file* lex_open(const char *file)
     lex->peekpos = 0;
     lex->eof = false;
 
-    lex_filenames_add(lex->name);
+    vec_push(lex_filenames, lex->name);
+    return lex;
+}
+
+lex_file* lex_open_string(const char *str, size_t len, const char *name)
+{
+    lex_file *lex;
+
+    lex = (lex_file*)mem_a(sizeof(*lex));
+    if (!lex) {
+        lexerror(NULL, "out of memory\n");
+        return NULL;
+    }
+
+    memset(lex, 0, sizeof(*lex));
+
+    lex->file = NULL;
+    lex->open_string        = str;
+    lex->open_string_length = len;
+    lex->open_string_pos    = 0;
+
+    lex->name = util_strdup(name ? name : "<string-source>");
+    lex->line = 1; /* we start counting at 1 */
+
+    lex->peekpos = 0;
+    lex->eof = false;
+
+    vec_push(lex_filenames, lex->name);
 
     return lex;
 }
@@ -165,9 +192,9 @@ lex_file* lex_open(const char *file)
 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);
+    for (i = 0; i < vec_size(lex_filenames); ++i)
+        mem_d(lex_filenames[i]);
+    vec_free(lex_filenames);
 }
 
 void lex_close(lex_file *lex)
@@ -192,6 +219,18 @@ void lex_close(lex_file *lex)
     mem_d(lex);
 }
 
+static int lex_fgetc(lex_file *lex)
+{
+    if (lex->file)
+        return fgetc(lex->file);
+    if (lex->open_string) {
+        if (lex->open_string_pos >= lex->open_string_length)
+            return EOF;
+        return lex->open_string[lex->open_string_pos++];
+    }
+    return EOF;
+}
+
 /* Get or put-back data
  * The following to functions do NOT understand what kind of data they
  * are working on.
@@ -201,13 +240,13 @@ static void lex_ungetch(lex_file *lex, int ch);
 static int lex_try_trigraph(lex_file *lex, int old)
 {
     int c2, c3;
-    c2 = fgetc(lex->file);
+    c2 = lex_fgetc(lex);
     if (c2 != '?') {
         lex_ungetch(lex, c2);
         return old;
     }
 
-    c3 = fgetc(lex->file);
+    c3 = lex_fgetc(lex);
     switch (c3) {
         case '=': return '#';
         case '/': return '\\';
@@ -228,7 +267,7 @@ static int lex_try_trigraph(lex_file *lex, int old)
 static int lex_try_digraph(lex_file *lex, int ch)
 {
     int c2;
-    c2 = fgetc(lex->file);
+    c2 = lex_fgetc(lex);
     if      (ch == '<' && c2 == ':')
         return '[';
     else if (ch == ':' && c2 == '>')
@@ -254,7 +293,7 @@ static int lex_getch(lex_file *lex)
         return lex->peek[lex->peekpos];
     }
 
-    ch = fgetc(lex->file);
+    ch = lex_fgetc(lex);
     if (ch == '\n')
         lex->line++;
     else if (ch == '?')
@@ -381,10 +420,10 @@ static int lex_skipwhite(lex_file *lex)
             if (ch == '/')
             {
                 /* one line comment */
-                haswhite = true;
                 ch = lex_getch(lex);
 
                 if (lex->flags.preprocessing) {
+                    haswhite = true;
                     if (!lex_tokench(lex, '/') ||
                         !lex_tokench(lex, '/'))
                     {
@@ -408,8 +447,8 @@ static int lex_skipwhite(lex_file *lex)
             if (ch == '*')
             {
                 /* multiline comment */
-                haswhite = true;
                 if (lex->flags.preprocessing) {
+                    haswhite = true;
                     if (!lex_tokench(lex, '/') ||
                         !lex_tokench(lex, '*'))
                     {
@@ -550,7 +589,7 @@ static int GMQCC_WARN lex_finish_string(lex_file *lex, int quote)
         if (ch == quote)
             return TOKEN_STRINGCONST;
 
-        if (ch == '\\') {
+        if (!lex->flags.preprocessing && ch == '\\') {
             ch = lex_getch(lex);
             if (ch == EOF) {
                 lexerror(lex, "unexpected end of file");
@@ -852,6 +891,7 @@ int lex_do(lex_file *lex)
     /* single-character tokens */
     switch (ch)
     {
+        case '[':
         case '(':
             if (!lex_tokench(lex, ch) ||
                 !lex_endtoken(lex))
@@ -866,7 +906,6 @@ int lex_do(lex_file *lex)
         case ';':
         case '{':
         case '}':
-        case '[':
         case ']':
 
         case '#':
@@ -1043,6 +1082,7 @@ int lex_do(lex_file *lex)
                  !strcmp(v, "else")   ||
                  !strcmp(v, "local")  ||
                  !strcmp(v, "return") ||
+                 !strcmp(v, "not")    ||
                  !strcmp(v, "const"))
         {
             lex->tok.ttype = TOKEN_KEYWORD;
@@ -1054,7 +1094,8 @@ int lex_do(lex_file *lex)
                 !strcmp(v, "struct") ||
                 !strcmp(v, "union")  ||
                 !strcmp(v, "break")  ||
-                !strcmp(v, "continue"))
+                !strcmp(v, "continue") ||
+                !strcmp(v, "var"))
             {
                 lex->tok.ttype = TOKEN_KEYWORD;
             }
@@ -1066,8 +1107,12 @@ int lex_do(lex_file *lex)
     if (ch == '"')
     {
         lex->flags.nodigraphs = true;
+        if (lex->flags.preprocessing && !lex_tokench(lex, ch))
+            return TOKEN_FATAL;
         lex->tok.ttype = lex_finish_string(lex, '"');
-        while (lex->tok.ttype == TOKEN_STRINGCONST)
+        if (lex->flags.preprocessing && !lex_tokench(lex, ch))
+            return TOKEN_FATAL;
+        while (!lex->flags.preprocessing && lex->tok.ttype == TOKEN_STRINGCONST)
         {
             /* Allow c style "string" "continuation" */
             ch = lex_skipwhite(lex);
@@ -1091,23 +1136,28 @@ int lex_do(lex_file *lex)
          * Likewise actual unescaping has to be done by the parser.
          * The difference is we don't allow 'char' 'continuation'.
          */
-         lex->tok.ttype = lex_finish_string(lex, '\'');
-         if (!lex_endtoken(lex))
-              return (lex->tok.ttype = TOKEN_FATAL);
+        if (lex->flags.preprocessing && !lex_tokench(lex, ch))
+            return TOKEN_FATAL;
+        lex->tok.ttype = lex_finish_string(lex, '\'');
+        if (lex->flags.preprocessing && !lex_tokench(lex, ch))
+            return TOKEN_FATAL;
+        if (!lex_endtoken(lex))
+            return (lex->tok.ttype = TOKEN_FATAL);
 
          /* It's a vector if we can successfully scan 3 floats */
 #ifdef WIN32
-         if (sscanf_s(lex->tok.value, " %f %f %f ",
-                    &lex->tok.constval.v.x, &lex->tok.constval.v.y, &lex->tok.constval.v.z) == 3)
+        if (sscanf_s(lex->tok.value, " %f %f %f ",
+                   &lex->tok.constval.v.x, &lex->tok.constval.v.y, &lex->tok.constval.v.z) == 3)
 #else
-         if (sscanf(lex->tok.value, " %f %f %f ",
-                    &lex->tok.constval.v.x, &lex->tok.constval.v.y, &lex->tok.constval.v.z) == 3)
+        if (sscanf(lex->tok.value, " %f %f %f ",
+                   &lex->tok.constval.v.x, &lex->tok.constval.v.y, &lex->tok.constval.v.z) == 3)
 #endif
-         {
-              lex->tok.ttype = TOKEN_VECTORCONST;
-         }
 
-         return lex->tok.ttype;
+        {
+             lex->tok.ttype = TOKEN_VECTORCONST;
+        }
+
+        return lex->tok.ttype;
     }
 
     if (isdigit(ch))