OSDN Git Service

(do_include): Diagnose #import and #include_next if pedantic and if
[pf3gnuchains/gcc-fork.git] / gcc / c-lex.c
index 594453d..b9c2190 100644 (file)
@@ -1,5 +1,5 @@
 /* Lexical analyzer for C and Objective C.
-   Copyright (C) 1987, 1988, 1989, 1992 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 89, 92, 94, 95, 1996 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -15,7 +15,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 
 #include <stdio.h>
@@ -30,6 +31,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "c-tree.h"
 #include "flags.h"
 #include "c-parse.h"
+#include "c-pragma.h"
+
+#include <ctype.h>
 
 #ifdef MULTIBYTE_CHARS
 #include <stdlib.h>
@@ -88,194 +92,11 @@ static int end_of_file;
 static int nextchar = -1;
 
 int check_newline ();
-
-/* Nonzero tells yylex to ignore \ in string constants.  */
-static int ignore_escape_flag = 0;
 \f
-/* C code produced by gperf version 2.5 (GNU C++ version) */
-/* Command-line: gperf -p -j1 -i 1 -g -o -t -G -N is_reserved_word -k1,3,$ c-parse.gperf  */
-struct resword { char *name; short token; enum rid rid; };
-
-#define TOTAL_KEYWORDS 79
-#define MIN_WORD_LENGTH 2
-#define MAX_WORD_LENGTH 20
-#define MIN_HASH_VALUE 10
-#define MAX_HASH_VALUE 144
-/* maximum key range = 135, duplicates = 0 */
-
-#ifdef __GNUC__
-__inline
-#endif
-static unsigned int
-hash (str, len)
-     register char *str;
-     register int unsigned len;
-{
-  static unsigned char asso_values[] =
-    {
-     145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
-     145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
-     145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
-     145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
-     145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
-     145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
-     145, 145, 145, 145,  25, 145, 145, 145, 145, 145,
-     145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
-     145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
-     145, 145, 145, 145, 145,   1, 145,  46,   8,  15,
-      61,   6,  36,  48,   3,   5, 145,  18,  63,  25,
-      29,  76,   1, 145,  13,   2,   1,  51,  37,   9,
-       9,   1,   3, 145, 145, 145, 145, 145,
-    };
-  register int hval = len;
-
-  switch (hval)
-    {
-      default:
-      case 3:
-        hval += asso_values[str[2]];
-      case 2:
-      case 1:
-        hval += asso_values[str[0]];
-    }
-  return hval + asso_values[str[len - 1]];
-}
-
-static struct resword wordlist[] =
-{
-  {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
-  {"",}, 
-  {"int",  TYPESPEC, RID_INT},
-  {"",}, {"",}, 
-  {"__typeof__",  TYPEOF, NORID},
-  {"__signed__",  TYPESPEC, RID_SIGNED},
-  {"__imag__",  IMAGPART, NORID},
-  {"switch",  SWITCH, NORID},
-  {"__inline__",  SCSPEC, RID_INLINE},
-  {"else",  ELSE, NORID},
-  {"__iterator__",  SCSPEC, RID_ITERATOR},
-  {"__inline",  SCSPEC, RID_INLINE},
-  {"__extension__",  EXTENSION, NORID},
-  {"struct",  STRUCT, NORID},
-  {"__real__",  REALPART, NORID},
-  {"__const",  TYPE_QUAL, RID_CONST},
-  {"while",  WHILE, NORID},
-  {"__const__",  TYPE_QUAL, RID_CONST},
-  {"case",  CASE, NORID},
-  {"__complex__",  TYPESPEC, RID_COMPLEX},
-  {"__iterator",  SCSPEC, RID_ITERATOR},
-  {"bycopy",  TYPE_QUAL, RID_BYCOPY},
-  {"",}, {"",}, {"",}, 
-  {"__complex",  TYPESPEC, RID_COMPLEX},
-  {"",}, 
-  {"in",  TYPE_QUAL, RID_IN},
-  {"break",  BREAK, NORID},
-  {"@defs",  DEFS, NORID},
-  {"",}, {"",}, {"",}, 
-  {"extern",  SCSPEC, RID_EXTERN},
-  {"if",  IF, NORID},
-  {"typeof",  TYPEOF, NORID},
-  {"typedef",  SCSPEC, RID_TYPEDEF},
-  {"__typeof",  TYPEOF, NORID},
-  {"sizeof",  SIZEOF, NORID},
-  {"",}, 
-  {"return",  RETURN, NORID},
-  {"const",  TYPE_QUAL, RID_CONST},
-  {"__volatile__",  TYPE_QUAL, RID_VOLATILE},
-  {"@private",  PRIVATE, NORID},
-  {"@selector",  SELECTOR, NORID},
-  {"__volatile",  TYPE_QUAL, RID_VOLATILE},
-  {"__asm__",  ASM_KEYWORD, NORID},
-  {"",}, {"",}, 
-  {"continue",  CONTINUE, NORID},
-  {"__alignof__",  ALIGNOF, NORID},
-  {"__imag",  IMAGPART, NORID},
-  {"__attribute__",  ATTRIBUTE, NORID},
-  {"",}, {"",}, 
-  {"__attribute",  ATTRIBUTE, NORID},
-  {"for",  FOR, NORID},
-  {"",}, 
-  {"@encode",  ENCODE, NORID},
-  {"id",  OBJECTNAME, RID_ID},
-  {"static",  SCSPEC, RID_STATIC},
-  {"@interface",  INTERFACE, NORID},
-  {"",}, 
-  {"__signed",  TYPESPEC, RID_SIGNED},
-  {"",}, 
-  {"__label__",  LABEL, NORID},
-  {"",}, {"",}, 
-  {"__asm",  ASM_KEYWORD, NORID},
-  {"char",  TYPESPEC, RID_CHAR},
-  {"",}, 
-  {"inline",  SCSPEC, RID_INLINE},
-  {"out",  TYPE_QUAL, RID_OUT},
-  {"register",  SCSPEC, RID_REGISTER},
-  {"__real",  REALPART, NORID},
-  {"short",  TYPESPEC, RID_SHORT},
-  {"",}, 
-  {"enum",  ENUM, NORID},
-  {"inout",  TYPE_QUAL, RID_INOUT},
-  {"",}, 
-  {"oneway",  TYPE_QUAL, RID_ONEWAY},
-  {"union",  UNION, NORID},
-  {"",}, 
-  {"__alignof",  ALIGNOF, NORID},
-  {"",}, 
-  {"@implementation",  IMPLEMENTATION, NORID},
-  {"",}, 
-  {"@class",  CLASS, NORID},
-  {"",}, 
-  {"@public",  PUBLIC, NORID},
-  {"asm",  ASM_KEYWORD, NORID},
-  {"",}, {"",}, {"",}, {"",}, {"",}, 
-  {"default",  DEFAULT, NORID},
-  {"",}, 
-  {"void",  TYPESPEC, RID_VOID},
-  {"",}, 
-  {"@protected",  PROTECTED, NORID},
-  {"@protocol",  PROTOCOL, NORID},
-  {"",}, {"",}, {"",}, 
-  {"volatile",  TYPE_QUAL, RID_VOLATILE},
-  {"",}, {"",}, 
-  {"signed",  TYPESPEC, RID_SIGNED},
-  {"float",  TYPESPEC, RID_FLOAT},
-  {"@end",  END, NORID},
-  {"",}, {"",}, 
-  {"unsigned",  TYPESPEC, RID_UNSIGNED},
-  {"@compatibility_alias",  ALIAS, NORID},
-  {"double",  TYPESPEC, RID_DOUBLE},
-  {"",}, {"",}, 
-  {"auto",  SCSPEC, RID_AUTO},
-  {"",}, 
-  {"goto",  GOTO, NORID},
-  {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
-  {"do",  DO, NORID},
-  {"",}, {"",}, {"",}, {"",}, 
-  {"long",  TYPESPEC, RID_LONG},
-};
-
-#ifdef __GNUC__
-__inline
-#endif
-struct resword *
-is_reserved_word (str, len)
-     register char *str;
-     register unsigned int len;
-{
-  if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
-    {
-      register int key = hash (str, len);
-
-      if (key <= MAX_HASH_VALUE && key >= 0)
-        {
-          register char *s = wordlist[key].name;
-
-          if (*s == *str && !strcmp (str + 1, s + 1))
-            return &wordlist[key];
-        }
-    }
-  return 0;
-}
+/* Do not insert generated code into the source, instead, include it.
+   This allows us to build gcc automatically even for targets that
+   need to add or modify the reserved keyword lists.  */
+#include "c-gperf.h"
 \f
 /* Return something to represent absolute declarators containing a *.
    TARGET is the absolute declarator that the * contains.
@@ -298,7 +119,8 @@ forget_protocol_qualifiers ()
   int i, n = sizeof wordlist / sizeof (struct resword);
 
   for (i = 0; i < n; i++)
-    if (wordlist[i].rid >= RID_IN && wordlist[i].rid <= RID_ONEWAY)
+    if ((int) wordlist[i].rid >= (int) RID_IN
+        && (int) wordlist[i].rid <= (int) RID_ONEWAY)
       wordlist[i].name = "";
 }
 
@@ -576,12 +398,29 @@ check_newline ()
              && getc (finput) == 'a'
              && ((c = getc (finput)) == ' ' || c == '\t' || c == '\n'))
            {
+             while (c == ' ' || c == '\t')
+               c = getc (finput);
+             if (c == '\n')
+               return c;
 #ifdef HANDLE_SYSV_PRAGMA
-             return handle_sysv_pragma (finput, c);
-#endif /* HANDLE_SYSV_PRAGMA */
+             ungetc (c, finput);
+             token = yylex ();
+             if (token != IDENTIFIER)
+               goto skipline;
+             return handle_sysv_pragma (finput, token);
+#else /* !HANDLE_SYSV_PRAGMA */
 #ifdef HANDLE_PRAGMA
-             HANDLE_PRAGMA (finput);
+             ungetc (c, finput);
+             token = yylex ();
+             if (token != IDENTIFIER)
+               goto skipline;
+             if (HANDLE_PRAGMA (finput, yylval.ttype))
+               {
+                 c = getc (finput);
+                 return c;
+               }
 #endif /* HANDLE_PRAGMA */
+#endif /* !HANDLE_SYSV_PRAGMA */
              goto skipline;
            }
        }
