]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - lexer.c
string-literals now do not treat digraphs as digraphs
[xonotic/gmqcc.git] / lexer.c
diff --git a/lexer.c b/lexer.c
index 75452a16f441e2172897a4b370b60891a03d93ca..634f90ca348da3584998bd94f3e83425820f61c9 100644 (file)
--- a/lexer.c
+++ b/lexer.c
@@ -197,6 +197,52 @@ void lex_close(lex_file *lex)
  * are working on.
  * The are merely wrapping get/put in order to count line numbers.
  */
+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);
+    if (c2 != '?') {
+        lex_ungetch(lex, c2);
+        return old;
+    }
+
+    c3 = fgetc(lex->file);
+    switch (c3) {
+        case '=': return '#';
+        case '/': return '\\';
+        case '\'': return '^';
+        case '(': return '[';
+        case ')': return ']';
+        case '!': return '|';
+        case '<': return '{';
+        case '>': return '}';
+        case '-': return '~';
+        default:
+            lex_ungetch(lex, c3);
+            lex_ungetch(lex, c2);
+            return old;
+    }
+}
+
+static int lex_try_digraph(lex_file *lex, int ch)
+{
+    int c2;
+    c2 = fgetc(lex->file);
+    if      (ch == '<' && c2 == ':')
+        return '[';
+    else if (ch == ':' && c2 == '>')
+        return ']';
+    else if (ch == '<' && c2 == '%')
+        return '{';
+    else if (ch == '%' && c2 == '>')
+        return '}';
+    else if (ch == '%' && c2 == ':')
+        return '#';
+    lex_ungetch(lex, c2);
+    return ch;
+}
+
 static int lex_getch(lex_file *lex)
 {
     int ch;
@@ -211,6 +257,10 @@ static int lex_getch(lex_file *lex)
     ch = fgetc(lex->file);
     if (ch == '\n')
         lex->line++;
+    else if (ch == '?')
+        return lex_try_trigraph(lex, ch);
+    else if (!lex->flags.nodigraphs && (ch == '<' || ch == ':' || ch == '%'))
+        return lex_try_digraph(lex, ch);
     return ch;
 }
 
@@ -698,6 +748,7 @@ int lex_do(lex_file *lex)
             }
             lex->modelname = lex->tok.value;
             lex->tok.value = NULL;
+            lex->tok.value_alloc = lex->tok.value_count = 0;
             for (frame = 0; frame < lex->frames_count; ++frame) {
                 if (!strcmp(v, lex->frames[frame].name)) {
                     lex->framevalue = lex->frames[frame].value;
@@ -947,6 +998,7 @@ int lex_do(lex_file *lex)
 
     if (ch == '"')
     {
+        lex->flags.nodigraphs = true;
         lex->tok.ttype = lex_finish_string(lex, '"');
         while (lex->tok.ttype == TOKEN_STRINGCONST)
         {
@@ -959,6 +1011,7 @@ int lex_do(lex_file *lex)
 
             lex->tok.ttype = lex_finish_string(lex, '"');
         }
+        lex->flags.nodigraphs = false;
         if (!lex_endtoken(lex))
             return (lex->tok.ttype = TOKEN_FATAL);
         return lex->tok.ttype;