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++) patch for cpplib integration


Not checked in pending approval of cpplib backend changes.

This patch speeds up lexing by taking advantage of the tokenization work
that cpplib has already done; knowing in advance how long the token will be
allows us to take some shortcuts.  It also simplifies a lot of the code.

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

	* lex.c (lang_init): Generalize.
	(lang_init_options): Tell cpplib this is C++.
	(nextchar): Remove.  Replace uses with put_back.
	(skip_white_space): Handle linemode here.  Optimize for cpplib.
	(extend_token_buffer_to): New fn.
	(extend_token_buffer): Use it.
	(read_line_number, check_newline): Just deal with tokens.
	(real_yylex): More cpplib optimizations.  Simplify.  Don't produce
	EXTERN_LANG_STRING, LEFT_RIGHT or PAREN_STAR_PAREN here.
	* spew.c (yylex): Produce LEFT_RIGHT and EXTERN_LANG_STRING.
	* parse.y (PAREN_STAR_PAREN): Remove.
	* input.c: Don't use the putback machinery with cpplib.
	(sub_getch): Fold back into getch.
	(getch): Don't handle linemode here.
	(feed_input): Unget any text in the token buffer.

	* lex.c	(set_typedecl_interface_info, set_vardecl_interface_info,
	nextyychar, nextyylval): Remove.

1999-07-10  Michael Tiemann  <tiemann@holodeck.cygnus.com>
	    Jason Merrill  <jason@yorick.cygnus.com>

	* lex.c (indent_level): New variable.
	(init_parse): Set cpp_token to CPP_DIRECTIVE.
	(consume_string): Make this smart about USE_CPPLIB.
	(yyungetc): Use put_back function.
	(pragma_getc, pragma_ungetc): Functions deleted.
	(check_newline): Rewrite to be intelligent about USE_CPPLIB.
	Also, call HANDLE_PRAGMA with getch, yyungetc, not pragma_getc and
	pragma_ungetc.
	(real_yylex): Rewrite to be intelligent about USE_CPPLIB.
	Also, clean up cases where we redundantly set token_buffer[0].
	(read_line_number): New fn.
	* input.c (feed_input): Use integrated cpplib if USE_CPPLIB.
	(end_input): Call cpp_pop_buffer if USE_CPPLIB.
	(sub_getch): Conditionalize out code that's not appropriate if
	USE_CPPLIB.
	(put_back): Rewrite in case USE_CPPLIB is defined.
	(input_redirected): Ditto.

Index: input.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/input.c,v
retrieving revision 1.10
diff -c -p -r1.10 input.c
*** input.c	1999/06/07 11:10:29	1.10
--- input.c	1999/07/10 23:49:12
***************
*** 1,6 ****
--- 1,7 ----
  /* Input handling for G++.
     Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc.
     Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
+    Enhanced by Michael Tiemann (tiemann@cygnus.com) to better support USE_CPPLIB
  
  This file is part of GNU CC.
  
*************** Boston, MA 02111-1307, USA.  */
*** 31,44 ****
  
  #include "system.h"
  
! extern FILE *finput;
! 
  struct putback_buffer {
    char *buffer;
    int   buffer_size;
    int   index;
  };
  
  struct input_source {
    /* saved string */
    char *str;
--- 32,47 ----
  
  #include "system.h"
  
! #if !USE_CPPLIB
  struct putback_buffer {
    char *buffer;
    int   buffer_size;
    int   index;
  };
  
+ static struct putback_buffer putback = {NULL, 0, -1};
+ #endif
+ 
  struct input_source {
    /* saved string */
    char *str;
*************** struct input_source {
*** 51,57 ****
--- 54,62 ----
    char *filename;
    int lineno;
    struct pending_input *input;
+ #if !USE_CPPLIB
    struct putback_buffer putback;
+ #endif
  };
  
  static struct input_source *input, *free_inputs;
*************** extern int lineno;
*** 62,70 ****
  #if USE_CPPLIB
  extern unsigned char *yy_cur, *yy_lim;
  extern int yy_get_token ();
- #define GETC() (yy_cur < yy_lim ? *yy_cur++ : yy_get_token ())
- #else
- #define GETC() getc (finput)
  #endif
  
  extern void feed_input PROTO((char *, int));
--- 67,72 ----
*************** extern int input_redirected PROTO((void)
*** 76,82 ****
  static inline struct input_source * allocate_input PROTO((void));
  static inline void free_input PROTO((struct input_source *));
  static inline void end_input PROTO((void));
- static inline int sub_getch PROTO((void));
  
  static inline struct input_source *
  allocate_input ()
--- 78,83 ----
*************** free_input (inp)
*** 104,111 ****
    free_inputs = inp;
  }
  
- static struct putback_buffer putback = {NULL, 0, -1};
- 
  /* Some of these external functions are declared inline in case this file
     is included in lex.c.  */
  
--- 105,110 ----
*************** feed_input (str, len)
*** 121,137 ****
    while (len && !str[len-1])
      len--;
  
    inp->str = str;
    inp->length = len;
    inp->offset = 0;
-   inp->next = input;
-   inp->filename = input_filename;
-   inp->lineno = lineno;
-   inp->input = save_pending_input ();
    inp->putback = putback;
    putback.buffer = NULL;
    putback.buffer_size = 0;
    putback.index = -1;
    input = inp;
  }
  
--- 120,149 ----
    while (len && !str[len-1])
      len--;
  
+ #if USE_CPPLIB
+   if (yy_lim > yy_cur)
+     {
+       /* We peeked ahead in real_yylex, so the cpplib token buffer contains
+ 	 the text for the next token.  Put it back so we can start reading
+ 	 from the new buffer.  */
+       cpp_unget (&parse_in, yy_lim - yy_cur);
+       yy_lim = yy_cur;
+     }
+   cpp_push_buffer (&parse_in, str, len);
+   CPP_BUFFER (&parse_in)->redirected_input_p = 1;
+ #else
    inp->str = str;
    inp->length = len;
    inp->offset = 0;
    inp->putback = putback;
    putback.buffer = NULL;
    putback.buffer_size = 0;
    putback.index = -1;
+ #endif
+   inp->next = input;
+   inp->filename = input_filename;
+   inp->lineno = lineno;
+   inp->input = save_pending_input ();
    input = inp;
  }
  
*************** end_input ()
*** 143,162 ****
  {
    struct input_source *inp = input;
  
    end_of_file = 0;
    input = inp->next;
    input_filename = inp->filename;
    lineno = inp->lineno;
    /* Get interface/implementation back in sync.  */
    extract_interface_info ();
-   putback = inp->putback;
    restore_pending_input (inp->input);
    free_input (inp);
  }
  
! static inline int
! sub_getch ()
  {
    if (putback.index != -1)
      {
        int ch = putback.buffer[putback.index];
--- 155,182 ----
  {
    struct input_source *inp = input;
  
+ #if USE_CPPLIB
+   cpp_pop_buffer (&parse_in);
+ #else
+   putback = inp->putback;
+ #endif
+ 
    end_of_file = 0;
    input = inp->next;
    input_filename = inp->filename;
    lineno = inp->lineno;
    /* Get interface/implementation back in sync.  */
    extract_interface_info ();
    restore_pending_input (inp->input);
    free_input (inp);
  }
  
! inline int
! getch ()
  {
+ #if USE_CPPLIB
+   return (yy_cur < yy_lim ? *yy_cur++ : yy_get_token ());
+ #else
    if (putback.index != -1)
      {
        int ch = putback.buffer[putback.index];
*************** sub_getch ()
*** 178,184 ****
  	}
        return (unsigned char)input->str[input->offset++];
      }
!   return GETC ();
  }
  
  inline
--- 198,205 ----
  	}
        return (unsigned char)input->str[input->offset++];
      }
!   return getc (finput);
! #endif
  }
  
  inline