@@ -595,11 +434,8 @@ check_newline ()
              && getc (finput) == 'e'
              && ((c = getc (finput)) == ' ' || c == '\t' || c == '\n'))
            {
-#ifdef DWARF_DEBUGGING_INFO
-             if ((debug_info_level == DINFO_LEVEL_VERBOSE)
-                 && (write_symbols == DWARF_DEBUG))
-               dwarfout_define (lineno, get_directive_line (finput));
-#endif /* DWARF_DEBUGGING_INFO */
+             if (c != '\n')
+               debug_define (lineno, get_directive_line (finput));
              goto skipline;
            }
        }
@@ -611,11 +447,8 @@ check_newline ()
              && getc (finput) == 'f'
              && ((c = getc (finput)) == ' ' || c == '\t' || c == '\n'))
            {
-#ifdef DWARF_DEBUGGING_INFO
-             if ((debug_info_level == DINFO_LEVEL_VERBOSE)
-                 && (write_symbols == DWARF_DEBUG))
-               dwarfout_undef (lineno, get_directive_line (finput));
-#endif /* DWARF_DEBUGGING_INFO */
+             if (c != '\n')
+               debug_undef (lineno, get_directive_line (finput));
              goto skipline;
            }
        }
@@ -713,10 +546,8 @@ linenum:
 
       /* More follows: it must be a string constant (filename).  */
 
