OSDN Git Service

(__objc_register_instance_methods_to_class): New function.
[pf3gnuchains/gcc-fork.git] / gcc / c-lex.c
index 997e9a0..b9c2190 100644 (file)
@@ -1,5 +1,5 @@
 /* Lexical analyzer for C and Objective C.
-   Copyright (C) 1987, 1988, 1989, 1992, 1994 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,7 @@ 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>
 
@@ -396,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;
            }
        }
@@ -415,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;
            }
        }
@@ -431,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;
            }
        }
@@ -587,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)
@@ -604,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");
@@ -643,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:
@@ -691,10 +701,21 @@ 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 ();
     }
 }
 
@@ -940,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.  */
       {
@@ -979,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':
@@ -995,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 == '@')
@@ -1002,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);
@@ -1093,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 '.':
       {
@@ -1258,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;
@@ -1329,6 +1367,8 @@ yylex ()
                      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;
 
@@ -1357,24 +1397,24 @@ yylex ()
 
                    type = float_type_node;
                    value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
-                   if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
-                       && REAL_VALUE_ISINF (value) && pedantic)
-                     pedwarn ("floating point number exceeds range of `float'");
+                   /* 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 (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
-                       && REAL_VALUE_ISINF (value) && pedantic)
-                     pedwarn ("floating point number exceeds range of `long double'");
+                   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 (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
-                       && REAL_VALUE_ISINF (value) && pedantic)
-                     pedwarn ("floating point number exceeds range of `double'");
+                   if (REAL_VALUE_ISINF (value) && pedantic)
+                     warning ("floating point number exceeds range of `double'");
                  }
 
                set_float_handler (NULL_PTR);
@@ -1384,38 +1424,28 @@ yylex ()
              {
                /* ERANGE is also reported for underflow,
                   so test the value to distinguish overflow from that.  */
-               if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
-                   && (REAL_VALUES_LESS (dconst1, value)
-                       || REAL_VALUES_LESS (value, dconstm1)))
+               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
-           garbage_chars = 0;
-           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
          {
@@ -1451,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
@@ -1598,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'");
              }
@@ -1615,10 +1629,16 @@ yylex ()
              }
            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;
       }
 
@@ -1788,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.  */
 
@@ -1853,6 +1876,7 @@ yylex ()
     case '-':
     case '&':
     case '|':
+    case ':':
     case '<':
     case '>':
     case '*':
@@ -1930,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;