*************** void
*** 186,191 ****
--- 207,220 ----
  put_back (ch)
       int ch;
  {
+ #if USE_CPPLIB
+   if (ch == EOF)
+     ;
+   else if (yy_cur[-1] == ch)
+     yy_cur--;
+   else
+     my_friendly_abort (990709);
+ #else
    if (ch != EOF)
      {
        if (putback.index == putback.buffer_size - 1)
*************** put_back (ch)
*** 196,220 ****
        my_friendly_assert (putback.buffer != NULL, 224);
        putback.buffer[++putback.index] = ch;
      }
! }
! 
! extern int linemode;
! 
! int
! getch ()
! {
!   int ch = sub_getch ();
!   if (linemode && ch == '\n')
!     {
!       put_back (ch);
!       ch = EOF;
!     }
!   return ch;
  }
  
  inline
  int
  input_redirected ()
  {
    return input != 0;
  }
--- 225,240 ----
        my_friendly_assert (putback.buffer != NULL, 224);
        putback.buffer[++putback.index] = ch;
      }
! #endif
  }
  
  inline
  int
  input_redirected ()
  {
+ #ifdef USE_CPPLIB
+   return CPP_BUFFER(&parse_in)->redirected_input_p;
+ #else
    return input != 0;
+ #endif
  }
Index: lex.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/lex.c,v
retrieving revision 1.119
diff -c -p -r1.119 lex.c
*** lex.c	1999/07/09 12:44:35	1.119
--- lex.c	1999/07/10 23:49:13
*************** static int check_newline PROTO((void));
*** 60,73 ****
  static int skip_white_space PROTO((int));
  static void finish_defarg PROTO((void));
  static int my_get_run_time PROTO((void));
- static int get_last_nonwhite_on_line PROTO((void));
  static int interface_strcmp PROTO((const char *));
  static int readescape PROTO((int *));
  static char *extend_token_buffer PROTO((const char *));
  static void consume_string PROTO((struct obstack *, int));
- static int set_typedecl_interface_info PROTO((tree *, void *));
  static void feed_defarg PROTO((tree, tree));
- static int set_vardecl_interface_info PROTO((tree *, void *));
  static void store_pending_inline PROTO((tree, struct pending_inline *));
  static void reinit_parse_for_expr PROTO((struct obstack *));
  static int *init_cpp_parse PROTO((void));
--- 60,70 ----
*************** char *inline_text_firstobj;
*** 113,124 ****
--- 110,124 ----
  extern cpp_reader  parse_in;
  extern cpp_options parse_options;
  extern unsigned char *yy_cur, *yy_lim;
+ extern enum cpp_token cpp_token;
  extern int errorcount;
  #else
  FILE *finput;
  #endif
  int end_of_file;
  
+ int linemode;
+ 
  /* Pending language change.
     Positive is push count, negative is pop count.  */
  int pending_lang_change = 0;
*************** extern int first_token;
*** 130,142 ****
  extern struct obstack token_obstack;
  
  /* ??? Don't really know where this goes yet.  */
- #if 1
  #include "input.c"
- #else
- extern void put_back (/* int */);
- extern int input_redirected ();
- extern void feed_input (/* char *, int */);
- #endif
  
  /* Holds translations from TREE_CODEs to operator name strings,
     i.e., opname_tab[PLUS_EXPR] == "+".  */
--- 130,136 ----
*************** static int maxtoken;		/* Current nominal
*** 309,314 ****
--- 303,310 ----
  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"
  
  
*************** lang_init_options ()
*** 397,402 ****
--- 393,399 ----
    cpp_reader_init (&parse_in);
    parse_in.opts = &parse_options;
    cpp_options_init (&parse_options);
+   parse_options.cplusplus = 1;
  #endif
  
    /* Default exceptions on.  */
*************** lang_init ()
*** 409,420 ****
    /* the beginning of the file is a new line; check for # */
    /* With luck, we discover the real source file's name from that
       and put it in input_filename.  */
- #if ! USE_CPPLIB
    put_back (check_newline ());
- #else
-   check_newline ();
-   yy_cur--;
- #endif
    if (flag_gnu_xref) GNU_xref_begin (input_filename);
    init_repo (input_filename);
  }
--- 406,412 ----
*************** init_parse (filename)
*** 498,503 ****
--- 490,496 ----
       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.  */
*************** cp_pragma_implementation (main_filename)
*** 1224,1263 ****
    TREE_INT_CST_LOW (fileinfo) = interface_only;
    TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
  }
- 
- static int
- set_typedecl_interface_info (t, data)
-      tree *t;
-      void *data ATTRIBUTE_UNUSED;
- {
-   tree id = get_time_identifier (DECL_SOURCE_FILE (*t));
-   tree fileinfo = TIME_IDENTIFIER_FILEINFO (id);
-   tree type = TREE_TYPE (*t);
- 
-   CLASSTYPE_INTERFACE_ONLY (type) = TREE_INT_CST_LOW (fileinfo)
-     = interface_strcmp (file_name_nondirectory (DECL_SOURCE_FILE (*t)));
-   return 0;
- }
- 
- static int
- set_vardecl_interface_info (t, data)
-      tree *t;
-      void *data ATTRIBUTE_UNUSED;
- {
-   tree type = DECL_CONTEXT (*t);
- 
-   if (CLASSTYPE_INTERFACE_KNOWN (type))
-     {
-       if (CLASSTYPE_INTERFACE_ONLY (type))
- 	set_typedecl_interface_info (&TYPE_MAIN_DECL (type), data);
-       else
- 	CLASSTYPE_VTABLE_NEEDS_WRITING (type) = 1;
-       DECL_EXTERNAL (*t) = CLASSTYPE_INTERFACE_ONLY (type);
-       TREE_PUBLIC (*t) = 1;
-       return 1;
-     }
-   return 0;
- }
  
  /* Set up the state required to correctly handle the definition of the
     inline function whose preparsed state has been saved in PI.  */
--- 1217,1222 ----
*************** do_pending_inlines ()
*** 1328,1335 ****
    begin_definition_of_inclass_inline (t);
  }
  
- static int nextchar = -1;
- 
  /* Called from the fndecl rule in the parser when the function just parsed
     was declared using a PRE_PARSED_FUNCTION_DECL (i.e. came from
     do_pending_inlines).  */
--- 1287,1292 ----
*************** process_next_inline (t)
*** 1352,1360 ****
  
        /* restore_pending_input will abort unless yychar is either
           END_OF_SAVED_INPUT or YYEMPTY; since we already know we're
!          hosed, feed back YYEMPTY.  We also need to discard nextchar,
!          since that may have gotten set as well.  */
!       nextchar = -1;
      }
    yychar = YYEMPTY;
    end_input ();
--- 1309,1315 ----
  
        /* restore_pending_input will abort unless yychar is either
           END_OF_SAVED_INPUT or YYEMPTY; since we already know we're
!          hosed, feed back YYEMPTY.  */
      }
    yychar = YYEMPTY;
    end_input ();
