OSDN Git Service

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