This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

(C++) sync lexer with C frontend


There's really no reason for the lexers of the C and C++ frontends to be
out of sync; their requirements are very similar.  This patch fixes a bunch
of inconsistencies.

1999-07-23  Jason Merrill  <jason@yorick.cygnus.com>

	* lex.c: Sync with C frontend.
	(whitespace_cr): New fn.
	(skip_white_space): Use it.
	(init_parse): Reorder.
	(yyprint): Support CONSTANT.
	(pragma_getc, pragma_ungetc): Bring back.
	(read_line_number): Change in_system_header directly.
	(handle_generic_pragma, handle_cp_pragma, yyerror): Move up in file.
	(parse_float): Update to C version.
	(yylex): Handle '$' under the letter case.
	Remove looking_for_typename handling.
	Support hex floating point constants.
	Follow C's lead for choosing type of integer constants.
	Rearrange stuff to match C frontend.
	(yyungetc, reinit_parse_for_block, yylex): Support indent_level.
	* spew.c (yylex): Clear looking_for_typename if we see a TYPESPEC.

Index: lex.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/lex.c,v
retrieving revision 1.122
diff -c -p -r1.122 lex.c
*** lex.c	1999/07/21 12:48:12	1.122
--- lex.c	1999/07/24 00:44:14
*************** extern void yyprint PROTO((FILE *, int, 
*** 57,62 ****
--- 57,63 ----
  
  static tree get_time_identifier PROTO((const char *));
  static int check_newline PROTO((void));
+ static int whitespace_cr		PROTO((int));
  static int skip_white_space PROTO((int));
  static void finish_defarg PROTO((void));
  static int my_get_run_time PROTO((void));
*************** static int maxtoken;		/* Current nominal
*** 303,315 ****
  char *token_buffer;		/* Pointer to token buffer.
  				   Actual allocated length is maxtoken + 2.  */
  
! static int indent_level = 0;	/* Number of { minus number of }. */
  
  #include "hash.h"
  
  
  /* Nonzero tells yylex to ignore \ in string constants.  */
! static int ignore_escape_flag = 0;
  
  static tree
  get_time_identifier (name)
--- 304,316 ----
  char *token_buffer;		/* Pointer to token buffer.
  				   Actual allocated length is maxtoken + 2.  */
  
! static int indent_level;	/* Number of { minus number of }. */
  
  #include "hash.h"
  
  
  /* Nonzero tells yylex to ignore \ in string constants.  */
! static int ignore_escape_flag;
  
  static tree
  get_time_identifier (name)
*************** init_parse (filename)
*** 481,498 ****
    literal_codeset = getenv ("LANG");
  #endif
  
! #if USE_CPPLIB
!   parse_in.show_column = 1;
!   if (! cpp_start_read (&parse_in, filename))
!     abort ();
! 
!   /* cpp_start_read always puts at least one line directive into the
!      token buffer.  We must arrange to read it out here. */
!   yy_cur = parse_in.token_buffer;
!   yy_lim = CPP_PWRITTEN (&parse_in);
!   cpp_token = CPP_DIRECTIVE;
! 
! #else
    /* Open input file.  */
    if (filename == 0 || !strcmp (filename, "-"))
      {
--- 482,488 ----
    literal_codeset = getenv ("LANG");
  #endif
  
! #if !USE_CPPLIB
    /* Open input file.  */
    if (filename == 0 || !strcmp (filename, "-"))
      {
*************** init_parse (filename)
*** 507,512 ****
--- 497,516 ----
  #ifdef IO_BUFFER_SIZE
    setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
  #endif
+ #else /* !USE_CPPLIB */
+   parse_in.show_column = 1;
+   if (! cpp_start_read (&parse_in, filename))
+     abort ();
+ 
+   if (filename == 0 || !strcmp (filename, "-"))
+     filename = "stdin";
+ 
+   /* cpp_start_read always puts at least one line directive into the
+      token buffer.  We must arrange to read it out here. */
+   yy_cur = parse_in.token_buffer;
+   yy_lim = CPP_PWRITTEN (&parse_in);
+   cpp_token = CPP_DIRECTIVE;
+ 
  #endif /* !USE_CPPLIB */
  
    /* Initialize the lookahead machinery.  */
*************** init_parse (filename)
*** 686,693 ****
    ridpointers[(int) RID_SIGNED] = get_identifier ("signed");
    ridpointers[(int) RID_INLINE] = get_identifier ("inline");
    ridpointers[(int) RID_CONST] = get_identifier ("const");
-   ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile");
    ridpointers[(int) RID_RESTRICT] = get_identifier ("__restrict");
    ridpointers[(int) RID_AUTO] = get_identifier ("auto");
    ridpointers[(int) RID_STATIC] = get_identifier ("static");
    ridpointers[(int) RID_EXTERN] = get_identifier ("extern");
--- 690,697 ----
    ridpointers[(int) RID_SIGNED] = get_identifier ("signed");
    ridpointers[(int) RID_INLINE] = get_identifier ("inline");
    ridpointers[(int) RID_CONST] = get_identifier ("const");
    ridpointers[(int) RID_RESTRICT] = get_identifier ("__restrict");
+   ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile");
    ridpointers[(int) RID_AUTO] = get_identifier ("auto");
    ridpointers[(int) RID_STATIC] = get_identifier ("static");
    ridpointers[(int) RID_EXTERN] = get_identifier ("extern");
*************** yyprint (file, yychar, yylval)
*** 921,926 ****
--- 925,931 ----
        if (IDENTIFIER_POINTER (t))
  	  fprintf (file, " `%s'", IDENTIFIER_POINTER (t));
        break;
+ 
      case AGGR:
        if (yylval.ttype == class_type_node)
  	fprintf (file, " `class'");
*************** yyprint (file, yychar, yylval)
*** 935,940 ****
--- 940,969 ----
        else
  	my_friendly_abort (80);
        break;
+ 
+     case CONSTANT:
+       t = yylval.ttype;
+       if (TREE_CODE (t) == INTEGER_CST)
+ 	fprintf (file,
+ #if HOST_BITS_PER_WIDE_INT == 64
+ #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
+ 		 " 0x%x%016x",
+ #else
+ #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
+ 		 " 0x%lx%016lx",
+ #else
+ 		 " 0x%llx%016llx",
+ #endif
+ #endif
+ #else
+ #if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT
+ 		 " 0x%lx%08lx",
+ #else
+ 		 " 0x%x%08x",
+ #endif
+ #endif
+ 		 TREE_INT_CST_HIGH (t), TREE_INT_CST_LOW (t));
+       break;
      }
  }
  
*************** yyungetc (ch, rescan)
*** 1435,1440 ****
--- 1464,1476 ----
    /* Unget a character from the input stream.  */
    if (yychar == YYEMPTY || rescan == 0)
      {
+       /* If we're putting back a brace, undo the change in indent_level
+ 	 from the first time we saw it.  */
+       if (ch == '{')
+ 	indent_level--;
+       else if (ch == '}')
+ 	indent_level++;
+ 
        put_back (ch);
      }
    else
*************** reinit_parse_for_block (pyychar, obstack
*** 1530,1536 ****
    int look_for_lbrac = 0;
  
    if (pyychar == '{')
!     obstack_1grow (obstackp, '{');
    else if (pyychar == '=')
      look_for_semicolon = 1;
    else if (pyychar == ':')
--- 1566,1576 ----
    int look_for_lbrac = 0;
  
    if (pyychar == '{')
!     {
!       obstack_1grow (obstackp, '{');
!       /* We incremented indent_level in yylex; undo that.  */
!       indent_level--;
!     }
    else if (pyychar == '=')
      look_for_semicolon = 1;
    else if (pyychar == ':')
*************** note_list_got_semicolon (declspecs)
*** 2117,2122 ****
--- 2157,2185 ----
    clear_anon_tags ();
  }
  
+ /* Iff C is a carriage return, warn about it - if appropriate -
+    and return nonzero.  */
+ static int
+ whitespace_cr (c)
+      int c;
+ {
+   static int newline_warning = 0;
+ 
+   if (c == '\r')
+     {
+       /* ANSI C says the effects of a carriage return in a source file
+ 	 are undefined.  */
+       if (pedantic && !newline_warning)
+ 	{
+ 	  warning ("carriage return in source file");
+ 	  warning ("(we only warn about the first carriage return)");
+ 	  newline_warning = 1;
+ 	}
+       return 1;
+     }
+   return 0;
+ }
+ 
  /* If C is not whitespace, return C.
     Otherwise skip whitespace and return first nonwhite char read.  */
  
*************** skip_white_space (c)
*** 2128,2133 ****
--- 2191,2200 ----
      {
        switch (c)
  	{
+ 	  /* We don't recognize comments here, because
+ 	     cpp output can include / and * consecutively as operators.
+ 	     Also, there's no need, since cpp removes all comments.  */
+ 
  	case '\n':
  	  if (linemode)
  	    {
*************** skip_white_space (c)
*** 2140,2146 ****
  	case ' ':
  	case '\t':
  	case '\f':
- 	case '\r':
  	case '\v':
  	case '\b':
  #if USE_CPPLIB
--- 2207,2212 ----
*************** skip_white_space (c)
*** 2153,2158 ****
--- 2219,2229 ----
  	    c = getch ();
  	  break;
  
+ 	case '\r':
+ 	  whitespace_cr (c);
+ 	  c = getch ();
+ 	  break;
+ 
  	case '\\':
  	  c = getch ();
  	  if (c == '\n')
*************** extend_token_buffer (p)
*** 2192,2197 ****
--- 2263,2284 ----
    return token_buffer + offset;
  }
  
+ #if defined HANDLE_PRAGMA
+ /* Local versions of these macros, that can be passed as function pointers.  */
+ static int
+ pragma_getc ()
+ {
+   return getch ();
+ }
+ 
+ static void
+ pragma_ungetc (arg)
+      int arg;
+ {
+   put_back (arg);
+ }
+ #endif
+ 
  static int
  read_line_number (num)
       int *num;
*************** check_newline ()
*** 2228,2234 ****
    int saw_line;
    enum { act_none, act_push, act_pop } action;
    int old_lineno, action_number, l;
-   int entering_system_header;
    int entering_c_header;
  
   restart:
--- 2315,2320 ----
*************** check_newline ()
*** 2288,2303 ****
        if (!strcmp (name, "pragma"))
  	{
  	  token = real_yylex ();
! 	  if (token == IDENTIFIER
! 	      && TREE_CODE (yylval.ttype) == IDENTIFIER_NODE)
! 	    {
! 	      /* If this is 1, we handled it; if it's -1, it was one we
! 		 wanted but had something wrong with it.  Only if it's
! 		 0 was it not handled.  */
! 	      if (handle_cp_pragma (IDENTIFIER_POINTER (yylval.ttype)))
! 		goto skipline;
! 	    }
! 	  else if (token == END_OF_LINE)
  	    goto skipline;
  
  #ifdef HANDLE_PRAGMA
--- 2374,2387 ----
        if (!strcmp (name, "pragma"))
  	{
  	  token = real_yylex ();
! 	  if (token != IDENTIFIER
! 	      || TREE_CODE (yylval.ttype) != IDENTIFIER_NODE)
! 	    goto skipline;
! 	  
! 	  /* If this is 1, we handled it; if it's -1, it was one we
! 	     wanted but had something wrong with it.  Only if it's
! 	     0 was it not handled.  */
! 	  if (handle_cp_pragma (IDENTIFIER_POINTER (yylval.ttype)))
  	    goto skipline;
  
  #ifdef HANDLE_PRAGMA
*************** check_newline ()
*** 2305,2311 ****
  	     (if both are defined), in order to give the back
  	     end a chance to override the interpretation of
  	     SYSV style pragmas.  */
! 	  if (HANDLE_PRAGMA (getch, put_back,
  			     IDENTIFIER_POINTER (yylval.ttype)))
  	    goto skipline;
  #endif /* HANDLE_PRAGMA */
--- 2389,2395 ----
  	     (if both are defined), in order to give the back
  	     end a chance to override the interpretation of
  	     SYSV style pragmas.  */
! 	  if (HANDLE_PRAGMA (pragma_getc, pragma_ungetc,
  			     IDENTIFIER_POINTER (yylval.ttype)))
  	    goto skipline;
  #endif /* HANDLE_PRAGMA */
*************** linenum:
*** 2466,2477 ****
    extract_interface_info ();
  
    old_lineno = lineno;
-   entering_system_header = 0;
-   entering_c_header = 0;
    action = act_none;
    action_number = 0;
    lineno = l;
  
    if (!read_line_number (&action_number))
      {
        /* Update the name in the top element of input_file_stack.  */
--- 2550,2564 ----
    extract_interface_info ();
  
    old_lineno = lineno;
    action = act_none;
    action_number = 0;
    lineno = l;
  
+   /* Each change of file name
+      reinitializes whether we are now in a system header.  */
+   in_system_header = 0;
+   entering_c_header = 0;
+ 
    if (!read_line_number (&action_number))
      {
        /* Update the name in the top element of input_file_stack.  */
*************** linenum:
*** 2495,2501 ****
    if (action_number == 3)
      {
        /* `3' after file name means this is a system header file.  */
!       entering_system_header = 1;
        read_line_number (&action_number);
      }
    if (action_number == 4)
--- 2582,2588 ----
    if (action_number == 3)
      {
        /* `3' after file name means this is a system header file.  */
!       in_system_header = 1;
        read_line_number (&action_number);
      }
    if (action_number == 4)
*************** linenum:
*** 2510,2518 ****
    if (action == act_push)
      {
        /* Pushing to a new file.  */
!       struct file_stack *p;
! 
!       p = (struct file_stack *) xmalloc (sizeof (struct file_stack));
        input_file_stack->line = old_lineno;
        p->next = input_file_stack;
        p->name = input_filename;
--- 2597,2604 ----
    if (action == act_push)
      {
        /* Pushing to a new file.  */
!       struct file_stack *p
! 	= (struct file_stack *) xmalloc (sizeof (struct file_stack));
        input_file_stack->line = old_lineno;
        p->next = input_file_stack;
        p->name = input_filename;
*************** linenum:
*** 2520,2526 ****
        input_file_stack = p;
        input_file_stack_tick++;
        debug_start_source_file (input_filename);
-       in_system_header = entering_system_header;
        if (c_header_level)
  	++c_header_level;
        else if (entering_c_header)
--- 2606,2611 ----
*************** linenum:
*** 2534,2540 ****
        /* Popping out of a file.  */
        if (input_file_stack->next)
  	{
! 	  struct file_stack *p;
  
  	  if (c_header_level && --c_header_level == 0)
  	    {
--- 2619,2625 ----
        /* Popping out of a file.  */
        if (input_file_stack->next)
  	{
! 	  struct file_stack *p = input_file_stack;
  
  	  if (c_header_level && --c_header_level == 0)
  	    {
*************** linenum:
*** 2542,2550 ****
  		warning ("badly nested C headers from preprocessor");
  	      --pending_lang_change;
  	    }
- 	  in_system_header = entering_system_header;
  
- 	  p = input_file_stack;
  	  if (indent_level != p->indent_level)
  	    {
  	      warning_with_file_and_line
--- 2627,2633 ----
*************** linenum:
*** 2561,2578 ****
        else
  	error ("#-lines for entering and leaving files don't match");
      }
-   else
-     in_system_header = entering_system_header;
  
    /* skip the rest of this line.  */
   skipline:
    linemode = 0;
    end_of_file = 0;
  
!   while ((c = getch ()) != EOF && c != '\n');
    return c;
  }
  
  void
  do_pending_lang_change ()
  {
--- 2644,2806 ----
        else
  	error ("#-lines for entering and leaving files don't match");
      }
  
+   /* Now that we've pushed or popped the input stack,
+      update the name in the top element.  */
+   if (input_file_stack)
+     input_file_stack->name = input_filename;
+ 
    /* skip the rest of this line.  */
   skipline:
    linemode = 0;
    end_of_file = 0;
  
!   do
!     c = getch ();
!   while (c != '\n' && c != EOF);
    return c;
  }
+ 
+ #ifdef HANDLE_GENERIC_PRAGMAS
+ 
+ /* Handle a #pragma directive.
+    TOKEN is the token we read after `#pragma'.  Processes the entire input
+    line and return non-zero iff the pragma has been successfully parsed.  */
+ 
+ /* This function has to be in this file, in order to get at
+    the token types.  */
+ 
+ static int
+ handle_generic_pragma (token)
+      register int token;
+ {
+   for (;;)
+     {
+       switch (token)
+ 	{
+ 	case IDENTIFIER:
+ 	case TYPENAME:
+         case STRING:
+         case CONSTANT:
+ 	  handle_pragma_token (token_buffer, yylval.ttype);
+ 	  break;
+ 
+ 	case LEFT_RIGHT:
+ 	  handle_pragma_token ("(", NULL_TREE);
+ 	  handle_pragma_token (")", NULL_TREE);
+ 	  break;
+ 
+ 	case END_OF_LINE:
+ 	  return handle_pragma_token (NULL_PTR, NULL_TREE);
+ 
+ 	default:
+ 	  handle_pragma_token (token_buffer, NULL_TREE);
+ 	}
+       
+       token = real_yylex ();
+     }
+ }
+ #endif /* HANDLE_GENERIC_PRAGMAS */
+ 
+ static int
+ handle_cp_pragma (pname)
+      const char *pname;
+ {
+   register int token;
+ 
+   if (! strcmp (pname, "vtable"))
+     {
+       extern tree pending_vtables;
+ 
+       /* More follows: it must be a string constant (class name).  */
+       token = real_yylex ();
+       if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
+ 	{
+ 	  error ("invalid #pragma vtable");
+ 	  return -1;
+ 	}
+ 
+       pending_vtables
+ 	= perm_tree_cons (NULL_TREE,
+ 			  get_identifier (TREE_STRING_POINTER (yylval.ttype)),
+ 			  pending_vtables);
+       token = real_yylex ();
+       if (token != END_OF_LINE)
+ 	warning ("trailing characters ignored");
+       return 1;
+     }
+   else if (! strcmp (pname, "unit"))
+     {
+       /* More follows: it must be a string constant (unit name).  */
+       token = real_yylex ();
+       if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
+ 	{
+ 	  error ("invalid #pragma unit");
+ 	  return -1;
+ 	}
+       token = real_yylex ();
+       if (token != END_OF_LINE)
+ 	warning ("trailing characters ignored");
+       return 1;
+     }
+   else if (! strcmp (pname, "interface"))
+     {
+       char *main_filename = input_filename;
+ 
+       main_filename = file_name_nondirectory (main_filename);
+ 
+       token = real_yylex ();
+       
+       if (token != END_OF_LINE)
+ 	{
+ 	  if (token != STRING
+ 	      || TREE_CODE (yylval.ttype) != STRING_CST)
+ 	    {
+ 	      error ("invalid `#pragma interface'");
+ 	      return -1;
+ 	    }
+ 	  main_filename = TREE_STRING_POINTER (yylval.ttype);
+ 	  token = real_yylex ();
+ 	}
+ 
+       if (token != END_OF_LINE)
+ 	warning ("garbage after `#pragma interface' ignored");
+ 
+       cp_pragma_interface (main_filename);
+ 
+       return 1;
+     }
+   else if (! strcmp (pname, "implementation"))
+     {
+       char *main_filename = main_input_filename ? main_input_filename : input_filename;
+ 
+       main_filename = file_name_nondirectory (main_filename);
+ 
+       token = real_yylex ();
+ 
+       if (token != END_OF_LINE)
+ 	{
+ 	  if (token != STRING
+ 	      || TREE_CODE (yylval.ttype) != STRING_CST)
+ 	    {
+ 	      error ("invalid `#pragma implementation'");
+ 	      return -1;
+ 	    }
+ 	  main_filename = TREE_STRING_POINTER (yylval.ttype);
+ 	  token = real_yylex ();
+ 	}
+ 
+       if (token != END_OF_LINE)
+ 	warning ("garbage after `#pragma implementation' ignored");
+ 
+       cp_pragma_implementation (main_filename);
  
+       return 1;
+     }
+ 
+   return 0;
+ }
+ 
  void
  do_pending_lang_change ()
  {
*************** readescape (ignore_ptr)
*** 2633,2640 ****
  	;
        else if ((count - 1) * 4 >= TYPE_PRECISION (integer_type_node)
  	       || (count > 1
! 		   && (((unsigned)1 <<
! 			(TYPE_PRECISION (integer_type_node) - (count - 1) * 4))
  		       <= firstdig)))
  	pedwarn ("hex escape out of range");
        return code;
--- 2861,2869 ----
  	;
        else if ((count - 1) * 4 >= TYPE_PRECISION (integer_type_node)
  	       || (count > 1
! 		   && (((unsigned)1
! 			<< (TYPE_PRECISION (integer_type_node)
! 			    - (count - 1) * 4))
  		       <= firstdig)))
  	pedwarn ("hex escape out of range");
        return code;
*************** readescape (ignore_ptr)
*** 2705,2711 ****
--- 2934,2970 ----
      pedwarn ("unknown escape sequence: `\\' followed by char code 0x%x", c);
    return c;
  }
+ 
+ void
+ yyerror (string)
+      const char *string;
+ {
+   extern int end_of_file;
+   char buf[200];
+ 
+   strcpy (buf, string);
+ 
+   /* We can't print string and character constants well
+      because the token_buffer contains the result of processing escapes.  */
+   if (end_of_file)
+     strcat (buf, input_redirected ()
+ 	    ? " at end of saved text"
+ 	    : " at end of input");
+   else if (token_buffer[0] == 0)
+     strcat (buf, " at null character");
+   else if (token_buffer[0] == '"')
+     strcat (buf, " before string constant");
+   else if (token_buffer[0] == '\'')
+     strcat (buf, " before character constant");
+   else if (!ISGRAPH ((unsigned char)token_buffer[0]))
+     sprintf (buf + strlen (buf), " before character 0%o",
+ 	     (unsigned char) token_buffer[0]);
+   else
+     strcat (buf, " before `%s'");
  
+   error (buf, token_buffer);
+ }
+ 
  /* Value is 1 (or 2) if we should try to make the next identifier look like
     a typename (when it may be a local variable or a class variable).
     Value is 0 if we treat this name in a default fashion.  */
*************** identifier_typedecl_value (node)
*** 3097,3111 ****
    return NULL_TREE;
  }
  
! struct pf_args 
  {
    /* Input */
    /* I/O */
-   char *p;
    int c;
    int imag;
    tree type;
!   /* Output */
    REAL_VALUE_TYPE value;
  };
  
--- 3356,3372 ----
    return NULL_TREE;
  }
  
! struct pf_args
  {
    /* Input */
+   int base;
+   char * p;
    /* I/O */
    int c;
+   /* Output */
    int imag;
    tree type;
!   int conversion_errno;
    REAL_VALUE_TYPE value;
  };
  
*************** parse_float (data)
*** 3120,3130 ****
       REAL_VALUE_ATOF may not work any more.  */
    char *copy = (char *) alloca (args->p - token_buffer + 1);
    bcopy (token_buffer, copy, args->p - token_buffer + 1);
!   
    while (1)
      {
        int lose = 0;
!       
        /* Read the suffixes to choose a data type.  */
        switch (args->c)
  	{
--- 3381,3394 ----
       REAL_VALUE_ATOF may not work any more.  */
    char *copy = (char *) alloca (args->p - token_buffer + 1);
    bcopy (token_buffer, copy, args->p - token_buffer + 1);
!   args->imag = 0;
!   args->conversion_errno = 0;
!   args->type = double_type_node;
! 
    while (1)
      {
        int lose = 0;
! 
        /* Read the suffixes to choose a data type.  */
        switch (args->c)
  	{
*************** parse_float (data)
*** 3133,3145 ****
  	    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 (args->imag)
  	    error ("more than one `i' or `j' in numeric constant");
--- 3397,3409 ----
  	    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 (args->imag)
  	    error ("more than one `i' or `j' in numeric constant");
*************** parse_float (data)
*** 3147,3180 ****
  	    pedwarn ("ANSI C++ forbids imaginary numeric constants");
  	  args->imag = 1;
  	  break;
! 	  
  	default:
  	  lose = 1;
  	}
!       
        if (lose)
  	break;
!       
        if (args->p >= token_buffer + maxtoken - 3)
  	args->p = extend_token_buffer (args->p);
        *(args->p++) = args->c;
        *(args->p) = 0;
        args->c = getch ();
      }
!   
    /* 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");
!       
        args->type = float_type_node;
!       args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->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 (args->value) && pedantic)
  	warning ("floating point number exceeds range of `float'");
--- 3411,3449 ----
  	    pedwarn ("ANSI C++ forbids imaginary numeric constants");
  	  args->imag = 1;
  	  break;
! 
  	default:
  	  lose = 1;
  	}
! 
        if (lose)
  	break;
! 
        if (args->p >= token_buffer + maxtoken - 3)
  	args->p = extend_token_buffer (args->p);
        *(args->p++) = args->c;
        *(args->p) = 0;
        args->c = getch ();
      }
! 
    /* 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");
! 
        args->type = float_type_node;
!       errno = 0;
!       if (args->base == 16)
! 	args->value = REAL_VALUE_HTOF (copy, TYPE_MODE (args->type));
!       else
! 	args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type));
!       args->conversion_errno = errno;
        /* A diagnostic is required here by some ANSI C testsuites.
! 	 This is not pedwarn, because some people don't want
  	 an error for this.  */
        if (REAL_VALUE_ISINF (args->value) && pedantic)
  	warning ("floating point number exceeds range of `float'");
*************** parse_float (data)
*** 3182,3194 ****
    else if (lflag)
      {
        args->type = long_double_type_node;
!       args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type));
        if (REAL_VALUE_ISINF (args->value) && pedantic)
  	warning ("floating point number exceeds range of `long double'");
      }
    else
      {
!       args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type));
        if (REAL_VALUE_ISINF (args->value) && pedantic)
  	warning ("floating point number exceeds range of `double'");
      }
--- 3451,3473 ----
    else if (lflag)
      {
        args->type = long_double_type_node;
!       errno = 0;
!       if (args->base == 16)
! 	args->value = REAL_VALUE_HTOF (copy, TYPE_MODE (args->type));
!       else
! 	args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type));
!       args->conversion_errno = errno;
        if (REAL_VALUE_ISINF (args->value) && pedantic)
  	warning ("floating point number exceeds range of `long double'");
      }
    else
      {
!       errno = 0;
!       if (args->base == 16)
! 	args->value = REAL_VALUE_HTOF (copy, TYPE_MODE (args->type));
!       else
! 	args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type));
!       args->conversion_errno = errno;
        if (REAL_VALUE_ISINF (args->value) && pedantic)
  	warning ("floating point number exceeds range of `double'");
      }
*************** int
*** 3232,3241 ****
  real_yylex ()
  {
    register int c;
    register int value;
    int wide_flag = 0;
-   int dollar_seen = 0;
-   int i;
  
    c = getch ();
  
--- 3511,3519 ----
  real_yylex ()
  {
    register int c;
+   register char *p;
    register int value;
    int wide_flag = 0;
  
    c = getch ();
  
*************** real_yylex ()
*** 3277,3284 ****
    switch (c)
      {
      case EOF:
-       token_buffer[0] = '\0';
        end_of_file = 1;
        if (input_redirected ())
  	value = END_OF_SAVED_INPUT;
        else if (linemode)
--- 3555,3562 ----
    switch (c)
      {
      case EOF:
        end_of_file = 1;
+       token_buffer[0] = 0;
        if (input_redirected ())
  	value = END_OF_SAVED_INPUT;
        else if (linemode)
*************** real_yylex ()
*** 3287,3300 ****
  	value = ENDFILE;
        break;
  
-     case '$':
-       if (! dollars_in_ident)
- 	error ("`$' in identifier");
-       else if (pedantic)
- 	pedwarn ("`$' in identifier");
-       dollar_seen = 1;
-       goto letter;
- 
      case 'L':
  #if USE_CPPLIB
        if (cpp_token == CPP_NAME)
--- 3565,3570 ----
*************** real_yylex ()
*** 3315,3321 ****
  	  }
  	token_put_back (c);
        }
! 
      case 'A':  case 'B':  case 'C':  case 'D':  case 'E':
      case 'F':  case 'G':  case 'H':  case 'I':  case 'J':
      case 'K':		  case 'M':  case 'N':  case 'O':
--- 3585,3591 ----
  	  }
  	token_put_back (c);
        }
!       
      case 'A':  case 'B':  case 'C':  case 'D':  case 'E':
      case 'F':  case 'G':  case 'H':  case 'I':  case 'J':
      case 'K':		  case 'M':  case 'N':  case 'O':
*************** real_yylex ()
*** 3329,3509 ****
      case 'u':  case 'v':  case 'w':  case 'x':  case 'y':
      case 'z':
      case '_':
      letter:
-       {
- 	register char *p;
- 
  #if USE_CPPLIB
! 	if (cpp_token == CPP_NAME)
! 	  {
! 	    /* Note that one character has already been read from
! 	       yy_cur into token_buffer.  */
! 
! 	    int len = yy_lim - yy_cur + 1;
! 	    if (len >= maxtoken)
! 	      extend_token_buffer_to (len + 1);
! 	    memcpy (token_buffer + 1, yy_cur, len);
! 	    p = token_buffer + len;
! 	    yy_cur = yy_lim;
! 	  }
! 	else
  #endif
! 	  {
! 	    /* We already installed C as the first char in token_buffer.  */
! 	    p = token_buffer+1;
! 	    c = token_getch ();
! 
! 	    while (ISALNUM (c) || (c == '_') || c == '$')
! 	      {
! 		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);
! 
! 		*p++ = c;
! 		c = token_getch ();
! 	      }
  
! 	    *p = 0;
! 	    token_put_back (c);
! 	  }
  
! 	value = IDENTIFIER;
! 	yylval.itype = 0;
  
! 	/* Try to recognize a keyword.  Uses minimum-perfect hash function */
  
! 	{
! 	  register struct resword *ptr;
  
! 	  if ((ptr = is_reserved_word (token_buffer, p - token_buffer)))
! 	    {
! 	      if (ptr->rid)
! 		{
! 		  tree old_ttype = ridpointers[(int) ptr->rid];
  
! 		  /* If this provides a type for us, then revert lexical
! 		     state to standard state.  */
! 		  if (TREE_CODE (old_ttype) == IDENTIFIER_NODE
! 		      && IDENTIFIER_GLOBAL_VALUE (old_ttype) != 0
! 		      && TREE_CODE (IDENTIFIER_GLOBAL_VALUE (old_ttype)) == TYPE_DECL)
! 		    looking_for_typename = 0;
! 		  else if (ptr->token == AGGR || ptr->token == ENUM)
! 		    looking_for_typename = 2;
  
! 		  if (ptr->token == VISSPEC)
! 		    {
! 		      switch (ptr->rid)
! 			{
! 			case RID_PUBLIC:
! 			  yylval.ttype = access_public_node;
! 			  break;
! 			case RID_PRIVATE:
! 			  yylval.ttype = access_private_node;
! 			  break;
! 			case RID_PROTECTED:
! 			  yylval.ttype = access_protected_node;
! 			  break;
! 			default:
! 			  my_friendly_abort (63);
! 			}
! 		    }
! 		  else
! 		    yylval.ttype = old_ttype;
! 		}
! 	      else switch (ptr->token)
! 		{
! 		case EQCOMPARE:
! 		  yylval.code = NE_EXPR;
! 		  token_buffer[0] = '!';
! 		  token_buffer[1] = '=';
! 		  token_buffer[2] = 0;
! 		  break;
  
! 		case ASSIGN:
! 		  if (strcmp ("and_eq", token_buffer) == 0)
! 		    {
! 		      yylval.code = BIT_AND_EXPR;
! 		      token_buffer[0] = '&';
! 		    }
! 		  else if (strcmp ("or_eq", token_buffer) == 0)
! 		    {
! 		      yylval.code = BIT_IOR_EXPR;
! 		      token_buffer[0] = '|';
! 		    }
! 		  else if (strcmp ("xor_eq", token_buffer) == 0)
! 		    {
! 		      yylval.code = BIT_XOR_EXPR;
! 		      token_buffer[0] = '^';
! 		    }
! 		  token_buffer[1] = '=';
! 		  token_buffer[2] = 0;
! 		  break;
  
! 		case '&':
! 		  yylval.code = BIT_AND_EXPR;
! 		  token_buffer[0] = '&';
! 		  token_buffer[1] = 0;
! 		  break;
  
! 		case '|':
! 		  yylval.code = BIT_IOR_EXPR;
! 		  token_buffer[0] = '|';
! 		  token_buffer[1] = 0;
! 		  break;
  
! 		case '^':
! 		  yylval.code = BIT_XOR_EXPR;
! 		  token_buffer[0] = '^';
! 		  token_buffer[1] = 0;
! 		  break;
! 		}
  
! 	      value = (int) ptr->token;
! 	    }
! 	}
  
! 	/* If we did not find a keyword, look for an identifier
! 	   (or a typename).  */
  
! 	if (value == IDENTIFIER || value == TYPESPEC)
! 	  GNU_xref_ref (current_function_decl, token_buffer);
  
! 	if (value == IDENTIFIER)
! 	  {
! 	    register tree tmp = get_identifier (token_buffer);
  
  #if !defined(VMS) && defined(JOINER)
! 	    /* Make sure that user does not collide with our internal
! 	       naming scheme.  */
! 	    if (JOINER == '$'
! 		&& dollar_seen
! 		&& (THIS_NAME_P (tmp)
! 		    || VPTR_NAME_P (tmp)
! 		    || DESTRUCTOR_NAME_P (tmp)
! 		    || VTABLE_NAME_P (tmp)
! 		    || TEMP_NAME_P (tmp)
! 		    || ANON_AGGRNAME_P (tmp)
! 		    || ANON_PARMNAME_P (tmp)))
! 	      warning ("identifier name `%s' conflicts with GNU C++ internal naming strategy",
! 		       token_buffer);
  #endif
  
! 	    yylval.ttype = tmp;
! 	  }
! 	if (value == NEW && ! global_bindings_p ())
! 	  {
! 	    value = NEW;
! 	    goto done;
! 	  }
!       }
! 
        break;
  
      case '.':
--- 3599,3762 ----
      case 'u':  case 'v':  case 'w':  case 'x':  case 'y':
      case 'z':
      case '_':
+     case '$':
      letter:
  #if USE_CPPLIB
!       if (cpp_token == CPP_NAME)
! 	{
! 	  /* Note that one character has already been read from
! 	     yy_cur into token_buffer.  Also, cpplib complains about
! 	     $ in identifiers, so we don't have to.  */
! 
! 	  int len = yy_lim - yy_cur + 1;
! 	  if (len >= maxtoken)
! 	    extend_token_buffer_to (len + 1);
! 	  memcpy (token_buffer + 1, yy_cur, len);
! 	  p = token_buffer + len;
! 	  yy_cur = yy_lim;
! 	}
!       else
  #endif
! 	{
! 	  p = token_buffer;
! 	  while (ISALNUM (c) || (c == '_') || c == '$')
! 	    {
! 	      /* Make sure this char really belongs in an identifier.  */
! 	      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);
  
! 	      *p++ = c;
! 	      c = token_getch ();
! 	    }
  
! 	  *p = 0;
! 	  token_put_back (c);
! 	}
  
!       value = IDENTIFIER;
!       yylval.itype = 0;
  
!       /* Try to recognize a keyword.  Uses minimum-perfect hash function */
  
!       {
! 	register struct resword *ptr;
  
! 	if ((ptr = is_reserved_word (token_buffer, p - token_buffer)))
! 	  {
! 	    if (ptr->rid)
! 	      {
! 		if (ptr->token == VISSPEC)
! 		  {
! 		    switch (ptr->rid)
! 		      {
! 		      case RID_PUBLIC:
! 			yylval.ttype = access_public_node;
! 			break;
! 		      case RID_PRIVATE:
! 			yylval.ttype = access_private_node;
! 			break;
! 		      case RID_PROTECTED:
! 			yylval.ttype = access_protected_node;
! 			break;
! 		      default:
! 			my_friendly_abort (63);
! 		      }
! 		  }
! 		else
! 		  yylval.ttype = ridpointers[(int) ptr->rid];
! 	      }
! 	    else switch (ptr->token)
! 	      {
! 	      case EQCOMPARE:
! 		yylval.code = NE_EXPR;
! 		token_buffer[0] = '!';
! 		token_buffer[1] = '=';
! 		token_buffer[2] = 0;
! 		break;
  
! 	      case ASSIGN:
! 		if (strcmp ("and_eq", token_buffer) == 0)
! 		  {
! 		    yylval.code = BIT_AND_EXPR;
! 		    token_buffer[0] = '&';
! 		  }
! 		else if (strcmp ("or_eq", token_buffer) == 0)
! 		  {
! 		    yylval.code = BIT_IOR_EXPR;
! 		    token_buffer[0] = '|';
! 		  }
! 		else if (strcmp ("xor_eq", token_buffer) == 0)
! 		  {
! 		    yylval.code = BIT_XOR_EXPR;
! 		    token_buffer[0] = '^';
! 		  }
! 		token_buffer[1] = '=';
! 		token_buffer[2] = 0;
! 		break;
  
! 	      case '&':
! 		yylval.code = BIT_AND_EXPR;
! 		token_buffer[0] = '&';
! 		token_buffer[1] = 0;
! 		break;
  
! 	      case '|':
! 		yylval.code = BIT_IOR_EXPR;
! 		token_buffer[0] = '|';
! 		token_buffer[1] = 0;
! 		break;
  
! 	      case '^':
! 		yylval.code = BIT_XOR_EXPR;
! 		token_buffer[0] = '^';
! 		token_buffer[1] = 0;
! 		break;
! 	      }
  
! 	    value = (int) ptr->token;
! 	  }
!       }
  
!       /* If we did not find a keyword, look for an identifier
! 	 (or a typename).  */
  
!       if (value == IDENTIFIER || value == TYPESPEC)
! 	GNU_xref_ref (current_function_decl, token_buffer);
  
!       if (value == IDENTIFIER)
! 	{
! 	  register tree tmp = get_identifier (token_buffer);
  
  #if !defined(VMS) && defined(JOINER)
! 	  /* Make sure that user does not collide with our internal
! 	     naming scheme.  */
! 	  if (JOINER == '$'
! 	      && (THIS_NAME_P (tmp)
! 		  || VPTR_NAME_P (tmp)
! 		  || DESTRUCTOR_NAME_P (tmp)
! 		  || VTABLE_NAME_P (tmp)
! 		  || TEMP_NAME_P (tmp)
! 		  || ANON_AGGRNAME_P (tmp)
! 		  || ANON_PARMNAME_P (tmp)))
! 	    warning ("identifier name `%s' conflicts with GNU C++ internal naming strategy",
! 		     token_buffer);
  #endif
  
! 	  yylval.ttype = tmp;
! 	}
!       if (value == NEW && ! global_bindings_p ())
! 	{
! 	  value = NEW;
! 	  goto done;
! 	}
        break;
  
      case '.':
*************** real_yylex ()
*** 3537,3549 ****
  	  if (ISDIGIT (c1))
  	    {
  	      token_put_back (c1);
! 	      goto resume_numerical_scan;
  	    }
  	  token_put_back (c1);
  	}
        value = '.';
        token_buffer[1] = 0;