*************** consume_string (this_obstack, matching_c
*** 1380,1386 ****
       int matching_char;
  {
    register int c;
!   int starting_lineno = lineno;
    do
      {
        c = getch ();
--- 1335,1354 ----
       int matching_char;
  {
    register int c;
!   int starting_lineno;
! 
! #if USE_CPPLIB
!   if (cpp_token == CPP_STRING)
!     {
!       /* The C preprocessor will warn about newlines in strings.  */
!       obstack_grow (this_obstack, yy_cur, (yy_lim - yy_cur));
!       yy_cur = yy_lim;
!       lineno = parse_in.lineno;
!       return;
!     }
! #endif
! 
!   starting_lineno = lineno;
    do
      {
        c = getch ();
*************** consume_string (this_obstack, matching_c
*** 1416,1427 ****
    while (c != matching_char);
  }
  
- static int nextyychar = YYEMPTY;
- static YYSTYPE nextyylval;
- 
  struct pending_input {
!   int nextchar, yychar, nextyychar, eof;
!   YYSTYPE yylval, nextyylval;
    struct obstack token_obstack;
    int first_token;
  };
--- 1384,1392 ----
    while (c != matching_char);
  }
  
  struct pending_input {
!   int yychar, eof;
!   YYSTYPE yylval;
    struct obstack token_obstack;
    int first_token;
  };
*************** save_pending_input ()
*** 1431,1444 ****
  {
    struct pending_input *p;
    p = (struct pending_input *) xmalloc (sizeof (struct pending_input));
-   p->nextchar = nextchar;
    p->yychar = yychar;
-   p->nextyychar = nextyychar;
    p->yylval = yylval;
-   p->nextyylval = nextyylval;
    p->eof = end_of_file;
!   yychar = nextyychar = YYEMPTY;
!   nextchar = -1;
    p->first_token = first_token;
    p->token_obstack = token_obstack;
  
--- 1396,1405 ----
  {
    struct pending_input *p;
    p = (struct pending_input *) xmalloc (sizeof (struct pending_input));
    p->yychar = yychar;
    p->yylval = yylval;
    p->eof = end_of_file;
!   yychar = YYEMPTY;
    p->first_token = first_token;
    p->token_obstack = token_obstack;
  
*************** void
*** 1452,1465 ****
  restore_pending_input (p)
       struct pending_input *p;
  {
-   my_friendly_assert (nextchar == -1, 229);
-   nextchar = p->nextchar;
    my_friendly_assert (yychar == YYEMPTY || yychar == END_OF_SAVED_INPUT, 230);
    yychar = p->yychar;
-   my_friendly_assert (nextyychar == YYEMPTY, 231);
-   nextyychar = p->nextyychar;
    yylval = p->yylval;
-   nextyylval = p->nextyylval;
    first_token = p->first_token;
    obstack_free (&token_obstack, (char *) 0);
    token_obstack = p->token_obstack;
--- 1413,1421 ----
*************** yyungetc (ch, rescan)
*** 1479,1493 ****
    /* Unget a character from the input stream.  */
    if (yychar == YYEMPTY || rescan == 0)
      {
!       if (nextchar >= 0)
! 	put_back (nextchar);
!       nextchar = ch;
      }
    else
      {
-       my_friendly_assert (nextyychar == YYEMPTY, 232);
-       nextyychar = yychar;
-       nextyylval = yylval;
        yychar = ch;
      }
  }
--- 1435,1444 ----
    /* Unget a character from the input stream.  */
    if (yychar == YYEMPTY || rescan == 0)
      {
!       put_back (ch);
      }
    else
      {
        yychar = ch;
      }
  }
*************** reinit_parse_for_block (pyychar, obstack
*** 1570,1576 ****
       int pyychar;
       struct obstack *obstackp;
  {
!   register int c = 0;
    int blev = 1;
    int starting_lineno = lineno;
    char *starting_filename = input_filename;
--- 1521,1527 ----
       int pyychar;
       struct obstack *obstackp;
  {
!   register int c;
    int blev = 1;
    int starting_lineno = lineno;
    char *starting_filename = input_filename;
*************** reinit_parse_for_block (pyychar, obstack
*** 1608,1621 ****
        obstack_1grow (obstackp, '{');
      }
  
!   if (nextchar != EOF)
!     {
!       c = nextchar;
!       nextchar = EOF;
!     }
!   else
!     c = getch ();
!   
    while (c != EOF)
      {
        int this_lineno = lineno;
--- 1559,1566 ----
        obstack_1grow (obstackp, '{');
      }
  
!   c = getch ();
! 
    while (c != EOF)
      {
        int this_lineno = lineno;
*************** static void
*** 1737,1756 ****
  reinit_parse_for_expr (obstackp)
       struct obstack *obstackp;
  {
!   register int c = 0;
    int starting_lineno = lineno;
    char *starting_filename = input_filename;
    int len;
    int plev = 0;
  
!   if (nextchar != EOF)
!     {
!       c = nextchar;
!       nextchar = EOF;
!     }
!   else
!     c = getch ();
!   
    while (c != EOF)
      {
        int this_lineno = lineno;
--- 1682,1695 ----
  reinit_parse_for_expr (obstackp)
       struct obstack *obstackp;
  {
!   register int c;
    int starting_lineno = lineno;
    char *starting_filename = input_filename;
    int len;
    int plev = 0;
  
!   c = getch ();
! 
    while (c != EOF)
      {
        int this_lineno = lineno;
*************** finish_defarg ()
*** 1922,1930 ****
  
        /* restore_pending_input will abort unless yychar is either
           END_OF_SAVED_INPUT or YYEMPTY; since we already know we're
!          hosed, feed back YYEMPTY.  We also need to discard nextchar,
!          since that may have gotten set as well.  */
!       nextchar = -1;
      }
    yychar = YYEMPTY;
    end_input ();
--- 1861,1867 ----
  
        /* restore_pending_input will abort unless yychar is either
           END_OF_SAVED_INPUT or YYEMPTY; since we already know we're
!          hosed, feed back YYEMPTY.  */
      }
    yychar = YYEMPTY;
    end_input ();
*************** skip_white_space (c)
*** 2193,2198 ****
--- 2130,2140 ----
        switch (c)
  	{
  	case '\n':
+ 	  if (linemode)
+ 	    {
+ 	      put_back (c);
+ 	      return EOF;
+ 	    }
  	  c = check_newline ();
  	  break;
  
*************** skip_white_space (c)
*** 2202,2210 ****
  	case '\r':
  	case '\v':
  	case '\b':
! 	  do
  	    c = getch ();
- 	  while (c == ' ' || c == '\t');
  	  break;
  
  	case '\\':
--- 2144,2157 ----
  	case '\r':
  	case '\v':
  	case '\b':
! #if USE_CPPLIB
! 	  /* While processing a # directive we don't get CPP_HSPACE
! 	     tokens, so we also need to handle whitespace the normal way.  */
! 	  if (cpp_token == CPP_HSPACE)
! 	    c = yy_get_token ();
! 	  else
! #endif
  	    c = getch ();
  	  break;
  
  	case '\\':
*************** skip_white_space (c)
*** 2222,2693 ****
      }
  }
  
- 
- 
  /* Make the token buffer longer, preserving the data in it.
     P should point to just beyond the last valid character in the old buffer.
     The value we return is a pointer to the new buffer
     at a place corresponding to P.  */
  
  static char *
  extend_token_buffer (p)
       const char *p;
  {
    int offset = p - token_buffer;
! 
!   maxtoken = maxtoken * 2 + 10;
!   token_buffer = (char *) xrealloc (token_buffer, maxtoken + 2);
! 
    return token_buffer + offset;
  }
  
  static int
! get_last_nonwhite_on_line ()
  {
!   register int c;
! 
!   /* Is this the last nonwhite stuff on the line?  */
!   if (nextchar >= 0)
!     c = nextchar, nextchar = -1;
!   else
!     c = getch ();
! 
!   while (c == ' ' || c == '\t')
!     c = getch ();
!   return c;
! }
  
! #if defined HANDLE_PRAGMA
! /* Local versions of these macros, that can be passed as function pointers.  */
! static int
! pragma_getc ()
! {
!   int c;
!       
!   if (nextchar != EOF)
      {
!       c = nextchar;
!       nextchar = EOF;
      }
    else
!     c = getch ();
! 
!   return c;
! }
! 
! static void
! pragma_ungetc (arg)
!      int arg;
! {
!   yyungetc (arg, 0);
  }
- #endif /* HANDLE_PRAGMA */
  
  /* At the beginning of a line, increment the line number
     and process any #-directive on this line.
     If the line is a #-directive, read the entire line and return a newline.
!    Otherwise, return the line's first non-whitespace character.  */
  
! int linemode;
  
  static int
  check_newline ()
  {
    register int c;
    register int token;
!   int saw_line = 0;
  
    /* Read first nonwhite char on the line.  Do this before incrementing the
       line number, in case we're at the end of saved text.  */
  
    do
      c = getch ();
    while (c == ' ' || c == '\t');
  
    lineno++;
  
    if (c != '#')
      {
        /* If not #, return it so caller will use it.  */
        return c;
      }
  
    /* Don't read beyond this line.  */
    linemode = 1;
    
!   /* Read first nonwhite char after the `#'.  */
  
!   do
!     c = getch ();
!   while (c == ' ' || c == '\t');
  
!   /* If a letter follows, then if the word here is `line', skip
!      it and ignore it; otherwise, ignore the line, with an error
!      if the word isn't `pragma'.  */
! 
!   if (ISALPHA (c))
!     {
!       if (c == 'p')
! 	{
! 	  if (getch () == 'r'
! 	      && getch () == 'a'
! 	      && getch () == 'g'
! 	      && getch () == 'm'
! 	      && getch () == 'a')
  	    {
! 	      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
! 	      /* We invoke HANDLE_PRAGMA before HANDLE_GENERIC_PRAGMAS
! 		 (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 */
  	      
  #ifdef HANDLE_GENERIC_PRAGMAS
! 	      if (handle_generic_pragma (token))
! 		goto skipline;
  #endif /* HANDLE_GENERIC_PRAGMAS */
  
! 	      /* Issue a warning message if we have been asked to do so.
! 		 Ignoring unknown pragmas in system header file unless
! 		 an explcit -Wunknown-pragmas has been given. */
! 	      if (warn_unknown_pragmas > 1
! 		  || (warn_unknown_pragmas && ! in_system_header))
! 		warning ("ignoring pragma: %s", token_buffer);
! 	    }
! 	  
  	  goto skipline;
  	}
!       else if (c == 'd')
  	{
! 	  if (getch () == 'e'
! 	      && getch () == 'f'
! 	      && getch () == 'i'
! 	      && getch () == 'n'
! 	      && getch () == 'e'
! 	      && ((c = getch ()) == ' ' || c == '\t'))
! 	    {
! 	      debug_define (lineno, GET_DIRECTIVE_LINE ());
! 	      goto skipline;
! 	    }
  	}
!       else if (c == 'u')
  	{
! 	  if (getch () == 'n'
! 	      && getch () == 'd'
! 	      && getch () == 'e'
! 	      && getch () == 'f'
! 	      && ((c = getch ()) == ' ' || c == '\t'))
! 	    {
! 	      debug_undef (lineno, GET_DIRECTIVE_LINE ());
! 	      goto skipline;
! 	    }
  	}
!       else if (c == 'l')
  	{
! 	  if (getch () == 'i'
! 	      && getch () == 'n'
! 	      && getch () == 'e'
! 	      && ((c = getch ()) == ' ' || c == '\t'))
! 	    {
! 	      saw_line = 1;
! 	      goto linenum;
! 	    }
  	}
!       else if (c == 'i')
  	{
! 	  if (getch () == 'd'
! 	      && getch () == 'e'
! 	      && getch () == 'n'
! 	      && getch () == 't'
! 	      && ((c = getch ()) == ' ' || c == '\t'))
! 	    {
! 	      /* #ident.  The pedantic warning is now in cccp.c.  */
! 
! 	      /* Here we have just seen `#ident '.
! 		 A string constant should follow.  */
! 
! 	      token = real_yylex ();
! 	      if (token == END_OF_LINE)
! 		goto skipline;
! 	      if (token != STRING
! 		  || TREE_CODE (yylval.ttype) != STRING_CST)
! 		{
! 		  error ("invalid #ident");
! 		  goto skipline;
! 		}
  
! 	      if (! flag_no_ident)
! 		{
! #ifdef ASM_OUTPUT_IDENT
! 		  ASM_OUTPUT_IDENT (asm_out_file,
! 				    TREE_STRING_POINTER (yylval.ttype));
! #endif
! 		}
  
! 	      /* Skip the rest of this line.  */
  	      goto skipline;
  	    }
! 	}
!       else if (c == 'n')
! 	{
! 	  if (getch () == 'e'
! 	      && getch () == 'w'
! 	      && getch () == 'w'
! 	      && getch () == 'o'
! 	      && getch () == 'r'
! 	      && getch () == 'l'
! 	      && getch () == 'd'
! 	      && ((c = getch ()) == ' ' || c == '\t'))
  	    {
! 	      /* Used to test incremental compilation.  */
! 	      sorry ("#pragma newworld");
! 	      goto skipline;
  	    }
  	}
        error ("undefined or invalid # directive");
        goto skipline;
      }
  
- linenum:
-   /* Here we have either `#line' or `# <nonletter>'.
-      In either case, it should be a line number; a digit should follow.  */
- 
-   while (c == ' ' || c == '\t')
-     c = getch ();
- 
    /* If the # is the only nonwhite char on the line,
       just ignore it.  Check the new newline.  */
!   if (c == EOF)
      goto skipline;
- 
-   /* Something follows the #; read a token.  */
  
!   put_back (c);
!   token = real_yylex ();
  
!   if (token == CONSTANT
!       && TREE_CODE (yylval.ttype) == INTEGER_CST)
      {
!       int old_lineno = lineno;
!       enum { act_none, act_push, act_pop } action = act_none;
!       int entering_system_header = 0;
!       int entering_c_header = 0;
  
!       /* subtract one, because it is the following line that
! 	 gets the specified number */
  
!       int l = TREE_INT_CST_LOW (yylval.ttype) - 1;
!       c = get_last_nonwhite_on_line ();
!       if (c == EOF)
! 	{
! 	  /* No more: store the line number and check following line.  */
! 	  lineno = l;
! 	  goto skipline;
! 	}
!       put_back (c);
  
!       /* More follows: it must be a string constant (filename).  */
  
!       if (saw_line)
! 	{
! 	  /* Don't treat \ as special if we are processing #line 1 "...".
! 	     If you want it to be treated specially, use # 1 "...".  */
! 	  ignore_escape_flag = 1;
! 	}
  
!       /* Read the string constant.  */
!       token = real_yylex ();
  
!       ignore_escape_flag = 0;
  
!       if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
! 	{
! 	  error ("invalid #line");
! 	  goto skipline;
! 	}
  
!       /* Changing files again.  This means currently collected time
! 	 is charged against header time, and body time starts back
! 	 at 0.  */
!       if (flag_detailed_statistics)
! 	{
! 	  int this_time = my_get_run_time ();
! 	  tree time_identifier = get_time_identifier (TREE_STRING_POINTER (yylval.ttype));
! 	  header_time += this_time - body_time;
! 	  TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (this_filename_time))
! 	    += this_time - body_time;
! 	  this_filename_time = time_identifier;
! 	  body_time = this_time;
! 	}
  
        input_filename
  	= (char *) permalloc (TREE_STRING_LENGTH (yylval.ttype) + 1);
        strcpy (input_filename, TREE_STRING_POINTER (yylval.ttype));
!       lineno = l;
!       GNU_xref_file (input_filename);
!       
!       if (main_input_filename == 0)
! 	{
! 	  struct impl_files *ifiles = impl_file_chain;
! 
! 	  if (ifiles)
! 	    {
! 	      while (ifiles->next)
! 		ifiles = ifiles->next;
! 	      ifiles->filename = file_name_nondirectory (input_filename);
! 	    }
! 
! 	  main_input_filename = input_filename;
! 	}
  
!       extract_interface_info ();
  
!       c = get_last_nonwhite_on_line ();
!       if (c == EOF)
  	{
! 	  /* Update the name in the top element of input_file_stack.  */
! 	  if (input_file_stack)
! 	    input_file_stack->name = input_filename;
  	}
-       else
- 	{
- 	  put_back (c);
- 
- 	  token = real_yylex ();
- 
- 	  /* `1' after file name means entering new file.
- 	     `2' after file name means just left a file.  */
  
! 	  if (token == CONSTANT
! 	      && TREE_CODE (yylval.ttype) == INTEGER_CST)
! 	    {
! 	      if (TREE_INT_CST_LOW (yylval.ttype) == 1)
! 		action = act_push;
! 	      else if (TREE_INT_CST_LOW (yylval.ttype) == 2)
! 		action = act_pop;
  
! 	      if (action)
! 		{
! 		  c = get_last_nonwhite_on_line ();
! 		  if (c != EOF)
! 		    {
! 		      put_back (c);
! 		      token = real_yylex ();
! 		    }
! 		}
! 	    }
  
! 	  /* `3' after file name means this is a system header file.  */
  
! 	  if (token == CONSTANT
! 	      && TREE_CODE (yylval.ttype) == INTEGER_CST
! 	      && TREE_INT_CST_LOW (yylval.ttype) == 3)
! 	    {
! 	      entering_system_header = 1;
  
! 	      c = get_last_nonwhite_on_line ();
! 	      if (c != EOF)
! 		{
! 		  put_back (c);
! 		  token = real_yylex ();
! 		}
! 	    }
  
! 	  /* `4' after file name means this is a C header file.  */
  
! 	  if (token == CONSTANT
! 	      && TREE_CODE (yylval.ttype) == INTEGER_CST
! 	      && TREE_INT_CST_LOW (yylval.ttype) == 4)
! 	    {
! 	      entering_c_header = 1;
  
! 	      c = get_last_nonwhite_on_line ();
! 	      if (c != EOF)
! 		{
! 		  put_back (c);
! 		  token = real_yylex ();
! 		}
! 	    }
  
! 	  /* Do the actions implied by the preceding numbers.  */
  
! 	  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;
! 	      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)
! 		{
! 		  c_header_level = 1;
! 		  ++pending_lang_change;
! 		}
  	    }
! 	  else if (action == act_pop)
! 	    {
! 	      /* Popping out of a file.  */
! 	      if (input_file_stack->next)
! 		{
! 		  struct file_stack *p;
! 
! 		  if (c_header_level && --c_header_level == 0)
! 		    {
! 		      if (entering_c_header)
! 			warning ("badly nested C headers from preprocessor");
! 		      --pending_lang_change;
! 		    }
! 		  in_system_header = entering_system_header;
  
! 		  p = input_file_stack;
! 		  input_file_stack = p->next;
! 		  free (p);
! 		  input_file_stack_tick++;
! 		  debug_end_source_file (input_file_stack->line);
! 		}
! 	      else
! 		error ("#-lines for entering and leaving files don't match");
  	    }
! 	  else
! 	    in_system_header = entering_system_header;
  	}
! 
!       /* If NEXTCHAR is not end of line, we don't care what it is.  */
!       if (nextchar == EOF)
! 	c = EOF;
      }
    else
!     error ("invalid #-line");
  
    /* skip the rest of this line.  */
   skipline:
    linemode = 0;
    end_of_file = 0;
!   nextchar = -1;
    while ((c = getch ()) != EOF && c != '\n');
    return c;
  }
--- 2169,2575 ----
      }
  }
  
  /* Make the token buffer longer, preserving the data in it.
     P should point to just beyond the last valid character in the old buffer.
     The value we return is a pointer to the new buffer
     at a place corresponding to P.  */
  
+ static void
+ extend_token_buffer_to (size)
+      int size;
+ {
+   do
+     maxtoken = maxtoken * 2 + 10;
+   while (maxtoken < size);
+   token_buffer = (char *) xrealloc (token_buffer, maxtoken + 2);
+ }
+ 
  static char *
  extend_token_buffer (p)
       const char *p;
  {
    int offset = p - token_buffer;
!   extend_token_buffer_to (offset);
    return token_buffer + offset;
  }
  
  static int
! read_line_number (num)
!      int *num;
  {
!   register int token = real_yylex ();
  
!   if (token == CONSTANT
!       && TREE_CODE (yylval.ttype) == INTEGER_CST)
      {
!       *num = TREE_INT_CST_LOW (yylval.ttype);
!       return 1;
      }
    else
!     {
!       if (token != END_OF_LINE)
! 	error ("invalid #-line");
!       return 0;
!     }
  }
  
  /* At the beginning of a line, increment the line number
     and process any #-directive on this line.
     If the line is a #-directive, read the entire line and return a newline.
!    Otherwise, return the line's first non-whitespace character.
  
!    Note that in the case of USE_CPPLIB, we get the whole line as one
!    CPP_DIRECTIVE token.  */
  
  static int
  check_newline ()
  {
    register int c;
    register int token;
!   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:
    /* Read first nonwhite char on the line.  Do this before incrementing the
       line number, in case we're at the end of saved text.  */
  
+ #ifdef USE_CPPLIB
+   c = getch ();
+   /* In some cases where we're leaving an include file, we can get multiple
+      CPP_HSPACE tokens in a row, so we need to loop.  */
+   while (cpp_token == CPP_HSPACE)
+     c = yy_get_token ();
+ #else
    do
      c = getch ();
    while (c == ' ' || c == '\t');
+ #endif
  
    lineno++;
  
    if (c != '#')
      {
+       /* Sequences of multiple newlines are very common; optimize them.  */
+       if (c == '\n')
+ 	goto restart;
+ 
        /* If not #, return it so caller will use it.  */
        return c;
      }
  
    /* Don't read beyond this line.  */
+   saw_line = 0;
    linemode = 1;
    
! #if USE_CPPLIB
!   if (cpp_token == CPP_VSPACE)
!     {
!       /* Format is "<space> <line number> <filename> <newline>".
! 	 Only the line number is interesting, and even that
! 	 we can get more efficiently than scanning the line.  */
!       yy_cur = yy_lim - 1;
!       lineno = parse_in.lineno - 1;
!       goto skipline;
!     }
! #endif
  
!   token = real_yylex ();
! 
!   if (token == IDENTIFIER)
!     {
!       /* If a letter follows, then if the word here is `line', skip
! 	 it and ignore it; otherwise, ignore the line, with an error
! 	 if the word isn't `pragma'.  */
! 
!       const char *name = IDENTIFIER_POINTER (yylval.ttype);
  
!       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
! 	  /* We invoke HANDLE_PRAGMA before HANDLE_GENERIC_PRAGMAS
! 	     (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 */
  	      
  #ifdef HANDLE_GENERIC_PRAGMAS
! 	  if (handle_generic_pragma (token))
! 	    goto skipline;
  #endif /* HANDLE_GENERIC_PRAGMAS */
  
! 	  /* Issue a warning message if we have been asked to do so.
! 	     Ignoring unknown pragmas in system header file unless
! 	     an explcit -Wunknown-pragmas has been given. */
! 	  if (warn_unknown_pragmas > 1
! 	      || (warn_unknown_pragmas && ! in_system_header))
! 	    warning ("ignoring pragma: %s", token_buffer);
! 
  	  goto skipline;
  	}
!       else if (!strcmp (name, "define"))
  	{
! 	  debug_define (lineno, GET_DIRECTIVE_LINE ());
! 	  goto skipline;
  	}
!       else if (!strcmp (name, "undef"))
  	{
! 	  debug_undef (lineno, GET_DIRECTIVE_LINE ());
! 	  goto skipline;
  	}
!       else if (!strcmp (name, "line"))
  	{
! 	  saw_line = 1;
! 	  token = real_yylex ();
! 	  goto linenum;
  	}
!       else if (!strcmp (name, "ident"))
  	{
! 	  /* #ident.  The pedantic warning is now in cccp.c.  */
  
! 	  /* Here we have just seen `#ident '.
! 	     A string constant should follow.  */
  
! 	  token = real_yylex ();
! 	  if (token == END_OF_LINE)
! 	    goto skipline;
! 	  if (token != STRING
! 	      || TREE_CODE (yylval.ttype) != STRING_CST)
! 	    {
! 	      error ("invalid #ident");
  	      goto skipline;
  	    }
! 
! 	  if (! flag_no_ident)
  	    {
! #ifdef ASM_OUTPUT_IDENT
! 	      ASM_OUTPUT_IDENT (asm_out_file,
! 				TREE_STRING_POINTER (yylval.ttype));
! #endif
  	    }
+ 
+ 	  /* Skip the rest of this line.  */
+ 	  goto skipline;
  	}
+ 
        error ("undefined or invalid # directive");
        goto skipline;
      }
  
    /* If the # is the only nonwhite char on the line,
       just ignore it.  Check the new newline.  */
!   if (token == END_OF_LINE)
      goto skipline;
  
! linenum:
!   /* Here we have either `#line' or `# <nonletter>'.
!      In either case, it should be a line number; a digit should follow.  */
  
!   if (token != CONSTANT
!       || TREE_CODE (yylval.ttype) != INTEGER_CST)
      {
!       error ("invalid #-line");
!       goto skipline;
!     }
  
!   /* subtract one, because it is the following line that
!      gets the specified number */
  
!   l = TREE_INT_CST_LOW (yylval.ttype) - 1;
  
!   /* More follows: it must be a string constant (filename).
!      It would be neat to use cpplib to quickly process the string, but
!      (1) we don't have a handy tokenization of the string, and
!      (2) I don't know how well that would work in the presense
!      of filenames that contain wide characters.  */
  
!   if (saw_line)
!     {
!       /* Don't treat \ as special if we are processing #line 1 "...".
! 	 If you want it to be treated specially, use # 1 "...".  */
!       ignore_escape_flag = 1;
!     }
  
!   /* Read the string constant.  */
!   token = real_yylex ();
  
!   ignore_escape_flag = 0;
  
!   if (token == END_OF_LINE)
!     {
!       /* No more: store the line number and check following line.  */
!       lineno = l;
!       goto skipline;
!     }
  
!   if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
!     {
!       error ("invalid #line");
!       goto skipline;
!     }
  
+   /* Changing files again.  This means currently collected time
+      is charged against header time, and body time starts back at 0.  */
+   if (flag_detailed_statistics)
+     {
+       int this_time = my_get_run_time ();
+       tree time_identifier = get_time_identifier (TREE_STRING_POINTER (yylval.ttype));
+       header_time += this_time - body_time;
+       TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (this_filename_time))
+ 	+= this_time - body_time;
+       this_filename_time = time_identifier;
+       body_time = this_time;
+     }
+ 
+   if (!TREE_PERMANENT (yylval.ttype))
+     {
        input_filename
  	= (char *) permalloc (TREE_STRING_LENGTH (yylval.ttype) + 1);
        strcpy (input_filename, TREE_STRING_POINTER (yylval.ttype));
!     }
!   else
!     input_filename = TREE_STRING_POINTER (yylval.ttype);
  
!   GNU_xref_file (input_filename);
!       
!   if (main_input_filename == 0)
!     {
!       struct impl_files *ifiles = impl_file_chain;
  
!       if (ifiles)
  	{
! 	  while (ifiles->next)
! 	    ifiles = ifiles->next;
! 	  ifiles->filename = file_name_nondirectory (input_filename);
  	}
  
!       main_input_filename = input_filename;
!     }
  
!   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.  */
!       if (input_file_stack)
! 	input_file_stack->name = input_filename;
!     }
  
!   /* `1' after file name means entering new file.
!      `2' after file name means just left a file.  */
  
!   if (action_number == 1)
!     {
!       action = act_push;
!       read_line_number (&action_number);
!     }
!   else if (action_number == 2)
!     {
!       action = act_pop;
!       read_line_number (&action_number);
!     }
!   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)
!     {
!       /* `4' after file name means this is a C header file.  */
!       entering_c_header = 1;
!       read_line_number (&action_number);
!     }
  
!   /* Do the actions implied by the preceding numbers.  */
  
!   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;
!       p->indent_level = indent_level;
!       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)
! 	{
! 	  c_header_level = 1;
! 	  ++pending_lang_change;
! 	}
!     }
!   else if (action == act_pop)
!     {
!       /* Popping out of a file.  */
!       if (input_file_stack->next)
! 	{
! 	  struct file_stack *p;
  
! 	  if (c_header_level && --c_header_level == 0)
  	    {
! 	      if (entering_c_header)
! 		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
! 		(p->name, old_lineno,
! 		 "This file contains more `%c's than `%c's.",
! 		 indent_level > p->indent_level ? '{' : '}',
! 		 indent_level > p->indent_level ? '}' : '{');
  	    }
! 	  input_file_stack = p->next;
! 	  free (p);
! 	  input_file_stack_tick++;
! 	  debug_end_source_file (input_file_stack->line);
  	}
!       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;
  }
