Commit 66a6250f by Jason Merrill

lang-specs.h (c++-cpp-output): Pass -fpreprocessed.

	* lang-specs.h (c++-cpp-output): Pass -fpreprocessed.

	* lex.c (token_getch, token_put_back): New fns.
	(real_yylex): Use them.

	* 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.

	* 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.

From-SVN: r28193
parent 81f374eb
1999-07-20 Jason Merrill <jason@yorick.cygnus.com>
* lang-specs.h (c++-cpp-output): Pass -fpreprocessed.
* lex.c (token_getch, token_put_back): New fns.
(real_yylex): Use them.
* 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-20 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.
Tue Jul 20 11:24:19 1999 Bernd Schmidt <bernds@cygnus.co.uk> Tue Jul 20 11:24:19 1999 Bernd Schmidt <bernds@cygnus.co.uk>
* cp-tree.h: Delete lots of declarations of tree nodes; replaced by * cp-tree.h: Delete lots of declarations of tree nodes; replaced by
......
...@@ -1176,8 +1176,8 @@ struct lang_type ...@@ -1176,8 +1176,8 @@ struct lang_type
/* For FUNCTION_TYPE or METHOD_TYPE, a list of the exceptions that /* For FUNCTION_TYPE or METHOD_TYPE, a list of the exceptions that
this type can raise. Each TREE_VALUE is a _TYPE. The TREE_VALUE this type can raise. Each TREE_VALUE is a _TYPE. The TREE_VALUE
will be NULL_TREE to indicate a throw specification of `(...)', or, will be NULL_TREE to indicate a throw specification of `()', or
equivalently, no throw specification. */ no exceptions allowed. */
#define TYPE_RAISES_EXCEPTIONS(NODE) TYPE_NONCOPIED_PARTS (NODE) #define TYPE_RAISES_EXCEPTIONS(NODE) TYPE_NONCOPIED_PARTS (NODE)
/* For FUNCTION_TYPE or METHOD_TYPE, return 1 iff it is declared `throw()'. */ /* For FUNCTION_TYPE or METHOD_TYPE, return 1 iff it is declared `throw()'. */
......
/* Input handling for G++. /* Input handling for G++.
Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc. Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc.
Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing. 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. This file is part of GNU CC.
...@@ -31,14 +32,16 @@ Boston, MA 02111-1307, USA. */ ...@@ -31,14 +32,16 @@ Boston, MA 02111-1307, USA. */
#include "system.h" #include "system.h"
extern FILE *finput; #if !USE_CPPLIB
struct putback_buffer { struct putback_buffer {
char *buffer; char *buffer;
int buffer_size; int buffer_size;
int index; int index;
}; };
static struct putback_buffer putback = {NULL, 0, -1};
#endif
struct input_source { struct input_source {
/* saved string */ /* saved string */
char *str; char *str;
...@@ -51,7 +54,9 @@ struct input_source { ...@@ -51,7 +54,9 @@ struct input_source {
char *filename; char *filename;
int lineno; int lineno;
struct pending_input *input; struct pending_input *input;
#if !USE_CPPLIB
struct putback_buffer putback; struct putback_buffer putback;
#endif
}; };
static struct input_source *input, *free_inputs; static struct input_source *input, *free_inputs;
...@@ -62,9 +67,6 @@ extern int lineno; ...@@ -62,9 +67,6 @@ extern int lineno;
#if USE_CPPLIB #if USE_CPPLIB
extern unsigned char *yy_cur, *yy_lim; extern unsigned char *yy_cur, *yy_lim;
extern int yy_get_token (); extern int yy_get_token ();
#define GETC() (yy_cur < yy_lim ? *yy_cur++ : yy_get_token ())
#else
#define GETC() getc (finput)
#endif #endif
extern void feed_input PROTO((char *, int)); extern void feed_input PROTO((char *, int));
...@@ -76,7 +78,6 @@ extern int input_redirected PROTO((void)); ...@@ -76,7 +78,6 @@ extern int input_redirected PROTO((void));
static inline struct input_source * allocate_input PROTO((void)); static inline struct input_source * allocate_input PROTO((void));
static inline void free_input PROTO((struct input_source *)); static inline void free_input PROTO((struct input_source *));
static inline void end_input PROTO((void)); static inline void end_input PROTO((void));
static inline int sub_getch PROTO((void));
static inline struct input_source * static inline struct input_source *
allocate_input () allocate_input ()
...@@ -104,8 +105,6 @@ free_input (inp) ...@@ -104,8 +105,6 @@ free_input (inp)
free_inputs = inp; free_inputs = inp;
} }
static struct putback_buffer putback = {NULL, 0, -1};
/* Some of these external functions are declared inline in case this file /* Some of these external functions are declared inline in case this file
is included in lex.c. */ is included in lex.c. */
...@@ -121,21 +120,28 @@ feed_input (str, len) ...@@ -121,21 +120,28 @@ feed_input (str, len)
while (len && !str[len-1]) while (len && !str[len-1])
len--; len--;
#if USE_CPPLIB
if (yy_lim > yy_cur)
/* If we've started reading the next token, we're hosed. */
my_friendly_abort (990710);
cpp_push_buffer (&parse_in, str, len);
CPP_BUFFER (&parse_in)->manual_pop = 1;
#else
inp->str = str; inp->str = str;
inp->length = len; inp->length = len;
inp->offset = 0; inp->offset = 0;
inp->next = input;
inp->filename = input_filename;
inp->lineno = lineno;
inp->input = save_pending_input ();
inp->putback = putback; inp->putback = putback;
putback.buffer = NULL; putback.buffer = NULL;
putback.buffer_size = 0; putback.buffer_size = 0;
putback.index = -1; putback.index = -1;
#endif
inp->next = input;
inp->filename = input_filename;
inp->lineno = lineno;
inp->input = save_pending_input ();
input = inp; input = inp;
} }
struct pending_input *to_be_restored; /* XXX */
extern int end_of_file; extern int end_of_file;
static inline void static inline void
...@@ -143,20 +149,28 @@ end_input () ...@@ -143,20 +149,28 @@ end_input ()
{ {
struct input_source *inp = input; struct input_source *inp = input;
#if USE_CPPLIB
cpp_pop_buffer (&parse_in);
#else
putback = inp->putback;
#endif
end_of_file = 0; end_of_file = 0;
input = inp->next; input = inp->next;
input_filename = inp->filename; input_filename = inp->filename;
lineno = inp->lineno; lineno = inp->lineno;
/* Get interface/implementation back in sync. */ /* Get interface/implementation back in sync. */
extract_interface_info (); extract_interface_info ();
putback = inp->putback;
restore_pending_input (inp->input); restore_pending_input (inp->input);
free_input (inp); free_input (inp);
} }
static inline int inline int
sub_getch () getch ()
{ {
#if USE_CPPLIB
return (yy_cur < yy_lim ? *yy_cur++ : yy_get_token ());
#else
if (putback.index != -1) if (putback.index != -1)
{ {
int ch = putback.buffer[putback.index]; int ch = putback.buffer[putback.index];
...@@ -178,7 +192,8 @@ sub_getch () ...@@ -178,7 +192,8 @@ sub_getch ()
} }
return (unsigned char)input->str[input->offset++]; return (unsigned char)input->str[input->offset++];
} }
return GETC (); return getc (finput);
#endif
} }
inline inline
...@@ -186,6 +201,14 @@ void ...@@ -186,6 +201,14 @@ void
put_back (ch) put_back (ch)
int ch; int ch;
{ {
#if USE_CPPLIB
if (ch == EOF)
;
else if (yy_cur[-1] != ch)
my_friendly_abort (990709);
else
yy_cur--;
#else
if (ch != EOF) if (ch != EOF)
{ {
if (putback.index == putback.buffer_size - 1) if (putback.index == putback.buffer_size - 1)
...@@ -196,25 +219,16 @@ put_back (ch) ...@@ -196,25 +219,16 @@ put_back (ch)
my_friendly_assert (putback.buffer != NULL, 224); my_friendly_assert (putback.buffer != NULL, 224);
putback.buffer[++putback.index] = ch; putback.buffer[++putback.index] = ch;
} }
} #endif
extern int linemode;
int
getch ()
{
int ch = sub_getch ();
if (linemode && ch == '\n')
{
put_back (ch);
ch = EOF;
}
return ch;
} }
inline inline
int int
input_redirected () input_redirected ()
{ {
#ifdef USE_CPPLIB
return CPP_BUFFER(&parse_in)->manual_pop;
#else
return input != 0; return input != 0;
#endif
} }
...@@ -88,7 +88,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -88,7 +88,7 @@ Boston, MA 02111-1307, USA. */
{"@c++-cpp-output", {"@c++-cpp-output",
{"%{!M:%{!MM:%{!E:cc1plus %i %1 %2 %{!Q:-quiet} %{d*} %{m*} %{a}\ {"%{!M:%{!MM:%{!E:cc1plus %i %1 %2 %{!Q:-quiet} %{d*} %{m*} %{a}\
%{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi}\ %{g*} %{O*} %{W*} %{w} %{pedantic*} %{ansi}\
%{v:-version} %{pg:-p} %{p}\ %{v:-version} %{pg:-p} %{p} -fpreprocessed\
%{f*} %{+e*} %{aux-info*} %{Qn:-fno-ident}\ %{f*} %{+e*} %{aux-info*} %{Qn:-fno-ident}\
%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\ %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
%{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\ %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%g.s}} |\n\
......
...@@ -60,14 +60,11 @@ static int check_newline PROTO((void)); ...@@ -60,14 +60,11 @@ static int check_newline PROTO((void));
static int skip_white_space PROTO((int)); static int skip_white_space PROTO((int));
static void finish_defarg PROTO((void)); static void finish_defarg PROTO((void));
static int my_get_run_time 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 interface_strcmp PROTO((const char *));
static int readescape PROTO((int *)); static int readescape PROTO((int *));
static char *extend_token_buffer PROTO((const char *)); static char *extend_token_buffer PROTO((const char *));
static void consume_string PROTO((struct obstack *, int)); 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 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 store_pending_inline PROTO((tree, struct pending_inline *));
static void reinit_parse_for_expr PROTO((struct obstack *)); static void reinit_parse_for_expr PROTO((struct obstack *));
static int *init_cpp_parse PROTO((void)); static int *init_cpp_parse PROTO((void));
...@@ -113,12 +110,15 @@ char *inline_text_firstobj; ...@@ -113,12 +110,15 @@ char *inline_text_firstobj;
extern cpp_reader parse_in; extern cpp_reader parse_in;
extern cpp_options parse_options; extern cpp_options parse_options;
extern unsigned char *yy_cur, *yy_lim; extern unsigned char *yy_cur, *yy_lim;
extern enum cpp_token cpp_token;
extern int errorcount; extern int errorcount;
#else #else
FILE *finput; FILE *finput;
#endif #endif
int end_of_file; int end_of_file;
int linemode;
/* Pending language change. /* Pending language change.
Positive is push count, negative is pop count. */ Positive is push count, negative is pop count. */
int pending_lang_change = 0; int pending_lang_change = 0;
...@@ -130,13 +130,7 @@ extern int first_token; ...@@ -130,13 +130,7 @@ extern int first_token;
extern struct obstack token_obstack; extern struct obstack token_obstack;
/* ??? Don't really know where this goes yet. */ /* ??? Don't really know where this goes yet. */
#if 1
#include "input.c" #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, /* Holds translations from TREE_CODEs to operator name strings,
i.e., opname_tab[PLUS_EXPR] == "+". */ i.e., opname_tab[PLUS_EXPR] == "+". */
...@@ -309,6 +303,8 @@ static int maxtoken; /* Current nominal length of token buffer. */ ...@@ -309,6 +303,8 @@ static int maxtoken; /* Current nominal length of token buffer. */
char *token_buffer; /* Pointer to token buffer. char *token_buffer; /* Pointer to token buffer.
Actual allocated length is maxtoken + 2. */ Actual allocated length is maxtoken + 2. */
static int indent_level = 0; /* Number of { minus number of }. */
#include "hash.h" #include "hash.h"
...@@ -397,6 +393,7 @@ lang_init_options () ...@@ -397,6 +393,7 @@ lang_init_options ()
cpp_reader_init (&parse_in); cpp_reader_init (&parse_in);
parse_in.opts = &parse_options; parse_in.opts = &parse_options;
cpp_options_init (&parse_options); cpp_options_init (&parse_options);
parse_options.cplusplus = 1;
#endif #endif
/* Default exceptions on. */ /* Default exceptions on. */
...@@ -409,12 +406,7 @@ lang_init () ...@@ -409,12 +406,7 @@ lang_init ()
/* the beginning of the file is a new line; check for # */ /* the beginning of the file is a new line; check for # */
/* With luck, we discover the real source file's name from that /* With luck, we discover the real source file's name from that
and put it in input_filename. */ and put it in input_filename. */
#if ! USE_CPPLIB
put_back (check_newline ()); put_back (check_newline ());
#else
check_newline ();
yy_cur--;
#endif
if (flag_gnu_xref) GNU_xref_begin (input_filename); if (flag_gnu_xref) GNU_xref_begin (input_filename);
init_repo (input_filename); init_repo (input_filename);
} }
...@@ -498,6 +490,7 @@ init_parse (filename) ...@@ -498,6 +490,7 @@ init_parse (filename)
token buffer. We must arrange to read it out here. */ token buffer. We must arrange to read it out here. */
yy_cur = parse_in.token_buffer; yy_cur = parse_in.token_buffer;
yy_lim = CPP_PWRITTEN (&parse_in); yy_lim = CPP_PWRITTEN (&parse_in);
cpp_token = CPP_DIRECTIVE;
#else #else
/* Open input file. */ /* Open input file. */
...@@ -1224,40 +1217,6 @@ cp_pragma_implementation (main_filename) ...@@ -1224,40 +1217,6 @@ cp_pragma_implementation (main_filename)
TREE_INT_CST_LOW (fileinfo) = interface_only; TREE_INT_CST_LOW (fileinfo) = interface_only;
TREE_INT_CST_HIGH (fileinfo) = interface_unknown; 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 /* Set up the state required to correctly handle the definition of the
inline function whose preparsed state has been saved in PI. */ inline function whose preparsed state has been saved in PI. */
...@@ -1328,8 +1287,6 @@ do_pending_inlines () ...@@ -1328,8 +1287,6 @@ do_pending_inlines ()
begin_definition_of_inclass_inline (t); begin_definition_of_inclass_inline (t);
} }
static int nextchar = -1;
/* Called from the fndecl rule in the parser when the function just parsed /* 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 was declared using a PRE_PARSED_FUNCTION_DECL (i.e. came from
do_pending_inlines). */ do_pending_inlines). */
...@@ -1352,9 +1309,7 @@ process_next_inline (t) ...@@ -1352,9 +1309,7 @@ process_next_inline (t)
/* restore_pending_input will abort unless yychar is either /* restore_pending_input will abort unless yychar is either
END_OF_SAVED_INPUT or YYEMPTY; since we already know we're END_OF_SAVED_INPUT or YYEMPTY; since we already know we're
hosed, feed back YYEMPTY. We also need to discard nextchar, hosed, feed back YYEMPTY. */
since that may have gotten set as well. */
nextchar = -1;
} }
yychar = YYEMPTY; yychar = YYEMPTY;
end_input (); end_input ();
...@@ -1380,7 +1335,20 @@ consume_string (this_obstack, matching_char) ...@@ -1380,7 +1335,20 @@ consume_string (this_obstack, matching_char)
int matching_char; int matching_char;
{ {
register int c; register int c;
int starting_lineno = lineno; 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 do
{ {
c = getch (); c = getch ();
...@@ -1416,12 +1384,9 @@ consume_string (this_obstack, matching_char) ...@@ -1416,12 +1384,9 @@ consume_string (this_obstack, matching_char)
while (c != matching_char); while (c != matching_char);
} }
static int nextyychar = YYEMPTY;
static YYSTYPE nextyylval;
struct pending_input { struct pending_input {
int nextchar, yychar, nextyychar, eof; int yychar, eof;
YYSTYPE yylval, nextyylval; YYSTYPE yylval;
struct obstack token_obstack; struct obstack token_obstack;
int first_token; int first_token;
}; };
...@@ -1431,14 +1396,10 @@ save_pending_input () ...@@ -1431,14 +1396,10 @@ save_pending_input ()
{ {
struct pending_input *p; struct pending_input *p;
p = (struct pending_input *) xmalloc (sizeof (struct pending_input)); p = (struct pending_input *) xmalloc (sizeof (struct pending_input));
p->nextchar = nextchar;
p->yychar = yychar; p->yychar = yychar;
p->nextyychar = nextyychar;
p->yylval = yylval; p->yylval = yylval;
p->nextyylval = nextyylval;
p->eof = end_of_file; p->eof = end_of_file;
yychar = nextyychar = YYEMPTY; yychar = YYEMPTY;
nextchar = -1;
p->first_token = first_token; p->first_token = first_token;
p->token_obstack = token_obstack; p->token_obstack = token_obstack;
...@@ -1452,14 +1413,9 @@ void ...@@ -1452,14 +1413,9 @@ void
restore_pending_input (p) restore_pending_input (p)
struct 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); my_friendly_assert (yychar == YYEMPTY || yychar == END_OF_SAVED_INPUT, 230);
yychar = p->yychar; yychar = p->yychar;
my_friendly_assert (nextyychar == YYEMPTY, 231);
nextyychar = p->nextyychar;
yylval = p->yylval; yylval = p->yylval;
nextyylval = p->nextyylval;
first_token = p->first_token; first_token = p->first_token;
obstack_free (&token_obstack, (char *) 0); obstack_free (&token_obstack, (char *) 0);
token_obstack = p->token_obstack; token_obstack = p->token_obstack;
...@@ -1479,15 +1435,10 @@ yyungetc (ch, rescan) ...@@ -1479,15 +1435,10 @@ yyungetc (ch, rescan)
/* Unget a character from the input stream. */ /* Unget a character from the input stream. */
if (yychar == YYEMPTY || rescan == 0) if (yychar == YYEMPTY || rescan == 0)
{ {
if (nextchar >= 0) put_back (ch);
put_back (nextchar);
nextchar = ch;
} }
else else
{ {
my_friendly_assert (nextyychar == YYEMPTY, 232);
nextyychar = yychar;
nextyylval = yylval;
yychar = ch; yychar = ch;
} }
} }
...@@ -1570,7 +1521,7 @@ reinit_parse_for_block (pyychar, obstackp) ...@@ -1570,7 +1521,7 @@ reinit_parse_for_block (pyychar, obstackp)
int pyychar; int pyychar;
struct obstack *obstackp; struct obstack *obstackp;
{ {
register int c = 0; register int c;
int blev = 1; int blev = 1;
int starting_lineno = lineno; int starting_lineno = lineno;
char *starting_filename = input_filename; char *starting_filename = input_filename;
...@@ -1608,14 +1559,8 @@ reinit_parse_for_block (pyychar, obstackp) ...@@ -1608,14 +1559,8 @@ reinit_parse_for_block (pyychar, obstackp)
obstack_1grow (obstackp, '{'); obstack_1grow (obstackp, '{');
} }
if (nextchar != EOF) c = getch ();
{
c = nextchar;
nextchar = EOF;
}
else
c = getch ();
while (c != EOF) while (c != EOF)
{ {
int this_lineno = lineno; int this_lineno = lineno;
...@@ -1737,20 +1682,14 @@ static void ...@@ -1737,20 +1682,14 @@ static void
reinit_parse_for_expr (obstackp) reinit_parse_for_expr (obstackp)
struct obstack *obstackp; struct obstack *obstackp;
{ {
register int c = 0; register int c;
int starting_lineno = lineno; int starting_lineno = lineno;
char *starting_filename = input_filename; char *starting_filename = input_filename;
int len; int len;
int plev = 0; int plev = 0;
if (nextchar != EOF) c = getch ();
{
c = nextchar;
nextchar = EOF;
}
else
c = getch ();
while (c != EOF) while (c != EOF)
{ {
int this_lineno = lineno; int this_lineno = lineno;
...@@ -1922,9 +1861,7 @@ finish_defarg () ...@@ -1922,9 +1861,7 @@ finish_defarg ()
/* restore_pending_input will abort unless yychar is either /* restore_pending_input will abort unless yychar is either
END_OF_SAVED_INPUT or YYEMPTY; since we already know we're END_OF_SAVED_INPUT or YYEMPTY; since we already know we're
hosed, feed back YYEMPTY. We also need to discard nextchar, hosed, feed back YYEMPTY. */
since that may have gotten set as well. */
nextchar = -1;
} }
yychar = YYEMPTY; yychar = YYEMPTY;
end_input (); end_input ();
...@@ -2192,6 +2129,11 @@ skip_white_space (c) ...@@ -2192,6 +2129,11 @@ skip_white_space (c)
switch (c) switch (c)
{ {
case '\n': case '\n':
if (linemode)
{
put_back (c);
return EOF;
}
c = check_newline (); c = check_newline ();
break; break;
...@@ -2201,9 +2143,14 @@ skip_white_space (c) ...@@ -2201,9 +2143,14 @@ skip_white_space (c)
case '\r': case '\r':
case '\v': case '\v':
case '\b': case '\b':
do #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 (); c = getch ();
while (c == ' ' || c == '\t');
break; break;
case '\\': case '\\':
...@@ -2221,472 +2168,407 @@ skip_white_space (c) ...@@ -2221,472 +2168,407 @@ skip_white_space (c)
} }
} }
/* Make the token buffer longer, preserving the data in it. /* Make the token buffer longer, preserving the data in it.
P should point to just beyond the last valid character in the old buffer. 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 The value we return is a pointer to the new buffer
at a place corresponding to P. */ 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 * static char *
extend_token_buffer (p) extend_token_buffer (p)
const char *p; const char *p;
{ {
int offset = p - token_buffer; int offset = p - token_buffer;
extend_token_buffer_to (offset);
maxtoken = maxtoken * 2 + 10;
token_buffer = (char *) xrealloc (token_buffer, maxtoken + 2);
return token_buffer + offset; return token_buffer + offset;
} }
static int static int
get_last_nonwhite_on_line () read_line_number (num)
int *num;
{ {
register int c; register int token = real_yylex ();
/* Is this the last nonwhite stuff on the line? */ if (token == CONSTANT
if (nextchar >= 0) && TREE_CODE (yylval.ttype) == INTEGER_CST)
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; *num = TREE_INT_CST_LOW (yylval.ttype);
nextchar = EOF; return 1;
} }
else else
c = getch (); {
if (token != END_OF_LINE)
return c; error ("invalid #-line");
} return 0;
}
static void
pragma_ungetc (arg)
int arg;
{
yyungetc (arg, 0);
} }
#endif /* HANDLE_PRAGMA */
/* At the beginning of a line, increment the line number /* At the beginning of a line, increment the line number
and process any #-directive on this line. and process any #-directive on this line.
If the line is a #-directive, read the entire line and return a newline. If the line is a #-directive, read the entire line and return a newline.
Otherwise, return the line's first non-whitespace character. */ Otherwise, return the line's first non-whitespace character.
int linemode; Note that in the case of USE_CPPLIB, we get the whole line as one
CPP_DIRECTIVE token. */
static int static int
check_newline () check_newline ()
{ {
register int c; register int c;
register int token; register int token;
int saw_line = 0; 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 /* Read first nonwhite char on the line. Do this before incrementing the
line number, in case we're at the end of saved text. */ 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 do
c = getch (); c = getch ();
while (c == ' ' || c == '\t'); while (c == ' ' || c == '\t');
#endif
lineno++; lineno++;
if (c != '#') 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. */ /* If not #, return it so caller will use it. */
return c; return c;
} }
/* Don't read beyond this line. */ /* Don't read beyond this line. */
saw_line = 0;
linemode = 1; linemode = 1;
/* Read first nonwhite char after the `#'. */ #if USE_CPPLIB
if (cpp_token == CPP_VSPACE)
do {
c = getch (); /* Format is "<space> <line number> <filename> <newline>".
while (c == ' ' || c == '\t'); 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
/* If a letter follows, then if the word here is `line', skip token = real_yylex ();
it and ignore it; otherwise, ignore the line, with an error
if the word isn't `pragma'. */
if (ISALPHA (c)) if (token == IDENTIFIER)
{ {
if (c == 'p') /* 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"))
{ {
if (getch () == 'r' token = real_yylex ();
&& getch () == 'a' if (token == IDENTIFIER
&& getch () == 'g' && TREE_CODE (yylval.ttype) == IDENTIFIER_NODE)
&& getch () == 'm'
&& getch () == 'a')
{ {
token = real_yylex (); /* If this is 1, we handled it; if it's -1, it was one we
if (token == IDENTIFIER wanted but had something wrong with it. Only if it's
&& TREE_CODE (yylval.ttype) == IDENTIFIER_NODE) 0 was it not handled. */
{ if (handle_cp_pragma (IDENTIFIER_POINTER (yylval.ttype)))
/* 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; goto skipline;
}
else if (token == END_OF_LINE)
goto skipline;
#ifdef HANDLE_PRAGMA #ifdef HANDLE_PRAGMA
/* We invoke HANDLE_PRAGMA before HANDLE_GENERIC_PRAGMAS /* We invoke HANDLE_PRAGMA before HANDLE_GENERIC_PRAGMAS
(if both are defined), in order to give the back (if both are defined), in order to give the back
end a chance to override the interpretation of end a chance to override the interpretation of
SYSV style pragmas. */ SYSV style pragmas. */
if (HANDLE_PRAGMA (pragma_getc, pragma_ungetc, if (HANDLE_PRAGMA (getch, put_back,
IDENTIFIER_POINTER (yylval.ttype))) IDENTIFIER_POINTER (yylval.ttype)))
goto skipline; goto skipline;
#endif /* HANDLE_PRAGMA */ #endif /* HANDLE_PRAGMA */
#ifdef HANDLE_GENERIC_PRAGMAS #ifdef HANDLE_GENERIC_PRAGMAS
if (handle_generic_pragma (token)) if (handle_generic_pragma (token))
goto skipline; goto skipline;
#endif /* HANDLE_GENERIC_PRAGMAS */ #endif /* HANDLE_GENERIC_PRAGMAS */
/* Issue a warning message if we have been asked to do so. /* Issue a warning message if we have been asked to do so.
Ignoring unknown pragmas in system header file unless Ignoring unknown pragmas in system header file unless
an explcit -Wunknown-pragmas has been given. */ an explcit -Wunknown-pragmas has been given. */
if (warn_unknown_pragmas > 1 if (warn_unknown_pragmas > 1
|| (warn_unknown_pragmas && ! in_system_header)) || (warn_unknown_pragmas && ! in_system_header))
warning ("ignoring pragma: %s", token_buffer); warning ("ignoring pragma: %s", token_buffer);
}
goto skipline; goto skipline;
} }
else if (c == 'd') else if (!strcmp (name, "define"))
{ {
if (getch () == 'e' debug_define (lineno, GET_DIRECTIVE_LINE ());
&& getch () == 'f' goto skipline;
&& getch () == 'i'
&& getch () == 'n'
&& getch () == 'e'
&& ((c = getch ()) == ' ' || c == '\t'))
{
debug_define (lineno, GET_DIRECTIVE_LINE ());
goto skipline;
}
} }
else if (c == 'u') else if (!strcmp (name, "undef"))
{ {
if (getch () == 'n' debug_undef (lineno, GET_DIRECTIVE_LINE ());
&& getch () == 'd' goto skipline;
&& getch () == 'e'
&& getch () == 'f'
&& ((c = getch ()) == ' ' || c == '\t'))
{
debug_undef (lineno, GET_DIRECTIVE_LINE ());
goto skipline;
}
} }
else if (c == 'l') else if (!strcmp (name, "line"))
{ {
if (getch () == 'i' saw_line = 1;
&& getch () == 'n' token = real_yylex ();
&& getch () == 'e' goto linenum;
&& ((c = getch ()) == ' ' || c == '\t'))
{
saw_line = 1;
goto linenum;
}
} }
else if (c == 'i') else if (!strcmp (name, "ident"))
{ {
if (getch () == 'd' /* #ident. The pedantic warning is now in cccp.c. */
&& 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) /* Here we have just seen `#ident '.
{ A string constant should follow. */
#ifdef ASM_OUTPUT_IDENT
ASM_OUTPUT_IDENT (asm_out_file,
TREE_STRING_POINTER (yylval.ttype));
#endif
}
/* Skip the rest of this line. */ token = real_yylex ();
if (token == END_OF_LINE)
goto skipline;
if (token != STRING
|| TREE_CODE (yylval.ttype) != STRING_CST)
{
error ("invalid #ident");
goto skipline; goto skipline;
} }
}
else if (c == 'n') if (! flag_no_ident)
{
if (getch () == 'e'
&& getch () == 'w'
&& getch () == 'w'
&& getch () == 'o'
&& getch () == 'r'
&& getch () == 'l'
&& getch () == 'd'
&& ((c = getch ()) == ' ' || c == '\t'))
{ {
/* Used to test incremental compilation. */ #ifdef ASM_OUTPUT_IDENT
sorry ("#pragma newworld"); ASM_OUTPUT_IDENT (asm_out_file,
goto skipline; TREE_STRING_POINTER (yylval.ttype));
#endif
} }
/* Skip the rest of this line. */
goto skipline;
} }
error ("undefined or invalid # directive");
error ("undefined or invalid # directive `%s'", name);
goto skipline; 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, /* If the # is the only nonwhite char on the line,
just ignore it. Check the new newline. */ just ignore it. Check the new newline. */
if (c == EOF) if (token == END_OF_LINE)
goto skipline; goto skipline;
/* Something follows the #; read a token. */ linenum:
/* Here we have either `#line' or `# <nonletter>'.
put_back (c); In either case, it should be a line number; a digit should follow. */
token = real_yylex ();
if (token == CONSTANT if (token != CONSTANT
&& TREE_CODE (yylval.ttype) == INTEGER_CST) || TREE_CODE (yylval.ttype) != INTEGER_CST)
{ {
int old_lineno = lineno; error ("invalid #-line");
enum { act_none, act_push, act_pop } action = act_none; goto skipline;
int entering_system_header = 0; }
int entering_c_header = 0;
/* subtract one, because it is the following line that /* subtract one, because it is the following line that
gets the specified number */ gets the specified number */
int l = TREE_INT_CST_LOW (yylval.ttype) - 1; 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). */ /* 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) if (saw_line)
{ {
/* Don't treat \ as special if we are processing #line 1 "...". /* Don't treat \ as special if we are processing #line 1 "...".
If you want it to be treated specially, use # 1 "...". */ If you want it to be treated specially, use # 1 "...". */
ignore_escape_flag = 1; ignore_escape_flag = 1;
} }
/* Read the string constant. */ /* Read the string constant. */
token = real_yylex (); token = real_yylex ();
ignore_escape_flag = 0; ignore_escape_flag = 0;
if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST) if (token == END_OF_LINE)
{ {
error ("invalid #line"); /* No more: store the line number and check following line. */
goto skipline; lineno = l;
} goto skipline;
}
/* Changing files again. This means currently collected time if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
is charged against header time, and body time starts back {
at 0. */ error ("invalid #line");
if (flag_detailed_statistics) goto skipline;
{ }
int this_time = my_get_run_time ();
tree time_identifier = get_time_identifier (TREE_STRING_POINTER (yylval.ttype)); /* Changing files again. This means currently collected time
header_time += this_time - body_time; is charged against header time, and body time starts back at 0. */
TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (this_filename_time)) if (flag_detailed_statistics)
+= this_time - body_time; {
this_filename_time = time_identifier; int this_time = my_get_run_time ();
body_time = this_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 input_filename
= (char *) permalloc (TREE_STRING_LENGTH (yylval.ttype) + 1); = (char *) permalloc (TREE_STRING_LENGTH (yylval.ttype) + 1);
strcpy (input_filename, TREE_STRING_POINTER (yylval.ttype)); strcpy (input_filename, TREE_STRING_POINTER (yylval.ttype));
lineno = l; }
GNU_xref_file (input_filename); else
input_filename = TREE_STRING_POINTER (yylval.ttype);
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 (); GNU_xref_file (input_filename);
if (main_input_filename == 0)
{
struct impl_files *ifiles = impl_file_chain;
c = get_last_nonwhite_on_line (); if (ifiles)
if (c == EOF)
{ {
/* Update the name in the top element of input_file_stack. */ while (ifiles->next)
if (input_file_stack) ifiles = ifiles->next;
input_file_stack->name = input_filename; ifiles->filename = file_name_nondirectory (input_filename);
} }
else
{
put_back (c);
token = real_yylex (); main_input_filename = input_filename;
}
/* `1' after file name means entering new file. extract_interface_info ();
`2' after file name means just left a file. */
if (token == CONSTANT old_lineno = lineno;
&& TREE_CODE (yylval.ttype) == INTEGER_CST) entering_system_header = 0;
{ entering_c_header = 0;
if (TREE_INT_CST_LOW (yylval.ttype) == 1) action = act_none;
action = act_push; action_number = 0;
else if (TREE_INT_CST_LOW (yylval.ttype) == 2) lineno = l;
action = act_pop;
if (action) if (!read_line_number (&action_number))
{ {
c = get_last_nonwhite_on_line (); /* Update the name in the top element of input_file_stack. */
if (c != EOF) if (input_file_stack)
{ input_file_stack->name = input_filename;
put_back (c); }
token = real_yylex ();
}
}
}
/* `3' after file name means this is a system header file. */ /* `1' after file name means entering new file.
`2' after file name means just left a file. */
if (token == CONSTANT if (action_number == 1)
&& TREE_CODE (yylval.ttype) == INTEGER_CST {
&& TREE_INT_CST_LOW (yylval.ttype) == 3) action = act_push;
{ read_line_number (&action_number);
entering_system_header = 1; }
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);
}
c = get_last_nonwhite_on_line (); /* Do the actions implied by the preceding numbers. */
if (c != EOF)
{
put_back (c);
token = real_yylex ();
}
}
/* `4' after file name means this is a C header file. */ 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 (token == CONSTANT if (c_header_level && --c_header_level == 0)
&& TREE_CODE (yylval.ttype) == INTEGER_CST
&& TREE_INT_CST_LOW (yylval.ttype) == 4)
{ {
entering_c_header = 1; if (entering_c_header)
warning ("badly nested C headers from preprocessor");
c = get_last_nonwhite_on_line (); --pending_lang_change;
if (c != EOF)
{
put_back (c);
token = real_yylex ();
}
} }
in_system_header = entering_system_header;
/* Do the actions implied by the preceding numbers. */ p = input_file_stack;
if (indent_level != p->indent_level)
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. */ warning_with_file_and_line
if (input_file_stack->next) (p->name, old_lineno,
{ "This file contains more `%c's than `%c's.",
struct file_stack *p; indent_level > p->indent_level ? '{' : '}',
indent_level > p->indent_level ? '}' : '{');
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 input_file_stack = p->next;
in_system_header = entering_system_header; free (p);
input_file_stack_tick++;
debug_end_source_file (input_file_stack->line);
} }
else
/* If NEXTCHAR is not end of line, we don't care what it is. */ error ("#-lines for entering and leaving files don't match");
if (nextchar == EOF)
c = EOF;
} }
else else
error ("invalid #-line"); in_system_header = entering_system_header;
/* skip the rest of this line. */ /* skip the rest of this line. */
skipline: skipline:
linemode = 0; linemode = 0;
end_of_file = 0; end_of_file = 0;
nextchar = -1;
while ((c = getch ()) != EOF && c != '\n'); while ((c = getch ()) != EOF && c != '\n');
return c; return c;
} }
...@@ -3312,6 +3194,40 @@ parse_float (data) ...@@ -3312,6 +3194,40 @@ parse_float (data)
} }
} }
/* Get the next character, staying within the current token if possible.
If we're lexing a token, we don't want to look beyond the end of the
token cpplib has prepared for us; otherwise, we end up reading in the
next token, which screws up feed_input. So just return a null
character. */
inline int
token_getch ()
{
#if USE_CPPLIB
if (yy_cur == yy_lim)
return '\0';
#endif
return getch ();
}
inline void
token_put_back (ch)
int ch;
{
#if USE_CPPLIB
if (ch == '\0')
return;
#endif
put_back (ch);
}
/* 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 int
real_yylex () real_yylex ()
{ {
...@@ -3321,10 +3237,7 @@ real_yylex () ...@@ -3321,10 +3237,7 @@ real_yylex ()
int dollar_seen = 0; int dollar_seen = 0;
int i; int i;
if (nextchar >= 0) c = getch ();
c = nextchar, nextchar = -1;
else
c = getch ();
/* Effectively do c = skip_white_space (c) /* Effectively do c = skip_white_space (c)
but do it faster in the usual cases. */ but do it faster in the usual cases. */
...@@ -3336,7 +3249,12 @@ real_yylex () ...@@ -3336,7 +3249,12 @@ real_yylex ()
case '\f': case '\f':
case '\v': case '\v':
case '\b': case '\b':
c = getch (); #if USE_CPPLIB
if (cpp_token == CPP_HSPACE)
c = yy_get_token ();
else
#endif
c = getch ();
break; break;
case '\r': case '\r':
...@@ -3378,9 +3296,13 @@ real_yylex () ...@@ -3378,9 +3296,13 @@ real_yylex ()
goto letter; goto letter;
case 'L': case 'L':
#if USE_CPPLIB
if (cpp_token == CPP_NAME)
goto letter;
#endif
/* Capital L may start a wide-string or wide-character constant. */ /* Capital L may start a wide-string or wide-character constant. */
{ {
register int c = getch (); register int c = token_getch ();
if (c == '\'') if (c == '\'')
{ {
wide_flag = 1; wide_flag = 1;
...@@ -3391,7 +3313,7 @@ real_yylex () ...@@ -3391,7 +3313,7 @@ real_yylex ()
wide_flag = 1; wide_flag = 1;
goto string_constant; goto string_constant;
} }
put_back (c); token_put_back (c);
} }
case 'A': case 'B': case 'C': case 'D': case 'E': case 'A': case 'B': case 'C': case 'D': case 'E':
...@@ -3411,48 +3333,25 @@ real_yylex () ...@@ -3411,48 +3333,25 @@ real_yylex ()
{ {
register char *p; register char *p;
p = token_buffer; #if USE_CPPLIB
if (input == 0) if (cpp_token == CPP_NAME)
{ {
/* We know that `token_buffer' can hold at least on char, /* Note that one character has already been read from
so we install C immediately. yy_cur into token_buffer. */
We may have to read the value in `putback_char', so call
`getch' once. */ int len = yy_lim - yy_cur + 1;
*p++ = c; if (len >= maxtoken)
c = getch (); extend_token_buffer_to (len + 1);
memcpy (token_buffer + 1, yy_cur, len);
/* Make this run fast. We know that we are reading straight p = token_buffer + len;
from FINPUT in this case (since identifiers cannot straddle yy_cur = yy_lim;
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 else
#endif
{ {
/* We know that `token_buffer' can hold at least on char, /* We already installed C as the first char in token_buffer. */
so we install C immediately. */ p = token_buffer+1;
*p++ = c; c = token_getch ();
c = getch ();
while (ISALNUM (c) || (c == '_') || c == '$') while (ISALNUM (c) || (c == '_') || c == '$')
{ {
...@@ -3468,17 +3367,17 @@ real_yylex () ...@@ -3468,17 +3367,17 @@ real_yylex ()
p = extend_token_buffer (p); p = extend_token_buffer (p);
*p++ = c; *p++ = c;
c = getch (); c = token_getch ();
} }
}
*p = 0; *p = 0;
nextchar = c; token_put_back (c);
}
value = IDENTIFIER; value = IDENTIFIER;
yylval.itype = 0; yylval.itype = 0;
/* Try to recognize a keyword. Uses minimum-perfect hash function */ /* Try to recognize a keyword. Uses minimum-perfect hash function */
{ {
register struct resword *ptr; register struct resword *ptr;
...@@ -3498,26 +3397,6 @@ real_yylex () ...@@ -3498,26 +3397,6 @@ real_yylex ()
else if (ptr->token == AGGR || ptr->token == ENUM) else if (ptr->token == AGGR || ptr->token == ENUM)
looking_for_typename = 2; 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) if (ptr->token == VISSPEC)
{ {
switch (ptr->rid) switch (ptr->rid)
...@@ -3538,15 +3417,16 @@ real_yylex () ...@@ -3538,15 +3417,16 @@ real_yylex ()
else else
yylval.ttype = old_ttype; yylval.ttype = old_ttype;
} }
else if (ptr->token == EQCOMPARE) else switch (ptr->token)
{ {
case EQCOMPARE:
yylval.code = NE_EXPR; yylval.code = NE_EXPR;
token_buffer[0] = '!'; token_buffer[0] = '!';
token_buffer[1] = '='; token_buffer[1] = '=';
token_buffer[2] = 0; token_buffer[2] = 0;
} break;
else if (ptr->token == ASSIGN)
{ case ASSIGN:
if (strcmp ("and_eq", token_buffer) == 0) if (strcmp ("and_eq", token_buffer) == 0)
{ {
yylval.code = BIT_AND_EXPR; yylval.code = BIT_AND_EXPR;
...@@ -3564,24 +3444,25 @@ real_yylex () ...@@ -3564,24 +3444,25 @@ real_yylex ()
} }
token_buffer[1] = '='; token_buffer[1] = '=';
token_buffer[2] = 0; token_buffer[2] = 0;
} break;
else if (ptr->token == '&')
{ case '&':
yylval.code = BIT_AND_EXPR; yylval.code = BIT_AND_EXPR;
token_buffer[0] = '&'; token_buffer[0] = '&';
token_buffer[1] = 0; token_buffer[1] = 0;
} break;
else if (ptr->token == '|')
{ case '|':
yylval.code = BIT_IOR_EXPR; yylval.code = BIT_IOR_EXPR;
token_buffer[0] = '|'; token_buffer[0] = '|';
token_buffer[1] = 0; token_buffer[1] = 0;
} break;
else if (ptr->token == '^')
{ case '^':
yylval.code = BIT_XOR_EXPR; yylval.code = BIT_XOR_EXPR;
token_buffer[0] = '^'; token_buffer[0] = '^';
token_buffer[1] = 0; token_buffer[1] = 0;
break;
} }
value = (int) ptr->token; value = (int) ptr->token;
...@@ -3622,61 +3503,72 @@ real_yylex () ...@@ -3622,61 +3503,72 @@ real_yylex ()
goto done; goto done;
} }
} }
break; break;
case '.': case '.':
{ #if USE_CPPLIB
register int c1 = getch (); if (yy_cur < yy_lim)
token_buffer[0] = c; #endif
token_buffer[1] = c1; {
if (c1 == '*') /* It's hard to preserve tokenization on '.' because
{ it could be a symbol by itself, or it could be the
value = DOT_STAR; start of a floating point number and cpp won't tell us. */
token_buffer[2] = 0; register int c1 = token_getch ();
goto done; token_buffer[1] = c1;
} if (c1 == '*')
if (c1 == '.') {
{ value = DOT_STAR;
c1 = getch (); token_buffer[2] = 0;
if (c1 == '.') goto done;
{ }
token_buffer[2] = c1; if (c1 == '.')
token_buffer[3] = 0; {
value = ELLIPSIS; c1 = token_getch ();
goto done; if (c1 == '.')
} {
error ("parse error at `..'"); token_buffer[2] = c1;
} token_buffer[3] = 0;
if (ISDIGIT (c1)) value = ELLIPSIS;
{ goto done;
put_back (c1); }
goto resume_numerical_scan; error ("parse error at `..'");
} }
nextchar = c1; if (ISDIGIT (c1))
value = '.'; {
token_buffer[1] = 0; token_put_back (c1);
goto done; goto resume_numerical_scan;
} }
token_put_back (c1);
}
value = '.';
token_buffer[1] = 0;
goto done;
case '0': case '1': case '0': case '1':
/* Optimize for most frequent case. */ /* Optimize for most frequent case. */
{ {
register int c1 = getch (); register int cond;
if (! ISALNUM (c1) && c1 != '.')
#if USE_CPPLIB
cond = (yy_cur == yy_lim);
#else
register int c1 = token_getch ();
token_put_back (c1);
cond = (! ISALNUM (c1) && c1 != '.');
#endif
if (cond)
{ {
/* Terminate string. */ /* Terminate string. */
token_buffer[0] = c;
token_buffer[1] = 0;
if (c == '0') if (c == '0')
yylval.ttype = integer_zero_node; yylval.ttype = integer_zero_node;
else else
yylval.ttype = integer_one_node; yylval.ttype = integer_one_node;
nextchar = c1;
value = CONSTANT; value = CONSTANT;
goto done; goto done;
} }
put_back (c1);
} }
/* fall through... */ /* fall through... */
case '2': case '3': case '4': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': case '5': case '6': case '7': case '8': case '9':
resume_numerical_scan: resume_numerical_scan:
...@@ -3707,11 +3599,11 @@ real_yylex () ...@@ -3707,11 +3599,11 @@ real_yylex ()
if (c == '0') if (c == '0')
{ {
*p++ = (c = getch ()); *p++ = (c = token_getch ());
if ((c == 'x') || (c == 'X')) if ((c == 'x') || (c == 'X'))
{ {
base = 16; base = 16;
*p++ = (c = getch ()); *p++ = (c = token_getch ());
} }
/* Leading 0 forces octal unless the 0 is the only digit. */ /* Leading 0 forces octal unless the 0 is the only digit. */
else if (c >= '0' && c <= '9') else if (c >= '0' && c <= '9')
...@@ -3750,30 +3642,11 @@ real_yylex () ...@@ -3750,30 +3642,11 @@ real_yylex ()
floatflag = AFTER_POINT; floatflag = AFTER_POINT;
base = 10; base = 10;
*p++ = c = getch (); *p++ = c = token_getch ();
/* Accept '.' as the start of a floating-point number /* Accept '.' as the start of a floating-point number
only when it is followed by a digit. 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 (p == token_buffer + 2 && !ISDIGIT (c))
{ my_friendly_abort (990710);
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 else
{ {
...@@ -3828,17 +3701,18 @@ real_yylex () ...@@ -3828,17 +3701,18 @@ real_yylex ()
if (p >= token_buffer + maxtoken - 3) if (p >= token_buffer + maxtoken - 3)
p = extend_token_buffer (p); p = extend_token_buffer (p);
*p++ = (c = getch ()); *p++ = (c = token_getch ());
} }
} }
if (numdigits == 0) if (numdigits == 0)
error ("numeric constant with no digits"); my_friendly_abort (990710);
if (largest_digit >= base) if (largest_digit >= base)
error ("numeric constant contains digits beyond the radix"); error ("numeric constant contains digits beyond the radix");
/* Remove terminating char from the token buffer and delimit the string */ /* Remove terminating char from the token buffer and delimit the
string. */
*--p = 0; *--p = 0;
if (floatflag != NOT_FLOAT) if (floatflag != NOT_FLOAT)
...@@ -3856,11 +3730,11 @@ real_yylex () ...@@ -3856,11 +3730,11 @@ real_yylex ()
if (p >= token_buffer + maxtoken - 3) if (p >= token_buffer + maxtoken - 3)
p = extend_token_buffer (p); p = extend_token_buffer (p);
*p++ = c; *p++ = c;
c = getch (); c = token_getch ();
if ((c == '+') || (c == '-')) if ((c == '+') || (c == '-'))
{ {
*p++ = c; *p++ = c;
c = getch (); c = token_getch ();
} }
if (! ISDIGIT (c)) if (! ISDIGIT (c))
error ("floating constant exponent has no digits"); error ("floating constant exponent has no digits");
...@@ -3869,7 +3743,7 @@ real_yylex () ...@@ -3869,7 +3743,7 @@ real_yylex ()
if (p >= token_buffer + maxtoken - 3) if (p >= token_buffer + maxtoken - 3)
p = extend_token_buffer (p); p = extend_token_buffer (p);
*p++ = c; *p++ = c;
c = getch (); c = token_getch ();
} }
} }
...@@ -3973,7 +3847,7 @@ real_yylex () ...@@ -3973,7 +3847,7 @@ real_yylex ()
if (p >= token_buffer + maxtoken - 3) if (p >= token_buffer + maxtoken - 3)
p = extend_token_buffer (p); p = extend_token_buffer (p);
*p++ = c; *p++ = c;
c = getch (); c = token_getch ();
} }
/* If it won't fit in the host's representation for integers, /* If it won't fit in the host's representation for integers,
...@@ -4049,7 +3923,7 @@ real_yylex () ...@@ -4049,7 +3923,7 @@ real_yylex ()
TREE_TYPE (yylval.ttype) = type; TREE_TYPE (yylval.ttype) = type;
} }
put_back (c); token_put_back (c);
*p = 0; *p = 0;
value = CONSTANT; break; value = CONSTANT; break;
...@@ -4065,7 +3939,7 @@ real_yylex () ...@@ -4065,7 +3939,7 @@ real_yylex ()
int max_chars; int max_chars;
#ifdef MULTIBYTE_CHARS #ifdef MULTIBYTE_CHARS
int longest_char = local_mb_cur_max (); int longest_char = local_mb_cur_max ();
(void) local_mbtowc (NULL_PTR, NULL_PTR, 0); local_mbtowc (NULL_PTR, NULL_PTR, 0);
#endif #endif
max_chars = TYPE_PRECISION (integer_type_node) / width; max_chars = TYPE_PRECISION (integer_type_node) / width;
...@@ -4075,7 +3949,7 @@ real_yylex () ...@@ -4075,7 +3949,7 @@ real_yylex ()
while (1) while (1)
{ {
tryagain: tryagain:
c = getch (); c = token_getch ();
if (c == '\'' || c == EOF) if (c == '\'' || c == EOF)
break; break;
...@@ -4118,13 +3992,13 @@ real_yylex () ...@@ -4118,13 +3992,13 @@ real_yylex ()
i); i);
if (char_len != -1) if (char_len != -1)
break; break;
c = getch (); c = token_getch ();
} }
if (char_len > 1) if (char_len > 1)
{ {
/* mbtowc sometimes needs an extra char before accepting */ /* mbtowc sometimes needs an extra char before accepting */
if (char_len < i) if (char_len < i)
put_back (c); token_put_back (c);
if (! wide_flag) if (! wide_flag)
{ {
/* Merge character into result; ignore excess chars. */ /* Merge character into result; ignore excess chars. */
...@@ -4151,7 +4025,7 @@ real_yylex () ...@@ -4151,7 +4025,7 @@ real_yylex ()
warning ("Ignoring invalid multibyte character"); warning ("Ignoring invalid multibyte character");
/* Replace all but the first byte. */ /* Replace all but the first byte. */
for (--i; i > 1; --i) for (--i; i > 1; --i)
put_back (token_buffer[i]); token_put_back (token_buffer[i]);
wc = token_buffer[1]; wc = token_buffer[1];
} }
#ifdef MAP_CHARACTER #ifdef MAP_CHARACTER
...@@ -4238,13 +4112,13 @@ real_yylex () ...@@ -4238,13 +4112,13 @@ real_yylex ()
: TYPE_PRECISION (char_type_node); : TYPE_PRECISION (char_type_node);
#ifdef MULTIBYTE_CHARS #ifdef MULTIBYTE_CHARS
int longest_char = local_mb_cur_max (); int longest_char = local_mb_cur_max ();
(void) local_mbtowc (NULL_PTR, NULL_PTR, 0); local_mbtowc (NULL_PTR, NULL_PTR, 0);
#endif #endif
c = getch (); c = token_getch ();
p = token_buffer + 1; p = token_buffer + 1;
while (c != '"' && c >= 0) while (c != '"' && c != EOF)
{ {
/* ignore_escape_flag is set for reading the filename in #line. */ /* ignore_escape_flag is set for reading the filename in #line. */
if (!ignore_escape_flag && c == '\\') if (!ignore_escape_flag && c == '\\')
...@@ -4278,24 +4152,24 @@ real_yylex () ...@@ -4278,24 +4152,24 @@ real_yylex ()
char_len = local_mbtowc (& wc, p, i + 1); char_len = local_mbtowc (& wc, p, i + 1);
if (char_len != -1) if (char_len != -1)
break; break;
c = getch (); c = token_getch ();
} }
if (char_len == -1) if (char_len == -1)
{ {
warning ("Ignoring invalid multibyte character"); warning ("Ignoring invalid multibyte character");
/* Replace all except the first byte. */ /* Replace all except the first byte. */
put_back (c); token_put_back (c);
for (--i; i > 0; --i) for (--i; i > 0; --i)
put_back (p[i]); token_put_back (p[i]);
char_len = 1; char_len = 1;
} }
/* mbtowc sometimes needs an extra char before accepting */ /* mbtowc sometimes needs an extra char before accepting */
if (char_len <= i) if (char_len <= i)
put_back (c); token_put_back (c);
if (! wide_flag) if (! wide_flag)
{ {
p += (i + 1); p += (i + 1);
c = getch (); c = token_getch ();
continue; continue;
} }
c = wc; c = wc;
...@@ -4335,7 +4209,7 @@ real_yylex () ...@@ -4335,7 +4209,7 @@ real_yylex ()
} }
skipnewline: skipnewline:
c = getch (); c = token_getch ();
if (c == EOF) { if (c == EOF) {
error ("Unterminated string"); error ("Unterminated string");
break; break;
...@@ -4420,7 +4294,7 @@ real_yylex () ...@@ -4420,7 +4294,7 @@ real_yylex ()
yylval.code = GT_EXPR; break; yylval.code = GT_EXPR; break;
} }
token_buffer[1] = c1 = getch (); token_buffer[1] = c1 = token_getch ();
token_buffer[2] = 0; token_buffer[2] = 0;
if (c1 == '=') if (c1 == '=')
...@@ -4458,21 +4332,21 @@ real_yylex () ...@@ -4458,21 +4332,21 @@ real_yylex ()
} }
else if ((c == '-') && (c1 == '>')) else if ((c == '-') && (c1 == '>'))
{ {
nextchar = getch (); c1 = token_getch ();
if (nextchar == '*') if (c1 == '*')
value = POINTSAT_STAR;
else
{ {
nextchar = -1; token_put_back (c1);
value = POINTSAT_STAR; value = POINTSAT;
} }
else
value = POINTSAT;
goto done; goto done;
} }
else if (c1 == '?' && (c == '<' || c == '>')) else if (c1 == '?' && (c == '<' || c == '>'))
{ {
token_buffer[3] = 0; token_buffer[3] = 0;
c1 = getch (); c1 = token_getch ();
yylval.code = (c == '<' ? MIN_EXPR : MAX_EXPR); yylval.code = (c == '<' ? MIN_EXPR : MAX_EXPR);
if (c1 == '=') if (c1 == '=')
{ {
...@@ -4483,7 +4357,7 @@ real_yylex () ...@@ -4483,7 +4357,7 @@ real_yylex ()
else else
{ {
value = MIN_MAX; value = MIN_MAX;
nextchar = c1; token_put_back (c1);
} }
if (pedantic) if (pedantic)
pedwarn ("use of `operator %s' is not standard C++", pedwarn ("use of `operator %s' is not standard C++",
...@@ -4500,7 +4374,7 @@ real_yylex () ...@@ -4500,7 +4374,7 @@ real_yylex ()
else if (c == '%' && c1 == ':') else if (c == '%' && c1 == ':')
{ value = '#'; goto done; } { value = '#'; goto done; }
nextchar = c1; token_put_back (c1);
token_buffer[1] = 0; token_buffer[1] = 0;
value = c; value = c;
...@@ -4508,7 +4382,7 @@ real_yylex () ...@@ -4508,7 +4382,7 @@ real_yylex ()
} }
case ':': case ':':
c = getch (); c = token_getch ();
if (c == ':') if (c == ':')
{ {
token_buffer[1] = ':'; token_buffer[1] = ':';
...@@ -4523,7 +4397,7 @@ real_yylex () ...@@ -4523,7 +4397,7 @@ real_yylex ()
} }
else else
{ {
nextchar = c; token_put_back (c);
value = ':'; value = ':';
} }
break; break;
...@@ -4533,33 +4407,6 @@ real_yylex () ...@@ -4533,33 +4407,6 @@ real_yylex ()
value = 1; value = 1;
break; 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: default:
value = c; value = c;
} }
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -69,21 +69,20 @@ typedef union {long itype; tree ttype; char *strtype; enum tree_code code; flagg ...@@ -69,21 +69,20 @@ typedef union {long itype; tree ttype; char *strtype; enum tree_code code; flagg
#define PLUSPLUS 325 #define PLUSPLUS 325
#define MINUSMINUS 326 #define MINUSMINUS 326
#define HYPERUNARY 327 #define HYPERUNARY 327
#define PAREN_STAR_PAREN 328 #define POINTSAT 328
#define POINTSAT 329 #define TRY 329
#define TRY 330 #define CATCH 330
#define CATCH 331 #define PRE_PARSED_FUNCTION_DECL 331
#define PRE_PARSED_FUNCTION_DECL 332 #define EXTERN_LANG_STRING 332
#define EXTERN_LANG_STRING 333 #define ALL 333
#define ALL 334 #define PRE_PARSED_CLASS_DECL 334
#define PRE_PARSED_CLASS_DECL 335 #define DEFARG 335
#define DEFARG 336 #define DEFARG_MARKER 336
#define DEFARG_MARKER 337 #define TYPENAME_DEFN 337
#define TYPENAME_DEFN 338 #define IDENTIFIER_DEFN 338
#define IDENTIFIER_DEFN 339 #define PTYPENAME_DEFN 339
#define PTYPENAME_DEFN 340 #define END_OF_LINE 340
#define END_OF_LINE 341 #define END_OF_SAVED_INPUT 341
#define END_OF_SAVED_INPUT 342
extern YYSTYPE yylval; extern YYSTYPE yylval;
......
...@@ -178,7 +178,7 @@ empty_parms () ...@@ -178,7 +178,7 @@ empty_parms ()
%left <code> POINTSAT_STAR DOT_STAR %left <code> POINTSAT_STAR DOT_STAR
%right <code> UNARY PLUSPLUS MINUSMINUS '~' %right <code> UNARY PLUSPLUS MINUSMINUS '~'
%left HYPERUNARY %left HYPERUNARY
%left <ttype> PAREN_STAR_PAREN LEFT_RIGHT %left <ttype> LEFT_RIGHT
%left <code> POINTSAT '.' '(' '[' %left <code> POINTSAT '.' '(' '['
%right SCOPE /* C++ extension */ %right SCOPE /* C++ extension */
...@@ -3174,7 +3174,6 @@ direct_abstract_declarator: ...@@ -3174,7 +3174,6 @@ direct_abstract_declarator:
'(' absdcl_intern ')' '(' absdcl_intern ')'
{ $$ = $2; } { $$ = $2; }
/* `(typedef)1' is `int'. */ /* `(typedef)1' is `int'. */
| PAREN_STAR_PAREN
| direct_abstract_declarator '(' parmlist ')' cv_qualifiers exception_specification_opt %prec '.' | direct_abstract_declarator '(' parmlist ')' cv_qualifiers exception_specification_opt %prec '.'
{ $$ = make_call_declarator ($$, $3, $5, $6); } { $$ = make_call_declarator ($$, $3, $5, $6); }
| direct_abstract_declarator LEFT_RIGHT cv_qualifiers exception_specification_opt %prec '.' | direct_abstract_declarator LEFT_RIGHT cv_qualifiers exception_specification_opt %prec '.'
......
/* Type Analyzer for GNU C++. /* Type Analyzer for GNU C++.
Copyright (C) 1987, 89, 92-97, 1998 Free Software Foundation, Inc. Copyright (C) 1987, 89, 92-97, 1998, 1999 Free Software Foundation, Inc.
Hacked... nay, bludgeoned... by Mark Eichin (eichin@cygnus.com) Hacked... nay, bludgeoned... by Mark Eichin (eichin@cygnus.com)
This file is part of GNU CC. This file is part of GNU CC.
...@@ -305,6 +305,16 @@ yylex () ...@@ -305,6 +305,16 @@ yylex ()
#endif #endif
goto retry; goto retry;
case '(':
scan_tokens (1);
if (nth_token (1)->yychar == ')')
{
consume_token ();
tmp_token.yychar = LEFT_RIGHT;
}
consume_token ();
break;
case IDENTIFIER: case IDENTIFIER:
scan_tokens (1); scan_tokens (1);
if (nth_token (1)->yychar == SCOPE) if (nth_token (1)->yychar == SCOPE)
...@@ -361,21 +371,31 @@ yylex () ...@@ -361,21 +371,31 @@ yylex ()
break; break;
case SCSPEC: 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. */ /* If export, warn that it's unimplemented and go on. */
if (tmp_token.yylval.ttype == get_identifier("export")) else if (tmp_token.yylval.ttype == ridpointers[RID_EXPORT])
{ {
warning ("keyword 'export' not implemented and will be ignored"); warning ("keyword 'export' not implemented and will be ignored");
consume_token (); consume_token ();
goto retry; goto retry;
} }
else /* do_aggr needs to check if the previous token was `friend',
{ so just increment first_token instead of calling consume_token. */
++first_token; ++first_token;
break; break;
}
case NEW: case NEW:
/* do_aggr needs to check if the previous token was RID_NEW, /* do_aggr needs to check if the previous token was `new',
so just increment first_token instead of calling consume_token. */ so just increment first_token instead of calling consume_token. */
++first_token; ++first_token;
break; break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment