OSDN Git Service

Wed May 6 06:36:41 1998 Robert Lipe <robertl@dgii.com>
[pf3gnuchains/gcc-fork.git] / gcc / cp / lex.c
1 /* Separate lexical analyzer for GNU C++.
2    Copyright (C) 1987, 89, 92-96, 1997 Free Software Foundation, Inc.
3    Hacked by Michael Tiemann (tiemann@cygnus.com)
4
5 This file is part of GNU CC.
6
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING.  If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22
23 /* This file is the lexical analyzer for GNU C++.  */
24
25 /* Cause the `yydebug' variable to be defined.  */
26 #define YYDEBUG 1
27
28 #include "config.h"
29 #include "system.h"
30 #include <setjmp.h>
31 #include "input.h"
32 #include "tree.h"
33 #include "lex.h"
34 #include "cp-tree.h"
35 #include "parse.h"
36 #include "flags.h"
37 #include "obstack.h"
38 #include "c-pragma.h"
39 #include "toplev.h"
40
41 /* MULTIBYTE_CHARS support only works for native compilers.
42    ??? Ideally what we want is to model widechar support after
43    the current floating point support.  */
44 #ifdef CROSS_COMPILE
45 #undef MULTIBYTE_CHARS
46 #endif
47
48 #ifdef MULTIBYTE_CHARS
49 #include <stdlib.h>
50 #include <locale.h>
51 #endif
52
53 #ifdef HAVE_STDLIB_H
54 #ifndef MULTIBYTE_CHARS
55 #include <stdlib.h>
56 #endif
57 #else
58 extern double atof ();
59 #endif
60
61 #define obstack_chunk_alloc xmalloc
62 #define obstack_chunk_free free
63
64 #ifndef DIR_SEPARATOR
65 #define DIR_SEPARATOR '/'
66 #endif
67
68 extern struct obstack permanent_obstack;
69 extern struct obstack *current_obstack, *saveable_obstack;
70
71 extern void yyprint PROTO((FILE *, int, YYSTYPE));
72 extern void set_float_handler PROTO((jmp_buf));
73 extern void compiler_error PROTO((char *, HOST_WIDE_INT,
74                                   HOST_WIDE_INT));
75
76 static tree get_time_identifier PROTO((char *));
77 static int check_newline PROTO((void));
78 static int skip_white_space PROTO((int));
79 static void finish_defarg PROTO((void));
80 static int my_get_run_time PROTO((void));
81 static int get_last_nonwhite_on_line PROTO((void));
82 static int interface_strcmp PROTO((char *));
83 static int readescape PROTO((int *));
84 static char *extend_token_buffer PROTO((char *));
85 static void consume_string PROTO((struct obstack *, int));
86 static void set_typedecl_interface_info PROTO((tree, tree));
87 static void feed_defarg PROTO((tree, tree));
88 static int set_vardecl_interface_info PROTO((tree, tree));
89 static void store_pending_inline PROTO((tree, struct pending_inline *));
90 static void reinit_parse_for_expr PROTO((struct obstack *));
91 static int *init_cpp_parse PROTO((void));
92 static int handle_cp_pragma PROTO((char *));
93 #ifdef HANDLE_SYSV_PRAGMA
94 static int handle_sysv_pragma PROTO((FILE *, int));
95 #endif
96 #ifdef GATHER_STATISTICS
97 #ifdef REDUCE_LENGTH
98 static int reduce_cmp PROTO((int *, int *));
99 static int token_cmp PROTO((int *, int *));
100 #endif
101 #endif
102
103 /* Given a file name X, return the nondirectory portion.
104    Keep in mind that X can be computed more than once.  */
105 char *
106 file_name_nondirectory (x)
107      char *x;
108 {
109   char *tmp = (char *) rindex (x, '/');
110   if (DIR_SEPARATOR != '/' && ! tmp)
111     tmp = (char *) rindex (x, DIR_SEPARATOR);
112   if (tmp)
113     return (char *) (tmp + 1);
114   else
115     return x;
116 }
117
118 /* This obstack is needed to hold text.  It is not safe to use
119    TOKEN_BUFFER because `check_newline' calls `yylex'.  */
120 struct obstack inline_text_obstack;
121 char *inline_text_firstobj;
122
123 #if !USE_CPPLIB
124 FILE *finput;
125 #endif
126 int end_of_file;
127
128 /* Pending language change.
129    Positive is push count, negative is pop count.  */
130 int pending_lang_change = 0;
131
132 /* Wrap the current header file in extern "C".  */
133 static int c_header_level = 0;
134
135 extern int first_token;
136 extern struct obstack token_obstack;
137
138 /* ??? Don't really know where this goes yet.  */
139 #if 1
140 #include "input.c"
141 #else
142 extern void put_back (/* int */);
143 extern int input_redirected ();
144 extern void feed_input (/* char *, int */);
145 #endif
146
147 /* Holds translations from TREE_CODEs to operator name strings,
148    i.e., opname_tab[PLUS_EXPR] == "+".  */
149 char **opname_tab;
150 char **assignop_tab;
151 \f
152 extern int yychar;              /*  the lookahead symbol                */
153 extern YYSTYPE yylval;          /*  the semantic value of the           */
154                                 /*  lookahead symbol                    */
155
156 #if 0
157 YYLTYPE yylloc;                 /*  location data for the lookahead     */
158                                 /*  symbol                              */
159 #endif
160
161
162 /* the declaration found for the last IDENTIFIER token read in.
163    yylex must look this up to detect typedefs, which get token type TYPENAME,
164    so it is left around in case the identifier is not a typedef but is
165    used in a context which makes it a reference to a variable.  */
166 tree lastiddecl;
167
168 /* The elements of `ridpointers' are identifier nodes
169    for the reserved type names and storage classes.
170    It is indexed by a RID_... value.  */
171 tree ridpointers[(int) RID_MAX];
172
173 /* We may keep statistics about how long which files took to compile.  */
174 static int header_time, body_time;
175 static tree filename_times;
176 static tree this_filename_time;
177
178 /* Array for holding counts of the numbers of tokens seen.  */
179 extern int *token_count;
180 \f
181 /* Return something to represent absolute declarators containing a *.
182    TARGET is the absolute declarator that the * contains.
183    CV_QUALIFIERS is a list of modifiers such as const or volatile
184    to apply to the pointer type, represented as identifiers.
185
186    We return an INDIRECT_REF whose "contents" are TARGET
187    and whose type is the modifier list.  */
188
189 tree
190 make_pointer_declarator (cv_qualifiers, target)
191      tree cv_qualifiers, target;
192 {
193   if (target && TREE_CODE (target) == IDENTIFIER_NODE
194       && ANON_AGGRNAME_P (target))
195     error ("type name expected before `*'");
196   target = build_parse_node (INDIRECT_REF, target);
197   TREE_TYPE (target) = cv_qualifiers;
198   return target;
199 }
200
201 /* Return something to represent absolute declarators containing a &.
202    TARGET is the absolute declarator that the & contains.
203    CV_QUALIFIERS is a list of modifiers such as const or volatile
204    to apply to the reference type, represented as identifiers.
205
206    We return an ADDR_EXPR whose "contents" are TARGET
207    and whose type is the modifier list.  */
208    
209 tree
210 make_reference_declarator (cv_qualifiers, target)
211      tree cv_qualifiers, target;
212 {
213   if (target)
214     {
215       if (TREE_CODE (target) == ADDR_EXPR)
216         {
217           error ("cannot declare references to references");
218           return target;
219         }
220       if (TREE_CODE (target) == INDIRECT_REF)
221         {
222           error ("cannot declare pointers to references");
223           return target;
224         }
225       if (TREE_CODE (target) == IDENTIFIER_NODE && ANON_AGGRNAME_P (target))
226           error ("type name expected before `&'");
227     }
228   target = build_parse_node (ADDR_EXPR, target);
229   TREE_TYPE (target) = cv_qualifiers;
230   return target;
231 }
232
233 tree
234 make_call_declarator (target, parms, cv_qualifiers, exception_specification)
235      tree target, parms, cv_qualifiers, exception_specification;
236 {
237   target = build_parse_node (CALL_EXPR, target, parms, cv_qualifiers);
238   TREE_TYPE (target) = exception_specification;
239   return target;
240 }
241
242 void
243 set_quals_and_spec (call_declarator, cv_qualifiers, exception_specification)
244      tree call_declarator, cv_qualifiers, exception_specification;
245 {
246   TREE_OPERAND (call_declarator, 2) = cv_qualifiers;
247   TREE_TYPE (call_declarator) = exception_specification;
248 }
249 \f
250 /* Build names and nodes for overloaded operators.  */
251
252 tree ansi_opname[LAST_CPLUS_TREE_CODE];
253 tree ansi_assopname[LAST_CPLUS_TREE_CODE];
254
255 char *
256 operator_name_string (name)
257      tree name;
258 {
259   char *opname = IDENTIFIER_POINTER (name) + 2;
260   tree *opname_table;
261   int i, assign;
262
263   /* Works for builtin and user defined types.  */
264   if (IDENTIFIER_GLOBAL_VALUE (name)
265       && TREE_CODE (IDENTIFIER_GLOBAL_VALUE (name)) == TYPE_DECL)
266     return IDENTIFIER_POINTER (name);
267
268   if (opname[0] == 'a' && opname[2] != '\0' && opname[2] != '_')
269     {
270       opname += 1;
271       assign = 1;
272       opname_table = ansi_assopname;
273     }
274   else
275     {
276       assign = 0;
277       opname_table = ansi_opname;
278     }
279
280   for (i = 0; i < (int) LAST_CPLUS_TREE_CODE; i++)
281     {
282       if (opname[0] == IDENTIFIER_POINTER (opname_table[i])[2+assign]
283           && opname[1] == IDENTIFIER_POINTER (opname_table[i])[3+assign])
284         break;
285     }
286
287   if (i == LAST_CPLUS_TREE_CODE)
288     return "<invalid operator>";
289
290   if (assign)
291     return assignop_tab[i];
292   else
293     return opname_tab[i];
294 }
295 \f
296 int interface_only;             /* whether or not current file is only for
297                                    interface definitions.  */
298 int interface_unknown;          /* whether or not we know this class
299                                    to behave according to #pragma interface.  */
300
301 /* lexical analyzer */
302
303 /* File used for outputting assembler code.  */
304 extern FILE *asm_out_file;
305
306 #ifndef WCHAR_TYPE_SIZE
307 #ifdef INT_TYPE_SIZE
308 #define WCHAR_TYPE_SIZE INT_TYPE_SIZE
309 #else
310 #define WCHAR_TYPE_SIZE BITS_PER_WORD
311 #endif
312 #endif
313
314 /* Number of bytes in a wide character.  */
315 #define WCHAR_BYTES (WCHAR_TYPE_SIZE / BITS_PER_UNIT)
316
317 static int maxtoken;            /* Current nominal length of token buffer.  */
318 char *token_buffer;             /* Pointer to token buffer.
319                                    Actual allocated length is maxtoken + 2.  */
320
321 #include "hash.h"
322 \f
323
324 /* Nonzero tells yylex to ignore \ in string constants.  */
325 static int ignore_escape_flag = 0;
326
327 static tree
328 get_time_identifier (name)
329      char *name;
330 {
331   tree time_identifier;
332   int len = strlen (name);
333   char *buf = (char *) alloca (len + 6);
334   strcpy (buf, "file ");
335   bcopy (name, buf+5, len);
336   buf[len+5] = '\0';
337   time_identifier = get_identifier (buf);
338   if (IDENTIFIER_LOCAL_VALUE (time_identifier) == NULL_TREE)
339     {
340       push_obstacks_nochange ();
341       end_temporary_allocation ();
342       IDENTIFIER_LOCAL_VALUE (time_identifier) = build_int_2 (0, 0);
343       IDENTIFIER_CLASS_VALUE (time_identifier) = build_int_2 (0, 1);
344       IDENTIFIER_GLOBAL_VALUE (time_identifier) = filename_times;
345       filename_times = time_identifier;
346       pop_obstacks ();
347     }
348   return time_identifier;
349 }
350
351 #ifdef __GNUC__
352 __inline
353 #endif
354 static int
355 my_get_run_time ()
356 {
357   int old_quiet_flag = quiet_flag;
358   int this_time;
359   quiet_flag = 0;
360   this_time = get_run_time ();
361   quiet_flag = old_quiet_flag;
362   return this_time;
363 }
364 \f
365 /* Table indexed by tree code giving a string containing a character
366    classifying the tree code.  Possibilities are
367    t, d, s, c, r, <, 1 and 2.  See cp/cp-tree.def for details.  */
368
369 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
370
371 char cplus_tree_code_type[] = {
372   'x',
373 #include "cp-tree.def"
374 };
375 #undef DEFTREECODE
376
377 /* Table indexed by tree code giving number of expression
378    operands beyond the fixed part of the node structure.
379    Not used for types or decls.  */
380
381 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
382
383 int cplus_tree_code_length[] = {
384   0,
385 #include "cp-tree.def"
386 };
387 #undef DEFTREECODE
388
389 /* Names of tree components.
390    Used for printing out the tree and error messages.  */
391 #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
392
393 char *cplus_tree_code_name[] = {
394   "@@dummy",
395 #include "cp-tree.def"
396 };
397 #undef DEFTREECODE
398 \f
399 /* toplev.c needs to call these.  */
400
401 void
402 lang_init ()
403 {
404   /* the beginning of the file is a new line; check for # */
405   /* With luck, we discover the real source file's name from that
406      and put it in input_filename.  */
407   put_back (check_newline ());
408   if (flag_gnu_xref) GNU_xref_begin (input_filename);
409   init_repo (input_filename);
410
411   /* See comments in toplev.c before the call to lang_init.  */
412   if (flag_exceptions == 2)
413     flag_exceptions = 1;
414 }
415
416 void
417 lang_finish ()
418 {
419   extern int errorcount, sorrycount;
420   if (flag_gnu_xref) GNU_xref_end (errorcount+sorrycount);
421 }
422
423 char *
424 lang_identify ()
425 {
426   return "cplusplus";
427 }
428
429 void
430 init_filename_times ()
431 {
432   this_filename_time = get_time_identifier ("<top level>");
433   if (flag_detailed_statistics)
434     {
435       header_time = 0;
436       body_time = my_get_run_time ();
437       TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time)) = body_time;
438     }
439 }
440
441 /* Change by Bryan Boreham, Kewill, Thu Jul 27 09:46:05 1989.
442    Stuck this hack in to get the files open correctly; this is called
443    in place of init_parse if we are an unexec'd binary.    */
444
445 #if 0
446 void
447 reinit_lang_specific ()
448 {
449   init_filename_times ();
450   reinit_search_statistics ();
451 }
452 #endif
453
454 static int *
455 init_cpp_parse ()
456 {
457 #ifdef GATHER_STATISTICS
458 #ifdef REDUCE_LENGTH
459   reduce_count = (int *)malloc (sizeof (int) * (REDUCE_LENGTH + 1));
460   bzero (reduce_count, sizeof (int) * (REDUCE_LENGTH + 1));
461   reduce_count += 1;
462   token_count = (int *)malloc (sizeof (int) * (TOKEN_LENGTH + 1));
463   bzero (token_count, sizeof (int) * (TOKEN_LENGTH + 1));
464   token_count += 1;
465 #endif
466 #endif
467   return token_count;
468 }
469
470 char *
471 init_parse (filename)
472      char *filename;
473 {
474   extern int flag_no_gnu_keywords;
475   extern int flag_operator_names;
476
477   int i;
478
479 #if !USE_CPPLIB
480   /* Open input file.  */
481   if (filename == 0 || !strcmp (filename, "-"))
482     {
483       finput = stdin;
484       filename = "stdin";
485     }
486   else
487     finput = fopen (filename, "r");
488   if (finput == 0)
489     pfatal_with_name (filename);
490
491 #ifdef IO_BUFFER_SIZE
492   setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
493 #endif
494 #endif /* !USE_CPPLIB */
495
496   /* Initialize the lookahead machinery.  */
497   init_spew ();
498
499   /* Make identifier nodes long enough for the language-specific slots.  */
500   set_identifier_size (sizeof (struct lang_identifier));
501   decl_printable_name = lang_printable_name;
502
503   init_cplus_expand ();
504
505   bcopy (cplus_tree_code_type,
506          tree_code_type + (int) LAST_AND_UNUSED_TREE_CODE,
507          (int)LAST_CPLUS_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE);
508   bcopy ((char *)cplus_tree_code_length,
509          (char *)(tree_code_length + (int) LAST_AND_UNUSED_TREE_CODE),
510          (LAST_CPLUS_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE) * sizeof (int));
511   bcopy ((char *)cplus_tree_code_name,
512          (char *)(tree_code_name + (int) LAST_AND_UNUSED_TREE_CODE),
513          (LAST_CPLUS_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE) * sizeof (char *));
514
515   opname_tab = (char **)oballoc ((int)LAST_CPLUS_TREE_CODE * sizeof (char *));
516   bzero ((char *)opname_tab, (int)LAST_CPLUS_TREE_CODE * sizeof (char *));
517   assignop_tab = (char **)oballoc ((int)LAST_CPLUS_TREE_CODE * sizeof (char *));
518   bzero ((char *)assignop_tab, (int)LAST_CPLUS_TREE_CODE * sizeof (char *));
519
520   ansi_opname[0] = get_identifier ("<invalid operator>");
521   for (i = 0; i < (int) LAST_CPLUS_TREE_CODE; i++)
522     {
523       ansi_opname[i] = ansi_opname[0];
524       ansi_assopname[i] = ansi_opname[0];
525     }
526
527   ansi_opname[(int) MULT_EXPR] = get_identifier ("__ml");
528   IDENTIFIER_OPNAME_P (ansi_opname[(int) MULT_EXPR]) = 1;
529   ansi_opname[(int) INDIRECT_REF] = ansi_opname[(int) MULT_EXPR];
530   ansi_assopname[(int) MULT_EXPR] = get_identifier ("__aml");
531   IDENTIFIER_OPNAME_P (ansi_assopname[(int) MULT_EXPR]) = 1;
532   ansi_assopname[(int) INDIRECT_REF] = ansi_assopname[(int) MULT_EXPR];
533   ansi_opname[(int) TRUNC_MOD_EXPR] = get_identifier ("__md");
534   IDENTIFIER_OPNAME_P (ansi_opname[(int) TRUNC_MOD_EXPR]) = 1;
535   ansi_assopname[(int) TRUNC_MOD_EXPR] = get_identifier ("__amd");
536   IDENTIFIER_OPNAME_P (ansi_assopname[(int) TRUNC_MOD_EXPR]) = 1;
537   ansi_opname[(int) CEIL_MOD_EXPR] = ansi_opname[(int) TRUNC_MOD_EXPR];
538   ansi_opname[(int) FLOOR_MOD_EXPR] = ansi_opname[(int) TRUNC_MOD_EXPR];
539   ansi_opname[(int) ROUND_MOD_EXPR] = ansi_opname[(int) TRUNC_MOD_EXPR];
540   ansi_opname[(int) MINUS_EXPR] = get_identifier ("__mi");
541   IDENTIFIER_OPNAME_P (ansi_opname[(int) MINUS_EXPR]) = 1;
542   ansi_opname[(int) NEGATE_EXPR] = ansi_opname[(int) MINUS_EXPR];
543   ansi_assopname[(int) MINUS_EXPR] = get_identifier ("__ami");
544   IDENTIFIER_OPNAME_P (ansi_assopname[(int) MINUS_EXPR]) = 1;
545   ansi_assopname[(int) NEGATE_EXPR] = ansi_assopname[(int) MINUS_EXPR];
546   ansi_opname[(int) RSHIFT_EXPR] = get_identifier ("__rs");
547   IDENTIFIER_OPNAME_P (ansi_opname[(int) RSHIFT_EXPR]) = 1;
548   ansi_assopname[(int) RSHIFT_EXPR] = get_identifier ("__ars");
549   IDENTIFIER_OPNAME_P (ansi_assopname[(int) RSHIFT_EXPR]) = 1;
550   ansi_opname[(int) NE_EXPR] = get_identifier ("__ne");
551   IDENTIFIER_OPNAME_P (ansi_opname[(int) NE_EXPR]) = 1;
552   ansi_opname[(int) GT_EXPR] = get_identifier ("__gt");
553   IDENTIFIER_OPNAME_P (ansi_opname[(int) GT_EXPR]) = 1;
554   ansi_opname[(int) GE_EXPR] = get_identifier ("__ge");
555   IDENTIFIER_OPNAME_P (ansi_opname[(int) GE_EXPR]) = 1;
556   ansi_opname[(int) BIT_IOR_EXPR] = get_identifier ("__or");
557   IDENTIFIER_OPNAME_P (ansi_opname[(int) BIT_IOR_EXPR]) = 1;
558   ansi_assopname[(int) BIT_IOR_EXPR] = get_identifier ("__aor");
559   IDENTIFIER_OPNAME_P (ansi_assopname[(int) BIT_IOR_EXPR]) = 1;
560   ansi_opname[(int) TRUTH_ANDIF_EXPR] = get_identifier ("__aa");
561   IDENTIFIER_OPNAME_P (ansi_opname[(int) TRUTH_ANDIF_EXPR]) = 1;
562   ansi_opname[(int) TRUTH_NOT_EXPR] = get_identifier ("__nt");
563   IDENTIFIER_OPNAME_P (ansi_opname[(int) TRUTH_NOT_EXPR]) = 1;
564   ansi_opname[(int) PREINCREMENT_EXPR] = get_identifier ("__pp");
565   IDENTIFIER_OPNAME_P (ansi_opname[(int) PREINCREMENT_EXPR]) = 1;
566   ansi_opname[(int) POSTINCREMENT_EXPR] = ansi_opname[(int) PREINCREMENT_EXPR];
567   ansi_opname[(int) MODIFY_EXPR] = get_identifier ("__as");
568   IDENTIFIER_OPNAME_P (ansi_opname[(int) MODIFY_EXPR]) = 1;
569   ansi_assopname[(int) NOP_EXPR] = ansi_opname[(int) MODIFY_EXPR];
570   ansi_opname[(int) COMPOUND_EXPR] = get_identifier ("__cm");
571   IDENTIFIER_OPNAME_P (ansi_opname[(int) COMPOUND_EXPR]) = 1;
572   ansi_opname[(int) EXACT_DIV_EXPR] = get_identifier ("__dv");
573   IDENTIFIER_OPNAME_P (ansi_opname[(int) EXACT_DIV_EXPR]) = 1;
574   ansi_assopname[(int) EXACT_DIV_EXPR] = get_identifier ("__adv");
575   IDENTIFIER_OPNAME_P (ansi_assopname[(int) EXACT_DIV_EXPR]) = 1;
576   ansi_opname[(int) TRUNC_DIV_EXPR] = ansi_opname[(int) EXACT_DIV_EXPR];
577   ansi_opname[(int) CEIL_DIV_EXPR] = ansi_opname[(int) EXACT_DIV_EXPR];
578   ansi_opname[(int) FLOOR_DIV_EXPR] = ansi_opname[(int) EXACT_DIV_EXPR];
579   ansi_opname[(int) ROUND_DIV_EXPR] = ansi_opname[(int) EXACT_DIV_EXPR];
580   ansi_opname[(int) PLUS_EXPR] = get_identifier ("__pl");
581   ansi_assopname[(int) TRUNC_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR];
582   ansi_assopname[(int) CEIL_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR];
583   ansi_assopname[(int) FLOOR_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR];
584   ansi_assopname[(int) ROUND_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR];
585   IDENTIFIER_OPNAME_P (ansi_opname[(int) PLUS_EXPR]) = 1;
586   ansi_assopname[(int) PLUS_EXPR] = get_identifier ("__apl");
587   IDENTIFIER_OPNAME_P (ansi_assopname[(int) PLUS_EXPR]) = 1;
588   ansi_opname[(int) CONVERT_EXPR] = ansi_opname[(int) PLUS_EXPR];
589   ansi_assopname[(int) CONVERT_EXPR] = ansi_assopname[(int) PLUS_EXPR];
590   ansi_opname[(int) LSHIFT_EXPR] = get_identifier ("__ls");
591   IDENTIFIER_OPNAME_P (ansi_opname[(int) LSHIFT_EXPR]) = 1;
592   ansi_assopname[(int) LSHIFT_EXPR] = get_identifier ("__als");
593   IDENTIFIER_OPNAME_P (ansi_assopname[(int) LSHIFT_EXPR]) = 1;
594   ansi_opname[(int) EQ_EXPR] = get_identifier ("__eq");
595   IDENTIFIER_OPNAME_P (ansi_opname[(int) EQ_EXPR]) = 1;
596   ansi_opname[(int) LT_EXPR] = get_identifier ("__lt");
597   IDENTIFIER_OPNAME_P (ansi_opname[(int) LT_EXPR]) = 1;
598   ansi_opname[(int) LE_EXPR] = get_identifier ("__le");
599   IDENTIFIER_OPNAME_P (ansi_opname[(int) LE_EXPR]) = 1;
600   ansi_opname[(int) BIT_AND_EXPR] = get_identifier ("__ad");
601   IDENTIFIER_OPNAME_P (ansi_opname[(int) BIT_AND_EXPR]) = 1;
602   ansi_assopname[(int) BIT_AND_EXPR] = get_identifier ("__aad");
603   IDENTIFIER_OPNAME_P (ansi_assopname[(int) BIT_AND_EXPR]) = 1;
604   ansi_opname[(int) ADDR_EXPR] = ansi_opname[(int) BIT_AND_EXPR];
605   ansi_assopname[(int) ADDR_EXPR] = ansi_assopname[(int) BIT_AND_EXPR];
606   ansi_opname[(int) BIT_XOR_EXPR] = get_identifier ("__er");
607   IDENTIFIER_OPNAME_P (ansi_opname[(int) BIT_XOR_EXPR]) = 1;
608   ansi_assopname[(int) BIT_XOR_EXPR] = get_identifier ("__aer");
609   IDENTIFIER_OPNAME_P (ansi_assopname[(int) BIT_XOR_EXPR]) = 1;
610   ansi_opname[(int) TRUTH_ORIF_EXPR] = get_identifier ("__oo");
611   IDENTIFIER_OPNAME_P (ansi_opname[(int) TRUTH_ORIF_EXPR]) = 1;
612   ansi_opname[(int) BIT_NOT_EXPR] = get_identifier ("__co");
613   IDENTIFIER_OPNAME_P (ansi_opname[(int) BIT_NOT_EXPR]) = 1;
614   ansi_opname[(int) PREDECREMENT_EXPR] = get_identifier ("__mm");
615   IDENTIFIER_OPNAME_P (ansi_opname[(int) PREDECREMENT_EXPR]) = 1;
616   ansi_opname[(int) POSTDECREMENT_EXPR] = ansi_opname[(int) PREDECREMENT_EXPR];
617   ansi_opname[(int) COMPONENT_REF] = get_identifier ("__rf");
618   IDENTIFIER_OPNAME_P (ansi_opname[(int) COMPONENT_REF]) = 1;
619   ansi_opname[(int) MEMBER_REF] = get_identifier ("__rm");
620   IDENTIFIER_OPNAME_P (ansi_opname[(int) MEMBER_REF]) = 1;
621   ansi_opname[(int) CALL_EXPR] = get_identifier ("__cl");
622   IDENTIFIER_OPNAME_P (ansi_opname[(int) CALL_EXPR]) = 1;
623   ansi_opname[(int) ARRAY_REF] = get_identifier ("__vc");
624   IDENTIFIER_OPNAME_P (ansi_opname[(int) ARRAY_REF]) = 1;
625   ansi_opname[(int) NEW_EXPR] = get_identifier ("__nw");
626   IDENTIFIER_OPNAME_P (ansi_opname[(int) NEW_EXPR]) = 1;
627   ansi_opname[(int) DELETE_EXPR] = get_identifier ("__dl");
628   IDENTIFIER_OPNAME_P (ansi_opname[(int) DELETE_EXPR]) = 1;
629   ansi_opname[(int) VEC_NEW_EXPR] = get_identifier ("__vn");
630   IDENTIFIER_OPNAME_P (ansi_opname[(int) VEC_NEW_EXPR]) = 1;
631   ansi_opname[(int) VEC_DELETE_EXPR] = get_identifier ("__vd");
632   IDENTIFIER_OPNAME_P (ansi_opname[(int) VEC_DELETE_EXPR]) = 1;
633   ansi_opname[(int) TYPE_EXPR] = get_identifier ("__op");
634   IDENTIFIER_OPNAME_P (ansi_opname[(int) TYPE_EXPR]) = 1;
635
636   /* This is not true: these operators are not defined in ANSI,
637      but we need them anyway.  */
638   ansi_opname[(int) MIN_EXPR] = get_identifier ("__mn");
639   IDENTIFIER_OPNAME_P (ansi_opname[(int) MIN_EXPR]) = 1;
640   ansi_opname[(int) MAX_EXPR] = get_identifier ("__mx");
641   IDENTIFIER_OPNAME_P (ansi_opname[(int) MAX_EXPR]) = 1;
642   ansi_opname[(int) COND_EXPR] = get_identifier ("__cn");
643   IDENTIFIER_OPNAME_P (ansi_opname[(int) COND_EXPR]) = 1;
644   ansi_opname[(int) SIZEOF_EXPR] = get_identifier ("__sz");
645   IDENTIFIER_OPNAME_P (ansi_opname[(int) SIZEOF_EXPR]) = 1;
646
647   init_method ();
648   init_error ();
649   gcc_obstack_init (&inline_text_obstack);
650   inline_text_firstobj = (char *) obstack_alloc (&inline_text_obstack, 0);
651
652   /* Start it at 0, because check_newline is called at the very beginning
653      and will increment it to 1.  */
654   lineno = 0;
655   input_filename = "<internal>";
656   current_function_decl = NULL;
657
658   maxtoken = 40;
659   token_buffer = (char *) xmalloc (maxtoken + 2);
660
661   ridpointers[(int) RID_INT] = get_identifier ("int");
662   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_INT],
663                           build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]));
664   ridpointers[(int) RID_BOOL] = get_identifier ("bool");
665   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_BOOL],
666                           build_tree_list (NULL_TREE, ridpointers[(int) RID_BOOL]));
667   ridpointers[(int) RID_CHAR] = get_identifier ("char");
668   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_CHAR],
669                           build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]));
670   ridpointers[(int) RID_VOID] = get_identifier ("void");
671   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VOID],
672                           build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]));
673   ridpointers[(int) RID_FLOAT] = get_identifier ("float");
674   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_FLOAT],
675                           build_tree_list (NULL_TREE, ridpointers[(int) RID_FLOAT]));
676   ridpointers[(int) RID_DOUBLE] = get_identifier ("double");
677   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_DOUBLE],
678                           build_tree_list (NULL_TREE, ridpointers[(int) RID_DOUBLE]));
679   ridpointers[(int) RID_SHORT] = get_identifier ("short");
680   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_SHORT],
681                           build_tree_list (NULL_TREE, ridpointers[(int) RID_SHORT]));
682   ridpointers[(int) RID_LONG] = get_identifier ("long");
683   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_LONG],
684                           build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]));
685   ridpointers[(int) RID_UNSIGNED] = get_identifier ("unsigned");
686   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_UNSIGNED],
687                           build_tree_list (NULL_TREE, ridpointers[(int) RID_UNSIGNED]));
688   ridpointers[(int) RID_SIGNED] = get_identifier ("signed");
689   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_SIGNED],
690                           build_tree_list (NULL_TREE, ridpointers[(int) RID_SIGNED]));
691   ridpointers[(int) RID_INLINE] = get_identifier ("inline");
692   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_INLINE],
693                           build_tree_list (NULL_TREE, ridpointers[(int) RID_INLINE]));
694   ridpointers[(int) RID_CONST] = get_identifier ("const");
695   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_CONST],
696                           build_tree_list (NULL_TREE, ridpointers[(int) RID_CONST]));
697   ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile");
698   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VOLATILE],
699                           build_tree_list (NULL_TREE, ridpointers[(int) RID_VOLATILE]));
700   ridpointers[(int) RID_AUTO] = get_identifier ("auto");
701   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_AUTO],
702                           build_tree_list (NULL_TREE, ridpointers[(int) RID_AUTO]));
703   ridpointers[(int) RID_STATIC] = get_identifier ("static");
704   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_STATIC],
705                           build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]));
706   ridpointers[(int) RID_EXTERN] = get_identifier ("extern");
707   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_EXTERN],
708                           build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]));
709   ridpointers[(int) RID_TYPEDEF] = get_identifier ("typedef");
710   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_TYPEDEF],
711                           build_tree_list (NULL_TREE, ridpointers[(int) RID_TYPEDEF]));
712   ridpointers[(int) RID_REGISTER] = get_identifier ("register");
713   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_REGISTER],
714                           build_tree_list (NULL_TREE, ridpointers[(int) RID_REGISTER]));
715   ridpointers[(int) RID_COMPLEX] = get_identifier ("__complex");
716   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_COMPLEX],
717                           build_tree_list (NULL_TREE, ridpointers[(int) RID_COMPLEX]));
718
719   /* C++ extensions. These are probably not correctly named.  */
720   ridpointers[(int) RID_WCHAR] = get_identifier ("__wchar_t");
721   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_WCHAR],
722                           build_tree_list (NULL_TREE, ridpointers[(int) RID_WCHAR]));
723   class_type_node = build_int_2 (class_type, 0);
724   TREE_TYPE (class_type_node) = class_type_node;
725   ridpointers[(int) RID_CLASS] = class_type_node;
726
727   record_type_node = build_int_2 (record_type, 0);
728   TREE_TYPE (record_type_node) = record_type_node;
729   ridpointers[(int) RID_RECORD] = record_type_node;
730
731   union_type_node = build_int_2 (union_type, 0);
732   TREE_TYPE (union_type_node) = union_type_node;
733   ridpointers[(int) RID_UNION] = union_type_node;
734
735   enum_type_node = build_int_2 (enum_type, 0);
736   TREE_TYPE (enum_type_node) = enum_type_node;
737   ridpointers[(int) RID_ENUM] = enum_type_node;
738
739   ridpointers[(int) RID_VIRTUAL] = get_identifier ("virtual");
740   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VIRTUAL],
741                           build_tree_list (NULL_TREE, ridpointers[(int) RID_VIRTUAL]));
742   ridpointers[(int) RID_EXPLICIT] = get_identifier ("explicit");
743   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_EXPLICIT],
744                           build_tree_list (NULL_TREE, ridpointers[(int) RID_EXPLICIT]));
745   ridpointers[(int) RID_FRIEND] = get_identifier ("friend");
746   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_FRIEND],
747                           build_tree_list (NULL_TREE, ridpointers[(int) RID_FRIEND]));
748
749   ridpointers[(int) RID_PUBLIC] = get_identifier ("public");
750   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_PUBLIC],
751                           build_tree_list (NULL_TREE, ridpointers[(int) RID_PUBLIC]));
752   ridpointers[(int) RID_PRIVATE] = get_identifier ("private");
753   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_PRIVATE],
754                           build_tree_list (NULL_TREE, ridpointers[(int) RID_PRIVATE]));
755   ridpointers[(int) RID_PROTECTED] = get_identifier ("protected");
756   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_PROTECTED],
757                           build_tree_list (NULL_TREE, ridpointers[(int) RID_PROTECTED]));
758   ridpointers[(int) RID_TEMPLATE] = get_identifier ("template");
759   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_TEMPLATE],
760                           build_tree_list (NULL_TREE, ridpointers[(int) RID_TEMPLATE]));
761   /* This is for ANSI C++.  */
762   ridpointers[(int) RID_MUTABLE] = get_identifier ("mutable");
763   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_MUTABLE],
764                           build_tree_list (NULL_TREE, ridpointers[(int) RID_MUTABLE]));
765
766   /* Signature handling extensions.  */
767   signature_type_node = build_int_2 (signature_type, 0);
768   TREE_TYPE (signature_type_node) = signature_type_node;
769   ridpointers[(int) RID_SIGNATURE] = signature_type_node;
770
771   null_node = build_int_2 (0, 0);
772   ridpointers[RID_NULL] = null_node;
773
774   opname_tab[(int) COMPONENT_REF] = "->";
775   opname_tab[(int) MEMBER_REF] = "->*";
776   opname_tab[(int) INDIRECT_REF] = "*";
777   opname_tab[(int) ARRAY_REF] = "[]";
778   opname_tab[(int) MODIFY_EXPR] = "=";
779   opname_tab[(int) NEW_EXPR] = "new";
780   opname_tab[(int) DELETE_EXPR] = "delete";
781   opname_tab[(int) VEC_NEW_EXPR] = "new []";
782   opname_tab[(int) VEC_DELETE_EXPR] = "delete []";
783   opname_tab[(int) COND_EXPR] = "?:";
784   opname_tab[(int) CALL_EXPR] = "()";
785   opname_tab[(int) PLUS_EXPR] = "+";
786   opname_tab[(int) MINUS_EXPR] = "-";
787   opname_tab[(int) MULT_EXPR] = "*";
788   opname_tab[(int) TRUNC_DIV_EXPR] = "/";
789   opname_tab[(int) CEIL_DIV_EXPR] = "(ceiling /)";
790   opname_tab[(int) FLOOR_DIV_EXPR] = "(floor /)";
791   opname_tab[(int) ROUND_DIV_EXPR] = "(round /)";
792   opname_tab[(int) TRUNC_MOD_EXPR] = "%";
793   opname_tab[(int) CEIL_MOD_EXPR] = "(ceiling %)";
794   opname_tab[(int) FLOOR_MOD_EXPR] = "(floor %)";
795   opname_tab[(int) ROUND_MOD_EXPR] = "(round %)";
796   opname_tab[(int) NEGATE_EXPR] = "-";
797   opname_tab[(int) MIN_EXPR] = "<?";
798   opname_tab[(int) MAX_EXPR] = ">?";
799   opname_tab[(int) ABS_EXPR] = "abs";
800   opname_tab[(int) FFS_EXPR] = "ffs";
801   opname_tab[(int) LSHIFT_EXPR] = "<<";
802   opname_tab[(int) RSHIFT_EXPR] = ">>";
803   opname_tab[(int) BIT_IOR_EXPR] = "|";
804   opname_tab[(int) BIT_XOR_EXPR] = "^";
805   opname_tab[(int) BIT_AND_EXPR] = "&";
806   opname_tab[(int) BIT_ANDTC_EXPR] = "&~";
807   opname_tab[(int) BIT_NOT_EXPR] = "~";
808   opname_tab[(int) TRUTH_ANDIF_EXPR] = "&&";
809   opname_tab[(int) TRUTH_ORIF_EXPR] = "||";
810   opname_tab[(int) TRUTH_AND_EXPR] = "strict &&";
811   opname_tab[(int) TRUTH_OR_EXPR] = "strict ||";
812   opname_tab[(int) TRUTH_NOT_EXPR] = "!";
813   opname_tab[(int) LT_EXPR] = "<";
814   opname_tab[(int) LE_EXPR] = "<=";
815   opname_tab[(int) GT_EXPR] = ">";
816   opname_tab[(int) GE_EXPR] = ">=";
817   opname_tab[(int) EQ_EXPR] = "==";
818   opname_tab[(int) NE_EXPR] = "!=";
819   opname_tab[(int) IN_EXPR] = "in";
820   opname_tab[(int) RANGE_EXPR] = "...";
821   opname_tab[(int) CONVERT_EXPR] = "+";
822   opname_tab[(int) ADDR_EXPR] = "&";
823   opname_tab[(int) PREDECREMENT_EXPR] = "--";
824   opname_tab[(int) PREINCREMENT_EXPR] = "++";
825   opname_tab[(int) POSTDECREMENT_EXPR] = "--";
826   opname_tab[(int) POSTINCREMENT_EXPR] = "++";
827   opname_tab[(int) COMPOUND_EXPR] = ",";
828
829   assignop_tab[(int) NOP_EXPR] = "=";
830   assignop_tab[(int) PLUS_EXPR] =  "+=";
831   assignop_tab[(int) CONVERT_EXPR] =  "+=";
832   assignop_tab[(int) MINUS_EXPR] = "-=";
833   assignop_tab[(int) NEGATE_EXPR] = "-=";
834   assignop_tab[(int) MULT_EXPR] = "*=";
835   assignop_tab[(int) INDIRECT_REF] = "*=";
836   assignop_tab[(int) TRUNC_DIV_EXPR] = "/=";
837   assignop_tab[(int) EXACT_DIV_EXPR] = "(exact /=)";
838   assignop_tab[(int) CEIL_DIV_EXPR] = "(ceiling /=)";
839   assignop_tab[(int) FLOOR_DIV_EXPR] = "(floor /=)";
840   assignop_tab[(int) ROUND_DIV_EXPR] = "(round /=)";
841   assignop_tab[(int) TRUNC_MOD_EXPR] = "%=";
842   assignop_tab[(int) CEIL_MOD_EXPR] = "(ceiling %=)";
843   assignop_tab[(int) FLOOR_MOD_EXPR] = "(floor %=)";
844   assignop_tab[(int) ROUND_MOD_EXPR] = "(round %=)";
845   assignop_tab[(int) MIN_EXPR] = "<?=";
846   assignop_tab[(int) MAX_EXPR] = ">?=";
847   assignop_tab[(int) LSHIFT_EXPR] = "<<=";
848   assignop_tab[(int) RSHIFT_EXPR] = ">>=";
849   assignop_tab[(int) BIT_IOR_EXPR] = "|=";
850   assignop_tab[(int) BIT_XOR_EXPR] = "^=";
851   assignop_tab[(int) BIT_AND_EXPR] = "&=";
852   assignop_tab[(int) ADDR_EXPR] = "&=";
853
854   init_filename_times ();
855
856   /* Some options inhibit certain reserved words.
857      Clear those words out of the hash table so they won't be recognized.  */
858 #define UNSET_RESERVED_WORD(STRING) \
859   do { struct resword *s = is_reserved_word (STRING, sizeof (STRING) - 1); \
860        if (s) s->name = ""; } while (0)
861
862 #if 0
863   /* let's parse things, and if they use it, then give them an error.  */
864   if (!flag_exceptions)
865     {
866       UNSET_RESERVED_WORD ("throw");
867       UNSET_RESERVED_WORD ("try");
868       UNSET_RESERVED_WORD ("catch");
869     }
870 #endif
871
872   if (!flag_rtti || flag_no_gnu_keywords)
873     {
874       UNSET_RESERVED_WORD ("classof");
875       UNSET_RESERVED_WORD ("headof");
876     }
877
878   if (! flag_handle_signatures || flag_no_gnu_keywords)
879     {
880       /* Easiest way to not recognize signature
881          handling extensions...  */
882       UNSET_RESERVED_WORD ("signature");
883       UNSET_RESERVED_WORD ("sigof");
884     }
885   if (flag_no_asm || flag_no_gnu_keywords)
886     UNSET_RESERVED_WORD ("typeof");
887   if (! flag_operator_names)
888     {
889       /* These are new ANSI keywords that may break code.  */
890       UNSET_RESERVED_WORD ("and");
891       UNSET_RESERVED_WORD ("and_eq");
892       UNSET_RESERVED_WORD ("bitand");
893       UNSET_RESERVED_WORD ("bitor");
894       UNSET_RESERVED_WORD ("compl");
895       UNSET_RESERVED_WORD ("not");
896       UNSET_RESERVED_WORD ("not_eq");
897       UNSET_RESERVED_WORD ("or");
898       UNSET_RESERVED_WORD ("or_eq");
899       UNSET_RESERVED_WORD ("xor");
900       UNSET_RESERVED_WORD ("xor_eq");
901     }
902
903   token_count = init_cpp_parse ();
904   interface_unknown = 1;
905
906   return filename;
907 }
908
909 void
910 finish_parse ()
911 {
912 #if USE_CPPLIB
913   cpp_finish (&parse_in);
914 #else
915   fclose (finput);
916 #endif
917 }
918
919 void
920 reinit_parse_for_function ()
921 {
922   current_base_init_list = NULL_TREE;
923   current_member_init_list = NULL_TREE;
924 }
925 \f
926 #ifdef __GNUC__
927 __inline
928 #endif
929 void
930 yyprint (file, yychar, yylval)
931      FILE *file;
932      int yychar;
933      YYSTYPE yylval;
934 {
935   tree t;
936   switch (yychar)
937     {
938     case IDENTIFIER:
939     case TYPENAME:
940     case TYPESPEC:
941     case PTYPENAME:
942     case IDENTIFIER_DEFN:
943     case TYPENAME_DEFN:
944     case PTYPENAME_DEFN:
945     case TYPENAME_ELLIPSIS:
946     case SCSPEC:
947     case PRE_PARSED_CLASS_DECL:
948       t = yylval.ttype;
949       if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (t) == TEMPLATE_DECL)
950         {
951           fprintf (file, " `%s'", IDENTIFIER_POINTER (DECL_NAME (t)));
952           break;
953         }
954       my_friendly_assert (TREE_CODE (t) == IDENTIFIER_NODE, 224);
955       if (IDENTIFIER_POINTER (t))
956           fprintf (file, " `%s'", IDENTIFIER_POINTER (t));
957       break;
958     case AGGR:
959       if (yylval.ttype == class_type_node)
960         fprintf (file, " `class'");
961       else if (yylval.ttype == record_type_node)
962         fprintf (file, " `struct'");
963       else if (yylval.ttype == union_type_node)
964         fprintf (file, " `union'");
965       else if (yylval.ttype == enum_type_node)
966         fprintf (file, " `enum'");
967       else if (yylval.ttype == signature_type_node)
968         fprintf (file, " `signature'");
969       else
970         my_friendly_abort (80);
971       break;
972     }
973 }
974
975 #if defined(GATHER_STATISTICS) && defined(REDUCE_LENGTH)
976 static int *reduce_count;
977 #endif
978
979 int *token_count;
980
981 #if 0
982 #define REDUCE_LENGTH (sizeof (yyr2) / sizeof (yyr2[0]))
983 #define TOKEN_LENGTH (256 + sizeof (yytname) / sizeof (yytname[0]))
984 #endif
985
986 #ifdef GATHER_STATISTICS
987 #ifdef REDUCE_LENGTH
988 void
989 yyhook (yyn)
990      int yyn;
991 {
992   reduce_count[yyn] += 1;
993 }
994
995 static int
996 reduce_cmp (p, q)
997      int *p, *q;
998 {
999   return reduce_count[*q] - reduce_count[*p];
1000 }
1001
1002 static int
1003 token_cmp (p, q)
1004      int *p, *q;
1005 {
1006   return token_count[*q] - token_count[*p];
1007 }
1008 #endif
1009 #endif
1010
1011 void
1012 print_parse_statistics ()
1013 {
1014 #ifdef GATHER_STATISTICS
1015 #ifdef REDUCE_LENGTH
1016 #if YYDEBUG != 0
1017   int i;
1018   int maxlen = REDUCE_LENGTH;
1019   unsigned *sorted;
1020   
1021   if (reduce_count[-1] == 0)
1022     return;
1023
1024   if (TOKEN_LENGTH > REDUCE_LENGTH)
1025     maxlen = TOKEN_LENGTH;
1026   sorted = (unsigned *) alloca (sizeof (int) * maxlen);
1027
1028   for (i = 0; i < TOKEN_LENGTH; i++)
1029     sorted[i] = i;
1030   qsort (sorted, TOKEN_LENGTH, sizeof (int), token_cmp);
1031   for (i = 0; i < TOKEN_LENGTH; i++)
1032     {
1033       int idx = sorted[i];
1034       if (token_count[idx] == 0)
1035         break;
1036       if (token_count[idx] < token_count[-1])
1037         break;
1038       fprintf (stderr, "token %d, `%s', count = %d\n",
1039                idx, yytname[YYTRANSLATE (idx)], token_count[idx]);
1040     }
1041   fprintf (stderr, "\n");
1042   for (i = 0; i < REDUCE_LENGTH; i++)
1043     sorted[i] = i;
1044   qsort (sorted, REDUCE_LENGTH, sizeof (int), reduce_cmp);
1045   for (i = 0; i < REDUCE_LENGTH; i++)
1046     {
1047       int idx = sorted[i];
1048       if (reduce_count[idx] == 0)
1049         break;
1050       if (reduce_count[idx] < reduce_count[-1])
1051         break;
1052       fprintf (stderr, "rule %d, line %d, count = %d\n",
1053                idx, yyrline[idx], reduce_count[idx]);
1054     }
1055   fprintf (stderr, "\n");
1056 #endif
1057 #endif
1058 #endif
1059 }
1060
1061 /* Sets the value of the 'yydebug' variable to VALUE.
1062    This is a function so we don't have to have YYDEBUG defined
1063    in order to build the compiler.  */
1064
1065 void
1066 set_yydebug (value)
1067      int value;
1068 {
1069 #if YYDEBUG != 0
1070   extern int yydebug;
1071   yydebug = value;
1072 #else
1073   warning ("YYDEBUG not defined.");
1074 #endif
1075 }
1076
1077 \f
1078 /* Functions and data structures for #pragma interface.
1079
1080    `#pragma implementation' means that the main file being compiled
1081    is considered to implement (provide) the classes that appear in
1082    its main body.  I.e., if this is file "foo.cc", and class `bar'
1083    is defined in "foo.cc", then we say that "foo.cc implements bar".
1084
1085    All main input files "implement" themselves automagically.
1086
1087    `#pragma interface' means that unless this file (of the form "foo.h"
1088    is not presently being included by file "foo.cc", the
1089    CLASSTYPE_INTERFACE_ONLY bit gets set.  The effect is that none
1090    of the vtables nor any of the inline functions defined in foo.h
1091    will ever be output.
1092
1093    There are cases when we want to link files such as "defs.h" and
1094    "main.cc".  In this case, we give "defs.h" a `#pragma interface',
1095    and "main.cc" has `#pragma implementation "defs.h"'.  */
1096
1097 struct impl_files
1098 {
1099   char *filename;
1100   struct impl_files *next;
1101 };
1102
1103 static struct impl_files *impl_file_chain;
1104
1105 /* Helper function to load global variables with interface
1106    information.  */
1107
1108 void
1109 extract_interface_info ()
1110 {
1111   tree fileinfo = 0;
1112
1113   if (flag_alt_external_templates)
1114     {
1115       struct tinst_level *til = tinst_for_decl ();
1116   
1117       if (til)
1118         fileinfo = get_time_identifier (til->file);
1119     }
1120   if (!fileinfo)
1121     fileinfo = get_time_identifier (input_filename);
1122   fileinfo = IDENTIFIER_CLASS_VALUE (fileinfo);
1123   interface_only = TREE_INT_CST_LOW (fileinfo);
1124   interface_unknown = TREE_INT_CST_HIGH (fileinfo);
1125 }
1126
1127 /* Return nonzero if S is not considered part of an
1128    INTERFACE/IMPLEMENTATION pair.  Otherwise, return 0.  */
1129
1130 static int
1131 interface_strcmp (s)
1132      char *s;
1133 {
1134   /* Set the interface/implementation bits for this scope.  */
1135   struct impl_files *ifiles;
1136   char *s1;
1137
1138   for (ifiles = impl_file_chain; ifiles; ifiles = ifiles->next)
1139     {
1140       char *t1 = ifiles->filename;
1141       s1 = s;
1142
1143       if (*s1 != *t1 || *s1 == 0)
1144         continue;
1145
1146       while (*s1 == *t1 && *s1 != 0)
1147         s1++, t1++;
1148
1149       /* A match.  */
1150       if (*s1 == *t1)
1151         return 0;
1152
1153       /* Don't get faked out by xxx.yyy.cc vs xxx.zzz.cc.  */
1154       if (index (s1, '.') || index (t1, '.'))
1155         continue;
1156
1157       if (*s1 == '\0' || s1[-1] != '.' || t1[-1] != '.')
1158         continue;
1159
1160       /* A match.  */
1161       return 0;
1162     }
1163
1164   /* No matches.  */
1165   return 1;
1166 }
1167
1168 static void
1169 set_typedecl_interface_info (prev, vars)
1170      tree prev, vars;
1171 {
1172   tree id = get_time_identifier (DECL_SOURCE_FILE (vars));
1173   tree fileinfo = IDENTIFIER_CLASS_VALUE (id);
1174   tree type = TREE_TYPE (vars);
1175
1176   CLASSTYPE_INTERFACE_ONLY (type) = TREE_INT_CST_LOW (fileinfo)
1177     = interface_strcmp (file_name_nondirectory (DECL_SOURCE_FILE (vars)));
1178 }
1179
1180 static int
1181 set_vardecl_interface_info (prev, vars)
1182      tree prev, vars;
1183 {
1184   tree type = DECL_CONTEXT (vars);
1185
1186   if (CLASSTYPE_INTERFACE_KNOWN (type))
1187     {
1188       if (CLASSTYPE_INTERFACE_ONLY (type))
1189         set_typedecl_interface_info (prev, TYPE_MAIN_DECL (type));
1190       else
1191         CLASSTYPE_VTABLE_NEEDS_WRITING (type) = 1;
1192       DECL_EXTERNAL (vars) = CLASSTYPE_INTERFACE_ONLY (type);
1193       TREE_PUBLIC (vars) = 1;
1194       return 1;
1195     }
1196   return 0;
1197 }
1198 \f
1199 /* Called from the top level: if there are any pending inlines to
1200    do, set up to process them now.  This function sets up the first function
1201    to be parsed; after it has been, the rule for fndef in parse.y will
1202    call process_next_inline to start working on the next one.  */
1203
1204 void
1205 do_pending_inlines ()
1206 {
1207   struct pending_inline *t;
1208   tree context;
1209
1210   /* Oops, we're still dealing with the last batch.  */
1211   if (yychar == PRE_PARSED_FUNCTION_DECL)
1212     return;
1213
1214   /* Reverse the pending inline functions, since
1215      they were cons'd instead of appended.  */
1216   {
1217     struct pending_inline *prev = 0, *tail;
1218     t = pending_inlines;
1219     pending_inlines = 0;
1220
1221     for (; t; t = tail)
1222       {
1223         tail = t->next;
1224         t->next = prev;
1225         t->deja_vu = 1;
1226         prev = t;
1227       }
1228     t = prev;
1229   }
1230
1231   if (t == 0)
1232     return;
1233             
1234   /* Now start processing the first inline function.  */
1235   context = hack_decl_function_context (t->fndecl);
1236   if (context)
1237     push_cp_function_context (context);
1238   maybe_begin_member_template_processing (t->fndecl);
1239   if (t->len > 0)
1240     {
1241       feed_input (t->buf, t->len);
1242       lineno = t->lineno;
1243 #if 0
1244       if (input_filename != t->filename)
1245         {
1246           input_filename = t->filename;
1247           /* Get interface/implementation back in sync.  */
1248           extract_interface_info ();
1249         }
1250 #else
1251       input_filename = t->filename;
1252       interface_unknown = t->interface == 1;
1253       interface_only = t->interface == 0;
1254 #endif
1255       yychar = PRE_PARSED_FUNCTION_DECL;
1256     }
1257   /* Pass back a handle on the rest of the inline functions, so that they
1258      can be processed later.  */
1259   yylval.ttype = build_tree_list ((tree) t, t->fndecl);
1260   DECL_PENDING_INLINE_INFO (t->fndecl) = 0;
1261 }
1262
1263 static int nextchar = -1;
1264
1265 /* Called from the fndecl rule in the parser when the function just parsed
1266    was declared using a PRE_PARSED_FUNCTION_DECL (i.e. came from
1267    do_pending_inlines).  */
1268
1269 void
1270 process_next_inline (t)
1271      tree t;
1272 {
1273   tree context;
1274   struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t);
1275   context = hack_decl_function_context (i->fndecl);  
1276   maybe_end_member_template_processing (i->fndecl);
1277   if (context)
1278     pop_cp_function_context (context);
1279   i = i->next;
1280   if (yychar == YYEMPTY)
1281     yychar = yylex ();
1282   if (yychar != END_OF_SAVED_INPUT)
1283     {
1284       error ("parse error at end of saved function text");
1285
1286       /* restore_pending_input will abort unless yychar is either
1287          END_OF_SAVED_INPUT or YYEMPTY; since we already know we're
1288          hosed, feed back YYEMPTY.  We also need to discard nextchar,
1289          since that may have gotten set as well.  */
1290       nextchar = -1;
1291     }
1292   yychar = YYEMPTY;
1293   end_input ();
1294   if (i && i->fndecl != NULL_TREE)
1295     {
1296       context = hack_decl_function_context (i->fndecl);
1297       if (context)
1298         push_cp_function_context (context);
1299       maybe_begin_member_template_processing (i->fndecl);
1300       feed_input (i->buf, i->len);
1301       lineno = i->lineno;
1302       input_filename = i->filename;
1303       yychar = PRE_PARSED_FUNCTION_DECL;
1304       yylval.ttype = build_tree_list ((tree) i, i->fndecl);
1305       DECL_PENDING_INLINE_INFO (i->fndecl) = 0;
1306     }
1307   if (i)
1308     {
1309       interface_unknown = i->interface == 1;
1310       interface_only = i->interface == 0;
1311     }
1312   else
1313     extract_interface_info ();
1314 }
1315
1316 /* Since inline methods can refer to text which has not yet been seen,
1317    we store the text of the method in a structure which is placed in the
1318    DECL_PENDING_INLINE_INFO field of the FUNCTION_DECL.
1319    After parsing the body of the class definition, the FUNCTION_DECL's are
1320    scanned to see which ones have this field set.  Those are then digested
1321    one at a time.
1322
1323    This function's FUNCTION_DECL will have a bit set in its common so
1324    that we know to watch out for it.  */
1325
1326 static void
1327 consume_string (this_obstack, matching_char)
1328      register struct obstack *this_obstack;
1329      int matching_char;
1330 {
1331   register int c;
1332   int starting_lineno = lineno;
1333   do
1334     {
1335       c = getch ();
1336       if (c == EOF)
1337         {
1338           int save_lineno = lineno;
1339           lineno = starting_lineno;
1340           if (matching_char == '"')
1341             error ("end of file encountered inside string constant");
1342           else
1343             error ("end of file encountered inside character constant");
1344           lineno = save_lineno;
1345           return;
1346         }
1347       if (c == '\\')
1348         {
1349           obstack_1grow (this_obstack, c);
1350           c = getch ();
1351           obstack_1grow (this_obstack, c);
1352
1353           /* Make sure we continue the loop */
1354           c = 0;
1355           continue;
1356         }
1357       if (c == '\n')
1358         {
1359           if (pedantic)
1360             pedwarn ("ANSI C++ forbids newline in string constant");
1361           lineno++;
1362         }
1363       obstack_1grow (this_obstack, c);
1364     }
1365   while (c != matching_char);
1366 }
1367
1368 static int nextyychar = YYEMPTY;
1369 static YYSTYPE nextyylval;
1370
1371 struct pending_input {
1372   int nextchar, yychar, nextyychar, eof;
1373   YYSTYPE yylval, nextyylval;
1374   struct obstack token_obstack;
1375   int first_token;
1376 };
1377
1378 struct pending_input *
1379 save_pending_input ()
1380 {
1381   struct pending_input *p;
1382   p = (struct pending_input *) xmalloc (sizeof (struct pending_input));
1383   p->nextchar = nextchar;
1384   p->yychar = yychar;
1385   p->nextyychar = nextyychar;
1386   p->yylval = yylval;
1387   p->nextyylval = nextyylval;
1388   p->eof = end_of_file;
1389   yychar = nextyychar = YYEMPTY;
1390   nextchar = -1;
1391   p->first_token = first_token;
1392   p->token_obstack = token_obstack;
1393
1394   first_token = 0;
1395   gcc_obstack_init (&token_obstack);
1396   end_of_file = 0;
1397   return p;
1398 }
1399
1400 void
1401 restore_pending_input (p)
1402      struct pending_input *p;
1403 {
1404   my_friendly_assert (nextchar == -1, 229);
1405   nextchar = p->nextchar;
1406   my_friendly_assert (yychar == YYEMPTY || yychar == END_OF_SAVED_INPUT, 230);
1407   yychar = p->yychar;
1408   my_friendly_assert (nextyychar == YYEMPTY, 231);
1409   nextyychar = p->nextyychar;
1410   yylval = p->yylval;
1411   nextyylval = p->nextyylval;
1412   first_token = p->first_token;
1413   obstack_free (&token_obstack, (char *) 0);
1414   token_obstack = p->token_obstack;
1415   end_of_file = p->eof;
1416   free (p);
1417 }
1418
1419 /* Unget character CH from the input stream.
1420    If RESCAN is non-zero, then we want to `see' this
1421    character as the next input token.  */
1422
1423 void
1424 yyungetc (ch, rescan)
1425      int ch;
1426      int rescan;
1427 {
1428   /* Unget a character from the input stream.  */
1429   if (yychar == YYEMPTY || rescan == 0)
1430     {
1431       if (nextchar >= 0)
1432         put_back (nextchar);
1433       nextchar = ch;
1434     }
1435   else
1436     {
1437       my_friendly_assert (nextyychar == YYEMPTY, 232);
1438       nextyychar = yychar;
1439       nextyylval = yylval;
1440       yychar = ch;
1441     }
1442 }
1443
1444 void
1445 clear_inline_text_obstack ()
1446 {
1447   obstack_free (&inline_text_obstack, inline_text_firstobj);
1448 }
1449
1450 /* This function stores away the text for an inline function that should
1451    be processed later.  It decides how much later, and may need to move
1452    the info between obstacks; therefore, the caller should not refer to
1453    the T parameter after calling this function.  */
1454
1455 static void
1456 store_pending_inline (decl, t)
1457      tree decl;
1458      struct pending_inline *t;
1459 {
1460   t->fndecl = decl;
1461   DECL_PENDING_INLINE_INFO (decl) = t;
1462
1463   /* Because we use obstacks, we must process these in precise order.  */
1464   t->next = pending_inlines;
1465   pending_inlines = t;
1466 }
1467
1468 void
1469 reinit_parse_for_method (yychar, decl)
1470      int yychar;
1471      tree decl;
1472 {
1473   int len;
1474   int starting_lineno = lineno;
1475   char *starting_filename = input_filename;
1476
1477   reinit_parse_for_block (yychar, &inline_text_obstack);
1478
1479   len = obstack_object_size (&inline_text_obstack);
1480   current_base_init_list = NULL_TREE;
1481   current_member_init_list = NULL_TREE;
1482   if (decl == void_type_node
1483       || (current_class_type && TYPE_REDEFINED (current_class_type)))
1484     {
1485       /* Happens when we get two declarations of the same
1486          function in the same scope.  */
1487       char *buf = obstack_finish (&inline_text_obstack);
1488       obstack_free (&inline_text_obstack, buf);
1489       return;
1490     }
1491   else
1492     {
1493       struct pending_inline *t;
1494       char *buf = obstack_finish (&inline_text_obstack);
1495
1496       t = (struct pending_inline *) obstack_alloc (&inline_text_obstack,
1497                                                    sizeof (struct pending_inline));
1498       t->lineno = starting_lineno;
1499       t->filename = starting_filename;
1500       t->token = YYEMPTY;
1501       t->token_value = 0;
1502       t->buf = buf;
1503       t->len = len;
1504       t->deja_vu = 0;
1505 #if 0
1506       if (interface_unknown && processing_template_defn && flag_external_templates && ! DECL_IN_SYSTEM_HEADER (decl))
1507         warn_if_unknown_interface (decl);
1508 #endif
1509       t->interface = (interface_unknown ? 1 : (interface_only ? 0 : 2));
1510       store_pending_inline (decl, t);
1511     }
1512 }
1513
1514 /* Consume a block -- actually, a method beginning
1515    with `:' or `{' -- and save it away on the specified obstack.  */
1516
1517 void
1518 reinit_parse_for_block (pyychar, obstackp)
1519      int pyychar;
1520      struct obstack *obstackp;
1521 {
1522   register int c = 0;
1523   int blev = 1;
1524   int starting_lineno = lineno;
1525   char *starting_filename = input_filename;
1526   int len;
1527   int look_for_semicolon = 0;
1528   int look_for_lbrac = 0;
1529
1530   if (pyychar == '{')
1531     obstack_1grow (obstackp, '{');
1532   else if (pyychar == '=')
1533     look_for_semicolon = 1;
1534   else if (pyychar == ':')
1535     {
1536       obstack_1grow (obstackp, pyychar);
1537       look_for_lbrac = 1;
1538       blev = 0;
1539     }
1540   else if (pyychar == RETURN)
1541     {
1542       obstack_grow (obstackp, "return", 6);
1543       look_for_lbrac = 1;
1544       blev = 0;
1545     }
1546   else if (pyychar == TRY)
1547     {
1548       obstack_grow (obstackp, "try", 3);
1549       look_for_lbrac = 1;
1550       blev = 0;
1551     }
1552   else
1553     {
1554       yyerror ("parse error in method specification");
1555       obstack_1grow (obstackp, '{');
1556     }
1557
1558   if (nextchar != EOF)
1559     {
1560       c = nextchar;
1561       nextchar = EOF;
1562     }
1563   else
1564     c = getch ();
1565   
1566   while (c != EOF)
1567     {
1568       int this_lineno = lineno;
1569
1570       c = skip_white_space (c);
1571
1572       /* Don't lose our cool if there are lots of comments.  */
1573       if (lineno == this_lineno + 1)
1574         obstack_1grow (obstackp, '\n');
1575       else if (lineno == this_lineno)
1576         ;
1577       else if (lineno - this_lineno < 10)
1578         {
1579           int i;
1580           for (i = lineno - this_lineno; i > 0; i--)
1581             obstack_1grow (obstackp, '\n');
1582         }
1583       else
1584         {
1585           char buf[16];
1586           sprintf (buf, "\n# %d \"", lineno);
1587           len = strlen (buf);
1588           obstack_grow (obstackp, buf, len);
1589
1590           len = strlen (input_filename);
1591           obstack_grow (obstackp, input_filename, len);
1592           obstack_1grow (obstackp, '\"');
1593           obstack_1grow (obstackp, '\n');
1594         }
1595
1596       while (c > ' ')           /* ASCII dependent...  */
1597         {
1598           obstack_1grow (obstackp, c);
1599           if (c == '{')
1600             {
1601               look_for_lbrac = 0;
1602               blev++;
1603             }
1604           else if (c == '}')
1605             {
1606               blev--;
1607               if (blev == 0 && !look_for_semicolon)
1608                 {
1609                   if (pyychar == TRY)
1610                     {
1611                       if (peekyylex () == CATCH)
1612                         {
1613                           yylex ();
1614                           obstack_grow (obstackp, " catch ", 7);
1615                           look_for_lbrac = 1;
1616                         }
1617                       else
1618                         {
1619                           yychar = '{';
1620                           goto done;
1621                         }
1622                     }
1623                   else
1624                     {
1625                       goto done;
1626                     }
1627                 }
1628             }
1629           else if (c == '\\')
1630             {
1631               /* Don't act on the next character...e.g, doing an escaped
1632                  double-quote.  */
1633               c = getch ();
1634               if (c == EOF)
1635                 {
1636                   error_with_file_and_line (starting_filename,
1637                                             starting_lineno,
1638                                             "end of file read inside definition");
1639                   goto done;
1640                 }
1641               obstack_1grow (obstackp, c);
1642             }
1643           else if (c == '\"')
1644             consume_string (obstackp, c);
1645           else if (c == '\'')
1646             consume_string (obstackp, c);
1647           else if (c == ';')
1648             {
1649               if (look_for_lbrac)
1650                 {
1651                   error ("function body for constructor missing");
1652                   obstack_1grow (obstackp, '{');
1653                   obstack_1grow (obstackp, '}');
1654                   len += 2;
1655                   goto done;
1656                 }
1657               else if (look_for_semicolon && blev == 0)
1658                 goto done;
1659             }
1660           c = getch ();
1661         }
1662
1663       if (c == EOF)
1664         {
1665           error_with_file_and_line (starting_filename,
1666                                     starting_lineno,
1667                                     "end of file read inside definition");
1668           goto done;
1669         }
1670       else if (c != '\n')
1671         {
1672           obstack_1grow (obstackp, c);
1673           c = getch ();
1674         }
1675     }
1676  done:
1677   obstack_1grow (obstackp, '\0');
1678 }
1679
1680 /* Consume a no-commas expression -- actually, a default argument -- and
1681    save it away on the specified obstack.  */
1682
1683 static void
1684 reinit_parse_for_expr (obstackp)
1685      struct obstack *obstackp;
1686 {
1687   register int c = 0;
1688   int starting_lineno = lineno;
1689   char *starting_filename = input_filename;
1690   int len;
1691   int plev = 0;
1692
1693   if (nextchar != EOF)
1694     {
1695       c = nextchar;
1696       nextchar = EOF;
1697     }
1698   else
1699     c = getch ();
1700   
1701   while (c != EOF)
1702     {
1703       int this_lineno = lineno;
1704
1705       c = skip_white_space (c);
1706
1707       /* Don't lose our cool if there are lots of comments.  */
1708       if (lineno == this_lineno + 1)
1709         obstack_1grow (obstackp, '\n');
1710       else if (lineno == this_lineno)
1711         ;
1712       else if (lineno - this_lineno < 10)
1713         {
1714           int i;
1715           for (i = lineno - this_lineno; i > 0; --i)
1716             obstack_1grow (obstackp, '\n');
1717         }
1718       else
1719         {
1720           char buf[16];
1721           sprintf (buf, "\n# %d \"", lineno);
1722           len = strlen (buf);
1723           obstack_grow (obstackp, buf, len);
1724
1725           len = strlen (input_filename);
1726           obstack_grow (obstackp, input_filename, len);
1727           obstack_1grow (obstackp, '\"');
1728           obstack_1grow (obstackp, '\n');
1729         }
1730
1731       while (c > ' ')           /* ASCII dependent...  */
1732         {
1733           if (plev <= 0 && (c == ')' || c == ','))
1734             {
1735               put_back (c);
1736               goto done;
1737             }
1738           obstack_1grow (obstackp, c);
1739           if (c == '(' || c == '[')
1740             ++plev;
1741           else if (c == ']' || c == ')')
1742             --plev;
1743           else if (c == '\\')
1744             {
1745               /* Don't act on the next character...e.g, doing an escaped
1746                  double-quote.  */
1747               c = getch ();
1748               if (c == EOF)
1749                 {
1750                   error_with_file_and_line (starting_filename,
1751                                             starting_lineno,
1752                                             "end of file read inside definition");
1753                   goto done;
1754                 }
1755               obstack_1grow (obstackp, c);
1756             }
1757           else if (c == '\"')
1758             consume_string (obstackp, c);
1759           else if (c == '\'')
1760             consume_string (obstackp, c);
1761           c = getch ();
1762         }
1763
1764       if (c == EOF)
1765         {
1766           error_with_file_and_line (starting_filename,
1767                                     starting_lineno,
1768                                     "end of file read inside definition");
1769           goto done;
1770         }
1771       else if (c != '\n')
1772         {
1773           obstack_1grow (obstackp, c);
1774           c = getch ();
1775         }
1776     }
1777  done:
1778   obstack_1grow (obstackp, '\0');
1779 }
1780
1781 int do_snarf_defarg;
1782
1783 /* Decide whether the default argument we are about to see should be
1784    gobbled up as text for later parsing.  */
1785
1786 void
1787 maybe_snarf_defarg ()
1788 {
1789   if (current_class_type && TYPE_BEING_DEFINED (current_class_type))
1790     do_snarf_defarg = 1;
1791 }
1792
1793 /* When we see a default argument in a method declaration, we snarf it as
1794    text using snarf_defarg.  When we get up to namespace scope, we then go
1795    through and parse all of them using do_pending_defargs.  Since yacc
1796    parsers are not reentrant, we retain defargs state in these two
1797    variables so that subsequent calls to do_pending_defargs can resume
1798    where the previous call left off.  */
1799
1800 tree defarg_fns;
1801 tree defarg_parm;
1802
1803 tree
1804 snarf_defarg ()
1805 {
1806   int len;
1807   char *buf;
1808   tree arg;
1809
1810   reinit_parse_for_expr (&inline_text_obstack);
1811   len = obstack_object_size (&inline_text_obstack);
1812   buf = obstack_finish (&inline_text_obstack);
1813
1814   push_obstacks (&inline_text_obstack, &inline_text_obstack);
1815   arg = make_node (DEFAULT_ARG);
1816   DEFARG_LENGTH (arg) = len - 1;
1817   DEFARG_POINTER (arg) = buf;
1818   pop_obstacks ();
1819
1820   return arg;
1821 }
1822
1823 /* Called from grokfndecl to note a function decl with unparsed default
1824    arguments for later processing.  Also called from grokdeclarator
1825    for function types with unparsed defargs; the call from grokfndecl
1826    will always come second, so we can overwrite the entry from the type.  */
1827
1828 void
1829 add_defarg_fn (decl)
1830      tree decl;
1831 {
1832   if (TREE_CODE (decl) == FUNCTION_DECL)
1833     TREE_VALUE (defarg_fns) = decl;
1834   else
1835     {
1836       push_obstacks (&inline_text_obstack, &inline_text_obstack);
1837       defarg_fns = tree_cons (current_class_type, decl, defarg_fns);  
1838       pop_obstacks ();
1839     }
1840 }
1841
1842 /* Helper for do_pending_defargs.  Starts the parsing of a default arg.  */
1843
1844 static void
1845 feed_defarg (f, p)
1846      tree f, p;
1847 {
1848   tree d = TREE_PURPOSE (p);
1849   feed_input (DEFARG_POINTER (d), DEFARG_LENGTH (d));
1850   if (TREE_CODE (f) == FUNCTION_DECL)
1851     {
1852       lineno = DECL_SOURCE_LINE (f);
1853       input_filename = DECL_SOURCE_FILE (f);
1854     }
1855   yychar = DEFARG_MARKER;
1856   yylval.ttype = p;
1857 }
1858
1859 /* Helper for do_pending_defargs.  Ends the parsing of a default arg.  */
1860
1861 static void
1862 finish_defarg ()
1863 {
1864   if (yychar == YYEMPTY)
1865     yychar = yylex ();
1866   if (yychar != END_OF_SAVED_INPUT)
1867     {
1868       error ("parse error at end of saved function text");
1869
1870       /* restore_pending_input will abort unless yychar is either
1871          END_OF_SAVED_INPUT or YYEMPTY; since we already know we're
1872          hosed, feed back YYEMPTY.  We also need to discard nextchar,
1873          since that may have gotten set as well.  */
1874       nextchar = -1;
1875     }
1876   yychar = YYEMPTY;
1877   end_input ();
1878 }  
1879
1880 /* Main function for deferred parsing of default arguments.  Called from
1881    the parser.  */
1882
1883 void
1884 do_pending_defargs ()
1885 {
1886   if (defarg_parm)
1887     finish_defarg ();
1888
1889   for (; defarg_fns; defarg_fns = TREE_CHAIN (defarg_fns))
1890     {
1891       tree defarg_fn = TREE_VALUE (defarg_fns);
1892       if (defarg_parm == NULL_TREE)
1893         {
1894           push_nested_class (TREE_PURPOSE (defarg_fns), 1);
1895           pushlevel (0);
1896           if (TREE_CODE (defarg_fn) == FUNCTION_DECL)
1897             maybe_begin_member_template_processing (defarg_fn);
1898
1899           if (TREE_CODE (defarg_fn) == FUNCTION_DECL)
1900             {
1901 #if 0
1902               tree p;
1903               for (p = DECL_ARGUMENTS (defarg_fn); p; p = TREE_CHAIN (p))
1904                 pushdecl (copy_node (p));
1905 #endif
1906               defarg_parm = TYPE_ARG_TYPES (TREE_TYPE (defarg_fn));
1907             }
1908           else
1909             defarg_parm = TYPE_ARG_TYPES (defarg_fn);
1910         }
1911       else
1912         defarg_parm = TREE_CHAIN (defarg_parm);
1913
1914       for (; defarg_parm; defarg_parm = TREE_CHAIN (defarg_parm))
1915         if (TREE_PURPOSE (defarg_parm)
1916             && TREE_CODE (TREE_PURPOSE (defarg_parm)) == DEFAULT_ARG)
1917           {
1918             feed_defarg (defarg_fn, defarg_parm);
1919
1920             /* Return to the parser, which will process this defarg
1921                and call us again.  */
1922             return;
1923           }
1924
1925       if (TREE_CODE (defarg_fn) == FUNCTION_DECL)
1926         maybe_end_member_template_processing (defarg_fn);
1927       poplevel (0, 0, 0);
1928       pop_nested_class (1);
1929     }
1930 }
1931
1932 /* Build a default function named NAME for type TYPE.
1933    KIND says what to build.
1934
1935    When KIND == 0, build default destructor.
1936    When KIND == 1, build virtual destructor.
1937    When KIND == 2, build default constructor.
1938    When KIND == 3, build default X(const X&) constructor.
1939    When KIND == 4, build default X(X&) constructor.
1940    When KIND == 5, build default operator = (const X&).
1941    When KIND == 6, build default operator = (X&).  */
1942
1943 tree
1944 cons_up_default_function (type, full_name, kind)
1945      tree type, full_name;
1946      int kind;
1947 {
1948   extern tree void_list_node;
1949   tree declspecs = NULL_TREE;
1950   tree fn, args = NULL_TREE;
1951   tree argtype;
1952   int retref = 0;
1953   tree name = constructor_name (full_name);
1954
1955   switch (kind)
1956     {
1957       /* Destructors.  */
1958     case 1:
1959       declspecs = build_decl_list (NULL_TREE, ridpointers [(int) RID_VIRTUAL]);
1960       /* Fall through...  */
1961     case 0:
1962       name = build_parse_node (BIT_NOT_EXPR, name);
1963       args = void_list_node;
1964       break;
1965
1966     case 2:
1967       /* Default constructor.  */
1968       args = void_list_node;
1969       break;
1970
1971     case 3:
1972       type = build_type_variant (type, 1, 0);
1973       /* Fall through...  */
1974     case 4:
1975       /* According to ARM $12.8, the default copy ctor will be declared, but
1976          not defined, unless it's needed.  */
1977       argtype = build_reference_type (type);
1978       args = tree_cons (NULL_TREE,
1979                         build_tree_list (hash_tree_chain (argtype, NULL_TREE),
1980                                          get_identifier ("_ctor_arg")),
1981                         void_list_node);
1982       break;
1983
1984     case 5:
1985     case 6:
1986       retref = 1;
1987       declspecs = build_decl_list (NULL_TREE, type);
1988
1989       if (kind == 5)
1990         type = build_type_variant (type, 1, 0);
1991
1992       name = ansi_opname [(int) MODIFY_EXPR];
1993
1994       argtype = build_reference_type (type);
1995       args = tree_cons (NULL_TREE,
1996                         build_tree_list (hash_tree_chain (argtype, NULL_TREE),
1997                                          get_identifier ("_ctor_arg")),
1998                         void_list_node);
1999       break;
2000
2001     default:
2002       my_friendly_abort (59);
2003     }
2004
2005   declspecs = decl_tree_cons (NULL_TREE, ridpointers [(int) RID_INLINE],
2006                               declspecs);
2007
2008   TREE_PARMLIST (args) = 1;
2009
2010   {
2011     tree declarator = make_call_declarator (name, args, NULL_TREE, NULL_TREE);
2012     if (retref)
2013       declarator = build_parse_node (ADDR_EXPR, declarator);
2014
2015     fn = grokfield (declarator, declspecs, NULL_TREE, NULL_TREE, NULL_TREE);
2016   }
2017   
2018   if (fn == void_type_node)
2019     return fn;
2020
2021   if (kind > 2)
2022     SET_DECL_ARTIFICIAL (TREE_CHAIN (DECL_ARGUMENTS (fn)));
2023
2024 #if 0
2025   if (processing_template_defn)
2026     {
2027       SET_DECL_IMPLICIT_INSTANTIATION (fn);
2028       repo_template_used (fn);
2029     }
2030 #endif
2031
2032 #if 0
2033   if (CLASSTYPE_INTERFACE_KNOWN (type))
2034     {
2035       DECL_INTERFACE_KNOWN (fn) = 1;
2036       DECL_NOT_REALLY_EXTERN (fn) = (!CLASSTYPE_INTERFACE_ONLY (type)
2037                                      && flag_implement_inlines);
2038     }
2039   else
2040 #endif
2041     DECL_NOT_REALLY_EXTERN (fn) = 1;
2042
2043   mark_inline_for_output (fn);
2044
2045 #ifdef DEBUG_DEFAULT_FUNCTIONS
2046   { char *fn_type = NULL;
2047     tree t = name;
2048     switch (kind)
2049       {
2050       case 0: fn_type = "default destructor"; break;
2051       case 1: fn_type = "virtual destructor"; break;
2052       case 2: fn_type = "default constructor"; break;
2053       case 3: fn_type = "default X(const X&)"; break;
2054       case 4: fn_type = "default X(X&)"; break;
2055       }
2056     if (fn_type)
2057       {
2058         if (TREE_CODE (name) == BIT_NOT_EXPR)
2059           t = TREE_OPERAND (name, 0);
2060         fprintf (stderr, "[[[[ %s for %s:\n%s]]]]\n", fn_type,
2061                  IDENTIFIER_POINTER (t), func_buf);
2062       }
2063   }
2064 #endif /* DEBUG_DEFAULT_FUNCTIONS */
2065
2066   /* Show that this function was generated by the compiler.  */
2067   SET_DECL_ARTIFICIAL (fn);
2068   
2069   return fn;
2070 }
2071
2072 /* Heuristic to tell whether the user is missing a semicolon
2073    after a struct or enum declaration.  Emit an error message
2074    if we know the user has blown it.  */
2075
2076 void
2077 check_for_missing_semicolon (type)
2078      tree type;
2079 {
2080   if (yychar < 0)
2081     yychar = yylex ();
2082
2083   if ((yychar > 255
2084        && yychar != SCSPEC
2085        && yychar != IDENTIFIER
2086        && yychar != TYPENAME
2087        && yychar != CV_QUALIFIER
2088        && yychar != SELFNAME)
2089       || end_of_file)
2090     {
2091       if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)))
2092         error ("semicolon missing after %s declaration",
2093                TREE_CODE (type) == ENUMERAL_TYPE ? "enum" : "struct");
2094       else
2095         cp_error ("semicolon missing after declaration of `%T'", type);
2096       shadow_tag (build_tree_list (0, type));
2097     }
2098   /* Could probably also hack cases where class { ... } f (); appears.  */
2099   clear_anon_tags ();
2100 }
2101
2102 void
2103 note_got_semicolon (type)
2104      tree type;
2105 {
2106   if (TREE_CODE_CLASS (TREE_CODE (type)) != 't')
2107     my_friendly_abort (60);
2108   if (IS_AGGR_TYPE (type))
2109     CLASSTYPE_GOT_SEMICOLON (type) = 1;
2110 }
2111
2112 void
2113 note_list_got_semicolon (declspecs)
2114      tree declspecs;
2115 {
2116   tree link;
2117
2118   for (link = declspecs; link; link = TREE_CHAIN (link))
2119     {
2120       tree type = TREE_VALUE (link);
2121       if (TREE_CODE_CLASS (TREE_CODE (type)) == 't')
2122         note_got_semicolon (type);
2123     }
2124   clear_anon_tags ();
2125 }
2126 \f
2127 /* If C is not whitespace, return C.
2128    Otherwise skip whitespace and return first nonwhite char read.  */
2129
2130 static int
2131 skip_white_space (c)
2132      register int c;
2133 {
2134   for (;;)
2135     {
2136       switch (c)
2137         {
2138         case '\n':
2139           c = check_newline ();
2140           break;
2141
2142         case ' ':
2143         case '\t':
2144         case '\f':
2145         case '\r':
2146         case '\v':
2147         case '\b':
2148           do
2149             c = getch ();
2150           while (c == ' ' || c == '\t');
2151           break;
2152
2153         case '\\':
2154           c = getch ();
2155           if (c == '\n')
2156             lineno++;
2157           else
2158             error ("stray '\\' in program");
2159           c = getch ();
2160           break;
2161
2162         default:
2163           return (c);
2164         }
2165     }
2166 }
2167
2168
2169
2170 /* Make the token buffer longer, preserving the data in it.
2171    P should point to just beyond the last valid character in the old buffer.
2172    The value we return is a pointer to the new buffer
2173    at a place corresponding to P.  */
2174
2175 static char *
2176 extend_token_buffer (p)
2177      char *p;
2178 {
2179   int offset = p - token_buffer;
2180
2181   maxtoken = maxtoken * 2 + 10;
2182   token_buffer = (char *) xrealloc (token_buffer, maxtoken + 2);
2183
2184   return token_buffer + offset;
2185 }
2186 \f
2187 static int
2188 get_last_nonwhite_on_line ()
2189 {
2190   register int c;
2191
2192   /* Is this the last nonwhite stuff on the line?  */
2193   if (nextchar >= 0)
2194     c = nextchar, nextchar = -1;
2195   else
2196     c = getch ();
2197
2198   while (c == ' ' || c == '\t')
2199     c = getch ();
2200   return c;
2201 }
2202
2203 /* At the beginning of a line, increment the line number
2204    and process any #-directive on this line.
2205    If the line is a #-directive, read the entire line and return a newline.
2206    Otherwise, return the line's first non-whitespace character.  */
2207
2208 int linemode;
2209
2210 #ifdef HANDLE_SYSV_PRAGMA
2211 static int handle_sysv_pragma PROTO((FILE *, int));
2212 #endif
2213 static int handle_cp_pragma PROTO((char *));
2214
2215 static int
2216 check_newline ()
2217 {
2218   register int c;
2219   register int token;
2220
2221   /* Read first nonwhite char on the line.  Do this before incrementing the
2222      line number, in case we're at the end of saved text.  */
2223
2224   do
2225     c = getch ();
2226   while (c == ' ' || c == '\t');
2227
2228   lineno++;
2229
2230   if (c != '#')
2231     {
2232       /* If not #, return it so caller will use it.  */
2233       return c;
2234     }
2235
2236   /* Don't read beyond this line.  */
2237   linemode = 1;
2238   
2239   /* Read first nonwhite char after the `#'.  */
2240
2241   do
2242     c = getch ();
2243   while (c == ' ' || c == '\t');
2244
2245   /* If a letter follows, then if the word here is `line', skip
2246      it and ignore it; otherwise, ignore the line, with an error
2247      if the word isn't `pragma'.  */
2248
2249   if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
2250     {
2251       if (c == 'p')
2252         {
2253           if (getch () == 'r'
2254               && getch () == 'a'
2255               && getch () == 'g'
2256               && getch () == 'm'
2257               && getch () == 'a')
2258             {
2259               token = real_yylex ();
2260               if (token == IDENTIFIER
2261                   && TREE_CODE (yylval.ttype) == IDENTIFIER_NODE)
2262                 {
2263                   /* If this is 1, we handled it; if it's -1, it was one we
2264                      wanted but had something wrong with it.  Only if it's
2265                      0 was it not handled.  */
2266                   if (handle_cp_pragma (IDENTIFIER_POINTER (yylval.ttype)))
2267                     goto skipline;
2268                 }
2269               else if (token == END_OF_LINE)
2270                 goto skipline;
2271
2272 #ifdef HANDLE_SYSV_PRAGMA
2273               if (handle_sysv_pragma (finput, token))
2274                 goto skipline;
2275 #else
2276 #ifdef HANDLE_PRAGMA
2277               if (HANDLE_PRAGMA (finput, yylval.ttype))
2278                 goto skipline;
2279 #endif
2280 #endif
2281             }
2282           goto skipline;
2283         }
2284       else if (c == 'd')
2285         {
2286           if (getch () == 'e'
2287               && getch () == 'f'
2288               && getch () == 'i'
2289               && getch () == 'n'
2290               && getch () == 'e'
2291               && ((c = getch ()) == ' ' || c == '\t'))
2292             {
2293               debug_define (lineno, get_directive_line (finput));
2294               goto skipline;
2295             }
2296         }
2297       else if (c == 'u')
2298         {
2299           if (getch () == 'n'
2300               && getch () == 'd'
2301               && getch () == 'e'
2302               && getch () == 'f'
2303               && ((c = getch ()) == ' ' || c == '\t'))
2304             {
2305               debug_undef (lineno, get_directive_line (finput));
2306               goto skipline;
2307             }
2308         }
2309       else if (c == 'l')
2310         {
2311           if (getch () == 'i'
2312               && getch () == 'n'
2313               && getch () == 'e'
2314               && ((c = getch ()) == ' ' || c == '\t'))
2315             goto linenum;
2316         }
2317       else if (c == 'i')
2318         {
2319           if (getch () == 'd'
2320               && getch () == 'e'
2321               && getch () == 'n'
2322               && getch () == 't'
2323               && ((c = getch ()) == ' ' || c == '\t'))
2324             {
2325 #ifdef ASM_OUTPUT_IDENT
2326               extern FILE *asm_out_file;
2327 #endif
2328               /* #ident.  The pedantic warning is now in cccp.c.  */
2329
2330               /* Here we have just seen `#ident '.
2331                  A string constant should follow.  */
2332
2333               token = real_yylex ();
2334               if (token == END_OF_LINE)
2335                 goto skipline;
2336               if (token != STRING
2337                   || TREE_CODE (yylval.ttype) != STRING_CST)
2338                 {
2339                   error ("invalid #ident");
2340                   goto skipline;
2341                 }
2342
2343               if (! flag_no_ident)
2344                 {
2345 #ifdef ASM_OUTPUT_IDENT
2346                   ASM_OUTPUT_IDENT (asm_out_file,
2347                                     TREE_STRING_POINTER (yylval.ttype));
2348 #endif
2349                 }
2350
2351               /* Skip the rest of this line.  */
2352               goto skipline;
2353             }
2354         }
2355       else if (c == 'n')
2356         {
2357           if (getch () == 'e'
2358               && getch () == 'w'
2359               && getch () == 'w'
2360               && getch () == 'o'
2361               && getch () == 'r'
2362               && getch () == 'l'
2363               && getch () == 'd'
2364               && ((c = getch ()) == ' ' || c == '\t'))
2365             {
2366               /* Used to test incremental compilation.  */
2367               sorry ("#pragma newworld");
2368               goto skipline;
2369             }
2370         }
2371       error ("undefined or invalid # directive");
2372       goto skipline;
2373     }
2374
2375 linenum:
2376   /* Here we have either `#line' or `# <nonletter>'.
2377      In either case, it should be a line number; a digit should follow.  */
2378
2379   while (c == ' ' || c == '\t')
2380     c = getch ();
2381
2382   /* If the # is the only nonwhite char on the line,
2383      just ignore it.  Check the new newline.  */
2384   if (c == EOF)
2385     goto skipline;
2386
2387   /* Something follows the #; read a token.  */
2388
2389   put_back (c);
2390   token = real_yylex ();
2391
2392   if (token == CONSTANT
2393       && TREE_CODE (yylval.ttype) == INTEGER_CST)
2394     {
2395       int old_lineno = lineno;
2396       enum { act_none, act_push, act_pop } action = act_none;
2397       int entering_system_header = 0;
2398       int entering_c_header = 0;
2399
2400       /* subtract one, because it is the following line that
2401          gets the specified number */
2402
2403       int l = TREE_INT_CST_LOW (yylval.ttype) - 1;
2404       c = get_last_nonwhite_on_line ();
2405       if (c == EOF)
2406         {
2407           /* No more: store the line number and check following line.  */
2408           lineno = l;
2409           goto skipline;
2410         }
2411       put_back (c);
2412
2413       /* More follows: it must be a string constant (filename).  */
2414
2415       /* Read the string constant, but don't treat \ as special.  */
2416       ignore_escape_flag = 1;
2417       token = real_yylex ();
2418       ignore_escape_flag = 0;
2419
2420       if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
2421         {
2422           error ("invalid #line");
2423           goto skipline;
2424         }
2425
2426       /* Changing files again.  This means currently collected time
2427          is charged against header time, and body time starts back
2428          at 0.  */
2429       if (flag_detailed_statistics)
2430         {
2431           int this_time = my_get_run_time ();
2432           tree time_identifier = get_time_identifier (TREE_STRING_POINTER (yylval.ttype));
2433           header_time += this_time - body_time;
2434           TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time))
2435             += this_time - body_time;
2436           this_filename_time = time_identifier;
2437           body_time = this_time;
2438         }
2439
2440       input_filename
2441         = (char *) permalloc (TREE_STRING_LENGTH (yylval.ttype) + 1);
2442       strcpy (input_filename, TREE_STRING_POINTER (yylval.ttype));
2443       lineno = l;
2444       GNU_xref_file (input_filename);
2445       
2446       if (main_input_filename == 0)
2447         {
2448           struct impl_files *ifiles = impl_file_chain;
2449
2450           if (ifiles)
2451             {
2452               while (ifiles->next)
2453                 ifiles = ifiles->next;
2454               ifiles->filename = file_name_nondirectory (input_filename);
2455             }
2456
2457           main_input_filename = input_filename;
2458           if (write_virtuals == 3)
2459             walk_vtables (set_typedecl_interface_info, set_vardecl_interface_info);
2460         }
2461
2462       extract_interface_info ();
2463
2464       c = get_last_nonwhite_on_line ();
2465       if (c == EOF)
2466         {
2467           /* Update the name in the top element of input_file_stack.  */
2468           if (input_file_stack)
2469             input_file_stack->name = input_filename;
2470         }
2471       else
2472         {
2473           put_back (c);
2474
2475           token = real_yylex ();
2476
2477           /* `1' after file name means entering new file.
2478              `2' after file name means just left a file.  */
2479
2480           if (token == CONSTANT
2481               && TREE_CODE (yylval.ttype) == INTEGER_CST)
2482             {
2483               if (TREE_INT_CST_LOW (yylval.ttype) == 1)
2484                 action = act_push;
2485               else if (TREE_INT_CST_LOW (yylval.ttype) == 2)
2486                 action = act_pop;
2487
2488               if (action)
2489                 {
2490                   c = get_last_nonwhite_on_line ();
2491                   if (c != EOF)
2492                     {
2493                       put_back (c);
2494                       token = real_yylex ();
2495                     }
2496                 }
2497             }
2498
2499           /* `3' after file name means this is a system header file.  */
2500
2501           if (token == CONSTANT
2502               && TREE_CODE (yylval.ttype) == INTEGER_CST
2503               && TREE_INT_CST_LOW (yylval.ttype) == 3)
2504             {
2505               entering_system_header = 1;
2506
2507               c = get_last_nonwhite_on_line ();
2508               if (c != EOF)
2509                 {
2510                   put_back (c);
2511                   token = real_yylex ();
2512                 }
2513             }
2514
2515           /* `4' after file name means this is a C header file.  */
2516
2517           if (token == CONSTANT
2518               && TREE_CODE (yylval.ttype) == INTEGER_CST
2519               && TREE_INT_CST_LOW (yylval.ttype) == 4)
2520             {
2521               entering_c_header = 1;
2522
2523               c = get_last_nonwhite_on_line ();
2524               if (c != EOF)
2525                 {
2526                   put_back (c);
2527                   token = real_yylex ();
2528                 }
2529             }
2530
2531           /* Do the actions implied by the preceding numbers.  */
2532
2533           if (action == act_push)
2534             {
2535               /* Pushing to a new file.  */
2536               struct file_stack *p;
2537
2538               p = (struct file_stack *) xmalloc (sizeof (struct file_stack));
2539               input_file_stack->line = old_lineno;
2540               p->next = input_file_stack;
2541               p->name = input_filename;
2542               input_file_stack = p;
2543               input_file_stack_tick++;
2544               debug_start_source_file (input_filename);
2545               in_system_header = entering_system_header;
2546               if (c_header_level)
2547                 ++c_header_level;
2548               else if (entering_c_header)
2549                 {
2550                   c_header_level = 1;
2551                   ++pending_lang_change;
2552                 }
2553             }
2554           else if (action == act_pop)
2555             {
2556               /* Popping out of a file.  */
2557               if (input_file_stack->next)
2558                 {
2559                   struct file_stack *p;
2560
2561                   if (c_header_level && --c_header_level == 0)
2562                     {
2563                       if (entering_c_header)
2564                         warning ("badly nested C headers from preprocessor");
2565                       --pending_lang_change;
2566                     }
2567                   in_system_header = entering_system_header;
2568
2569                   p = input_file_stack;
2570                   input_file_stack = p->next;
2571                   free (p);
2572                   input_file_stack_tick++;
2573                   debug_end_source_file (input_file_stack->line);
2574                 }
2575               else
2576                 error ("#-lines for entering and leaving files don't match");
2577             }
2578           else
2579             in_system_header = entering_system_header;
2580         }
2581
2582       /* If NEXTCHAR is not end of line, we don't care what it is.  */
2583       if (nextchar == EOF)
2584         c = EOF;
2585     }
2586   else
2587     error ("invalid #-line");
2588
2589   /* skip the rest of this line.  */
2590  skipline:
2591   linemode = 0;
2592   end_of_file = 0;
2593   nextchar = -1;
2594   while ((c = getch ()) != EOF && c != '\n');
2595   return c;
2596 }
2597
2598 void
2599 do_pending_lang_change ()
2600 {
2601   for (; pending_lang_change > 0; --pending_lang_change)
2602     push_lang_context (lang_name_c);
2603   for (; pending_lang_change < 0; ++pending_lang_change)
2604     pop_lang_context ();
2605 }
2606 \f
2607 #if 0
2608 #define isalnum(char) (char >= 'a' ? char <= 'z' : char >= '0' ? char <= '9' || (char >= 'A' && char <= 'Z') : 0)
2609 #define isdigit(char) (char >= '0' && char <= '9')
2610 #else
2611 #include <ctype.h>
2612 #endif
2613
2614 #define ENDFILE -1  /* token that represents end-of-file */
2615
2616 /* Read an escape sequence, returning its equivalent as a character,
2617    or store 1 in *ignore_ptr if it is backslash-newline.  */
2618
2619 static int
2620 readescape (ignore_ptr)
2621      int *ignore_ptr;
2622 {
2623   register int c = getch ();
2624   register int code;
2625   register unsigned count;
2626   unsigned firstdig = 0;
2627   int nonnull;
2628
2629   switch (c)
2630     {
2631     case 'x':
2632       code = 0;
2633       count = 0;
2634       nonnull = 0;
2635       while (1)
2636         {
2637           c = getch ();
2638           if (! isxdigit (c))
2639             {
2640               put_back (c);
2641               break;
2642             }
2643           code *= 16;
2644           if (c >= 'a' && c <= 'f')
2645             code += c - 'a' + 10;
2646           if (c >= 'A' && c <= 'F')
2647             code += c - 'A' + 10;
2648           if (c >= '0' && c <= '9')
2649             code += c - '0';
2650           if (code != 0 || count != 0)
2651             {
2652               if (count == 0)
2653                 firstdig = code;
2654               count++;
2655             }
2656           nonnull = 1;
2657         }
2658       if (! nonnull)
2659         error ("\\x used with no following hex digits");
2660       else if (count == 0)
2661         /* Digits are all 0's.  Ok.  */
2662         ;
2663       else if ((count - 1) * 4 >= TYPE_PRECISION (integer_type_node)
2664                || (count > 1
2665                    && ((1 << (TYPE_PRECISION (integer_type_node) - (count - 1) * 4))
2666                        <= firstdig)))
2667         pedwarn ("hex escape out of range");
2668       return code;
2669
2670     case '0':  case '1':  case '2':  case '3':  case '4':
2671     case '5':  case '6':  case '7':
2672       code = 0;
2673       count = 0;
2674       while ((c <= '7') && (c >= '0') && (count++ < 3))
2675         {
2676           code = (code * 8) + (c - '0');
2677           c = getch ();
2678         }
2679       put_back (c);
2680       return code;
2681
2682     case '\\': case '\'': case '"':
2683       return c;
2684
2685     case '\n':
2686       lineno++;
2687       *ignore_ptr = 1;
2688       return 0;
2689
2690     case 'n':
2691       return TARGET_NEWLINE;
2692
2693     case 't':
2694       return TARGET_TAB;
2695
2696     case 'r':
2697       return TARGET_CR;
2698
2699     case 'f':
2700       return TARGET_FF;
2701
2702     case 'b':
2703       return TARGET_BS;
2704
2705     case 'a':
2706       return TARGET_BELL;
2707
2708     case 'v':
2709       return TARGET_VT;
2710
2711     case 'e':
2712     case 'E':
2713       if (pedantic)
2714         pedwarn ("non-ANSI-standard escape sequence, `\\%c'", c);
2715       return 033;
2716
2717     case '?':
2718       return c;
2719
2720       /* `\(', etc, are used at beginning of line to avoid confusing Emacs.  */
2721     case '(':
2722     case '{':
2723     case '[':
2724       /* `\%' is used to prevent SCCS from getting confused.  */
2725     case '%':
2726       if (pedantic)
2727         pedwarn ("unknown escape sequence `\\%c'", c);
2728       return c;
2729     }
2730   if (c >= 040 && c < 0177)
2731     pedwarn ("unknown escape sequence `\\%c'", c);
2732   else
2733     pedwarn ("unknown escape sequence: `\\' followed by char code 0x%x", c);
2734   return c;
2735 }
2736
2737 /* Value is 1 (or 2) if we should try to make the next identifier look like
2738    a typename (when it may be a local variable or a class variable).
2739    Value is 0 if we treat this name in a default fashion.  */
2740 int looking_for_typename = 0;
2741
2742 #ifdef __GNUC__
2743 __inline
2744 #endif
2745 int
2746 identifier_type (decl)
2747      tree decl;
2748 {
2749   if (TREE_CODE (decl) == TEMPLATE_DECL)
2750     {
2751       if (TREE_CODE (DECL_RESULT (decl)) == TYPE_DECL)
2752         return PTYPENAME;
2753       else if (looking_for_template) 
2754         return PFUNCNAME;
2755     }
2756   if (looking_for_template && really_overloaded_fn (decl))
2757     {
2758       tree t;
2759       for (t = TREE_VALUE (decl); t != NULL_TREE; t = DECL_CHAIN (t))
2760         if (DECL_FUNCTION_TEMPLATE_P (t)) 
2761           return PFUNCNAME;
2762     }
2763   if (TREE_CODE (decl) == NAMESPACE_DECL)
2764     return NSNAME;
2765   if (TREE_CODE (decl) != TYPE_DECL)
2766     return IDENTIFIER;
2767   if (((got_scope && TREE_TYPE (decl) == got_scope)
2768        || TREE_TYPE (decl) == current_class_type)
2769       && DECL_ARTIFICIAL (decl))
2770     return SELFNAME;
2771   return TYPENAME;
2772 }
2773
2774 void
2775 see_typename ()
2776 {
2777   looking_for_typename = 1;
2778   if (yychar < 0)
2779     if ((yychar = yylex ()) < 0) yychar = 0;
2780   looking_for_typename = 0;
2781   if (yychar == IDENTIFIER)
2782     {
2783       lastiddecl = lookup_name (yylval.ttype, -2);
2784       if (lastiddecl == 0)
2785         {
2786           if (flag_labels_ok)
2787             lastiddecl = IDENTIFIER_LABEL_VALUE (yylval.ttype);
2788         }
2789       else
2790         yychar = identifier_type (lastiddecl);
2791     }
2792 }
2793
2794 tree
2795 do_identifier (token, parsing)
2796      register tree token;
2797      int parsing;
2798 {
2799   register tree id;
2800
2801   if (! parsing || IDENTIFIER_OPNAME_P (token))
2802     id = lookup_name (token, 0);
2803   else
2804     id = lastiddecl;
2805
2806   if (parsing && yychar == YYEMPTY)
2807     yychar = yylex ();
2808   /* Scope class declarations before global
2809      declarations.  */
2810   if (id == IDENTIFIER_NAMESPACE_VALUE (token)
2811       && current_class_type != 0
2812       && TYPE_SIZE (current_class_type) == 0)
2813     {
2814       /* Could be from one of the base classes.  */
2815       tree field = lookup_field (current_class_type, token, 1, 0);
2816       if (field == 0)
2817         ;
2818       else if (field == error_mark_node)
2819         /* We have already generated the error message.
2820            But we still want to return this value.  */
2821         id = lookup_field (current_class_type, token, 0, 0);
2822       else if (TREE_CODE (field) == VAR_DECL
2823                || TREE_CODE (field) == CONST_DECL
2824                || TREE_CODE (field) == TEMPLATE_DECL)
2825         id = field;
2826       else if (TREE_CODE (field) != FIELD_DECL)
2827         my_friendly_abort (61);
2828       else
2829         {
2830           cp_error ("invalid use of member `%D' from base class `%T'", field,
2831                       DECL_FIELD_CONTEXT (field));
2832           id = error_mark_node;
2833           return id;
2834         }
2835     }
2836
2837   /* Remember that this name has been used in the class definition, as per
2838      [class.scope0] */
2839   if (id && current_class_type && parsing
2840       && TYPE_BEING_DEFINED (current_class_type)
2841       && ! IDENTIFIER_CLASS_VALUE (token)
2842       /* Avoid breaking if we get called for a default argument that
2843          refers to an overloaded method.  Eventually this will not be
2844          necessary, since default arguments shouldn't be parsed until
2845          after the class is complete.  (jason 3/12/97) */
2846       && TREE_CODE (id) != TREE_LIST)
2847     pushdecl_class_level (id);
2848     
2849   if (!id || id == error_mark_node)
2850     {
2851       if (id == error_mark_node && current_class_type != NULL_TREE)
2852         {
2853           id = lookup_nested_field (token, 1);
2854           /* In lookup_nested_field(), we marked this so we can gracefully
2855              leave this whole mess.  */
2856           if (id && id != error_mark_node && TREE_TYPE (id) == error_mark_node)
2857             return id;
2858         }
2859
2860       if (current_template_parms)
2861         return build_min_nt (LOOKUP_EXPR, token, NULL_TREE);
2862       else if (IDENTIFIER_OPNAME_P (token))
2863         {
2864           if (token != ansi_opname[ERROR_MARK])
2865             cp_error ("`%D' not defined", token);
2866           id = error_mark_node;
2867         }
2868       else if (parsing && (yychar == '(' || yychar == LEFT_RIGHT))
2869         {
2870           id = implicitly_declare (token);
2871         }
2872       else if (current_function_decl == 0)
2873         {
2874           cp_error ("`%D' was not declared in this scope", token);
2875           id = error_mark_node;
2876         }
2877       else
2878         {
2879           if (IDENTIFIER_NAMESPACE_VALUE (token) != error_mark_node
2880               || IDENTIFIER_ERROR_LOCUS (token) != current_function_decl)
2881             {
2882               static int undeclared_variable_notice;
2883
2884               cp_error ("`%D' undeclared (first use this function)", token);
2885
2886               if (! undeclared_variable_notice)
2887                 {
2888                   error ("(Each undeclared identifier is reported only once");
2889                   error ("for each function it appears in.)");
2890                   undeclared_variable_notice = 1;
2891                 }
2892             }
2893           id = error_mark_node;
2894           /* Prevent repeated error messages.  */
2895           IDENTIFIER_NAMESPACE_VALUE (token) = error_mark_node;
2896           SET_IDENTIFIER_ERROR_LOCUS (token, current_function_decl);
2897         }
2898     }
2899
2900   if (TREE_CODE (id) == VAR_DECL && DECL_DEAD_FOR_LOCAL (id))
2901     {
2902       tree shadowed = DECL_SHADOWED_FOR_VAR (id);
2903       while (shadowed != NULL_TREE && TREE_CODE (shadowed) == VAR_DECL
2904              && DECL_DEAD_FOR_LOCAL (shadowed))
2905         shadowed = DECL_SHADOWED_FOR_VAR (shadowed);
2906       if (!shadowed)
2907         shadowed = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (id));
2908       if (shadowed)
2909         {
2910           if (!DECL_ERROR_REPORTED (id))
2911             {
2912               warning ("name lookup of `%s' changed",
2913                        IDENTIFIER_POINTER (token));
2914               cp_warning_at ("  matches this `%D' under current ANSI rules",
2915                              shadowed);
2916               cp_warning_at ("  matches this `%D' under old rules", id);
2917               DECL_ERROR_REPORTED (id) = 1;
2918             }
2919           id = shadowed;
2920         }
2921       else if (!DECL_ERROR_REPORTED (id))
2922         {
2923           static char msg[]
2924             = "name lookup of `%s' changed for new ANSI `for' scoping";
2925           DECL_ERROR_REPORTED (id) = 1;
2926           if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (id)))
2927             {
2928               error (msg, IDENTIFIER_POINTER (token));
2929               cp_error_at ("  cannot use obsolete binding at `%D' because it has a destructor", id);
2930               id = error_mark_node;
2931             }
2932           else
2933             {
2934               pedwarn (msg, IDENTIFIER_POINTER (token));
2935               cp_pedwarn_at ("  using obsolete binding at `%D'", id);
2936             }
2937         }
2938     }
2939   /* TREE_USED is set in `hack_identifier'.  */
2940   if (TREE_CODE (id) == CONST_DECL)
2941     {
2942       if (IDENTIFIER_CLASS_VALUE (token) == id)
2943         {
2944           /* Check access.  */
2945           tree access = compute_access (TYPE_BINFO (current_class_type), id);
2946           if (access == access_private_node)
2947             cp_error ("enum `%D' is private", id);
2948           /* protected is OK, since it's an enum of `this'.  */
2949         }
2950       if (! processing_template_decl
2951           || (DECL_INITIAL (id)
2952               && TREE_CODE (DECL_INITIAL (id)) == TEMPLATE_PARM_INDEX))
2953         id = DECL_INITIAL (id);
2954     }
2955   else
2956     id = hack_identifier (id, token);
2957
2958   if (current_template_parms)
2959     {
2960       if (is_overloaded_fn (id))
2961         {
2962           tree t = build_min (LOOKUP_EXPR, unknown_type_node,
2963                               token, get_first_fn (id));
2964           if (id != IDENTIFIER_NAMESPACE_VALUE (token))
2965             TREE_OPERAND (t, 1) = error_mark_node;
2966           id = t;
2967         }
2968       else if (! TREE_PERMANENT (id) || TREE_CODE (id) == PARM_DECL
2969                || TREE_CODE (id) == USING_DECL)
2970         id = build_min (LOOKUP_EXPR, TREE_TYPE (id), token, error_mark_node);
2971       /* else just use the decl */
2972     }
2973       
2974   return id;
2975 }
2976
2977 tree
2978 do_scoped_id (token, parsing)
2979      tree token;
2980      int parsing;
2981 {
2982   tree id;
2983   /* during parsing, this is ::name. Otherwise, it is black magic. */
2984   if (parsing)
2985     id = qualified_lookup_using_namespace (token, global_namespace);
2986   else
2987     id = IDENTIFIER_GLOBAL_VALUE (token);
2988   if (parsing && yychar == YYEMPTY)
2989     yychar = yylex ();
2990   if (! id)
2991     {
2992       if (processing_template_decl)
2993         {
2994           id = build_min_nt (LOOKUP_EXPR, token, NULL_TREE);
2995           LOOKUP_EXPR_GLOBAL (id) = 1;
2996           return id;
2997         }
2998       if (parsing && (yychar == '(' || yychar == LEFT_RIGHT))
2999         id = implicitly_declare (token);
3000       else
3001         {
3002           if (IDENTIFIER_NAMESPACE_VALUE (token) != error_mark_node)
3003             error ("undeclared variable `%s' (first use here)",
3004                    IDENTIFIER_POINTER (token));
3005           id = error_mark_node;
3006           /* Prevent repeated error messages.  */
3007           IDENTIFIER_NAMESPACE_VALUE (token) = error_mark_node;
3008         }
3009     }
3010   else
3011     {
3012       if (TREE_CODE (id) == ADDR_EXPR)
3013         mark_used (TREE_OPERAND (id, 0));
3014       else if (TREE_CODE (id) != TREE_LIST)
3015         mark_used (id);
3016     }
3017   if (TREE_CODE (id) == CONST_DECL && ! processing_template_decl)
3018     {
3019       /* XXX CHS - should we set TREE_USED of the constant? */
3020       id = DECL_INITIAL (id);
3021       /* This is to prevent an enum whose value is 0
3022          from being considered a null pointer constant.  */
3023       id = build1 (NOP_EXPR, TREE_TYPE (id), id);
3024       TREE_CONSTANT (id) = 1;
3025     }
3026
3027   if (processing_template_decl)
3028     {
3029       if (is_overloaded_fn (id))
3030         {
3031           id = build_min (LOOKUP_EXPR, unknown_type_node,
3032                           token, get_first_fn (id));
3033           LOOKUP_EXPR_GLOBAL (id) = 1;
3034         }
3035       /* else just use the decl */
3036     }
3037   return convert_from_reference (id);
3038 }
3039
3040 tree
3041 identifier_typedecl_value (node)
3042      tree node;
3043 {
3044   tree t, type;
3045   type = IDENTIFIER_TYPE_VALUE (node);
3046   if (type == NULL_TREE)
3047     return NULL_TREE;
3048 #define do(X) \
3049   { \
3050     t = (X); \
3051     if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type) \
3052       return t; \
3053   }
3054   do (IDENTIFIER_LOCAL_VALUE (node));
3055   do (IDENTIFIER_CLASS_VALUE (node));
3056   do (IDENTIFIER_NAMESPACE_VALUE (node));
3057 #undef do
3058   /* Will this one ever happen?  */
3059   if (TYPE_MAIN_DECL (type))
3060     return TYPE_MAIN_DECL (type);
3061
3062   /* We used to do an internal error of 62 here, but instead we will
3063      handle the return of a null appropriately in the callers.  */
3064   return NULL_TREE;
3065 }
3066
3067 int
3068 real_yylex ()
3069 {
3070   register int c;
3071   register int value;
3072   int wide_flag = 0;
3073   int dollar_seen = 0;
3074   int i;
3075
3076   if (nextchar >= 0)
3077     c = nextchar, nextchar = -1;
3078   else
3079     c = getch ();
3080
3081   /* Effectively do c = skip_white_space (c)
3082      but do it faster in the usual cases.  */
3083   while (1)
3084     switch (c)
3085       {
3086       case ' ':
3087       case '\t':
3088       case '\f':
3089       case '\v':
3090       case '\b':
3091         c = getch ();
3092         break;
3093
3094       case '\r':
3095         /* Call skip_white_space so we can warn if appropriate.  */
3096
3097       case '\n':
3098       case '/':
3099       case '\\':
3100         c = skip_white_space (c);
3101       default:
3102         goto found_nonwhite;
3103       }
3104  found_nonwhite:
3105
3106   token_buffer[0] = c;
3107   token_buffer[1] = 0;
3108
3109 /*  yylloc.first_line = lineno; */
3110
3111   switch (c)
3112     {
3113     case EOF:
3114       token_buffer[0] = '\0';
3115       end_of_file = 1;
3116       if (input_redirected ())
3117         value = END_OF_SAVED_INPUT;
3118       else if (linemode)
3119         value = END_OF_LINE;
3120       else
3121         value = ENDFILE;
3122       break;
3123
3124     case '$':
3125       if (! dollars_in_ident)
3126         error ("`$' in identifier");
3127       else if (pedantic)
3128         pedwarn ("`$' in identifier");
3129       dollar_seen = 1;
3130       goto letter;
3131
3132     case 'L':
3133       /* Capital L may start a wide-string or wide-character constant.  */
3134       {
3135         register int c = getch ();
3136         if (c == '\'')
3137           {
3138             wide_flag = 1;
3139             goto char_constant;
3140           }
3141         if (c == '"')
3142           {
3143             wide_flag = 1;
3144             goto string_constant;
3145           }
3146         put_back (c);
3147       }
3148
3149     case 'A':  case 'B':  case 'C':  case 'D':  case 'E':
3150     case 'F':  case 'G':  case 'H':  case 'I':  case 'J':
3151     case 'K':             case 'M':  case 'N':  case 'O':
3152     case 'P':  case 'Q':  case 'R':  case 'S':  case 'T':
3153     case 'U':  case 'V':  case 'W':  case 'X':  case 'Y':
3154     case 'Z':
3155     case 'a':  case 'b':  case 'c':  case 'd':  case 'e':
3156     case 'f':  case 'g':  case 'h':  case 'i':  case 'j':
3157     case 'k':  case 'l':  case 'm':  case 'n':  case 'o':
3158     case 'p':  case 'q':  case 'r':  case 's':  case 't':
3159     case 'u':  case 'v':  case 'w':  case 'x':  case 'y':
3160     case 'z':
3161     case '_':
3162     letter:
3163       {
3164         register char *p;
3165
3166         p = token_buffer;
3167         if (input == 0)
3168           {
3169             /* We know that `token_buffer' can hold at least on char,
3170                so we install C immediately.
3171                We may have to read the value in `putback_char', so call
3172                `getch' once.  */
3173             *p++ = c;
3174             c = getch ();
3175
3176             /* Make this run fast.  We know that we are reading straight
3177                from FINPUT in this case (since identifiers cannot straddle
3178                input sources.  */
3179             while (isalnum (c) || (c == '_') || c == '$')
3180               {
3181                 if (c == '$')
3182                   {
3183                     if (! dollars_in_ident)
3184                       error ("`$' in identifier");
3185                     else if (pedantic)
3186                       pedwarn ("`$' in identifier");
3187                   }
3188
3189                 if (p >= token_buffer + maxtoken)
3190                   p = extend_token_buffer (p);
3191
3192                 *p++ = c;
3193                 c = getch ();
3194               }
3195
3196             if (linemode && c == '\n')
3197               {
3198                 put_back (c);
3199                 c = EOF;
3200               }
3201           }
3202         else
3203           {
3204             /* We know that `token_buffer' can hold at least on char,
3205                so we install C immediately.  */
3206             *p++ = c;
3207             c = getch ();
3208
3209             while (isalnum (c) || (c == '_') || c == '$')
3210               {
3211                 if (c == '$')
3212                   {
3213                     if (! dollars_in_ident)
3214                       error ("`$' in identifier");
3215                     else if (pedantic)
3216                       pedwarn ("`$' in identifier");
3217                   }
3218
3219                 if (p >= token_buffer + maxtoken)
3220                   p = extend_token_buffer (p);
3221
3222                 *p++ = c;
3223                 c = getch ();
3224               }
3225           }
3226
3227         *p = 0;
3228         nextchar = c;
3229
3230         value = IDENTIFIER;
3231         yylval.itype = 0;
3232
3233       /* Try to recognize a keyword.  Uses minimum-perfect hash function */
3234
3235         {
3236           register struct resword *ptr;
3237
3238           if ((ptr = is_reserved_word (token_buffer, p - token_buffer)))
3239             {
3240               if (ptr->rid)
3241                 {
3242                   tree old_ttype = ridpointers[(int) ptr->rid];
3243
3244                   /* If this provides a type for us, then revert lexical
3245                      state to standard state.  */
3246                   if (TREE_CODE (old_ttype) == IDENTIFIER_NODE
3247                       && IDENTIFIER_GLOBAL_VALUE (old_ttype) != 0
3248                       && TREE_CODE (IDENTIFIER_GLOBAL_VALUE (old_ttype)) == TYPE_DECL)
3249                     looking_for_typename = 0;
3250                   else if (ptr->token == AGGR || ptr->token == ENUM)
3251                     looking_for_typename = 1;
3252
3253                   /* Check if this is a language-type declaration.
3254                      Just glimpse the next non-white character.  */
3255                   nextchar = skip_white_space (nextchar);
3256                   if (nextchar == '"')
3257                     {
3258                       /* We are looking at a string.  Complain
3259                          if the token before the string is no `extern'.
3260                          
3261                          Could cheat some memory by placing this string
3262                          on the temporary_, instead of the saveable_
3263                          obstack.  */
3264
3265                       if (ptr->rid != RID_EXTERN)
3266                         error ("invalid modifier `%s' for language string",
3267                                ptr->name);
3268                       real_yylex ();
3269                       value = EXTERN_LANG_STRING;
3270                       yylval.ttype = get_identifier (TREE_STRING_POINTER (yylval.ttype));
3271                       break;
3272                     }
3273                   if (ptr->token == VISSPEC)
3274                     {
3275                       switch (ptr->rid)
3276                         {
3277                         case RID_PUBLIC:
3278                           yylval.ttype = access_public_node;
3279                           break;
3280                         case RID_PRIVATE:
3281                           yylval.ttype = access_private_node;
3282                           break;
3283                         case RID_PROTECTED:
3284                           yylval.ttype = access_protected_node;
3285                           break;
3286                         default:
3287                           my_friendly_abort (63);
3288                         }
3289                     }
3290                   else
3291                     yylval.ttype = old_ttype;
3292                 }
3293               else if (ptr->token == EQCOMPARE)
3294                 {
3295                   yylval.code = NE_EXPR;
3296                   token_buffer[0] = '!';
3297                   token_buffer[1] = '=';
3298                   token_buffer[2] = 0;
3299                 }
3300               else if (ptr->token == ASSIGN)
3301                 {
3302                   if (strcmp ("and_eq", token_buffer) == 0)
3303                     {
3304                       yylval.code = BIT_AND_EXPR;
3305                       token_buffer[0] = '&';
3306                     }
3307                   else if (strcmp ("or_eq", token_buffer) == 0)
3308                     {
3309                       yylval.code = BIT_IOR_EXPR;
3310                       token_buffer[0] = '|';
3311                     }
3312                   else if (strcmp ("xor_eq", token_buffer) == 0)
3313                     {
3314                       yylval.code = BIT_XOR_EXPR;
3315                       token_buffer[0] = '^';
3316                     }
3317                   token_buffer[1] = '=';
3318                   token_buffer[2] = 0;
3319                 }
3320               else if (ptr->token == '&')
3321                 {
3322                   yylval.code = BIT_AND_EXPR;
3323                   token_buffer[0] = '&';
3324                   token_buffer[1] = 0;
3325                 }
3326               else if (ptr->token == '|')
3327                 {
3328                   yylval.code = BIT_IOR_EXPR;
3329                   token_buffer[0] = '|';
3330                   token_buffer[1] = 0;
3331                 }
3332               else if (ptr->token == '^')
3333                 {
3334                   yylval.code = BIT_XOR_EXPR;
3335                   token_buffer[0] = '^';
3336                   token_buffer[1] = 0;
3337                 }
3338
3339               value = (int) ptr->token;
3340             }
3341         }
3342
3343         /* If we did not find a keyword, look for an identifier
3344            (or a typename).  */
3345
3346         if (value == IDENTIFIER || value == TYPESPEC)
3347           GNU_xref_ref (current_function_decl, token_buffer);
3348
3349         if (value == IDENTIFIER)
3350           {
3351             register tree tmp = get_identifier (token_buffer);
3352
3353 #if !defined(VMS) && defined(JOINER)
3354             /* Make sure that user does not collide with our internal
3355                naming scheme.  */
3356             if (JOINER == '$'
3357                 && dollar_seen
3358                 && (THIS_NAME_P (tmp)
3359                     || VPTR_NAME_P (tmp)
3360                     || DESTRUCTOR_NAME_P (tmp)
3361                     || VTABLE_NAME_P (tmp)
3362                     || TEMP_NAME_P (tmp)
3363                     || ANON_AGGRNAME_P (tmp)
3364                     || ANON_PARMNAME_P (tmp)))
3365               warning ("identifier name `%s' conflicts with GNU C++ internal naming strategy",
3366                        token_buffer);
3367 #endif
3368
3369             yylval.ttype = tmp;
3370           }
3371         if (value == NEW && ! global_bindings_p ())
3372           {
3373             value = NEW;
3374             goto done;
3375           }
3376       }
3377       break;
3378
3379     case '.':
3380       {
3381         register int c1 = getch ();
3382         token_buffer[0] = c;
3383         token_buffer[1] = c1;
3384         if (c1 == '*')
3385           {
3386             value = DOT_STAR;
3387             token_buffer[2] = 0;
3388             goto done;
3389           }
3390         if (c1 == '.')
3391           {
3392             c1 = getch ();
3393             if (c1 == '.')
3394               {
3395                 token_buffer[2] = c1;
3396                 token_buffer[3] = 0;
3397                 value = ELLIPSIS;
3398                 goto done;
3399               }
3400             error ("parse error at `..'");
3401           }
3402         if (isdigit (c1))
3403           {
3404             put_back (c1);
3405             goto resume_numerical_scan;
3406           }
3407         nextchar = c1;
3408         value = '.';
3409         token_buffer[1] = 0;
3410         goto done;
3411       }
3412     case '0':  case '1':
3413         /* Optimize for most frequent case.  */
3414       {
3415         register int c1 = getch ();
3416         if (! isalnum (c1) && c1 != '.')
3417           {
3418             /* Terminate string.  */
3419             token_buffer[0] = c;
3420             token_buffer[1] = 0;
3421             if (c == '0')
3422               yylval.ttype = integer_zero_node;
3423             else
3424               yylval.ttype = integer_one_node;
3425             nextchar = c1;
3426             value = CONSTANT;
3427             goto done;
3428           }
3429         put_back (c1);
3430       }
3431       /* fall through...  */
3432                           case '2':  case '3':  case '4':
3433     case '5':  case '6':  case '7':  case '8':  case '9':
3434     resume_numerical_scan:
3435       {
3436         register char *p;
3437         int base = 10;
3438         int count = 0;
3439         int largest_digit = 0;
3440         int numdigits = 0;
3441         /* for multi-precision arithmetic,
3442            we actually store only HOST_BITS_PER_CHAR bits in each part.
3443            The number of parts is chosen so as to be sufficient to hold
3444            the enough bits to fit into the two HOST_WIDE_INTs that contain
3445            the integer value (this is always at least as many bits as are
3446            in a target `long long' value, but may be wider).  */
3447 #define TOTAL_PARTS ((HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR) * 2 + 2)
3448         int parts[TOTAL_PARTS];
3449         int overflow = 0;
3450
3451         enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS} floatflag
3452           = NOT_FLOAT;
3453
3454         for (count = 0; count < TOTAL_PARTS; count++)
3455           parts[count] = 0;
3456
3457         p = token_buffer;
3458         *p++ = c;
3459
3460         if (c == '0')
3461           {
3462             *p++ = (c = getch ());
3463             if ((c == 'x') || (c == 'X'))
3464               {
3465                 base = 16;
3466                 *p++ = (c = getch ());
3467               }
3468             /* Leading 0 forces octal unless the 0 is the only digit.  */
3469             else if (c >= '0' && c <= '9')
3470               {
3471                 base = 8;
3472                 numdigits++;
3473               }
3474             else
3475               numdigits++;
3476           }
3477
3478         /* Read all the digits-and-decimal-points.  */
3479
3480         while (c == '.'
3481                || (isalnum (c) && (c != 'l') && (c != 'L')
3482                    && (c != 'u') && (c != 'U')
3483                    && c != 'i' && c != 'I' && c != 'j' && c != 'J'
3484                    && (floatflag == NOT_FLOAT || ((c != 'f') && (c != 'F')))))
3485           {
3486             if (c == '.')
3487               {
3488                 if (base == 16)
3489                   error ("floating constant may not be in radix 16");
3490                 if (floatflag == TOO_MANY_POINTS)
3491                   /* We have already emitted an error.  Don't need another.  */
3492                   ;
3493                 else if (floatflag == AFTER_POINT)
3494                   {
3495                     error ("malformed floating constant");
3496                     floatflag = TOO_MANY_POINTS;
3497                     /* Avoid another error from atof by forcing all characters
3498                        from here on to be ignored.  */
3499                     p[-1] = '\0';
3500                   }
3501                 else
3502                   floatflag = AFTER_POINT;
3503
3504                 base = 10;
3505                 *p++ = c = getch ();
3506                 /* Accept '.' as the start of a floating-point number
3507                    only when it is followed by a digit.
3508                    Otherwise, unread the following non-digit
3509                    and use the '.' as a structural token.  */
3510                 if (p == token_buffer + 2 && !isdigit (c))
3511                   {
3512                     if (c == '.')
3513                       {
3514                         c = getch ();
3515                         if (c == '.')
3516                           {
3517                             *p++ = '.';
3518                             *p = '\0';
3519                             value = ELLIPSIS;
3520                             goto done;
3521                           }
3522                         error ("parse error at `..'");
3523                       }
3524                     nextchar = c;
3525                     token_buffer[1] = '\0';
3526                     value = '.';
3527                     goto done;
3528                   }
3529               }
3530             else
3531               {
3532                 /* It is not a decimal point.
3533                    It should be a digit (perhaps a hex digit).  */
3534
3535                 if (isdigit (c))
3536                   {
3537                     c = c - '0';
3538                   }
3539                 else if (base <= 10)
3540                   {
3541                     if (c == 'e' || c == 'E')
3542                       {
3543                         base = 10;
3544                         floatflag = AFTER_POINT;
3545                         break;   /* start of exponent */
3546                       }
3547                     error ("nondigits in number and not hexadecimal");
3548                     c = 0;
3549                   }
3550                 else if (c >= 'a')
3551                   {
3552                     c = c - 'a' + 10;
3553                   }
3554                 else
3555                   {
3556                     c = c - 'A' + 10;
3557                   }
3558                 if (c >= largest_digit)
3559                   largest_digit = c;
3560                 numdigits++;
3561
3562                 for (count = 0; count < TOTAL_PARTS; count++)
3563                   {
3564                     parts[count] *= base;
3565                     if (count)
3566                       {
3567                         parts[count]
3568                           += (parts[count-1] >> HOST_BITS_PER_CHAR);
3569                         parts[count-1]
3570                           &= (1 << HOST_BITS_PER_CHAR) - 1;
3571                       }
3572                     else
3573                       parts[0] += c;
3574                   }
3575
3576                 /* If the extra highest-order part ever gets anything in it,
3577                    the number is certainly too big.  */
3578                 if (parts[TOTAL_PARTS - 1] != 0)
3579                   overflow = 1;
3580
3581                 if (p >= token_buffer + maxtoken - 3)
3582                   p = extend_token_buffer (p);
3583                 *p++ = (c = getch ());
3584               }
3585           }
3586
3587         if (numdigits == 0)
3588           error ("numeric constant with no digits");
3589
3590         if (largest_digit >= base)
3591           error ("numeric constant contains digits beyond the radix");
3592
3593         /* Remove terminating char from the token buffer and delimit the string */
3594         *--p = 0;
3595
3596         if (floatflag != NOT_FLOAT)
3597           {
3598             tree type = double_type_node;
3599             int exceeds_double = 0;
3600             int imag = 0;
3601             REAL_VALUE_TYPE value;
3602             jmp_buf handler;
3603
3604             /* Read explicit exponent if any, and put it in tokenbuf.  */
3605
3606             if ((c == 'e') || (c == 'E'))
3607               {
3608                 if (p >= token_buffer + maxtoken - 3)
3609                   p = extend_token_buffer (p);
3610                 *p++ = c;
3611                 c = getch ();
3612                 if ((c == '+') || (c == '-'))
3613                   {
3614                     *p++ = c;
3615                     c = getch ();
3616                   }
3617                 if (! isdigit (c))
3618                   error ("floating constant exponent has no digits");
3619                 while (isdigit (c))
3620                   {
3621                     if (p >= token_buffer + maxtoken - 3)
3622                       p = extend_token_buffer (p);
3623                     *p++ = c;
3624                     c = getch ();
3625                   }
3626               }
3627
3628             *p = 0;
3629             errno = 0;
3630
3631             /* Convert string to a double, checking for overflow.  */
3632             if (setjmp (handler))
3633               {
3634                 error ("floating constant out of range");
3635                 value = dconst0;
3636               }
3637             else
3638               {
3639                 int fflag = 0, lflag = 0;
3640                 /* Copy token_buffer now, while it has just the number
3641                    and not the suffixes; once we add `f' or `i',
3642                    REAL_VALUE_ATOF may not work any more.  */
3643                 char *copy = (char *) alloca (p - token_buffer + 1);
3644                 bcopy (token_buffer, copy, p - token_buffer + 1);
3645
3646                 set_float_handler (handler);
3647
3648                 while (1)
3649                   {
3650                     int lose = 0;
3651
3652                     /* Read the suffixes to choose a data type.  */
3653                     switch (c)
3654                       {
3655                       case 'f': case 'F':
3656                         if (fflag)
3657                           error ("more than one `f' in numeric constant");
3658                         fflag = 1;
3659                         break;
3660
3661                       case 'l': case 'L':
3662                         if (lflag)
3663                           error ("more than one `l' in numeric constant");
3664                         lflag = 1;
3665                         break;
3666
3667                       case 'i': case 'I':
3668                         if (imag)
3669                           error ("more than one `i' or `j' in numeric constant");
3670                         else if (pedantic)
3671                           pedwarn ("ANSI C++ forbids imaginary numeric constants");
3672                         imag = 1;
3673                         break;
3674
3675                       default:
3676                         lose = 1;
3677                       }
3678
3679                     if (lose)
3680                       break;
3681
3682                     if (p >= token_buffer + maxtoken - 3)
3683                       p = extend_token_buffer (p);
3684                     *p++ = c;
3685                     *p = 0;
3686                     c = getch ();
3687                   }
3688
3689                 /* The second argument, machine_mode, of REAL_VALUE_ATOF
3690                    tells the desired precision of the binary result
3691                    of decimal-to-binary conversion.  */
3692
3693                 if (fflag)
3694                   {
3695                     if (lflag)
3696                       error ("both `f' and `l' in floating constant");
3697
3698                     type = float_type_node;
3699                     value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
3700                     /* A diagnostic is required here by some ANSI C testsuites.
3701                        This is not pedwarn, become some people don't want
3702                        an error for this.  */
3703                     if (REAL_VALUE_ISINF (value) && pedantic)
3704                       warning ("floating point number exceeds range of `float'");
3705                   }
3706                 else if (lflag)
3707                   {
3708                     type = long_double_type_node;
3709                     value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
3710                     if (REAL_VALUE_ISINF (value) && pedantic)
3711                       warning ("floating point number exceeds range of `long double'");
3712                   }
3713                 else
3714                   {
3715                     value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
3716                     if (REAL_VALUE_ISINF (value) && pedantic)
3717                       warning ("floating point number exceeds range of `double'");
3718                   }
3719
3720                 set_float_handler (NULL_PTR);
3721               }
3722 #ifdef ERANGE
3723             if (errno == ERANGE && pedantic)
3724               {
3725                 /* ERANGE is also reported for underflow,
3726                    so test the value to distinguish overflow from that.  */
3727                 if (REAL_VALUES_LESS (dconst1, value)
3728                     || REAL_VALUES_LESS (value, dconstm1))
3729                   {
3730                     pedwarn ("floating point number exceeds range of `%s'",
3731                              IDENTIFIER_POINTER (TYPE_IDENTIFIER (type)));
3732                     exceeds_double = 1;
3733                   }
3734               }
3735 #endif
3736
3737             /* If the result is not a number, assume it must have been
3738                due to some error message above, so silently convert
3739                it to a zero.  */
3740             if (REAL_VALUE_ISNAN (value))
3741               value = dconst0;
3742
3743             /* Create a node with determined type and value.  */
3744             if (imag)
3745               yylval.ttype = build_complex (NULL_TREE,
3746                                             cp_convert (type, integer_zero_node),
3747                                             build_real (type, value));
3748             else
3749               yylval.ttype = build_real (type, value);
3750           }
3751         else
3752           {
3753             tree type;
3754             HOST_WIDE_INT high, low;
3755             int spec_unsigned = 0;
3756             int spec_long = 0;
3757             int spec_long_long = 0;
3758             int spec_imag = 0;
3759             int bytes, warn;
3760
3761             while (1)
3762               {
3763                 if (c == 'u' || c == 'U')
3764                   {
3765                     if (spec_unsigned)
3766                       error ("two `u's in integer constant");
3767                     spec_unsigned = 1;
3768                   }
3769                 else if (c == 'l' || c == 'L')
3770                   {
3771                     if (spec_long)
3772                       {
3773                         if (spec_long_long)
3774                           error ("three `l's in integer constant");
3775                         else if (pedantic)
3776                           pedwarn ("ANSI C++ forbids long long integer constants");
3777                         spec_long_long = 1;
3778                       }
3779                     spec_long = 1;
3780                   }
3781                 else if (c == 'i' || c == 'j' || c == 'I' || c == 'J')
3782                   {
3783                     if (spec_imag)
3784                       error ("more than one `i' or `j' in numeric constant");
3785                     else if (pedantic)
3786                       pedwarn ("ANSI C++ forbids imaginary numeric constants");
3787                     spec_imag = 1;
3788                   }
3789                 else
3790                   break;
3791                 if (p >= token_buffer + maxtoken - 3)
3792                   p = extend_token_buffer (p);
3793                 *p++ = c;
3794                 c = getch ();
3795               }
3796
3797             /* If the constant is not long long and it won't fit in an
3798                unsigned long, or if the constant is long long and won't fit
3799                in an unsigned long long, then warn that the constant is out
3800                of range.  */
3801
3802             /* ??? This assumes that long long and long integer types are
3803                a multiple of 8 bits.  This better than the original code
3804                though which assumed that long was exactly 32 bits and long
3805                long was exactly 64 bits.  */
3806
3807             if (spec_long_long)
3808               bytes = TYPE_PRECISION (long_long_integer_type_node) / 8;
3809             else
3810               bytes = TYPE_PRECISION (long_integer_type_node) / 8;
3811
3812             warn = overflow;
3813             for (i = bytes; i < TOTAL_PARTS; i++)
3814               if (parts[i])
3815                 warn = 1;
3816             if (warn)
3817               pedwarn ("integer constant out of range");
3818
3819             /* This is simplified by the fact that our constant
3820                is always positive.  */
3821             high = low = 0;
3822
3823             for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; i++)
3824               {
3825                 high |= ((HOST_WIDE_INT) parts[i + (HOST_BITS_PER_WIDE_INT
3826                                                     / HOST_BITS_PER_CHAR)]
3827                          << (i * HOST_BITS_PER_CHAR));
3828                 low |= (HOST_WIDE_INT) parts[i] << (i * HOST_BITS_PER_CHAR);
3829               }
3830             
3831             
3832             yylval.ttype = build_int_2 (low, high);
3833             TREE_TYPE (yylval.ttype) = long_long_unsigned_type_node;
3834
3835             /* Calculate the ANSI type.  */
3836             if (!spec_long && !spec_unsigned
3837                 && int_fits_type_p (yylval.ttype, integer_type_node))
3838               type = integer_type_node;
3839             else if (!spec_long && (base != 10 || spec_unsigned)
3840                      && int_fits_type_p (yylval.ttype, unsigned_type_node))
3841               /* Nondecimal constants try unsigned even in traditional C.  */
3842               type = unsigned_type_node;
3843             else if (!spec_unsigned && !spec_long_long
3844                      && int_fits_type_p (yylval.ttype, long_integer_type_node))
3845               type = long_integer_type_node;
3846             else if (! spec_long_long)
3847               type = long_unsigned_type_node;
3848             else if (! spec_unsigned
3849                      /* Verify value does not overflow into sign bit.  */
3850                      && TREE_INT_CST_HIGH (yylval.ttype) >= 0
3851                      && int_fits_type_p (yylval.ttype,
3852                                          long_long_integer_type_node))
3853               type = long_long_integer_type_node;
3854             else
3855               type = long_long_unsigned_type_node;
3856
3857             if (!int_fits_type_p (yylval.ttype, type) && !warn)
3858               pedwarn ("integer constant out of range");
3859
3860             if (base == 10 && ! spec_unsigned && TREE_UNSIGNED (type))
3861               warning ("decimal integer constant is so large that it is unsigned");
3862
3863             if (spec_imag)
3864               {
3865                 if (TYPE_PRECISION (type)
3866                     <= TYPE_PRECISION (integer_type_node))
3867                   yylval.ttype
3868                     = build_complex (NULL_TREE, integer_zero_node,
3869                                      cp_convert (integer_type_node,
3870                                                  yylval.ttype));
3871                 else
3872                   error ("complex integer constant is too wide for `__complex int'");
3873               }
3874             else
3875               TREE_TYPE (yylval.ttype) = type;
3876           }
3877
3878         put_back (c);
3879         *p = 0;
3880
3881         value = CONSTANT; break;
3882       }
3883
3884     case '\'':
3885     char_constant:
3886       {
3887         register int result = 0;
3888         register int num_chars = 0;
3889         unsigned width = TYPE_PRECISION (char_type_node);
3890         int max_chars;
3891
3892         if (wide_flag)
3893           {
3894             width = WCHAR_TYPE_SIZE;
3895 #ifdef MULTIBYTE_CHARS
3896             max_chars = MB_CUR_MAX;
3897 #else
3898             max_chars = 1;
3899 #endif
3900           }
3901         else
3902           max_chars = TYPE_PRECISION (integer_type_node) / width;
3903
3904         while (1)
3905           {
3906           tryagain:
3907
3908             c = getch ();
3909
3910             if (c == '\'' || c == EOF)
3911               break;
3912
3913             if (c == '\\')
3914               {
3915                 int ignore = 0;
3916                 c = readescape (&ignore);
3917                 if (ignore)
3918                   goto tryagain;
3919                 if (width < HOST_BITS_PER_INT
3920                     && (unsigned) c >= (1 << width))
3921                   warning ("escape sequence out of range for character");
3922 #ifdef MAP_CHARACTER
3923                 if (isprint (c))
3924                   c = MAP_CHARACTER (c);
3925 #endif
3926               }
3927             else if (c == '\n')
3928               {
3929                 if (pedantic)
3930                   pedwarn ("ANSI C++ forbids newline in character constant");
3931                 lineno++;
3932               }
3933 #ifdef MAP_CHARACTER
3934             else
3935               c = MAP_CHARACTER (c);
3936 #endif
3937
3938             num_chars++;
3939             if (num_chars > maxtoken - 4)
3940               extend_token_buffer (token_buffer);
3941
3942             token_buffer[num_chars] = c;
3943
3944             /* Merge character into result; ignore excess chars.  */
3945             if (num_chars < max_chars + 1)
3946               {
3947                 if (width < HOST_BITS_PER_INT)
3948                   result = (result << width) | (c & ((1 << width) - 1));
3949                 else
3950                   result = c;
3951               }
3952           }
3953
3954         token_buffer[num_chars + 1] = '\'';
3955         token_buffer[num_chars + 2] = 0;
3956
3957         if (c != '\'')
3958           error ("malformatted character constant");
3959         else if (num_chars == 0)
3960           error ("empty character constant");
3961         else if (num_chars > max_chars)
3962           {
3963             num_chars = max_chars;
3964             error ("character constant too long");
3965           }
3966         else if (num_chars != 1)
3967           warning ("multi-character character constant");
3968
3969         /* If char type is signed, sign-extend the constant.  */
3970         if (! wide_flag)
3971           {
3972             int num_bits = num_chars * width;
3973             if (num_bits == 0)
3974               /* We already got an error; avoid invalid shift.  */
3975               yylval.ttype = build_int_2 (0, 0);
3976             else if (TREE_UNSIGNED (char_type_node)
3977                      || ((result >> (num_bits - 1)) & 1) == 0)
3978               yylval.ttype
3979                 = build_int_2 (result & ((unsigned HOST_WIDE_INT) ~0
3980                                          >> (HOST_BITS_PER_WIDE_INT - num_bits)),
3981                                0);
3982             else
3983               yylval.ttype
3984                 = build_int_2 (result | ~((unsigned HOST_WIDE_INT) ~0
3985                                           >> (HOST_BITS_PER_WIDE_INT - num_bits)),
3986                                -1);
3987             if (num_chars<=1)
3988               TREE_TYPE (yylval.ttype) = char_type_node;
3989             else
3990               TREE_TYPE (yylval.ttype) = integer_type_node;
3991           }
3992         else
3993           {
3994 #ifdef MULTIBYTE_CHARS
3995             /* Set the initial shift state and convert the next sequence.  */
3996             result = 0;
3997             /* In all locales L'\0' is zero and mbtowc will return zero,
3998                so don't use it.  */
3999             if (num_chars > 1
4000                 || (num_chars == 1 && token_buffer[1] != '\0'))
4001               {
4002                 wchar_t wc;
4003                 (void) mbtowc (NULL, NULL, 0);
4004                 if (mbtowc (& wc, token_buffer + 1, num_chars) == num_chars)
4005                   result = wc;
4006                 else
4007                   warning ("Ignoring invalid multibyte character");
4008               }
4009 #endif
4010             yylval.ttype = build_int_2 (result, 0);
4011             TREE_TYPE (yylval.ttype) = wchar_type_node;
4012           }
4013
4014         value = CONSTANT;
4015         break;
4016       }
4017
4018     case '"':
4019     string_constant:
4020       {
4021         register char *p;
4022
4023         c = getch ();
4024         p = token_buffer + 1;
4025
4026         while (c != '"' && c >= 0)
4027           {
4028             /* ignore_escape_flag is set for reading the filename in #line.  */
4029             if (!ignore_escape_flag && c == '\\')
4030               {
4031                 int ignore = 0;
4032                 c = readescape (&ignore);
4033                 if (ignore)
4034                   goto skipnewline;
4035                 if (!wide_flag
4036                     && TYPE_PRECISION (char_type_node) < HOST_BITS_PER_INT
4037                     && c >= ((unsigned) 1 << TYPE_PRECISION (char_type_node)))
4038                   warning ("escape sequence out of range for character");
4039               }
4040             else if (c == '\n')
4041               {
4042                 if (pedantic)
4043                   pedwarn ("ANSI C++ forbids newline in string constant");
4044                 lineno++;
4045               }
4046
4047             if (p == token_buffer + maxtoken)
4048               p = extend_token_buffer (p);
4049             *p++ = c;
4050
4051           skipnewline:
4052             c = getch ();
4053             if (c == EOF) {
4054                 error ("Unterminated string");
4055                 break;
4056             }
4057           }
4058         *p = 0;
4059
4060         /* We have read the entire constant.
4061            Construct a STRING_CST for the result.  */
4062
4063         if (wide_flag)
4064           {
4065             /* If this is a L"..." wide-string, convert the multibyte string
4066                to a wide character string.  */
4067             char *widep = (char *) alloca ((p - token_buffer) * WCHAR_BYTES);
4068             int len;
4069
4070 #ifdef MULTIBYTE_CHARS
4071             len = mbstowcs ((wchar_t *) widep, token_buffer + 1, p - token_buffer);
4072             if (len < 0 || len >= (p - token_buffer))
4073               {
4074                 warning ("Ignoring invalid multibyte string");
4075                 len = 0;
4076               }
4077             bzero (widep + (len * WCHAR_BYTES), WCHAR_BYTES);
4078 #else
4079             {
4080               char *wp, *cp;
4081
4082               wp = widep + (BYTES_BIG_ENDIAN ? WCHAR_BYTES - 1 : 0);
4083               bzero (widep, (p - token_buffer) * WCHAR_BYTES);
4084               for (cp = token_buffer + 1; cp < p; cp++)
4085                 *wp = *cp, wp += WCHAR_BYTES;
4086               len = p - token_buffer - 1;
4087             }
4088 #endif
4089             if (processing_template_decl)
4090               push_obstacks (&permanent_obstack, &permanent_obstack);
4091             yylval.ttype = build_string ((len + 1) * WCHAR_BYTES, widep);
4092             if (processing_template_decl)
4093               pop_obstacks ();
4094             TREE_TYPE (yylval.ttype) = wchar_array_type_node;
4095           }
4096         else
4097           {
4098             if (processing_template_decl)
4099               push_obstacks (&permanent_obstack, &permanent_obstack);
4100             yylval.ttype = build_string (p - token_buffer, token_buffer + 1);
4101             if (processing_template_decl)
4102               pop_obstacks ();
4103             TREE_TYPE (yylval.ttype) = char_array_type_node;
4104           }
4105
4106         *p++ = '"';
4107         *p = 0;
4108
4109         value = STRING; break;
4110       }
4111
4112     case '+':
4113     case '-':
4114     case '&':
4115     case '|':
4116     case '<':
4117     case '>':
4118     case '*':
4119     case '/':
4120     case '%':
4121     case '^':
4122     case '!':
4123     case '=':
4124       {
4125         register int c1;
4126
4127       combine:
4128
4129         switch (c)
4130           {
4131           case '+':
4132             yylval.code = PLUS_EXPR; break;
4133           case '-':
4134             yylval.code = MINUS_EXPR; break;
4135           case '&':
4136             yylval.code = BIT_AND_EXPR; break;
4137           case '|':
4138             yylval.code = BIT_IOR_EXPR; break;
4139           case '*':
4140             yylval.code = MULT_EXPR; break;
4141           case '/':
4142             yylval.code = TRUNC_DIV_EXPR; break;
4143           case '%':
4144             yylval.code = TRUNC_MOD_EXPR; break;
4145           case '^':
4146             yylval.code = BIT_XOR_EXPR; break;
4147           case LSHIFT:
4148             yylval.code = LSHIFT_EXPR; break;
4149           case RSHIFT:
4150             yylval.code = RSHIFT_EXPR; break;
4151           case '<':
4152             yylval.code = LT_EXPR; break;
4153           case '>':
4154             yylval.code = GT_EXPR; break;
4155           }
4156
4157         token_buffer[1] = c1 = getch ();
4158         token_buffer[2] = 0;
4159
4160         if (c1 == '=')
4161           {
4162             switch (c)
4163               {
4164               case '<':
4165                 value = ARITHCOMPARE; yylval.code = LE_EXPR; goto done;
4166               case '>':
4167                 value = ARITHCOMPARE; yylval.code = GE_EXPR; goto done;
4168               case '!':
4169                 value = EQCOMPARE; yylval.code = NE_EXPR; goto done;
4170               case '=':
4171                 value = EQCOMPARE; yylval.code = EQ_EXPR; goto done;
4172               }
4173             value = ASSIGN; goto done;
4174           }
4175         else if (c == c1)
4176           switch (c)
4177             {
4178             case '+':
4179               value = PLUSPLUS; goto done;
4180             case '-':
4181               value = MINUSMINUS; goto done;
4182             case '&':
4183               value = ANDAND; goto done;
4184             case '|':
4185               value = OROR; goto done;
4186             case '<':
4187               c = LSHIFT;
4188               goto combine;
4189             case '>':
4190               c = RSHIFT;
4191               goto combine;
4192             }
4193         else if ((c == '-') && (c1 == '>'))
4194           {
4195             nextchar = getch ();
4196             if (nextchar == '*')
4197               {
4198                 nextchar = -1;
4199                 value = POINTSAT_STAR;
4200               }
4201             else
4202               value = POINTSAT;
4203             goto done;
4204           }
4205         else if (c1 == '?' && (c == '<' || c == '>'))
4206           {
4207             token_buffer[3] = 0;
4208
4209             c1 = getch ();
4210             yylval.code = (c == '<' ? MIN_EXPR : MAX_EXPR);
4211             if (c1 == '=')
4212               {
4213                 /* <?= or >?= expression.  */
4214                 token_buffer[2] = c1;
4215                 value = ASSIGN;
4216               }
4217             else
4218               {
4219                 value = MIN_MAX;
4220                 nextchar = c1;
4221               }
4222             if (pedantic)
4223               pedwarn ("use of `operator %s' is not standard C++",
4224                        token_buffer);
4225             goto done;
4226           }
4227         /* digraphs */
4228         else if (c == '<' && c1 == '%')
4229           { value = '{'; goto done; }
4230         else if (c == '<' && c1 == ':')
4231           { value = '['; goto done; }
4232         else if (c == '%' && c1 == '>')
4233           { value = '}'; goto done; }
4234         else if (c == '%' && c1 == ':')
4235           { value = '#'; goto done; }
4236
4237         nextchar = c1;
4238         token_buffer[1] = 0;
4239
4240         value = c;
4241         goto done;
4242       }
4243
4244     case ':':
4245       c = getch ();
4246       if (c == ':')
4247         {
4248           token_buffer[1] = ':';
4249           token_buffer[2] = '\0';
4250           value = SCOPE;
4251           yylval.itype = 1;
4252         }
4253       else if (c == '>')
4254         {
4255           value = ']';
4256           goto done;
4257         }
4258       else
4259         {
4260           nextchar = c;
4261           value = ':';
4262         }
4263       break;
4264
4265     case 0:
4266       /* Don't make yyparse think this is eof.  */
4267       value = 1;
4268       break;
4269
4270     case '(':
4271       /* try, weakly, to handle casts to pointers to functions.  */
4272       nextchar = skip_white_space (getch ());
4273       if (nextchar == '*')
4274         {
4275           int next_c = skip_white_space (getch ());
4276           if (next_c == ')')
4277             {
4278               nextchar = -1;
4279               yylval.ttype = build1 (INDIRECT_REF, 0, 0);
4280               value = PAREN_STAR_PAREN;
4281             }
4282           else
4283             {
4284               put_back (next_c);
4285               value = c;
4286             }
4287         }
4288       else if (nextchar == ')')
4289         {
4290           nextchar = -1;
4291           yylval.ttype = NULL_TREE;
4292           value = LEFT_RIGHT;
4293         }
4294       else value = c;
4295       break;
4296
4297     default:
4298       value = c;
4299     }
4300
4301 done:
4302 /*  yylloc.last_line = lineno; */
4303 #ifdef GATHER_STATISTICS
4304 #ifdef REDUCE_LENGTH
4305   token_count[value] += 1;
4306 #endif
4307 #endif
4308
4309   return value;
4310 }
4311
4312 int
4313 is_rid (t)
4314      tree t;
4315 {
4316   return !!is_reserved_word (IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t));
4317 }
4318
4319 #ifdef GATHER_STATISTICS
4320 /* The original for tree_node_kind is in the toplevel tree.c; changes there
4321    need to be brought into here, unless this were actually put into a header
4322    instead.  */
4323 /* Statistics-gathering stuff.  */
4324 typedef enum
4325 {
4326   d_kind,
4327   t_kind,
4328   b_kind,
4329   s_kind,
4330   r_kind,
4331   e_kind,
4332   c_kind,
4333   id_kind,
4334   op_id_kind,
4335   perm_list_kind,
4336   temp_list_kind,
4337   vec_kind,
4338   x_kind,
4339   lang_decl,
4340   lang_type,
4341   all_kinds
4342 } tree_node_kind;
4343
4344 extern int tree_node_counts[];
4345 extern int tree_node_sizes[];
4346 #endif
4347
4348 /* Place to save freed lang_decls which were allocated on the
4349    permanent_obstack.  @@ Not currently used.  */
4350 tree free_lang_decl_chain;
4351
4352 tree
4353 build_lang_decl (code, name, type)
4354      enum tree_code code;
4355      tree name;
4356      tree type;
4357 {
4358   register tree t = build_decl (code, name, type);
4359   struct obstack *obstack = current_obstack;
4360   register int i = sizeof (struct lang_decl) / sizeof (int);
4361   register int *pi;
4362
4363   if (! TREE_PERMANENT (t))
4364     obstack = saveable_obstack;
4365   else
4366     /* Could be that saveable is permanent and current is not.  */
4367     obstack = &permanent_obstack;
4368
4369   if (free_lang_decl_chain && obstack == &permanent_obstack)
4370     {
4371       pi = (int *)free_lang_decl_chain;
4372       free_lang_decl_chain = TREE_CHAIN (free_lang_decl_chain);
4373     }
4374   else
4375     pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl));
4376
4377   while (i > 0)
4378     pi[--i] = 0;
4379
4380   DECL_LANG_SPECIFIC (t) = (struct lang_decl *) pi;
4381   LANG_DECL_PERMANENT ((struct lang_decl *) pi)
4382     = obstack == &permanent_obstack;
4383   my_friendly_assert (LANG_DECL_PERMANENT ((struct lang_decl *) pi)
4384           == TREE_PERMANENT  (t), 234);
4385   DECL_MAIN_VARIANT (t) = t;
4386   if (current_lang_name == lang_name_cplusplus)
4387     DECL_LANGUAGE (t) = lang_cplusplus;
4388   else if (current_lang_name == lang_name_c)
4389     DECL_LANGUAGE (t) = lang_c;
4390   else if (current_lang_name == lang_name_java)
4391     DECL_LANGUAGE (t) = lang_java;
4392   else my_friendly_abort (64);
4393
4394   SET_DECL_NAMESPACE (t, current_namespace);
4395
4396 #if 0 /* not yet, should get fixed properly later */
4397   if (code == TYPE_DECL)
4398     {
4399       tree id;
4400       id = get_identifier (build_overload_name (type, 1, 1));
4401       DECL_ASSEMBLER_NAME (t) = id;
4402     }
4403
4404 #endif
4405 #ifdef GATHER_STATISTICS
4406   tree_node_counts[(int)lang_decl] += 1;
4407   tree_node_sizes[(int)lang_decl] += sizeof (struct lang_decl);
4408 #endif
4409
4410   return t;
4411 }
4412
4413 tree
4414 build_lang_field_decl (code, name, type)
4415      enum tree_code code;
4416      tree name;
4417      tree type;
4418 {
4419   extern struct obstack *current_obstack, *saveable_obstack;
4420   register tree t = build_decl (code, name, type);
4421   struct obstack *obstack = current_obstack;
4422   register int i = sizeof (struct lang_decl_flags) / sizeof (int);
4423   register int *pi;
4424 #if 0 /* not yet, should get fixed properly later */
4425
4426   if (code == TYPE_DECL)
4427     {
4428       tree id;
4429       id = get_identifier (build_overload_name (type, 1, 1));
4430       DECL_ASSEMBLER_NAME (t) = id;
4431     }
4432 #endif
4433
4434   if (! TREE_PERMANENT (t))
4435     obstack = saveable_obstack;
4436   else
4437     my_friendly_assert (obstack == &permanent_obstack, 235);
4438
4439   pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl_flags));
4440   while (i > 0)
4441     pi[--i] = 0;
4442
4443   DECL_LANG_SPECIFIC (t) = (struct lang_decl *) pi;
4444   return t;
4445 }
4446
4447 void
4448 copy_lang_decl (node)
4449      tree node;
4450 {
4451   int size;
4452   int *pi;
4453
4454   if (! DECL_LANG_SPECIFIC (node))
4455     return;
4456
4457   if (TREE_CODE (node) == FIELD_DECL)
4458     size = sizeof (struct lang_decl_flags);
4459   else
4460     size = sizeof (struct lang_decl);
4461   pi = (int *)obstack_alloc (&permanent_obstack, size);
4462   bcopy ((char *)DECL_LANG_SPECIFIC (node), (char *)pi, size);
4463   DECL_LANG_SPECIFIC (node) = (struct lang_decl *)pi;
4464 }
4465
4466 tree
4467 make_lang_type (code)
4468      enum tree_code code;
4469 {
4470   extern struct obstack *current_obstack, *saveable_obstack;
4471   register tree t = make_node (code);
4472   struct obstack *obstack = current_obstack;
4473   register int i = sizeof (struct lang_type) / sizeof (int);
4474   register int *pi;
4475
4476   /* Set up some flags that give proper default behavior.  */
4477   IS_AGGR_TYPE (t) = 1;
4478
4479   if (! TREE_PERMANENT (t))
4480     obstack = saveable_obstack;
4481   else
4482     my_friendly_assert (obstack == &permanent_obstack, 236);
4483
4484   pi = (int *) obstack_alloc (obstack, sizeof (struct lang_type));
4485   while (i > 0)
4486     pi[--i] = 0;
4487
4488   TYPE_LANG_SPECIFIC (t) = (struct lang_type *) pi;
4489   CLASSTYPE_AS_LIST (t) = build_expr_list (NULL_TREE, t);
4490   SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown);
4491   CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
4492   TYPE_BINFO (t) = make_binfo (integer_zero_node, t, NULL_TREE, NULL_TREE,
4493                                NULL_TREE);
4494   CLASSTYPE_BINFO_AS_LIST (t) = build_tree_list (NULL_TREE, TYPE_BINFO (t));
4495
4496   /* Make sure this is laid out, for ease of use later.
4497      In the presence of parse errors, the normal was of assuring
4498      this might not ever get executed, so we lay it out *immediately*.  */
4499   build_pointer_type (t);
4500
4501 #ifdef GATHER_STATISTICS
4502   tree_node_counts[(int)lang_type] += 1;
4503   tree_node_sizes[(int)lang_type] += sizeof (struct lang_type);
4504 #endif
4505
4506   return t;
4507 }
4508
4509 void
4510 dump_time_statistics ()
4511 {
4512   register tree prev = 0, decl, next;
4513   int this_time = my_get_run_time ();
4514   TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time))
4515     += this_time - body_time;
4516
4517   fprintf (stderr, "\n******\n");
4518   print_time ("header files (total)", header_time);
4519   print_time ("main file (total)", this_time - body_time);
4520   fprintf (stderr, "ratio = %g : 1\n",
4521            (double)header_time / (double)(this_time - body_time));
4522   fprintf (stderr, "\n******\n");
4523
4524   for (decl = filename_times; decl; decl = next)
4525     {
4526       next = IDENTIFIER_GLOBAL_VALUE (decl);
4527       IDENTIFIER_GLOBAL_VALUE (decl) = prev;
4528       prev = decl;
4529     }
4530
4531   for (decl = prev; decl; decl = IDENTIFIER_GLOBAL_VALUE (decl))
4532     print_time (IDENTIFIER_POINTER (decl),
4533                 TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (decl)));
4534 }
4535
4536 void
4537 compiler_error (s, v, v2)
4538      char *s;
4539      HOST_WIDE_INT v, v2;                       /* @@also used as pointer */
4540 {
4541   char buf[1024];
4542   sprintf (buf, s, v, v2);
4543   error_with_file_and_line (input_filename, lineno, "%s (compiler error)", buf);
4544 }
4545 \f
4546 void
4547 yyerror (string)
4548      char *string;
4549 {
4550   extern int end_of_file;
4551   char buf[200];
4552
4553   strcpy (buf, string);
4554
4555   /* We can't print string and character constants well
4556      because the token_buffer contains the result of processing escapes.  */
4557   if (end_of_file)
4558     strcat (buf, input_redirected ()
4559             ? " at end of saved text"
4560             : " at end of input");
4561   else if (token_buffer[0] == 0)
4562     strcat (buf, " at null character");
4563   else if (token_buffer[0] == '"')
4564     strcat (buf, " before string constant");
4565   else if (token_buffer[0] == '\'')
4566     strcat (buf, " before character constant");
4567   else if (token_buffer[0] < 040 || (unsigned char) token_buffer[0] >= 0177)
4568     sprintf (buf + strlen (buf), " before character 0%o",
4569              (unsigned char) token_buffer[0]);
4570   else
4571     strcat (buf, " before `%s'");
4572
4573   error (buf, token_buffer);
4574 }
4575 \f
4576 static int
4577 handle_cp_pragma (pname)
4578      char *pname;
4579 {
4580   register int token;
4581
4582   if (! strcmp (pname, "vtable"))
4583     {
4584       extern tree pending_vtables;
4585
4586       /* More follows: it must be a string constant (class name).  */
4587       token = real_yylex ();
4588       if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
4589         {
4590           error ("invalid #pragma vtable");
4591           return -1;
4592         }
4593
4594       if (write_virtuals != 2)
4595         {
4596           warning ("use `+e2' option to enable #pragma vtable");
4597           return -1;
4598         }
4599       pending_vtables
4600         = perm_tree_cons (NULL_TREE,
4601                           get_identifier (TREE_STRING_POINTER (yylval.ttype)),
4602                           pending_vtables);
4603       token = real_yylex ();
4604       if (token != END_OF_LINE)
4605         warning ("trailing characters ignored");
4606       return 1;
4607     }
4608   else if (! strcmp (pname, "unit"))
4609     {
4610       /* More follows: it must be a string constant (unit name).  */
4611       token = real_yylex ();
4612       if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
4613         {
4614           error ("invalid #pragma unit");
4615           return -1;
4616         }
4617       token = real_yylex ();
4618       if (token != END_OF_LINE)
4619         warning ("trailing characters ignored");
4620       return 1;
4621     }
4622   else if (! strcmp (pname, "interface"))
4623     {
4624       tree fileinfo = IDENTIFIER_CLASS_VALUE (get_time_identifier (input_filename));
4625       char *main_filename = input_filename;
4626
4627       main_filename = file_name_nondirectory (main_filename);
4628
4629       token = real_yylex ();
4630       
4631       if (token != END_OF_LINE)
4632         {
4633           if (token != STRING
4634               || TREE_CODE (yylval.ttype) != STRING_CST)
4635             {
4636               error ("invalid `#pragma interface'");
4637               return -1;
4638             }
4639           main_filename = TREE_STRING_POINTER (yylval.ttype);
4640           token = real_yylex ();
4641         }
4642
4643       if (token != END_OF_LINE)
4644         warning ("garbage after `#pragma interface' ignored");
4645
4646 #ifndef NO_LINKAGE_HEURISTICS
4647       write_virtuals = 3;
4648
4649       if (impl_file_chain == 0)
4650         {
4651           /* If this is zero at this point, then we are
4652              auto-implementing.  */
4653           if (main_input_filename == 0)
4654             main_input_filename = input_filename;
4655
4656 #ifdef AUTO_IMPLEMENT
4657           filename = file_name_nondirectory (main_input_filename);
4658           fi = get_time_identifier (filename);
4659           fi = IDENTIFIER_CLASS_VALUE (fi);
4660           TREE_INT_CST_LOW (fi) = 0;
4661           TREE_INT_CST_HIGH (fi) = 1;
4662           /* Get default.  */
4663           impl_file_chain = (struct impl_files *)permalloc (sizeof (struct impl_files));
4664           impl_file_chain->filename = filename;
4665           impl_file_chain->next = 0;
4666 #endif
4667         }
4668
4669       interface_only = interface_strcmp (main_filename);
4670       interface_unknown = 0;
4671       TREE_INT_CST_LOW (fileinfo) = interface_only;
4672       TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
4673 #endif /* NO_LINKAGE_HEURISTICS */
4674
4675       return 1;
4676     }
4677   else if (! strcmp (pname, "implementation"))
4678     {
4679       tree fileinfo = IDENTIFIER_CLASS_VALUE (get_time_identifier (input_filename));
4680       char *main_filename = main_input_filename ? main_input_filename : input_filename;
4681
4682       main_filename = file_name_nondirectory (main_filename);
4683       token = real_yylex ();
4684       if (token != END_OF_LINE)
4685         {
4686           if (token != STRING
4687               || TREE_CODE (yylval.ttype) != STRING_CST)
4688             {
4689               error ("invalid `#pragma implementation'");
4690               return -1;
4691             }
4692           main_filename = TREE_STRING_POINTER (yylval.ttype);
4693           token = real_yylex ();
4694         }
4695
4696       if (token != END_OF_LINE)
4697         warning ("garbage after `#pragma implementation' ignored");
4698
4699 #ifndef NO_LINKAGE_HEURISTICS
4700       if (write_virtuals == 3)
4701         {
4702           struct impl_files *ifiles = impl_file_chain;
4703           while (ifiles)
4704             {
4705               if (! strcmp (ifiles->filename, main_filename))
4706                 break;
4707               ifiles = ifiles->next;
4708             }
4709           if (ifiles == 0)
4710             {
4711               ifiles = (struct impl_files*) permalloc (sizeof (struct impl_files));
4712               ifiles->filename = main_filename;
4713               ifiles->next = impl_file_chain;
4714               impl_file_chain = ifiles;
4715             }
4716         }
4717       else if ((main_input_filename != 0
4718                 && ! strcmp (main_input_filename, input_filename))
4719                || ! strcmp (input_filename, main_filename))
4720         {
4721           write_virtuals = 3;
4722           if (impl_file_chain == 0)
4723             {
4724               impl_file_chain = (struct impl_files*) permalloc (sizeof (struct impl_files));
4725               impl_file_chain->filename = main_filename;
4726               impl_file_chain->next = 0;
4727             }
4728         }
4729       else
4730         error ("`#pragma implementation' can only appear at top-level");
4731       interface_only = 0;
4732 #if 1
4733       /* We make this non-zero so that we infer decl linkage
4734          in the impl file only for variables first declared
4735          in the interface file.  */
4736       interface_unknown = 1;
4737 #else
4738       /* We make this zero so that templates in the impl
4739          file will be emitted properly.  */
4740       interface_unknown = 0;
4741 #endif
4742       TREE_INT_CST_LOW (fileinfo) = interface_only;
4743       TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
4744 #endif /* NO_LINKAGE_HEURISTICS */
4745
4746       return 1;
4747     }
4748
4749   return 0;
4750 }
4751 \f
4752 #ifdef HANDLE_SYSV_PRAGMA
4753
4754 /* Handle a #pragma directive.  INPUT is the current input stream,
4755    and C is a character to reread.  Processes the entire input line
4756    and returns a character for the caller to reread: either \n or EOF.  */
4757
4758 /* This function has to be in this file, in order to get at
4759    the token types.  */
4760
4761 static int
4762 handle_sysv_pragma (finput, token)
4763      FILE *finput;
4764      register int token;
4765 {
4766   for (;;)
4767     {
4768       switch (token)
4769         {
4770         case IDENTIFIER:
4771         case TYPENAME:
4772         case STRING:
4773         case CONSTANT:
4774           handle_pragma_token ("ignored", yylval.ttype);
4775           break;
4776         case '(':
4777           handle_pragma_token ("(", NULL_TREE);
4778           break;
4779         case ')':
4780           handle_pragma_token (")", NULL_TREE);
4781           break;
4782         case ',':
4783           handle_pragma_token (",", NULL_TREE);
4784           break;
4785         case '=':
4786           handle_pragma_token ("=", NULL_TREE);
4787           break;
4788         case LEFT_RIGHT:
4789           handle_pragma_token ("(", NULL_TREE);
4790           handle_pragma_token (")", NULL_TREE);
4791           break;
4792         case END_OF_LINE:
4793         default:
4794           handle_pragma_token (NULL_PTR, NULL_TREE);
4795           return 1;
4796         }
4797       token = real_yylex ();
4798     }
4799 }
4800 #endif /* HANDLE_SYSV_PRAGMA */