-      /* Read the string constant, but don't treat \ as special.  */
-      ignore_escape_flag = 1;
+      /* Read the string constant.  */
       token = yylex ();
-      ignore_escape_flag = 0;
 
       if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
        {
@@ -769,12 +600,7 @@ linenum:
              p->name = input_filename;
              input_file_stack = p;
              input_file_stack_tick++;
-#ifdef DWARF_DEBUGGING_INFO
-             if (debug_info_level == DINFO_LEVEL_VERBOSE
-                 && write_symbols == DWARF_DEBUG)
-               dwarfout_start_new_source_file (input_filename);
-#endif /* DWARF_DEBUGGING_INFO */
-
+             debug_start_source_file (input_filename);
              used_up = 1;
            }
          else if (TREE_INT_CST_LOW (yylval.ttype) == 2)
@@ -786,11 +612,7 @@ linenum:
                  input_file_stack = p->next;
                  free (p);
                  input_file_stack_tick++;
-#ifdef DWARF_DEBUGGING_INFO
-                 if (debug_info_level == DINFO_LEVEL_VERBOSE
-                     && write_symbols == DWARF_DEBUG)
-                   dwarfout_resume_previous_source_file (input_file_stack->line);
-#endif /* DWARF_DEBUGGING_INFO */
+                 debug_end_source_file (input_file_stack->line);
                }
              else
                error ("#-lines for entering and leaving files don't match");