*************** parse_float (data)
*** 3313,3318 ****
--- 3195,3207 ----
      }
  }
  
+ /* Read a single token from the input stream, and assign it lexical
+    semantics.
+ 
+    Note: We used to do token pasting here, to produce compound tokens like
+    LEFT_RIGHT and EXTERN_LANG_STRING.  That's now handled in spew.c, along
+    with symbol table interaction and other context-sensitivity.  */
+ 
  int
  real_yylex ()
  {
*************** real_yylex ()
*** 3322,3331 ****
    int dollar_seen = 0;
    int i;
  
!   if (nextchar >= 0)
!     c = nextchar, nextchar = -1;
!   else
!     c = getch ();
  
    /* Effectively do c = skip_white_space (c)
       but do it faster in the usual cases.  */
--- 3211,3217 ----
    int dollar_seen = 0;
    int i;
  
!   c = getch ();
  
    /* Effectively do c = skip_white_space (c)
       but do it faster in the usual cases.  */
*************** real_yylex ()
*** 3337,3343 ****
        case '\f':
        case '\v':
        case '\b':
! 	c = getch ();
  	break;
  
        case '\r':
--- 3223,3234 ----
        case '\f':
        case '\v':
        case '\b':
! #if USE_CPPLIB
! 	if (cpp_token == CPP_HSPACE)
! 	  c = yy_get_token ();
! 	else
! #endif
! 	  c = getch ();
  	break;
  
        case '\r':
*************** real_yylex ()
*** 3379,3384 ****
--- 3270,3279 ----
        goto letter;
  
      case 'L':
+ #if USE_CPPLIB
+       if (cpp_token == CPP_NAME)
+ 	goto letter;
+ #endif
        /* Capital L may start a wide-string or wide-character constant.  */
        {
  	register int c = getch ();
*************** real_yylex ()
*** 3412,3458 ****
        {
  	register char *p;
  
! 	p = token_buffer;
! 	if (input == 0)
  	  {
! 	    /* We know that `token_buffer' can hold at least on char,
! 	       so we install C immediately.
! 	       We may have to read the value in `putback_char', so call
! 	       `getch' once.  */
! 	    *p++ = c;
! 	    c = getch ();
! 
! 	    /* Make this run fast.  We know that we are reading straight
! 	       from FINPUT in this case (since identifiers cannot straddle
! 	       input sources.  */
! 	    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 = getch ();
! 	      }
! 
! 	    if (linemode && c == '\n')
! 	      {
! 		put_back (c);
! 		c = EOF;
! 	      }
  	  }
  	else
  	  {
! 	    /* We know that `token_buffer' can hold at least on char,
! 	       so we install C immediately.  */
! 	    *p++ = c;
  	    c = getch ();
  
  	    while (ISALNUM (c) || (c == '_') || c == '$')
--- 3307,3330 ----
        {
  	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 = getch ();
  
  	    while (ISALNUM (c) || (c == '_') || c == '$')
*************** real_yylex ()
*** 3465,3485 ****
  		      pedwarn ("`$' in identifier");
  		  }
  
! 		if (p >= token_buffer + maxtoken)
  		  p = extend_token_buffer (p);
  
  		*p++ = c;
  		c = getch ();
  	      }
- 	  }
  
! 	*p = 0;
! 	nextchar = c;
  
  	value = IDENTIFIER;
  	yylval.itype = 0;
  
!       /* Try to recognize a keyword.  Uses minimum-perfect hash function */
  
  	{
  	  register struct resword *ptr;
--- 3337,3357 ----
  		      pedwarn ("`$' in identifier");
  		  }
  
! 		if ((char *)p >= token_buffer + maxtoken)
  		  p = extend_token_buffer (p);
  
  		*p++ = c;
  		c = getch ();
  	      }
  
