]> git.sur5r.net Git - cc65/blobdiff - src/cc65/scanner.c
Fixed a bug
[cc65] / src / cc65 / scanner.c
index b6321780e21f346c3b5355b4fd99da84d3f681e4..a0ff4530497c3a5563c54fe9b6426f17f6c731e3 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2002 Ullrich von Bassewitz                                       */
-/*               Wacholderweg 14                                             */
-/*               D-70597 Stuttgart                                           */
-/* EMail:        uz@musoftware.de                                            */
+/* (C) 1998-2003 Ullrich von Bassewitz                                       */
+/*               Römerstrasse 52                                             */
+/*               D-70794 Filderstadt                                         */
+/* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
@@ -81,15 +81,16 @@ static const struct Keyword {
     unsigned char   Type;              /* Token type */
 } Keywords [] = {
     { "_Pragma",        TOK_PRAGMA,     TT_C    },
+    { "__AX__",                TOK_AX,         TT_C    },
     { "__A__",         TOK_A,          TT_C    },
-    { "__AX__",                TOK_AX,         TT_C    },
-    { "__EAX__",               TOK_EAX,        TT_C    },
-    { "__X__",                 TOK_X,          TT_C    },
-    { "__Y__",                 TOK_Y,          TT_C    },
-    { "__asm__",               TOK_ASM,        TT_C    },
-    { "__attribute__", TOK_ATTRIBUTE,  TT_C    },
-    { "__far__",       TOK_FAR,        TT_C    },
-    { "__fastcall__",          TOK_FASTCALL,   TT_C    },
+    { "__EAX__",               TOK_EAX,        TT_C    },
+    { "__X__",                 TOK_X,          TT_C    },
+    { "__Y__",                 TOK_Y,          TT_C    },
+    { "__asm__",               TOK_ASM,        TT_C    },
+    { "__attribute__", TOK_ATTRIBUTE,  TT_C    },
+    { "__far__",       TOK_FAR,        TT_C    },
+    { "__fastcall__",          TOK_FASTCALL,   TT_C    },
+    { "__near__",              TOK_NEAR,       TT_C    },
     { "asm",                   TOK_ASM,        TT_EXT  },
     { "auto",                  TOK_AUTO,       TT_C    },
     { "break",                 TOK_BREAK,      TT_C    },
@@ -111,7 +112,9 @@ static const struct Keyword {
     { "if",                    TOK_IF,         TT_C    },
     { "int",                   TOK_INT,        TT_C    },
     { "long",                  TOK_LONG,       TT_C    },
+    { "near",                  TOK_NEAR,       TT_EXT  },
     { "register",              TOK_REGISTER,   TT_C    },
+    { "restrict",              TOK_RESTRICT,   TT_C    },
     { "return",                TOK_RETURN,     TT_C    },
     { "short",                 TOK_SHORT,      TT_C    },
     { "signed",                TOK_SIGNED,     TT_C    },
@@ -237,23 +240,11 @@ static void SetTok (int tok)
 
 
 
-static int SignExtendChar (int C)
-/* Do correct sign extension of a character */
-{
-    if (SignedChars && (C & 0x80) != 0) {
-               return C | ~0xFF;
-    } else {
-               return C & 0xFF;
-    }
-}
-
-
-
 static int ParseChar (void)
 /* Parse a character. Converts \n into EOL, etc. */
 {
-    int i;
-    unsigned val;
+    int I;
+    unsigned Val;
     int C;
 
     /* Check for escape chars */
@@ -262,49 +253,71 @@ static int ParseChar (void)
        switch (CurC) {
            case 'b':
                C = '\b';
-               break;
+               break;
            case 'f':
-               C = '\f';
-               break;
+               C = '\f';
+               break;
            case 'r':
-               C = '\r';
-               break;
+               C = '\r';
+               break;
            case 'n':
-               C = '\n';
-               break;
+               C = '\n';
+               break;
            case 't':
-               C = '\t';
-               break;
+               C = '\t';
+               break;
+            case 'v':
+                C = '\v';
+                break;
            case '\"':
-               C = '\"';
-               break;
+               C = '\"';
+               break;
            case '\'':
-               C = '\'';
-               break;
+               C = '\'';
+               break;
            case '\\':
-               C = '\\';
-               break;
+               C = '\\';
+               break;
            case 'x':
            case 'X':
-               /* Hex character constant */
-               NextChar ();
-               val = HexVal (CurC) << 4;
-               NextChar ();
-                       C = val | HexVal (CurC);        /* Do not translate */
-               break;
+               /* Hex character constant */
+               NextChar ();
+               Val = HexVal (CurC) << 4;
+               NextChar ();
+                       C = Val | HexVal (CurC);        /* Do not translate */
+               break;
            case '0':
            case '1':
+           case '2':
+           case '3':
+           case '4':
+           case '5':
+           case '6':
+           case '7':
                /* Octal constant */
-               i = 0;
-               C = CurC - '0';
-                       while (NextC >= '0' && NextC <= '7' && i++ < 4) {
+               I = 0;
+                       Val = CurC - '0';
+                       while (NextC >= '0' && NextC <= '7' && ++I <= 3) {
                    NextChar ();
-                   C = (C << 3) | (CurC - '0');
+                   Val = (Val << 3) | (CurC - '0');
                }
+                C = (int) Val;
+                if (Val >= 256) {
+                    Error ("Character constant out of range");
+                    C = ' ';
+                }
                break;
            default:
                Error ("Illegal character constant");
                C = ' ';
+                /* Try to do error recovery, otherwise the compiler will spit
+                 * out thousands of errors in this place and abort.
+                 */
+                if (CurC != '\'' && CurC != '\0') {
+                    while (NextC != '\'' && NextC != '\"' && NextC != '\0') {
+                        NextChar ();
+                    }
+                }
                break;
        }
     } else {
@@ -403,6 +416,14 @@ void NextToken (void)
     }
     CurTok = NextTok;
 
+    /* When reading the first time from the file, the line info in NextTok,
+     * which was copied to CurTok is invalid. Since the information from
+     * the token is used for error messages, we must make it valid.
+     */
+    if (CurTok.LI == 0) {
+       CurTok.LI = UseLineInfo (GetCurLineInfo ());
+    }
+
     /* Remember the starting position of the next token */
     NextTok.LI = UseLineInfo (GetCurLineInfo ());
 
@@ -419,11 +440,12 @@ void NextToken (void)
        /* A number */
        int HaveSuffix;         /* True if we have a type suffix */
        unsigned types;         /* Possible types */
-       unsigned base;
-       unsigned long k;        /* Value */
+       unsigned Base;
+        unsigned DigitVal;
+       unsigned long k;        /* Value */
 
        k     = 0;
-       base  = 10;
+       Base  = 10;
        types = IT_INT | IT_LONG | IT_ULONG;
 
                if (CurC == '0') {
@@ -432,23 +454,30 @@ void NextToken (void)
            /* gobble 0 and examin next char */
            NextChar ();
            if (toupper (CurC) == 'X') {
-               base = 16;
-               NextTok.Type = type_uint;
+               Base = 16;
+               NextTok.Type = type_uint;
                        NextChar ();    /* gobble "x" */
            } else {
-               base = 8;
-           }
-       }
-       while (1) {
-           if (IsDigit (CurC)) {
-               k = k * base + (CurC - '0');
-           } else if (base == 16 && IsXDigit (CurC)) {
-               k = (k << 4) + HexVal (CurC);
-           } else {
-               break;          /* not digit */
+               Base = 8;
            }
-                   NextChar ();        /* gobble char */
        }
+        while (IsXDigit (CurC) && (DigitVal = HexVal (CurC)) < Base) {
+            k = k * Base + DigitVal;
+            NextChar ();
+        }
+        /* Check for errorneous digits */
+        if (Base == 8 && IsDigit (CurC)) {
+            Error ("Numeric constant contains digits beyond the radix");
+            /* Do error recovery */
+            do {
+                NextChar ();
+            } while (IsDigit (CurC));
+        } else if (Base != 16 && IsXDigit (CurC)) {
+            Error ("Nondigits in number and not hexadecimal");
+            do {
+                NextChar ();
+            } while (IsXDigit (CurC));
+        }
 
        /* Check for a suffix */
        HaveSuffix = 1;