@@ -825,44 +647,50 @@ linenum:
       if (token == CONSTANT
          && TREE_CODE (yylval.ttype) == INTEGER_CST
          && TREE_INT_CST_LOW (yylval.ttype) == 3)
-       in_system_header = 1;
+       in_system_header = 1, used_up = 1;
+
+      if (used_up)
+       {
+         /* Is this the last nonwhite stuff on the line?  */
+         c = getc (finput);
+         while (c == ' ' || c == '\t')
+           c = getc (finput);
+         if (c == '\n')
+           return c;
+         ungetc (c, finput);
+       }
+
+      warning ("unrecognized text at end of #line");
     }
   else
     error ("invalid #-line");
 
   /* skip the rest of this line.  */
  skipline:
-  if (c == '\n')
-    return c;
-  while ((c = getc (finput)) != EOF && c != '\n');
+  while (c != '\n' && c != EOF)
+    c = getc (finput);
   return c;
 }
 \f
 #ifdef HANDLE_SYSV_PRAGMA
 
 /* Handle a #pragma directive.  INPUT is the current input stream,
-   and C is a character to reread.  Processes the entire input line
-   and returns a character for the caller to reread: either \n or EOF.  */
+   and TOKEN is the token we read after `#pragma'.  Processes the entire input
+   line and returns a character for the caller to reread: either \n or EOF.  */
 
 /* This function has to be in this file, in order to get at
    the token types.  */
 
 int
-handle_sysv_pragma (input, c)
+handle_sysv_pragma (input, token)
      FILE *input;
-     int c;
+     register int token;
 {
+  register int c;
+
   for (;;)
     {
-      while (c == ' ' || c == '\t')
-       c = getc (input);
-      if (c == '\n' || c == EOF)
-       {
-         handle_pragma_token (0, 0);
-         return c;
-       }
-      ungetc (c, input);
-      switch (yylex ())
+      switch (token)
        {
        case IDENTIFIER:
        case TYPENAME:
@@ -873,17 +701,26 @@ handle_sysv_pragma (input, c)
        default:
          handle_pragma_token (token_buffer, 0);
        }
+
       if (nextchar >= 0)
        c = nextchar, nextchar = -1;
       else
        c = getc (input);
+
+      while (c == ' ' || c == '\t')
+       c = getc (input);
+      if (c == '\n' || c == EOF)
+       {
+         handle_pragma_token (0, 0);
+         return c;
+       }
+      ungetc (c, input);
+      token = yylex ();
     }
 }
 
 #endif /* HANDLE_SYSV_PRAGMA */
 \f
-#define isalnum(char) ((char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z') || (char >= '0' && char <= '9'))
-#define isdigit(char) (char >= '0' && char <= '9')
 #define ENDFILE -1  /* token that represents end-of-file */
 
 /* Read an escape sequence, returning its equivalent as a character,
@@ -896,7 +733,7 @@ readescape (ignore_ptr)
   register int c = getc (finput);
   register int code;
   register unsigned count;
-  unsigned firstdig;
+  unsigned firstdig = 0;
   int nonnull;
 
   switch (c)
@@ -1011,6 +848,8 @@ readescape (ignore_ptr)
     case '(':
     case '{':
     case '[':
+      /* `\%' is used to prevent SCCS from getting confused.  */
+    case '%':
       if (pedantic)
        pedwarn ("non-ANSI escape sequence `\\%c'", c);
       return c;