! 	    *p = 0;
! 	    put_back (c);
! 	  }
  
  	value = IDENTIFIER;
  	yylval.itype = 0;
  
! 	/* Try to recognize a keyword.  Uses minimum-perfect hash function */
  
  	{
  	  register struct resword *ptr;
*************** real_yylex ()
*** 3499,3524 ****
  		  else if (ptr->token == AGGR || ptr->token == ENUM)
  		    looking_for_typename = 2;
  
- 		  /* Check if this is a language-type declaration.
- 		     Just glimpse the next non-white character.  */
- 		  nextchar = skip_white_space (nextchar);
- 		  if (nextchar == '"')
- 		    {
- 		      /* We are looking at a string.  Complain
- 			 if the token before the string is no `extern'.
- 			 
- 			 Could cheat some memory by placing this string
- 			 on the temporary_, instead of the saveable_
- 			 obstack.  */
- 
- 		      if (ptr->rid != RID_EXTERN)
- 			error ("invalid modifier `%s' for language string",
- 			       ptr->name);
- 		      real_yylex ();
- 		      value = EXTERN_LANG_STRING;
- 		      yylval.ttype = get_identifier (TREE_STRING_POINTER (yylval.ttype));
- 		      break;
- 		    }
  		  if (ptr->token == VISSPEC)
  		    {
  		      switch (ptr->rid)
--- 3371,3376 ----
*************** real_yylex ()
*** 3539,3553 ****
  		  else
  		    yylval.ttype = old_ttype;
  		}
! 	      else if (ptr->token == EQCOMPARE)
  		{
  		  yylval.code = NE_EXPR;
  		  token_buffer[0] = '!';
  		  token_buffer[1] = '=';
  		  token_buffer[2] = 0;
! 		}
! 	      else if (ptr->token == ASSIGN)
! 		{
  		  if (strcmp ("and_eq", token_buffer) == 0)
  		    {
  		      yylval.code = BIT_AND_EXPR;
--- 3391,3406 ----
  		  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;
*************** real_yylex ()
*** 3565,3588 ****
  		    }
  		  token_buffer[1] = '=';
  		  token_buffer[2] = 0;
! 		}
! 	      else if (ptr->token == '&')
! 		{
  		  yylval.code = BIT_AND_EXPR;
  		  token_buffer[0] = '&';
  		  token_buffer[1] = 0;
! 		}
! 	      else if (ptr->token == '|')
! 		{
  		  yylval.code = BIT_IOR_EXPR;
  		  token_buffer[0] = '|';
  		  token_buffer[1] = 0;
! 		}
! 	      else if (ptr->token == '^')
! 		{
  		  yylval.code = BIT_XOR_EXPR;
  		  token_buffer[0] = '^';
  		  token_buffer[1] = 0;
  		}
  
  	      value = (int) ptr->token;
--- 3418,3442 ----
  		    }
  		  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;