!       goto done;
  
      case '0':  case '1':
        /* Optimize for most frequent case.  */
--- 3790,3802 ----
  	  if (ISDIGIT (c1))
  	    {
  	      token_put_back (c1);
! 	      goto number;
  	    }
  	  token_put_back (c1);
  	}
        value = '.';
        token_buffer[1] = 0;
!       break;
  
      case '0':  case '1':
        /* Optimize for most frequent case.  */
*************** real_yylex ()
*** 3559,3579 ****
  #endif
  	if (cond)
  	  {
! 	    /* Terminate string.  */
! 	    if (c == '0')
! 	      yylval.ttype = integer_zero_node;
! 	    else
! 	      yylval.ttype = integer_one_node;
  	    value = CONSTANT;
! 	    goto done;
  	  }
        }
!     /* fall through...  */
! 			  case '2':  case '3':  case '4':
      case '5':  case '6':  case '7':  case '8':  case '9':
!     resume_numerical_scan:
        {
- 	register char *p;
  	int base = 10;
  	int count = 0;
  	int largest_digit = 0;
--- 3812,3827 ----
  #endif
  	if (cond)
  	  {
! 	    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':
!     number:
        {
  	int base = 10;
  	int count = 0;
  	int largest_digit = 0;
*************** real_yylex ()
*** 3591,3598 ****
  #define TOTAL_PARTS ((HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR) * 2)
  	unsigned int parts[TOTAL_PARTS];
  
! 	enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS} floatflag
! 	  = NOT_FLOAT;
  
  	for (count = 0; count < TOTAL_PARTS; count++)
  	  parts[count] = 0;
--- 3839,3846 ----
  #define TOTAL_PARTS ((HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR) * 2)
  	unsigned int parts[TOTAL_PARTS];
  
! 	enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS, AFTER_EXPON }
! 	  floatflag = NOT_FLOAT;
  
  	for (count = 0; count < TOTAL_PARTS; count++)
  	  parts[count] = 0;
*************** real_yylex ()
*** 3621,3639 ****
  	/* Read all the digits-and-decimal-points.  */
  
  	while (c == '.'
! 	       || (ISALNUM (c) && (c != 'l') && (c != 'L')
! 		   && (c != 'u') && (c != 'U')
  		   && c != 'i' && c != 'I' && c != 'j' && c != 'J'
  		   && (floatflag == NOT_FLOAT || ((c != 'f') && (c != 'F')))))
  	  {
  	    if (c == '.')
  	      {
! 		if (base == 16)
! 		  error ("floating constant may not be in radix 16");
  		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;
--- 3869,3887 ----
  	/* Read all the digits-and-decimal-points.  */
  
  	while (c == '.'
! 	       || (ISALNUM (c) && c != 'l' && c != 'L'
! 		   && c != 'u' && c != 'U'
  		   && c != 'i' && c != 'I' && c != 'j' && c != 'J'
  		   && (floatflag == NOT_FLOAT || ((c != 'f') && (c != 'F')))))
  	  {
  	    if (c == '.')
  	      {
! 		if (base == 16 && pedantic)
! 		  pedwarn ("floating constant may not be in radix 16");
  		if (floatflag == TOO_MANY_POINTS)
  		  /* We have already emitted an error.  Don't need another.  */
  		  ;
! 		else if (floatflag == AFTER_POINT || floatflag == AFTER_EXPON)
  		  {
  		    error ("malformed floating constant");
  		    floatflag = TOO_MANY_POINTS;
*************** real_yylex ()
*** 3644,3650 ****
  		else
  		  floatflag = AFTER_POINT;
  
! 		base = 10;
  		*p++ = c = token_getch ();
  		/* Accept '.' as the start of a floating-point number
  		   only when it is followed by a digit.  */
--- 3892,3899 ----
  		else
  		  floatflag = AFTER_POINT;
  
! 		if (base == 8)
! 		  base = 10;
  		*p++ = c = token_getch ();
  		/* Accept '.' as the start of a floating-point number
  		   only when it is followed by a digit.  */
*************** real_yylex ()
*** 3665,3676 ****
  		    if (c == 'e' || c == 'E')
  		      {
  			base = 10;
! 			floatflag = AFTER_POINT;
  			break;   /* start of exponent */
  		      }
  		    error ("nondigits in number and not hexadecimal");
  		    c = 0;
  		  }
  		else if (c >= 'a')
  		  {
  		    c = c - 'a' + 10;
--- 3914,3930 ----
  		    if (c == 'e' || c == 'E')
  		      {
  			base = 10;
! 			floatflag = AFTER_EXPON;
  			break;   /* start of exponent */
  		      }
  		    error ("nondigits in number and not hexadecimal");
  		    c = 0;
  		  }
+ 		else if (base == 16 && (c == 'p' || c == 'P'))
+ 		  {
+ 		    floatflag = AFTER_EXPON;
+ 		    break;   /* start of exponent */
+ 		  }
  		else if (c >= 'a')
  		  {
  		    c = c - 'a' + 10;
*************** real_yylex ()
*** 3725,3739 ****
  
  	if (floatflag != NOT_FLOAT)
  	  {
! 	    tree type = double_type_node;
! 	    int exceeds_double = 0;
! 	    int imag = 0;
  	    REAL_VALUE_TYPE value;
  	    struct pf_args args;
  
  	    /* Read explicit exponent if any, and put it in tokenbuf.  */
  
! 	    if ((c == 'e') || (c == 'E'))
  	      {
  		if (p >= token_buffer + maxtoken - 3)
  		  p = extend_token_buffer (p);
--- 3979,3993 ----
  
  	if (floatflag != NOT_FLOAT)
  	  {
! 	    tree type;
! 	    int imag, conversion_errno;
  	    REAL_VALUE_TYPE value;
  	    struct pf_args args;
  
  	    /* Read explicit exponent if any, and put it in tokenbuf.  */
  
! 	    if ((base == 10 && ((c == 'e') || (c == 'E')))
! 		|| (base == 16 && (c == 'p' || c == 'P')))
  	      {
  		if (p >= token_buffer + maxtoken - 3)
  		  p = extend_token_buffer (p);
*************** real_yylex ()
*** 3744,3752 ****
  		    *p++ = c;
  		    c = token_getch ();
  		  }
  		if (! ISDIGIT (c))
  		  error ("floating constant exponent has no digits");
! 	        while (ISDIGIT (c))
  		  {
  		    if (p >= token_buffer + maxtoken - 3)
  		      p = extend_token_buffer (p);
--- 3998,4007 ----
  		    *p++ = c;
  		    c = token_getch ();
  		  }
+ 		/* Exponent is decimal, even if string is a hex float.  */
  		if (! ISDIGIT (c))
  		  error ("floating constant exponent has no digits");
! 		while (ISDIGIT (c))
  		  {
  		    if (p >= token_buffer + maxtoken - 3)
  		      p = extend_token_buffer (p);
*************** real_yylex ()
*** 3754,3769 ****
  		    c = token_getch ();
  		  }
  	      }
  
  	    *p = 0;
- 	    errno = 0;
  
  	    /* Setup input for parse_float() */
  	    args.p = p;
  	    args.c = c;
! 	    args.imag = imag;
! 	    args.type = type;
! 	    
  	    /* Convert string to a double, checking for overflow.  */
  	    if (do_float_handler (parse_float, (PTR) &args))
  	      {
--- 4009,4024 ----
  		    c = token_getch ();
  		  }
  	      }
+ 	    if (base == 16 && floatflag != AFTER_EXPON)
+ 	      error ("hexadecimal floating constant has no exponent");
  
  	    *p = 0;
  
  	    /* Setup input for parse_float() */
+ 	    args.base = base;
  	    args.p = p;
  	    args.c = c;
! 
  	    /* Convert string to a double, checking for overflow.  */
  	    if (do_float_handler (parse_float, (PTR) &args))
  	      {
*************** real_yylex ()
*** 3778,3801 ****
  	      }
  
  	    /* Receive output from parse_float() */
- 	    p = args.p;
  	    c = args.c;
  	    imag = args.imag;
  	    type = args.type;
  	    
  #ifdef ERANGE
! 	    if (errno == ERANGE && pedantic)
! 	      {
!   		/* ERANGE is also reported for underflow,
!   		   so test the value to distinguish overflow from that.  */
! 		if (REAL_VALUES_LESS (dconst1, value)
! 		    || REAL_VALUES_LESS (value, dconstm1))
! 		  {
! 		    pedwarn ("floating point number exceeds range of `%s'",
! 			     IDENTIFIER_POINTER (TYPE_IDENTIFIER (type)));
! 		    exceeds_double = 1;
! 		  }
! 	      }
  #endif
  
  	    /* If the result is not a number, assume it must have been
--- 4033,4050 ----
  	      }
  
  	    /* Receive output from parse_float() */
  	    c = args.c;
  	    imag = args.imag;
  	    type = args.type;
+ 	    conversion_errno = args.conversion_errno;
  	    
  #ifdef ERANGE
! 	    /* ERANGE is also reported for underflow,
! 	       so test the value to distinguish overflow from that.  */
! 	    if (conversion_errno == ERANGE && pedantic
! 		&& (REAL_VALUES_LESS (dconst1, value)
! 		    || REAL_VALUES_LESS (value, dconstm1)))
! 	      warning ("floating point number exceeds range of `double'");
  #endif
  
  	    /* If the result is not a number, assume it must have been
*************** real_yylex ()
*** 3807,3813 ****
  	    /* Create a node with determined type and value.  */
  	    if (imag)
  	      yylval.ttype = build_complex (NULL_TREE,
! 					    cp_convert (type, integer_zero_node),
  					    build_real (type, value));
  	    else
  	      yylval.ttype = build_real (type, value);
--- 4056,4062 ----
  	    /* Create a node with determined type and value.  */
  	    if (imag)
  	      yylval.ttype = build_complex (NULL_TREE,
! 					    convert (type, integer_zero_node),
  					    build_real (type, value));
  	    else
  	      yylval.ttype = build_real (type, value);
*************** real_yylex ()
*** 3820,3826 ****
  	    int spec_long = 0;
  	    int spec_long_long = 0;
  	    int spec_imag = 0;
! 	    int warn;
  
  	    while (1)
  	      {
--- 4069,4075 ----
  	    int spec_long = 0;
  	    int spec_long_long = 0;
  	    int spec_imag = 0;
! 	    int warn, i;
  
  	    while (1)
  	      {
*************** real_yylex ()
*** 3867,3872 ****
--- 4116,4122 ----
  
  	    /* This is simplified by the fact that our constant
  	       is always positive.  */
+ 
  	    high = low = 0;
  
  	    for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; i++)
*************** real_yylex ()
*** 3876,3902 ****
  			 << (i * HOST_BITS_PER_CHAR));
  		low |= (HOST_WIDE_INT) parts[i] << (i * HOST_BITS_PER_CHAR);
  	      }
! 	    
! 	    
  	    yylval.ttype = build_int_2 (low, high);
  	    TREE_TYPE (yylval.ttype) = long_long_unsigned_type_node;
  
  	    /* Calculate the ANSI type.  */
! 	    if (!spec_long && !spec_unsigned
  		&& int_fits_type_p (yylval.ttype, integer_type_node))
  	      type = integer_type_node;
! 	    else if (!spec_long && (base != 10 || spec_unsigned)
  		     && int_fits_type_p (yylval.ttype, unsigned_type_node))
- 	      /* Nondecimal constants try unsigned even in traditional C.  */
  	      type = unsigned_type_node;
! 	    else if (!spec_unsigned && !spec_long_long
  		     && int_fits_type_p (yylval.ttype, long_integer_type_node))
  	      type = long_integer_type_node;
! 	    else if (! spec_long_long)
  	      type = long_unsigned_type_node;
  	    else if (! spec_unsigned
- 		     /* Verify value does not overflow into sign bit.  */
- 		     && TREE_INT_CST_HIGH (yylval.ttype) >= 0
  		     && int_fits_type_p (yylval.ttype,
  					 long_long_integer_type_node))
  	      type = long_long_integer_type_node;
--- 4126,4150 ----
  			 << (i * HOST_BITS_PER_CHAR));
  		low |= (HOST_WIDE_INT) parts[i] << (i * HOST_BITS_PER_CHAR);
  	      }
! 
  	    yylval.ttype = build_int_2 (low, high);
  	    TREE_TYPE (yylval.ttype) = long_long_unsigned_type_node;
  
  	    /* Calculate the ANSI type.  */
! 	    if (! spec_long && ! spec_unsigned
  		&& int_fits_type_p (yylval.ttype, integer_type_node))
  	      type = integer_type_node;
! 	    else if (! spec_long && (base != 10 || spec_unsigned)
  		     && int_fits_type_p (yylval.ttype, unsigned_type_node))
  	      type = unsigned_type_node;
! 	    else if (! spec_unsigned && !spec_long_long
  		     && int_fits_type_p (yylval.ttype, long_integer_type_node))
  	      type = long_integer_type_node;
! 	    else if (! spec_long_long
! 		     && int_fits_type_p (yylval.ttype,
! 					 long_unsigned_type_node))
  	      type = long_unsigned_type_node;
  	    else if (! spec_unsigned
  		     && int_fits_type_p (yylval.ttype,
  					 long_long_integer_type_node))
  	      type = long_long_integer_type_node;
*************** real_yylex ()
*** 3910,3920 ****
  	    else
  	      type = widest_unsigned_literal_type_node;
  
! 	    if (!int_fits_type_p (yylval.ttype, type) && !warn)
! 	      pedwarn ("integer constant is larger than the maximum value for its type");
  
  	    if (base == 10 && ! spec_unsigned && TREE_UNSIGNED (type))
! 	      warning ("decimal integer constant is so large that it is unsigned");
  
  	    if (spec_imag)
  	      {
--- 4158,4173 ----
  	    else
  	      type = widest_unsigned_literal_type_node;
  
! 	    if (pedantic && !spec_long_long && !warn
! 		&& (TYPE_PRECISION (long_integer_type_node)
! 		    < TYPE_PRECISION (type)))
! 	      {
! 		warn = 1;
! 		pedwarn ("integer constant larger than the maximum value of an unsigned long int");
! 	      }
  
  	    if (base == 10 && ! spec_unsigned && TREE_UNSIGNED (type))
! 	      warning ("decimal constant is so large that it is unsigned");
  
  	    if (spec_imag)
  	      {
*************** real_yylex ()
*** 3922,3939 ****
  		    <= TYPE_PRECISION (integer_type_node))
  		  yylval.ttype
  		    = build_complex (NULL_TREE, integer_zero_node,
! 				     cp_convert (integer_type_node,
! 						 yylval.ttype));
  		else
  		  error ("complex integer constant is too wide for `__complex int'");
  	      }
  	    else
  	      TREE_TYPE (yylval.ttype) = type;
  	  }
  
  	token_put_back (c);
  	*p = 0;
  
  	value = CONSTANT; break;
        }
  
--- 4175,4206 ----
  		    <= TYPE_PRECISION (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'");
  	      }
  	    else
  	      TREE_TYPE (yylval.ttype) = type;
+ 
+ 
+ 	    /* If it's still an integer (not a complex), and it doesn't
+ 	       fit in the type we choose for it, then pedwarn. */
+ 
+ 	    if (! warn
+ 		&& TREE_CODE (TREE_TYPE (yylval.ttype)) == INTEGER_TYPE
+ 		&& ! int_fits_type_p (yylval.ttype, TREE_TYPE (yylval.ttype)))
+ 	      pedwarn ("integer constant is larger than the maximum value for its type");
  	  }
  
  	token_put_back (c);
  	*p = 0;
  
+ 	if (ISALNUM (c) || c == '.' || c == '_' || c == '$'
+ 	    || ((c == '-' || c == '+')
+ 		&& (p[-1] == 'e' || p[-1] == 'E')))
+ 	  error ("missing white space after number `%s'", token_buffer);
+ 
  	value = CONSTANT; break;
        }
  