@@ -1122,11 +961,6 @@ yylex ()
       value = ENDFILE;
       break;
 
-    case '$':
-      if (dollars_in_ident)
-       goto letter;
-      return '$';
-
     case 'L':
       /* Capital L may start a wide-string or wide-character constant.  */
       {
@@ -1161,7 +995,7 @@ yylex ()
              goto string_constant;
            }
          ungetc(c, finput);
-         /* Fall through to treat '@' as the start of an indentifier.  */
+         /* Fall through to treat '@' as the start of an identifier.  */
        }
 
     case 'A':  case 'B':  case 'C':  case 'D':  case 'E':
@@ -1177,6 +1011,7 @@ yylex ()
     case 'u':  case 'v':  case 'w':  case 'x':  case 'y':
     case 'z':
     case '_':
+    case '$':
     letter:
       p = token_buffer;
       while (isalnum (c) || c == '_' || c == '$' || c == '@')
@@ -1184,8 +1019,13 @@ yylex ()
          /* Make sure this char really belongs in an identifier.  */
          if (c == '@' && ! doing_objc_thang)
            break;
-         if (c == '$' && ! dollars_in_ident)
-           break;
+         if (c == '$')
+           {
+             if (! dollars_in_ident)
+               error ("`$' in identifier");
+             else if (pedantic)
+               pedwarn ("`$' in identifier");
+           }
 
          if (p >= token_buffer + maxtoken)
            p = extend_token_buffer (p);
@@ -1275,7 +1115,23 @@ yylex ()
 
       break;
 