*************** real_yylex ()
*** 3623,3683 ****
  	    goto done;
  	  }
        }
        break;
  
      case '.':
!       {
! 	register int c1 = getch ();
! 	token_buffer[0] = c;
! 	token_buffer[1] = c1;
! 	if (c1 == '*')
! 	  {
! 	    value = DOT_STAR;
! 	    token_buffer[2] = 0;
! 	    goto done;
! 	  }
! 	if (c1 == '.')
! 	  {
! 	    c1 = getch ();
! 	    if (c1 == '.')
! 	      {
! 		token_buffer[2] = c1;
! 		token_buffer[3] = 0;
! 		value = ELLIPSIS;
! 		goto done;
! 	      }
! 	    error ("parse error at `..'");
! 	  }
! 	if (ISDIGIT (c1))
! 	  {
! 	    put_back (c1);
! 	    goto resume_numerical_scan;
! 	  }
! 	nextchar = c1;
! 	value = '.';
! 	token_buffer[1] = 0;
! 	goto done;
!       }
      case '0':  case '1':
! 	/* Optimize for most frequent case.  */
        {
  	register int c1 = getch ();
! 	if (! ISALNUM (c1) && c1 != '.')
  	  {
  	    /* Terminate string.  */
- 	    token_buffer[0] = c;
- 	    token_buffer[1] = 0;
  	    if (c == '0')
  	      yylval.ttype = integer_zero_node;
  	    else
  	      yylval.ttype = integer_one_node;
- 	    nextchar = c1;
  	    value = CONSTANT;
  	    goto done;
  	  }
- 	put_back (c1);
        }