*************** real_yylex ()
*** 4057,4063 ****
  	      }
  
  	    /* Merge character into result; ignore excess chars.  */
! 	    num_chars++;
  	    if (num_chars < max_chars + 1)
  	      {
  		if (width < HOST_BITS_PER_INT)
--- 4324,4330 ----
  	      }
  
  	    /* Merge character into result; ignore excess chars.  */
! 	    num_chars += (width / TYPE_PRECISION (char_type_node));
  	    if (num_chars < max_chars + 1)
  	      {
  		if (width < HOST_BITS_PER_INT)
*************** real_yylex ()
*** 4097,4102 ****
--- 4364,4370 ----
  		= build_int_2 (result | ~(~(unsigned HOST_WIDE_INT) 0
  					  >> (HOST_BITS_PER_WIDE_INT - num_bits)),
  			       -1);
+ 	    /* In C, a character constant has type 'int'; in C++, 'char'.  */
  	    if (chars_seen <= 1)
  	      TREE_TYPE (yylval.ttype) = char_type_node;
  	    else
*************** real_yylex ()
*** 4115,4121 ****
      case '"':
      string_constant:
        {
- 	register char *p;
  	unsigned width = wide_flag ? WCHAR_TYPE_SIZE
  	                           : TYPE_PRECISION (char_type_node);
  #ifdef MULTIBYTE_CHARS
--- 4383,4388 ----
*************** real_yylex ()
*** 4137,4143 ****
  		  goto skipnewline;
  		if (width < HOST_BITS_PER_INT
  		    && (unsigned) c >= ((unsigned)1 << width))
! 		  warning ("escape sequence out of range for character");
  	      }
  	    else if (c == '\n')
  	      {
--- 4404,4410 ----
  		  goto skipnewline;
  		if (width < HOST_BITS_PER_INT
  		    && (unsigned) c >= ((unsigned)1 << width))
! 		  pedwarn ("escape sequence out of range for character");
  	      }
  	    else if (c == '\n')
  	      {
*************** real_yylex ()
*** 4198,4204 ****
  		for (byte = 0; byte < WCHAR_BYTES; ++byte)
  		  {
  		    int value;
! 		    if (byte >= (int) sizeof(c))
  		      value = 0;
  		    else
  		      value = (c >> (byte * width)) & bytemask;
--- 4465,4471 ----
  		for (byte = 0; byte < WCHAR_BYTES; ++byte)
  		  {
  		    int value;
! 		    if (byte >= (int) sizeof (c))
  		      value = 0;
  		    else
  		      value = (c >> (byte * width)) & bytemask;
*************** real_yylex ()
*** 4218,4227 ****
  
  	  skipnewline:
  	    c = token_getch ();
- 	    if (c == EOF) {
- 		error ("Unterminated string");
- 		break;
- 	    }
  	  }
  
  	/* Terminate the string value, either with a single byte zero
--- 4485,4490 ----
*************** real_yylex ()
*** 4240,4245 ****
--- 4503,4511 ----
  	    *p++ = 0;
  	  }
  
+ 	if (c == EOF)
+ 	  error ("Unterminated string constant");
+ 
  	/* We have read the entire constant.
  	   Construct a STRING_CST for the result.  */
  
*************** real_yylex ()
*** 4261,4266 ****
--- 4527,4533 ----
      case '-':
      case '&':
      case '|':
+     case ':':
      case '<':
      case '>':
      case '*':
*************** real_yylex ()
*** 4337,4355 ****
  	    case '>':
  	      c = RSHIFT;
  	      goto combine;
  	    }
- 	else if ((c == '-') && (c1 == '>'))
- 	  {
- 	    c1 = token_getch ();
- 	    if (c1 == '*')
- 	      value = POINTSAT_STAR;
- 	    else
- 	      {
- 		token_put_back (c1);
- 		value = POINTSAT;
- 	      }
- 	    goto done;
- 	  }
  	else if (c1 == '?' && (c == '<' || c == '>'))
  	  {
  	    token_buffer[3] = 0;
--- 4604,4614 ----
  	    case '>':
  	      c = RSHIFT;
  	      goto combine;
+ 	    case ':':
+ 	      value = SCOPE;
+ 	      yylval.itype = 1;
+ 	      goto done;
  	    }
  	else if (c1 == '?' && (c == '<' || c == '>'))
  	  {
  	    token_buffer[3] = 0;
*************** real_yylex ()
*** 4372,4420 ****
  		       token_buffer);
  	    goto done;
  	  }
! 	/* digraphs */
! 	else if (c == '<' && c1 == '%')
! 	  { value = '{'; goto done; }
! 	else if (c == '<' && c1 == ':')
! 	  { value = '['; goto done; }
! 	else if (c == '%' && c1 == '>')
! 	  { value = '}'; goto done; }
! 	else if (c == '%' && c1 == ':')
! 	  { value = '#'; goto done; }
  
  	token_put_back (c1);
  	token_buffer[1] = 0;
  
  	value = c;
! 	goto done;
        }
  