-    case '0':  case '1':  case '2':  case '3':  case '4':
+    case '0':  case '1':
+      {
+       int next_c;
+       /* Check first for common special case:  single-digit 0 or 1.  */
+
+       next_c = getc (finput);
+       ungetc (next_c, finput);        /* Always undo this lookahead.  */
+       if (!isalnum (next_c) && next_c != '.')
+         {
+           token_buffer[0] = (char)c,  token_buffer[1] = '\0';
+           yylval.ttype = (c == '0') ? integer_zero_node : integer_one_node;
+           value = CONSTANT;
+           break;
+         }
+       /*FALLTHRU*/
+      }
+    case '2':  case '3':  case '4':
     case '5':  case '6':  case '7':  case '8':  case '9':
     case '.':
       {
@@ -1332,10 +1188,16 @@ yylex ()
              {
                if (base == 16)
                  error ("floating constant may not be in radix 16");
-               if (floatflag == AFTER_POINT)
+               if (floatflag == TOO_MANY_POINTS)
+                 /* We have already emitted an error.  Don't need another.  */
+                 ;
+               else if (floatflag == AFTER_POINT)
                  {
                    error ("malformed floating constant");
                    floatflag = TOO_MANY_POINTS;
+                   /* Avoid another error from atof by forcing all characters
+                      from here on to be ignored.  */
+                   p[-1] = '\0';
                  }
                else
                  floatflag = AFTER_POINT;
@@ -1434,7 +1296,7 @@ yylex ()
        if (floatflag != NOT_FLOAT)
          {
            tree type = double_type_node;
-           int garbage_chars = 0, exceeds_double = 0;
+           int exceeds_double = 0;
            int imag = 0;
            REAL_VALUE_TYPE value;
            jmp_buf handler;
@@ -1474,44 +1336,88 @@ yylex ()
              }
            else
              {
+               int fflag = 0, lflag = 0;
+               /* Copy token_buffer now, while it has just the number
+                  and not the suffixes; once we add `f' or `i',
+                  REAL_VALUE_ATOF may not work any more.  */
+               char *copy = (char *) alloca (p - token_buffer + 1);
+               bcopy (token_buffer, copy, p - token_buffer + 1);
+
                set_float_handler (handler);
 
-/* The second argument, machine_mode, of REAL_VALUE_ATOF tells the
-   desired precision of the binary result of decimal-to-binary conversion.  */
+               while (1)
+                 {
+                   int lose = 0;
 
-           /* Read the suffixes to choose a data type.  */
-           switch (c)
-             {
-             case 'f': case 'F':
-               type = float_type_node;
-               value = REAL_VALUE_ATOF (token_buffer, TYPE_MODE (type));
-               if (REAL_VALUE_ISINF (value) && pedantic)
-                 pedwarn ("floating point number exceeds range of `float'");
-               garbage_chars = -1;
-               break;
-
-             case 'l': case 'L':
-               type = long_double_type_node;
-               value = REAL_VALUE_ATOF (token_buffer, TYPE_MODE (type));
-               if (REAL_VALUE_ISINF (value) && pedantic)
-                 pedwarn (
-                     "floating point number exceeds range of `long double'");
-               garbage_chars = -1;
-               break;
-
-             case 'i': case 'I':
-               if (imag)
-                 error ("more than one `i' or `j' in numeric constant");
-               imag = 1;
-               garbage_chars = -1;
-               break;
-
-              default:
-               value = REAL_VALUE_ATOF (token_buffer, TYPE_MODE (type));
-               if (REAL_VALUE_ISINF (value) && pedantic)
-                 pedwarn ("floating point number exceeds range of `double'");
-             }
-           set_float_handler (NULL_PTR);
+                   /* Read the suffixes to choose a data type.  */
+                   switch (c)
+                     {
+                     case 'f': case 'F':
+                       if (fflag)
+                         error ("more than one `f' in numeric constant");
+                       fflag = 1;
+                       break;
+
+                     case 'l': case 'L':
+                       if (lflag)
+                         error ("more than one `l' in numeric constant");
+                       lflag = 1;
+                       break;
+
+                     case 'i': case 'I':
+                       if (imag)
+                         error ("more than one `i' or `j' in numeric constant");
+                       else if (pedantic)
+                         pedwarn ("ANSI C forbids imaginary numeric constants");
+                       imag = 1;
+                       break;
+
+                     default:
+                       lose = 1;
+                     }
+
+                   if (lose)
+                     break;
+
+                   if (p >= token_buffer + maxtoken - 3)
+                     p = extend_token_buffer (p);
+                   *p++ = c;
+                   *p = 0;
+                   c = getc (finput);
+                 }
+
+               /* The second argument, machine_mode, of REAL_VALUE_ATOF
+                  tells the desired precision of the binary result
+                  of decimal-to-binary conversion.  */
+
+               if (fflag)
+                 {
+                   if (lflag)
+                     error ("both `f' and `l' in floating constant");
+
+                   type = float_type_node;
+                   value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
+                   /* A diagnostic is required here by some ANSI C testsuites.
+                      This is not pedwarn, become some people don't want
+                      an error for this.  */
+                   if (REAL_VALUE_ISINF (value) && pedantic)
+                     warning ("floating point number exceeds range of `float'");
+                 }
+               else if (lflag)
+                 {
+                   type = long_double_type_node;
+                   value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
+                   if (REAL_VALUE_ISINF (value) && pedantic)
+                     warning ("floating point number exceeds range of `long double'");
+                 }
+               else
+                 {
+                   value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
+                   if (REAL_VALUE_ISINF (value) && pedantic)
+                     warning ("floating point number exceeds range of `double'");
+                 }
+
+               set_float_handler (NULL_PTR);
            }
 #ifdef ERANGE
            if (errno == ERANGE && !flag_traditional && pedantic)
@@ -1521,34 +1427,25 @@ yylex ()
                if (REAL_VALUES_LESS (dconst1, value)
                    || REAL_VALUES_LESS (value, dconstm1))
                  {
-                   pedwarn ("floating point number exceeds range of `double'");
+                   warning ("floating point number exceeds range of `double'");
                    exceeds_double = 1;
                  }
              }
 #endif
-           /* Note: garbage_chars is -1 if first char is *not* garbage.  */
-           while (isalnum (c) || c == '.' || c == '_'
-                  || (!flag_traditional && (c == '+' || c == '-')
-                      && (p[-1] == 'e' || p[-1] == 'E')))
-             {
-               if (p >= token_buffer + maxtoken - 3)
-                 p = extend_token_buffer (p);
-               *p++ = c;
-               c = getc (finput);
-               garbage_chars++;
-             }
-           if (garbage_chars > 0)
-             error ("garbage at end of number");
+
+           /* If the result is not a number, assume it must have been
+              due to some error message above, so silently convert
+              it to a zero.  */
+           if (REAL_VALUE_ISNAN (value))
+             value = dconst0;
 
            /* Create a node with determined type and value.  */
            if (imag)
-             yylval.ttype = build_complex (convert (type, integer_zero_node),
+             yylval.ttype = build_complex (NULL_TREE,
+                                           convert (type, integer_zero_node),
                                            build_real (type, value));
            else
              yylval.ttype = build_real (type, value);
-
-           ungetc (c, finput);
-           *p = 0;
          }
        else
          {
@@ -1584,35 +1481,18 @@ yylex ()
                  {
                    if (spec_imag)
                      error ("more than one `i' or `j' in numeric constant");
+                   else if (pedantic)
+                     pedwarn ("ANSI C forbids imaginary numeric constants");
                    spec_imag = 1;
                  }
                else
-                 {
-                   if (isalnum (c) || c == '.' || c == '_'
-                       || (!flag_traditional && (c == '+' || c == '-')
-                           && (p[-1] == 'e' || p[-1] == 'E')))
-                     {
-                       error ("garbage at end of number");
-                       while (isalnum (c) || c == '.' || c == '_'
-                              || (!flag_traditional && (c == '+' || c == '-')
-                                  && (p[-1] == 'e' || p[-1] == 'E')))
-                         {
-                           if (p >= token_buffer + maxtoken - 3)
-                             p = extend_token_buffer (p);
-                           *p++ = c;
-                           c = getc (finput);
-                         }
-                     }
-                   break;
-                 }
+                 break;
                if (p >= token_buffer + maxtoken - 3)
                  p = extend_token_buffer (p);
                *p++ = c;
                c = getc (finput);
              }
 
-           ungetc (c, finput);
-
            /* If the constant is not long long and it won't fit in an
               unsigned long, or if the constant is long long and won't fit
               in an unsigned long long, then warn that the constant is out
@@ -1731,8 +1611,9 @@ yylex ()
                if (TYPE_PRECISION (type)
                    <= TYPE_PRECISION (integer_type_node))
                  yylval.ttype
-                   = build_complex (integer_zero_node,
-                                    convert (integer_type_node, yylval.ttype));
+                   = build_complex (NULL_TREE, integer_zero_node,
+                                    convert (integer_type_node,
+                                             yylval.ttype));
                else
                  error ("complex integer constant is too wide for `complex int'");
              }
@@ -1743,13 +1624,21 @@ yylex ()
              {
                TREE_TYPE (yylval.ttype) = unsigned_type (type);
                yylval.ttype = convert (type, yylval.ttype);
+               TREE_OVERFLOW (yylval.ttype)
+                 = TREE_CONSTANT_OVERFLOW (yylval.ttype) = 0;
              }
            else
              TREE_TYPE (yylval.ttype) = type;
-
-           *p = 0;
          }
 
+       ungetc (c, finput);
+       *p = 0;
+
+       if (isalnum (c) || c == '.' || c == '_' || c == '$'
+           || (!flag_traditional && (c == '-' || c == '+')
+               && (p[-1] == 'e' || p[-1] == 'E')))
+         error ("missing white space after number `%s'", token_buffer);
+
        value = CONSTANT; break;
       }
 
@@ -1842,8 +1731,11 @@ yylex ()
        if (! wide_flag)
          {
            int num_bits = num_chars * width;
-           if (TREE_UNSIGNED (char_type_node)
-               || ((result >> (num_bits - 1)) & 1) == 0)
+           if (num_bits == 0)
+             /* We already got an error; avoid invalid shift.  */
+             yylval.ttype = build_int_2 (0, 0);
+           else if (TREE_UNSIGNED (char_type_node)
+                    || ((result >> (num_bits - 1)) & 1) == 0)
              yylval.ttype
                = build_int_2 (result & ((unsigned HOST_WIDE_INT) ~0
                                         >> (HOST_BITS_PER_WIDE_INT - num_bits)),
@@ -1889,8 +1781,7 @@ yylex ()
 
        while (c != '"' && c >= 0)
          {
-           /* ignore_escape_flag is set for reading the filename in #line.  */
-           if (!ignore_escape_flag && c == '\\')
+           if (c == '\\')
              {
                int ignore = 0;
                c = readescape (&ignore);
@@ -1917,6 +1808,9 @@ yylex ()
          }
        *p = 0;
 
+       if (c < 0)
+         error ("Unterminated string constant");
+
        /* We have read the entire constant.
           Construct a STRING_CST for the result.  */
 
@@ -1929,7 +1823,7 @@ yylex ()
 
 #ifdef MULTIBYTE_CHARS
            len = mbstowcs ((wchar_t *) widep, token_buffer + 1, p - token_buffer);
-           if ((unsigned) len >= (p - token_buffer))
+           if (len < 0 || len >= (p - token_buffer))
              {
                warning ("Ignoring invalid multibyte string");
                len = 0;
@@ -1982,6 +1876,7 @@ yylex ()
     case '-':
     case '&':
     case '|':
+    case ':':
     case '<':
     case '>':
     case '*':
@@ -2059,8 +1954,28 @@ yylex ()
              c = RSHIFT;
              goto combine;
            }
-       else if ((c == '-') && (c1 == '>'))
-         { value = POINTSAT; goto done; }
+       else
+         switch (c)
+           {
+           case '-':
+             if (c1 == '>')
+               { value = POINTSAT; goto done; }
+             break;
+           case ':':
+             if (c1 == '>')
+               { value = ']'; goto done; }
+             break;
+           case '<':
+             if (c1 == '%')
+               { value = '{'; goto done; }
+             if (c1 == ':')
+               { value = '['; goto done; }
+             break;
+           case '%':
+             if (c1 == '>')
+               { value = '}'; goto done; }
+             break;
+           }
        ungetc (c1, finput);
        token_buffer[1] = 0;