]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - lexer.c
Allow float constants which start with a dot
[xonotic/gmqcc.git] / lexer.c
diff --git a/lexer.c b/lexer.c
index 49b8ada16eaadfdb8f123eb1be69f26548c9f776..6fbe41def69acdc486d96e031091deb7d07cff2f 100644 (file)
--- a/lexer.c
+++ b/lexer.c
@@ -47,7 +47,8 @@ static const char *keywords_fg[] = {
     "switch", "case", "default",
     "struct", "union",
     "break", "continue",
-    "typedef"
+    "typedef",
+    "goto"
 };
 static size_t num_keywords_fg = sizeof(keywords_fg) / sizeof(keywords_fg[0]);
 
@@ -318,6 +319,11 @@ static int lex_try_digraph(lex_file *lex, int ch)
 {
     int c2;
     c2 = lex_fgetc(lex);
+    /* we just used fgetc() so count lines
+     * need to offset a \n the ungetch would recognize
+     */
+    if (!lex->push_line && c2 == '\n')
+        lex->line++;
     if      (ch == '<' && c2 == ':')
         return '[';
     else if (ch == ':' && c2 == '>')
@@ -445,7 +451,8 @@ static bool lex_try_pragma(lex_file *lex)
     if (!strcmp(command, "push")) {
         if (!strcmp(param, "line")) {
             lex->push_line++;
-            --line;
+            if (lex->push_line == 1)
+                --line;
         }
         else
             goto unroll;
@@ -454,7 +461,8 @@ static bool lex_try_pragma(lex_file *lex)
         if (!strcmp(param, "line")) {
             if (lex->push_line)
                 lex->push_line--;
-            --line;
+            if (lex->push_line == 0)
+                --line;
         }
         else
             goto unroll;
@@ -768,6 +776,7 @@ static int GMQCC_WARN lex_finish_string(lex_file *lex, int quote)
             case 't':  ch = '\t'; break;
             case 'f':  ch = '\f'; break;
             case 'v':  ch = '\v'; break;
+            case '\n':  ch = '\n'; break;
             default:
                 lexwarn(lex, WARN_UNKNOWN_CONTROL_SEQUENCE, "unrecognized control sequence: \\%c", ch);
                 /* so we just add the character plus backslash no matter what it actually is */
@@ -791,7 +800,10 @@ static int GMQCC_WARN lex_finish_digit(lex_file *lex, int lastch)
     int  ch = lastch;
 
     /* parse a number... */
-    lex->tok.ttype = TOKEN_INTCONST;
+    if (ch == '.')
+        lex->tok.ttype = TOKEN_FLOATCONST;
+    else
+        lex->tok.ttype = TOKEN_INTCONST;
 
     lex_tokench(lex, ch);
 
@@ -824,7 +836,7 @@ static int GMQCC_WARN lex_finish_digit(lex_file *lex, int lastch)
         }
     }
     /* NOT else, '.' can come from above as well */
-    if (ch == '.' && !ishex)
+    if (lex->tok.ttype != TOKEN_FLOATCONST && ch == '.' && !ishex)
     {
         /* Allow floating comma in non-hex mode */
         lex->tok.ttype = TOKEN_FLOATCONST;
@@ -1069,6 +1081,18 @@ int lex_do(lex_file *lex)
             break;
     }
 
+    if (ch == '.') {
+        nextch = lex_getch(lex);
+        /* digits starting with a dot */
+        if (isdigit(nextch)) {
+            lex_ungetch(lex, nextch);
+            lex->tok.ttype = lex_finish_digit(lex, ch);
+            lex_endtoken(lex);
+            return lex->tok.ttype;
+        }
+        lex_ungetch(lex, nextch);
+    }
+
     if (lex->flags.noops)
     {
         /* Detect characters early which are normally
@@ -1076,8 +1100,10 @@ int lex_do(lex_file *lex)
          */
         switch (ch)
         {
+            /*
             case '+':
             case '-':
+            */
             case '*':
             case '/':
             case '<':
@@ -1266,6 +1292,7 @@ int lex_do(lex_file *lex)
             lex_tokench(lex, ch);
         lex_endtoken(lex);
 
+        lex->tok.ttype = TOKEN_CHARCONST;
          /* It's a vector if we can successfully scan 3 floats */
 #ifdef WIN32
         if (sscanf_s(lex->tok.value, " %f %f %f ",
@@ -1278,6 +1305,14 @@ int lex_do(lex_file *lex)
         {
              lex->tok.ttype = TOKEN_VECTORCONST;
         }
+        else
+        {
+            if (!lex->flags.preprocessing && strlen(lex->tok.value) > 1) {
+                if (lexwarn(lex, WARN_MULTIBYTE_CHARACTER, "multibyte character: `%s`", lex->tok.value))
+                    return (lex->tok.ttype = TOKEN_ERROR);
+            }
+            lex->tok.constval.i = lex->tok.value[0];
+        }
 
         return lex->tok.ttype;
     }