-     case ':':
-       c = token_getch ();
-       if (c == ':')
- 	{
- 	  token_buffer[1] = ':';
- 	  token_buffer[2] = '\0';
- 	  value = SCOPE;
- 	  yylval.itype = 1;
- 	}
-       else if (c == '>')
- 	{
- 	  value = ']';
- 	  goto done;
- 	}
-       else
- 	{
- 	  token_put_back (c);
- 	  value = ':';
- 	}
-       break;
- 
      case 0:
        /* Don't make yyparse think this is eof.  */
        value = 1;
        break;
  
      default:
        value = c;
      }
--- 4631,4696 ----
  		       token_buffer);
  	    goto done;
  	  }
! 	else
! 	  switch (c)
! 	    {
! 	    case '-':
! 	      if (c1 == '>')
! 		{
! 		  c1 = token_getch ();
! 		  if (c1 == '*')
! 		    value = POINTSAT_STAR;
! 		  else
! 		    {
! 		      token_put_back (c1);
! 		      value = POINTSAT;
! 		    }
! 		  goto done;
! 		}
! 	      break;
! 
! 	      /* digraphs */
! 	    case ':':
! 	      if (c1 == '>')
! 		{ value = ']'; goto done; }
! 	      break;
! 	    case '<':
! 	      if (c1 == '%')
! 		{ value = '{'; indent_level++; goto done; }
! 	      if (c1 == ':')
! 		{ value = '['; goto done; }
! 	      break;
! 	    case '%':
! 	      if (c1 == '>')
! 		{ value = '}'; indent_level--; goto done; }
! 	      break;
! 	    }
  
  	token_put_back (c1);
  	token_buffer[1] = 0;
  
