This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
(C++) patch for cpplib integration
- To: egcs-patches at egcs dot cygnus dot com
- Subject: (C++) patch for cpplib integration
- From: Jason Merrill <jason at cygnus dot com>
- Date: Sat, 10 Jul 1999 16:58:32 -0700
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;