!       /* fall through...  */
  			  case '2':  case '3':  case '4':
      case '5':  case '6':  case '7':  case '8':  case '9':
      resume_numerical_scan:
--- 3477,3548 ----
  	    goto done;
  	  }
        }
+ 
        break;
  
      case '.':
! #if USE_CPPLIB
!       if (yy_cur < yy_lim)
! #endif
! 	{
! 	  /* It's hard to preserve tokenization on '.' because
! 	     it could be a symbol by itself, or it could be the
! 	     start of a floating point number and cpp won't tell us.  */
! 	  register int c1 = getch ();
! 	  token_buffer[1] = c1;
! 	  if (c1 == '*')
! 	    {
! 	      value = DOT_STAR;
! 	      token_buffer[2] = 0;
! 	      goto done;
! 	    }
! 	  if (c1 == '.')
! 	    {
! 	      c1 = getch ();
! 	      if (c1 == '.')
! 		{
! 		  token_buffer[2] = c1;
! 		  token_buffer[3] = 0;
! 		  value = ELLIPSIS;
! 		  goto done;
! 		}
! 	      error ("parse error at `..'");
! 	    }
! 	  if (ISDIGIT (c1))
! 	    {
! 	      put_back (c1);
! 	      goto resume_numerical_scan;
! 	    }
! 	  put_back (c1);
! 	}
!       value = '.';
!       token_buffer[1] = 0;
!       goto done;
! 
      case '0':  case '1':
!       /* Optimize for most frequent case.  */
        {
+ 	register int cond;
+ 
+ #if USE_CPPLIB
+ 	cond = (yy_cur == yy_lim);
+ #else
  	register int c1 = getch ();
! 	put_back (c1);
! 	cond = (! ISALNUM (c1) && c1 != '.');
! #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:
*************** real_yylex ()
*** 3753,3780 ****
  		base = 10;
  		*p++ = c = getch ();
  		/* Accept '.' as the start of a floating-point number
! 		   only when it is followed by a digit.
! 		   Otherwise, unread the following non-digit
! 		   and use the '.' as a structural token.  */
  		if (p == token_buffer + 2 && !ISDIGIT (c))
! 		  {
! 		    if (c == '.')
! 		      {
! 			c = getch ();
! 			if (c == '.')
! 			  {
! 			    *p++ = '.';
! 			    *p = '\0';
! 			    value = ELLIPSIS;
! 			    goto done;
! 			  }
! 			error ("parse error at `..'");
! 		      }
! 		    nextchar = c;
! 		    token_buffer[1] = '\0';
! 		    value = '.';
! 		    goto done;
! 		  }
  	      }
  	    else
  	      {
--- 3618,3626 ----
  		base = 10;
  		*p++ = c = getch ();
  		/* Accept '.' as the start of a floating-point number
! 		   only when it is followed by a digit.  */
  		if (p == token_buffer + 2 && !ISDIGIT (c))
! 		  my_friendly_abort (990710);
  	      }
  	    else
  	      {
*************** real_yylex ()
*** 3834,3845 ****
  	  }
  
  	if (numdigits == 0)
! 	  error ("numeric constant with no digits");
  
  	if (largest_digit >= base)
  	  error ("numeric constant contains digits beyond the radix");
  
! 	/* Remove terminating char from the token buffer and delimit the string */
  	*--p = 0;
  
  	if (floatflag != NOT_FLOAT)
--- 3680,3692 ----
  	  }
  
  	if (numdigits == 0)
! 	  my_friendly_abort (990710);
  
  	if (largest_digit >= base)
  	  error ("numeric constant contains digits beyond the radix");
  
! 	/* Remove terminating char from the token buffer and delimit the
!            string.  */
  	*--p = 0;
  
  	if (floatflag != NOT_FLOAT)
*************** real_yylex ()
*** 4066,4072 ****
  	int max_chars;
  #ifdef MULTIBYTE_CHARS
  	int longest_char = local_mb_cur_max ();
! 	(void) local_mbtowc (NULL_PTR, NULL_PTR, 0);
  #endif
  
  	max_chars = TYPE_PRECISION (integer_type_node) / width;
--- 3913,3919 ----
  	int max_chars;
  #ifdef MULTIBYTE_CHARS
  	int longest_char = local_mb_cur_max ();
! 	local_mbtowc (NULL_PTR, NULL_PTR, 0);
  #endif
  
  	max_chars = TYPE_PRECISION (integer_type_node) / width;
*************** real_yylex ()
*** 4239,4251 ****
  	                           : TYPE_PRECISION (char_type_node);
  #ifdef MULTIBYTE_CHARS
  	int longest_char = local_mb_cur_max ();
! 	(void) local_mbtowc (NULL_PTR, NULL_PTR, 0);
  #endif
  
  	c = getch ();
  	p = token_buffer + 1;
  
