X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fscanner.c;h=cc073e37313157786eea0c0e761245ce868ee501;hb=dbb9a31fd908fe85fd9d4ccf1397564a3d027953;hp=183898ff1a46fdb055245d638cfc912f2c8d6375;hpb=92dfde6c4e748946c5e13323bb48bf2abd72c2b3;p=cc65 diff --git a/src/cc65/scanner.c b/src/cc65/scanner.c index 183898ff1..cc073e373 100644 --- a/src/cc65/scanner.c +++ b/src/cc65/scanner.c @@ -6,8 +6,8 @@ /* */ /* */ /* */ -/* (C) 1998-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ +/* (C) 1998-2008 Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ /* */ @@ -38,6 +38,7 @@ #include #include #include +#include /* common */ #include "chartype.h" @@ -53,14 +54,14 @@ #include "input.h" #include "litpool.h" #include "preproc.h" -#include "symtab.h" -#include "util.h" #include "scanner.h" +#include "standard.h" +#include "symtab.h" /*****************************************************************************/ -/* data */ +/* data */ /*****************************************************************************/ @@ -71,63 +72,68 @@ Token NextTok; /* The next token */ /* Token types */ -#define TT_C 0 /* ANSI C token */ -#define TT_EXT 1 /* cc65 extension */ +enum { + TT_C89 = 0x01 << STD_C89, /* Token valid in C89 */ + TT_C99 = 0x01 << STD_C99, /* Token valid in C99 */ + TT_CC65 = 0x01 << STD_CC65 /* Token valid in cc65 */ +}; /* Token table */ static const struct Keyword { char* Key; /* Keyword name */ unsigned char Tok; /* The token */ - unsigned char Type; /* Token type */ + unsigned char Std; /* Token supported in which standards? */ } Keywords [] = { - { "_Pragma", TOK_PRAGMA, TT_C }, - { "__AX__", TOK_AX, TT_C }, - { "__A__", TOK_A, 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 }, - { "case", TOK_CASE, TT_C }, - { "char", TOK_CHAR, TT_C }, - { "const", TOK_CONST, TT_C }, - { "continue", TOK_CONTINUE, TT_C }, - { "default", TOK_DEFAULT, TT_C }, - { "do", TOK_DO, TT_C }, - { "double", TOK_DOUBLE, TT_C }, - { "else", TOK_ELSE, TT_C }, - { "enum", TOK_ENUM, TT_C }, - { "extern", TOK_EXTERN, TT_C }, - { "far", TOK_FAR, TT_EXT }, - { "fastcall", TOK_FASTCALL, TT_EXT }, - { "float", TOK_FLOAT, TT_C }, - { "for", TOK_FOR, TT_C }, - { "goto", TOK_GOTO, TT_C }, - { "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 }, - { "sizeof", TOK_SIZEOF, TT_C }, - { "static", TOK_STATIC, TT_C }, - { "struct", TOK_STRUCT, TT_C }, - { "switch", TOK_SWITCH, TT_C }, - { "typedef", TOK_TYPEDEF, TT_C }, - { "union", TOK_UNION, TT_C }, - { "unsigned", TOK_UNSIGNED, TT_C }, - { "void", TOK_VOID, TT_C }, - { "volatile", TOK_VOLATILE, TT_C }, - { "while", TOK_WHILE, TT_C }, + { "_Pragma", TOK_PRAGMA, TT_C89 | TT_C99 | TT_CC65 }, /* !! */ + { "__AX__", TOK_AX, TT_C89 | TT_C99 | TT_CC65 }, + { "__A__", TOK_A, TT_C89 | TT_C99 | TT_CC65 }, + { "__EAX__", TOK_EAX, TT_C89 | TT_C99 | TT_CC65 }, + { "__X__", TOK_X, TT_C89 | TT_C99 | TT_CC65 }, + { "__Y__", TOK_Y, TT_C89 | TT_C99 | TT_CC65 }, + { "__asm__", TOK_ASM, TT_C89 | TT_C99 | TT_CC65 }, + { "__attribute__", TOK_ATTRIBUTE, TT_C89 | TT_C99 | TT_CC65 }, + { "__far__", TOK_FAR, TT_C89 | TT_C99 | TT_CC65 }, + { "__fastcall__", TOK_FASTCALL, TT_C89 | TT_C99 | TT_CC65 }, + { "__inline__", TOK_INLINE, TT_C89 | TT_C99 | TT_CC65 }, + { "__near__", TOK_NEAR, TT_C89 | TT_C99 | TT_CC65 }, + { "asm", TOK_ASM, TT_CC65 }, + { "auto", TOK_AUTO, TT_C89 | TT_C99 | TT_CC65 }, + { "break", TOK_BREAK, TT_C89 | TT_C99 | TT_CC65 }, + { "case", TOK_CASE, TT_C89 | TT_C99 | TT_CC65 }, + { "char", TOK_CHAR, TT_C89 | TT_C99 | TT_CC65 }, + { "const", TOK_CONST, TT_C89 | TT_C99 | TT_CC65 }, + { "continue", TOK_CONTINUE, TT_C89 | TT_C99 | TT_CC65 }, + { "default", TOK_DEFAULT, TT_C89 | TT_C99 | TT_CC65 }, + { "do", TOK_DO, TT_C89 | TT_C99 | TT_CC65 }, + { "double", TOK_DOUBLE, TT_C89 | TT_C99 | TT_CC65 }, + { "else", TOK_ELSE, TT_C89 | TT_C99 | TT_CC65 }, + { "enum", TOK_ENUM, TT_C89 | TT_C99 | TT_CC65 }, + { "extern", TOK_EXTERN, TT_C89 | TT_C99 | TT_CC65 }, + { "far", TOK_FAR, TT_CC65 }, + { "fastcall", TOK_FASTCALL, TT_CC65 }, + { "float", TOK_FLOAT, TT_C89 | TT_C99 | TT_CC65 }, + { "for", TOK_FOR, TT_C89 | TT_C99 | TT_CC65 }, + { "goto", TOK_GOTO, TT_C89 | TT_C99 | TT_CC65 }, + { "if", TOK_IF, TT_C89 | TT_C99 | TT_CC65 }, + { "inline", TOK_INLINE, TT_C99 | TT_CC65 }, + { "int", TOK_INT, TT_C89 | TT_C99 | TT_CC65 }, + { "long", TOK_LONG, TT_C89 | TT_C99 | TT_CC65 }, + { "near", TOK_NEAR, TT_CC65 }, + { "register", TOK_REGISTER, TT_C89 | TT_C99 | TT_CC65 }, + { "restrict", TOK_RESTRICT, TT_C99 | TT_CC65 }, + { "return", TOK_RETURN, TT_C89 | TT_C99 | TT_CC65 }, + { "short", TOK_SHORT, TT_C89 | TT_C99 | TT_CC65 }, + { "signed", TOK_SIGNED, TT_C89 | TT_C99 | TT_CC65 }, + { "sizeof", TOK_SIZEOF, TT_C89 | TT_C99 | TT_CC65 }, + { "static", TOK_STATIC, TT_C89 | TT_C99 | TT_CC65 }, + { "struct", TOK_STRUCT, TT_C89 | TT_C99 | TT_CC65 }, + { "switch", TOK_SWITCH, TT_C89 | TT_C99 | TT_CC65 }, + { "typedef", TOK_TYPEDEF, TT_C89 | TT_C99 | TT_CC65 }, + { "union", TOK_UNION, TT_C89 | TT_C99 | TT_CC65 }, + { "unsigned", TOK_UNSIGNED, TT_C89 | TT_C99 | TT_CC65 }, + { "void", TOK_VOID, TT_C89 | TT_C99 | TT_CC65 }, + { "volatile", TOK_VOLATILE, TT_C89 | TT_C99 | TT_CC65 }, + { "while", TOK_WHILE, TT_C89 | TT_C99 | TT_CC65 }, }; #define KEY_COUNT (sizeof (Keywords) / sizeof (Keywords [0])) @@ -142,7 +148,7 @@ static const struct Keyword { /*****************************************************************************/ -/* code */ +/* code */ /*****************************************************************************/ @@ -155,14 +161,14 @@ static int CmpKey (const void* Key, const void* Elem) -static int FindKey (const char* Key) +static token_t FindKey (const char* Key) /* Find a keyword and return the token. Return IDENT if the token is not a * keyword. */ { struct Keyword* K; K = bsearch (Key, Keywords, KEY_COUNT, sizeof (Keywords [0]), CmpKey); - if (K && (K->Type != TT_EXT || ANSI == 0)) { + if (K && (K->Std & (0x01 << IS_Get (&Standard))) != 0) { return K->Tok; } else { return TOK_IDENT; @@ -177,7 +183,7 @@ static int SkipWhite (void) */ { while (1) { - while (CurC == 0) { + while (CurC == '\0') { if (NextLine () == 0) { return 0; } @@ -193,27 +199,39 @@ static int SkipWhite (void) -void SymName (char* s) -/* Get symbol from input stream */ +int TokIsFuncSpec (const Token* T) +/* Return true if the token is a function specifier */ { - unsigned k = 0; + return (T->Tok == TOK_INLINE) || (T->Tok == TOK_FASTCALL) || + (T->Tok == TOK_NEAR) || (T->Tok == TOK_FAR); +} + + + +void SymName (char* S) +/* Read a symbol from the input stream. The first character must have been + * checked before calling this function. The buffer is expected to be at + * least of size MAX_IDENTLEN+1. + */ +{ + unsigned Len = 0; do { - if (k != MAX_IDENTLEN) { - ++k; - *s++ = CurC; - } + if (Len < MAX_IDENTLEN) { + ++Len; + *S++ = CurC; + } NextChar (); } while (IsIdent (CurC) || IsDigit (CurC)); - *s = '\0'; + *S = '\0'; } -int IsSym (char *s) -/* Get symbol from input stream or return 0 if not a symbol. */ +int IsSym (char* S) +/* If a symbol follows, read it and return 1, otherwise return 0 */ { if (IsIdent (CurC)) { - SymName (s); + SymName (S); return 1; } else { return 0; @@ -241,63 +259,104 @@ static void SetTok (int tok) static int ParseChar (void) -/* Parse a character. Converts \n into EOL, etc. */ +/* Parse a character. Converts escape chars into character codes. */ { - int i; - unsigned val; int C; + int HadError; /* Check for escape chars */ if (CurC == '\\') { NextChar (); switch (CurC) { + case '?': + C = '\?'; + break; + case 'a': + C = '\a'; + break; 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 */ + if (!IsXDigit (NextC)) { + Error ("\\x used with no following hex digits"); + C = ' '; + } else { + HadError = 0; + C = 0; + while (IsXDigit (NextC)) { + if ((C << 4) >= 256) { + if (!HadError) { + Error ("Hex character constant out of range"); + HadError = 1; + } + } else { + C = (C << 4) | HexVal (NextC); + } + NextChar (); + } + } + break; case '0': case '1': case '2': case '3': - /* Octal constant */ - i = 0; - C = CurC - '0'; - while (NextC >= '0' && NextC <= '7' && i++ < 4) { - NextChar (); - C = (C << 3) | (CurC - '0'); - } - break; + case '4': + case '5': + case '6': + case '7': + /* Octal constant */ + HadError = 0; + C = HexVal (CurC); + while (IsODigit (NextC)) { + if ((C << 3) >= 256) { + if (!HadError) { + Error ("Octal character constant out of range"); + HadError = 1; + } + } else { + C = (C << 3) | HexVal (NextC); + } + NextChar (); + } + break; default: - Error ("Illegal character constant"); - C = ' '; + 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 { @@ -365,7 +424,7 @@ static void StringConst (void) } /* Skip closing quote char if there was one */ - NextChar (); + NextChar (); /* Skip white space, read new input */ SkipWhite (); @@ -378,6 +437,254 @@ static void StringConst (void) +static void NumericConst (void) +/* Parse a numeric constant */ +{ + unsigned Base; /* Temporary number base */ + unsigned Prefix; /* Base according to prefix */ + StrBuf S = STATIC_STRBUF_INITIALIZER; + int IsFloat; + char C; + unsigned DigitVal; + unsigned long IVal; /* Value */ + + /* Check for a leading hex or octal prefix and determine the possible + * integer types. + */ + if (CurC == '0') { + /* Gobble 0 and examine next char */ + NextChar (); + if (toupper (CurC) == 'X') { + Base = Prefix = 16; + NextChar (); /* gobble "x" */ + } else { + Base = 10; /* Assume 10 for now - see below */ + Prefix = 8; /* Actual prefix says octal */ + } + } else { + Base = Prefix = 10; + } + + /* Because floating point numbers don't have octal prefixes (a number + * with a leading zero is decimal), we first have to read the number + * before converting it, so we can determine if it's a float or an + * integer. + */ + while (IsXDigit (CurC) && HexVal (CurC) < Base) { + SB_AppendChar (&S, CurC); + NextChar (); + } + SB_Terminate (&S); + + /* The following character tells us if we have an integer or floating + * point constant. Note: Hexadecimal floating point constants aren't + * supported in C89. + */ + IsFloat = (CurC == '.' || + (Base == 10 && toupper (CurC) == 'E') || + (Base == 16 && toupper (CurC) == 'P' && IS_Get (&Standard) >= STD_C99)); + + /* If we don't have a floating point type, an octal prefix results in an + * octal base. + */ + if (!IsFloat && Prefix == 8) { + Base = 8; + } + + /* Since we do now know the correct base, convert the remembered input + * into a number. + */ + SB_Reset (&S); + IVal = 0; + while ((C = SB_Get (&S)) != '\0') { + DigitVal = HexVal (C); + if (DigitVal >= Base) { + Error ("Numeric constant contains digits beyond the radix"); + } + IVal = (IVal * Base) + DigitVal; + } + + /* We don't need the string buffer any longer */ + SB_Done (&S); + + /* Distinguish between integer and floating point constants */ + if (!IsFloat) { + + unsigned Types; + int HaveSuffix; + + /* Check for a suffix and determine the possible types */ + HaveSuffix = 1; + if (toupper (CurC) == 'U') { + /* Unsigned type */ + NextChar (); + if (toupper (CurC) != 'L') { + Types = IT_UINT | IT_ULONG; + } else { + NextChar (); + Types = IT_ULONG; + } + } else if (toupper (CurC) == 'L') { + /* Long type */ + NextChar (); + if (toupper (CurC) != 'U') { + Types = IT_LONG | IT_ULONG; + } else { + NextChar (); + Types = IT_ULONG; + } + } else { + HaveSuffix = 0; + if (Prefix == 10) { + /* Decimal constants are of any type but uint */ + Types = IT_INT | IT_LONG | IT_ULONG; + } else { + /* Octal or hex constants are of any type */ + Types = IT_INT | IT_UINT | IT_LONG | IT_ULONG; + } + } + + /* Check the range to determine the type */ + if (IVal > 0x7FFF) { + /* Out of range for int */ + Types &= ~IT_INT; + /* If the value is in the range 0x8000..0xFFFF, unsigned int is not + * allowed, and we don't have a type specifying suffix, emit a + * warning, because the constant is of type long. + */ + if (IVal <= 0xFFFF && (Types & IT_UINT) == 0 && !HaveSuffix) { + Warning ("Constant is long"); + } + } + if (IVal > 0xFFFF) { + /* Out of range for unsigned int */ + Types &= ~IT_UINT; + } + if (IVal > 0x7FFFFFFF) { + /* Out of range for long int */ + Types &= ~IT_LONG; + } + + /* Now set the type string to the smallest type in types */ + if (Types & IT_INT) { + NextTok.Type = type_int; + } else if (Types & IT_UINT) { + NextTok.Type = type_uint; + } else if (Types & IT_LONG) { + NextTok.Type = type_long; + } else { + NextTok.Type = type_ulong; + } + + /* Set the value and the token */ + NextTok.IVal = IVal; + NextTok.Tok = TOK_ICONST; + + } else { + + /* Float constant */ + double FVal = IVal; /* Convert to float */ + + /* Check for a fractional part and read it */ + if (CurC == '.') { + + unsigned Digits; + unsigned long Frac; + unsigned long Scale; + + /* Skip the dot */ + NextChar (); + + /* Read fractional digits. Since we support only 32 bit floats + * with a maximum of 7 fractional digits, we read the fractional + * part as integer with up to 8 digits and drop the remainder. + * This avoids an overflow of Frac and Scale. + */ + Digits = 0; + Frac = 0; + Scale = 1; + while (IsXDigit (CurC) && (DigitVal = HexVal (CurC)) < Base) { + if (Digits < 8) { + Frac = Frac * Base + DigitVal; + ++Digits; + Scale *= Base; + } + NextChar (); + } + + /* Scale the fractional part and add it */ + if (Frac) { + FVal += ((double) Frac) / ((double) Scale); + } + } + + /* Check for an exponent and read it */ + if ((Base == 16 && toupper (CurC) == 'F') || + (Base == 10 && toupper (CurC) == 'E')) { + + int Sign; + unsigned Digits; + unsigned Exp; + + /* Skip the exponent notifier */ + NextChar (); + + /* Read an optional sign */ + Sign = 1; + if (CurC == '-') { + Sign = -1; + NextChar (); + } else if (CurC == '+') { + NextChar (); + } + + /* Read exponent digits. Since we support only 32 bit floats + * with a maximum exponent of +-/127, we read the exponent + * part as integer with up to 3 digits and drop the remainder. + * This avoids an overflow of Exp. The exponent is always + * decimal, even for hex float consts. + */ + Digits = 0; + Exp = 0; + while (IsDigit (CurC)) { + if (++Digits <= 3) { + Exp = Exp * 10 + HexVal (CurC); + } + NextChar (); + } + + /* Check for errors: We must have exponent digits, and not more + * than three. + */ + if (Digits == 0) { + Error ("Floating constant exponent has no digits"); + } else if (Digits > 3) { + Warning ("Floating constant exponent is too large"); + } + + /* Scale the exponent and adjust the value accordingly */ + if (Exp) { + FVal *= pow (10, Exp); + } + } + + /* Check for a suffix and determine the type of the constant */ + if (toupper (CurC) == 'F') { + NextChar (); + NextTok.Type = type_float; + } else { + NextTok.Type = type_double; + } + + /* Set the value and the token */ + NextTok.FVal = FVal; + NextTok.Tok = TOK_FCONST; + + } +} + + + void NextToken (void) /* Get next token from input stream */ { @@ -396,6 +703,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 ()); @@ -407,109 +722,9 @@ void NextToken (void) } /* Determine the next token from the lookahead */ - if (IsDigit (CurC)) { - + if (IsDigit (CurC) || (CurC == '.' && IsDigit (NextC))) { /* A number */ - int HaveSuffix; /* True if we have a type suffix */ - unsigned types; /* Possible types */ - unsigned Base; - unsigned DigitVal; - unsigned long k; /* Value */ - - k = 0; - Base = 10; - types = IT_INT | IT_LONG | IT_ULONG; - - if (CurC == '0') { - /* Octal or hex constants may also be of type unsigned int */ - types = IT_INT | IT_UINT | IT_LONG | IT_ULONG; - /* gobble 0 and examin next char */ - NextChar (); - if (toupper (CurC) == 'X') { - Base = 16; - NextTok.Type = type_uint; - NextChar (); /* gobble "x" */ - } else { - Base = 8; - } - } - 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; - if (CurC == 'u' || CurC == 'U') { - /* Unsigned type */ - NextChar (); - if (toupper (CurC) != 'L') { - types = IT_UINT | IT_ULONG; - } else { - NextChar (); - types = IT_ULONG; - } - } else if (CurC == 'l' || CurC == 'L') { - /* Long type */ - NextChar (); - if (toupper (CurC) != 'U') { - types = IT_LONG | IT_ULONG; - } else { - NextChar (); - types = IT_ULONG; - } - } else { - HaveSuffix = 0; - } - - /* Check the range to determine the type */ - if (k > 0x7FFF) { - /* Out of range for int */ - types &= ~IT_INT; - /* If the value is in the range 0x8000..0xFFFF, unsigned int is not - * allowed, and we don't have a type specifying suffix, emit a - * warning. - */ - if (k <= 0xFFFF && (types & IT_UINT) == 0 && !HaveSuffix) { - Warning ("Constant is long"); - } - } - if (k > 0xFFFF) { - /* Out of range for unsigned int */ - types &= ~IT_UINT; - } - if (k > 0x7FFFFFFF) { - /* Out of range for long int */ - types &= ~IT_LONG; - } - - /* Now set the type string to the smallest type in types */ - if (types & IT_INT) { - NextTok.Type = type_int; - } else if (types & IT_UINT) { - NextTok.Type = type_uint; - } else if (types & IT_LONG) { - NextTok.Type = type_long; - } else { - NextTok.Type = type_ulong; - } - - /* Set the value and the token */ - NextTok.IVal = k; - NextTok.Tok = TOK_ICONST; + NumericConst (); return; } @@ -521,18 +736,18 @@ void NextToken (void) return; } /* No reserved word, check for special symbols */ - if (token [0] == '_') { + if (token[0] == '_' && token[1] == '_') { /* Special symbols */ - if (strcmp (token, "__FILE__") == 0) { + if (strcmp (token+2, "FILE__") == 0) { NextTok.IVal = AddLiteral (GetCurrentFile()); NextTok.Tok = TOK_SCONST; return; - } else if (strcmp (token, "__LINE__") == 0) { + } else if (strcmp (token+2, "LINE__") == 0) { NextTok.Tok = TOK_ICONST; NextTok.IVal = GetCurrentLine(); NextTok.Type = type_int; return; - } else if (strcmp (token, "__func__") == 0) { + } else if (strcmp (token+2, "func__") == 0) { /* __func__ is only defined in functions */ if (CurrentFunc) { NextTok.IVal = AddLiteral (F_GetFuncName (CurrentFunc)); @@ -644,17 +859,17 @@ void NextToken (void) break; case '.': - NextChar (); - if (CurC == '.') { - NextChar (); - if (CurC == '.') { - SetTok (TOK_ELLIPSIS); - } else { - UnknownChar (CurC); - } - } else { - NextTok.Tok = TOK_DOT; - } + NextChar (); + if (CurC == '.') { + NextChar (); + if (CurC == '.') { + SetTok (TOK_ELLIPSIS); + } else { + UnknownChar (CurC); + } + } else { + NextTok.Tok = TOK_DOT; + } break; case '/':