+ 	/* Here the C frontend changes < and > to ARITHCOMPARE.  We don't
+ 	   do that because of templates.  */
+ 
  	value = c;
! 	break;
        }
  
      case 0:
        /* Don't make yyparse think this is eof.  */
        value = 1;
        break;
  
+     case '{':
+       indent_level++;
+       value = c;
+       break;
+ 
+     case '}':
+       indent_level--;
+       value = c;
+       break;
+ 
      default:
        value = c;
      }
*************** compiler_error VPROTO ((const char *msg,
*** 4690,4824 ****
    error_with_file_and_line (input_filename, lineno, "%s (compiler error)", buf);
  }
  
- void
- yyerror (string)
-      const char *string;
- {
-   extern int end_of_file;
-   char buf[200];
- 
-   strcpy (buf, string);
- 
-   /* We can't print string and character constants well
-      because the token_buffer contains the result of processing escapes.  */
-   if (end_of_file)
-     strcat (buf, input_redirected ()
- 	    ? " at end of saved text"
- 	    : " at end of input");
-   else if (token_buffer[0] == 0)
-     strcat (buf, " at null character");
-   else if (token_buffer[0] == '"')
-     strcat (buf, " before string constant");
-   else if (token_buffer[0] == '\'')
-     strcat (buf, " before character constant");
-   else if (!ISGRAPH ((unsigned char)token_buffer[0]))
-     sprintf (buf + strlen (buf), " before character 0%o",
- 	     (unsigned char) token_buffer[0]);
-   else
-     strcat (buf, " before `%s'");
- 
-   error (buf, token_buffer);
- }
- 
- static int
- handle_cp_pragma (pname)
-      const char *pname;
- {
-   register int token;
- 
-   if (! strcmp (pname, "vtable"))
-     {
-       extern tree pending_vtables;
- 
-       /* More follows: it must be a string constant (class name).  */
-       token = real_yylex ();
-       if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
- 	{
- 	  error ("invalid #pragma vtable");
- 	  return -1;
- 	}
- 
-       pending_vtables
- 	= perm_tree_cons (NULL_TREE,
- 			  get_identifier (TREE_STRING_POINTER (yylval.ttype)),
- 			  pending_vtables);
-       token = real_yylex ();
-       if (token != END_OF_LINE)
- 	warning ("trailing characters ignored");
-       return 1;
-     }
-   else if (! strcmp (pname, "unit"))
-     {
-       /* More follows: it must be a string constant (unit name).  */
-       token = real_yylex ();
-       if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
- 	{
- 	  error ("invalid #pragma unit");
- 	  return -1;
- 	}
-       token = real_yylex ();
-       if (token != END_OF_LINE)
- 	warning ("trailing characters ignored");
-       return 1;
-     }
-   else if (! strcmp (pname, "interface"))
-     {
-       char *main_filename = input_filename;
- 
-       main_filename = file_name_nondirectory (main_filename);
- 
-       token = real_yylex ();
-       
-       if (token != END_OF_LINE)
- 	{
- 	  if (token != STRING
- 	      || TREE_CODE (yylval.ttype) != STRING_CST)
- 	    {
- 	      error ("invalid `#pragma interface'");
- 	      return -1;
- 	    }
- 	  main_filename = TREE_STRING_POINTER (yylval.ttype);
- 	  token = real_yylex ();
- 	}
- 
-       if (token != END_OF_LINE)
- 	warning ("garbage after `#pragma interface' ignored");
- 
-       cp_pragma_interface (main_filename);
- 
-       return 1;
-     }
-   else if (! strcmp (pname, "implementation"))
-     {
-       char *main_filename = main_input_filename ? main_input_filename : input_filename;
- 
-       main_filename = file_name_nondirectory (main_filename);
- 
-       token = real_yylex ();
- 
-       if (token != END_OF_LINE)
- 	{
- 	  if (token != STRING
- 	      || TREE_CODE (yylval.ttype) != STRING_CST)
- 	    {
- 	      error ("invalid `#pragma implementation'");
- 	      return -1;
- 	    }
- 	  main_filename = TREE_STRING_POINTER (yylval.ttype);
- 	  token = real_yylex ();
- 	}
- 
-       if (token != END_OF_LINE)
- 	warning ("garbage after `#pragma implementation' ignored");
- 
-       cp_pragma_implementation (main_filename);
- 
-       return 1;
-     }
- 
-   return 0;
- }
- 
  /* Return the type-qualifier corresponding to the identifier given by
     RID.  */
  
--- 4966,4971 ----
*************** cp_type_qual_from_rid (rid)
*** 4836,4880 ****
    my_friendly_abort (0);
    return TYPE_UNQUALIFIED;
  }