! 	while (c != '"' && c >= 0)
  	  {
  	    /* ignore_escape_flag is set for reading the filename in #line.  */
  	    if (!ignore_escape_flag && c == '\\')
--- 4086,4098 ----
  	                           : TYPE_PRECISION (char_type_node);
  #ifdef MULTIBYTE_CHARS
  	int longest_char = local_mb_cur_max ();
! 	local_mbtowc (NULL_PTR, NULL_PTR, 0);
  #endif
  
  	c = getch ();
  	p = token_buffer + 1;
  
! 	while (c != '"' && c != EOF)
  	  {
  	    /* ignore_escape_flag is set for reading the filename in #line.  */
  	    if (!ignore_escape_flag && c == '\\')
*************** real_yylex ()
*** 4459,4472 ****
  	    }
  	else if ((c == '-') && (c1 == '>'))
  	  {
! 	    nextchar = getch ();
! 	    if (nextchar == '*')
  	      {
! 		nextchar = -1;
! 		value = POINTSAT_STAR;
  	      }
- 	    else
- 	      value = POINTSAT;
  	    goto done;
  	  }
  	else if (c1 == '?' && (c == '<' || c == '>'))
--- 4306,4319 ----
  	    }
  	else if ((c == '-') && (c1 == '>'))
  	  {
! 	    c1 = getch ();
! 	    if (c1 == '*')
! 	      value = POINTSAT_STAR;
! 	    else
  	      {
! 		put_back (c1);
! 		value = POINTSAT;
  	      }
  	    goto done;
  	  }
  	else if (c1 == '?' && (c == '<' || c == '>'))
*************** real_yylex ()
*** 4484,4490 ****
  	    else
  	      {
  		value = MIN_MAX;
! 		nextchar = c1;
  	      }
  	    if (pedantic)
  	      pedwarn ("use of `operator %s' is not standard C++",
--- 4331,4337 ----
  	    else
  	      {
  		value = MIN_MAX;
! 		put_back (c1);
  	      }
  	    if (pedantic)
  	      pedwarn ("use of `operator %s' is not standard C++",
*************** real_yylex ()
*** 4501,4507 ****
  	else if (c == '%' && c1 == ':')
  	  { value = '#'; goto done; }
  
! 	nextchar = c1;
  	token_buffer[1] = 0;
  
  	value = c;
--- 4348,4354 ----
  	else if (c == '%' && c1 == ':')
  	  { value = '#'; goto done; }
  
! 	put_back (c1);
  	token_buffer[1] = 0;
  
  	value = c;
*************** real_yylex ()
*** 4524,4530 ****
  	}
        else
  	{
! 	  nextchar = c;
  	  value = ':';
  	}
        break;
--- 4371,4377 ----
  	}
        else
  	{
! 	  put_back (c);
  	  value = ':';
  	}
        break;
*************** real_yylex ()
*** 4532,4564 ****
      case 0:
        /* Don't make yyparse think this is eof.  */
        value = 1;
-       break;
- 
-     case '(':
-       /* try, weakly, to handle casts to pointers to functions.  */
-       nextchar = skip_white_space (getch ());
-       if (nextchar == '*')
- 	{
- 	  int next_c = skip_white_space (getch ());
- 	  if (next_c == ')')
- 	    {
- 	      nextchar = -1;
- 	      yylval.ttype = build1 (INDIRECT_REF, 0, 0);
- 	      value = PAREN_STAR_PAREN;
- 	    }
- 	  else
- 	    {
- 	      put_back (next_c);
- 	      value = c;
- 	    }
- 	}
-       else if (nextchar == ')')
- 	{
- 	  nextchar = -1;
- 	  yylval.ttype = NULL_TREE;
- 	  value = LEFT_RIGHT;
- 	}
-       else value = c;
        break;
  
      default:
--- 4379,4384 ----
Index: parse.y
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/parse.y,v
retrieving revision 1.123
diff -c -p -r1.123 parse.y
*** parse.y	1999/05/24 00:46:54	1.123
--- parse.y	1999/07/10 23:49:14
*************** empty_parms ()
*** 179,185 ****
  %left <code> POINTSAT_STAR DOT_STAR
  %right <code> UNARY PLUSPLUS MINUSMINUS '~'
  %left HYPERUNARY
! %left <ttype> PAREN_STAR_PAREN LEFT_RIGHT
  %left <code> POINTSAT '.' '(' '['
  
  %right SCOPE			/* C++ extension */
--- 179,185 ----
  %left <code> POINTSAT_STAR DOT_STAR
  %right <code> UNARY PLUSPLUS MINUSMINUS '~'
  %left HYPERUNARY
! %left <ttype> LEFT_RIGHT
  %left <code> POINTSAT '.' '(' '['
  
  %right SCOPE			/* C++ extension */
*************** direct_abstract_declarator:
*** 3175,3181 ****
  	  '(' absdcl_intern ')'
  		{ $$ = $2; }
  	  /* `(typedef)1' is `int'.  */
- 	| PAREN_STAR_PAREN
  	| direct_abstract_declarator '(' parmlist ')' cv_qualifiers exception_specification_opt  %prec '.'
  		{ $$ = make_call_declarator ($$, $3, $5, $6); }
  	| direct_abstract_declarator LEFT_RIGHT cv_qualifiers exception_specification_opt  %prec '.'
--- 3175,3180 ----
Index: spew.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/spew.c,v
retrieving revision 1.20
diff -c -p -r1.20 spew.c
*** spew.c	1998/12/16 21:16:11	1.20
--- spew.c	1999/07/10 23:49:14
***************
*** 1,5 ****
  /* Type Analyzer for GNU C++.
!    Copyright (C) 1987, 89, 92-97, 1998 Free Software Foundation, Inc.
     Hacked... nay, bludgeoned... by Mark Eichin (eichin@cygnus.com)
  
  This file is part of GNU CC.
--- 1,5 ----
  /* Type Analyzer for GNU C++.
!    Copyright (C) 1987, 89, 92-97, 1998, 1999 Free Software Foundation, Inc.
     Hacked... nay, bludgeoned... by Mark Eichin (eichin@cygnus.com)
  
  This file is part of GNU CC.
*************** yylex ()
*** 305,310 ****
--- 305,320 ----
  #endif
        goto retry;
  
+     case '(':
+       scan_tokens (1);
+       if (nth_token (1)->yychar == ')')
+ 	{
+ 	  consume_token ();
+ 	  tmp_token.yychar = LEFT_RIGHT;
+ 	}
+       consume_token ();
+       break;
+ 
      case IDENTIFIER:
        scan_tokens (1);
        if (nth_token (1)->yychar == SCOPE)
*************** yylex ()
*** 361,381 ****
        break;
  
      case SCSPEC:
        /* If export, warn that it's unimplemented and go on. */
!       if (tmp_token.yylval.ttype == get_identifier("export"))
  	{
  	  warning ("keyword 'export' not implemented and will be ignored");
  	  consume_token ();
  	  goto retry;
  	}
!       else
! 	{
! 	  ++first_token;
! 	  break;
! 	}
  
      case NEW:
!       /* do_aggr needs to check if the previous token was RID_NEW,
  	 so just increment first_token instead of calling consume_token.  */
        ++first_token;
        break;
--- 371,401 ----
        break;
  
      case SCSPEC:
+       if (tmp_token.yylval.ttype == ridpointers[RID_EXTERN])
+ 	{
+ 	  scan_tokens (1);
+ 	  if (nth_token (1)->yychar == STRING)
+ 	    {
+ 	      tmp_token.yychar = EXTERN_LANG_STRING;
+ 	      tmp_token.yylval.ttype = get_identifier
+ 		(TREE_STRING_POINTER (nth_token (1)->yylval.ttype));
+ 	      consume_token ();
+ 	    }
+ 	}
        /* If export, warn that it's unimplemented and go on. */
!       else if (tmp_token.yylval.ttype == ridpointers[RID_EXPORT])
  	{
  	  warning ("keyword 'export' not implemented and will be ignored");
  	  consume_token ();
  	  goto retry;
  	}
!       /* do_aggr needs to check if the previous token was `friend',
! 	 so just increment first_token instead of calling consume_token.  */
!       ++first_token;
!       break;
  
      case NEW:
!       /* do_aggr needs to check if the previous token was `new',
  	 so just increment first_token instead of calling consume_token.  */
        ++first_token;
        break;


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