- 
- 
- #ifdef HANDLE_GENERIC_PRAGMAS
- 
- /* Handle a #pragma directive.  TOKEN is the type of the word following
-    the #pragma directive on the line.  Process the entire input line and
-    return non-zero iff the directive successfully parsed.  */
- 
- /* This function has to be in this file, in order to get at
-    the token types.  */
- 
- static int
- handle_generic_pragma (token)
-      register int token;
- {
-   for (;;)
-     {
-       switch (token)
- 	{
- 	case IDENTIFIER:
- 	case TYPENAME:
-         case STRING:
-         case CONSTANT:
- 	  handle_pragma_token (token_buffer, yylval.ttype);
- 	  break;
- 
- 	case LEFT_RIGHT:
- 	  handle_pragma_token ("(", NULL_TREE);
- 	  handle_pragma_token (")", NULL_TREE);
- 	  break;
- 
- 	case END_OF_LINE:
- 	  return handle_pragma_token (NULL_PTR, NULL_TREE);
- 
- 	default:
- 	  handle_pragma_token (token_buffer, NULL_TREE);
- 	}
-       
-       token = real_yylex ();
-     }
- }
- #endif /* HANDLE_GENERIC_PRAGMAS */
--- 4983,4985 ----
Index: spew.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/spew.c,v
retrieving revision 1.21
diff -c -p -r1.21 spew.c
*** spew.c	1999/07/20 19:53:38	1.21
--- spew.c	1999/07/24 00:44:14
*************** yylex ()
*** 401,406 ****
--- 401,409 ----
        break;
  
      case TYPESPEC:
+       /* If this provides a type for us, then revert lexical
+ 	 state to standard state.  */
+       looking_for_typename = 0;
        consume_token ();
        break;
  


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]