|
|
1.1 root 1: /* Separate lexical analyzer for GNU C++.
2: Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
3: Hacked by Michael Tiemann ([email protected])
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
20:
21:
22: /* This file is the lexical analyzer for GNU C++. */
23:
24: #include <sys/types.h>
25: #include <stdio.h>
26: #include <errno.h>
27: #include <setjmp.h>
28: #include <string.h>
29: #include "config.h"
30: #include "input.h"
31: #include "tree.h"
32: #include "cp-lex.h"
33: #include "cp-parse.h"
34: #include "cp-tree.h"
35: #include "flags.h"
36: #include "obstack.h"
37: #include <assert.h>
38: extern int errno; /* needed for VAX. */
39: extern jmp_buf toplevel;
40:
41: #define obstack_chunk_alloc xmalloc
42: #define obstack_chunk_free free
43:
44: extern int xmalloc ();
45: extern void free ();
46:
47: extern struct obstack *expression_obstack, permanent_obstack;
48: extern struct obstack *current_obstack, *saveable_obstack;
49:
50: extern double atof ();
51:
52: extern char *get_directive_line (); /* In c-common.c */
53:
54: /* Given a file name X, return the nondirectory portion.
55: Keep in mind that X can be computed more than once. */
56: #ifndef FILE_NAME_NONDIRECTORY
57: #define FILE_NAME_NONDIRECTORY(X) \
58: (strrchr (X, '/') != 0 ? strrchr (X, '/') + 1 : X)
59: #endif
60:
61: /* If you don't have strrchr, but instead have rindex,
62: add your machine to this list, and send mail to
63: [email protected]. */
64: #if defined(sequent) || defined(convex)
65: #define strrchr rindex
66: #endif
67: extern char *strrchr ();
68: void extract_interface_info ();
69:
70: /* This obstack is needed to hold text. It is not safe to use
71: TOKEN_BUFFER because `check_newline' calls `yylex'. */
72: static struct obstack inline_text_obstack;
73: static char *inline_text_firstobj;
74:
75: int end_of_file;
76:
77: extern int first_token;
78: extern struct obstack token_obstack;
79:
80: /* ??? Don't really know where this goes yet. */
81: #if 1
82: #include "cp-input.c"
83: #else
84: extern void put_back (/* int */);
85: extern int input_redirected ();
86: extern void feed_input (/* char *, int, struct obstack * */);
87: #endif
88:
89: /* Holds translations from TREE_CODEs to operator name strings,
90: i.e., opname_tab[PLUS_EXPR] == "+". */
91: char **opname_tab;
92: char **assignop_tab;
93:
94: #define YYEMPTY -2
95: extern int yychar; /* the lookahead symbol */
96: extern YYSTYPE yylval; /* the semantic value of the */
97: /* lookahead symbol */
98:
99: #if 0
100: YYLTYPE yylloc; /* location data for the lookahead */
101: /* symbol */
102: #endif
103:
104:
105: /* the declaration found for the last IDENTIFIER token read in.
106: yylex must look this up to detect typedefs, which get token type TYPENAME,
107: so it is left around in case the identifier is not a typedef but is
108: used in a context which makes it a reference to a variable. */
109: extern tree lastiddecl;
110:
111: /* C++ extensions */
112: extern tree ridpointers[]; /* need this up here */
113:
114: /* We may keep statistics about how long which files took to compile. */
115: static int header_time, body_time;
116: static tree get_time_identifier ();
117: static tree filename_times;
118: static tree this_filename_time;
119:
120: /* For implementing #pragma unit. */
121: tree current_unit_name;
122: tree current_unit_language;
123:
124: /* Array for holding counts of the numbers of tokens seen. */
125: extern int *token_count;
126:
127: /* Textual definition used for default functions. */
128: static char default_def[] = "{}";
129:
130: /* Return something to represent absolute declarators containing a *.
131: TARGET is the absolute declarator that the * contains.
132: TYPE_QUALS is a list of modifiers such as const or volatile
133: to apply to the pointer type, represented as identifiers.
134:
135: We return an INDIRECT_REF whose "contents" are TARGET
136: and whose type is the modifier list. */
137:
138: tree
139: make_pointer_declarator (type_quals, target)
140: tree type_quals, target;
141: {
142: if (target && TREE_CODE (target) == IDENTIFIER_NODE
143: && ANON_AGGRNAME_P (target))
144: error ("type name expected before `*'");
145: target = build_parse_node (INDIRECT_REF, target);
146: TREE_TYPE (target) = type_quals;
147: return target;
148: }
149:
150: /* Return something to represent absolute declarators containing a &.
151: TARGET is the absolute declarator that the & contains.
152: TYPE_QUALS is a list of modifiers such as const or volatile
153: to apply to the reference type, represented as identifiers.
154:
155: We return an ADDR_EXPR whose "contents" are TARGET
156: and whose type is the modifier list. */
157:
158: tree
159: make_reference_declarator (type_quals, target)
160: tree type_quals, target;
161: {
162: if (target)
163: {
164: if (TREE_CODE (target) == ADDR_EXPR)
165: {
166: error ("cannot declare references to references");
167: return target;
168: }
169: if (TREE_CODE (target) == INDIRECT_REF)
170: {
171: error ("cannot declare pointers to references");
172: return target;
173: }
174: if (TREE_CODE (target) == IDENTIFIER_NODE && ANON_AGGRNAME_P (target))
175: error ("type name expected before `&'");
176: }
177: target = build_parse_node (ADDR_EXPR, target);
178: TREE_TYPE (target) = type_quals;
179: return target;
180: }
181:
182: /* Build names and nodes for overloaded operators. */
183:
184: tree ansi_opname[LAST_CPLUS_TREE_CODE];
185: tree ansi_assopname[LAST_CPLUS_TREE_CODE];
186:
187: char *
188: operator_name_string (name)
189: tree name;
190: {
191: char *opname = IDENTIFIER_POINTER (name) + 2;
192: tree *opname_table;
193: int i, assign;
194:
195: /* Works for builtin and user defined types. */
196: if (IDENTIFIER_GLOBAL_VALUE (name)
197: && TREE_CODE (IDENTIFIER_GLOBAL_VALUE (name)) == TYPE_DECL)
198: return IDENTIFIER_POINTER (name);
199:
200: if (opname[0] == 'a' && opname[2] != '\0')
201: {
202: opname += 1;
203: assign = 1;
204: opname_table = ansi_assopname;
205: }
206: else
207: {
208: assign = 0;
209: opname_table = ansi_opname;
210: }
211:
212: for (i = 0; i < (int) LAST_CPLUS_TREE_CODE; i++)
213: {
214: if (opname[0] == IDENTIFIER_POINTER (opname_table[i])[2+assign]
215: && opname[1] == IDENTIFIER_POINTER (opname_table[i])[3+assign])
216: break;
217: }
218:
219: if (i == LAST_CPLUS_TREE_CODE)
220: return "<invalid operator>";
221:
222: if (assign)
223: return assignop_tab[i];
224: else
225: return opname_tab[i];
226: }
227:
228: int interface_only; /* whether or not current file is only for
229: interface definitions. */
230: int interface_unknown; /* whether or not we know this class
231: to behave according to #pragma interface. */
232:
233: /* lexical analyzer */
234:
235: static int maxtoken; /* Current nominal length of token buffer. */
236: char *token_buffer; /* Pointer to token buffer.
237: Actual allocated length is maxtoken + 2. */
238: static int max_wide; /* Current nominal length of wide_buffer. */
239: static int *wide_buffer; /* Pointer to wide-string buffer.
240: Actual allocated length is max_wide + 1. */
241:
242: #define NORID RID_UNUSED
243:
244: #include "cp-hash.h"
245:
246: int check_newline ();
247:
248: static int skip_white_space ();
249:
250: static tree
251: get_time_identifier (name)
252: char *name;
253: {
254: tree time_identifier;
255: int len = strlen (name);
256: char *buf = (char *)alloca (len + 6);
257: strcpy (buf, "file ");
258: bcopy (name, buf+5, len);
259: buf[len+5] = '\0';
260: time_identifier = get_identifier (buf);
261: if (IDENTIFIER_LOCAL_VALUE (time_identifier) == NULL_TREE)
262: {
263: push_obstacks_nochange ();
264: end_temporary_allocation ();
265: IDENTIFIER_LOCAL_VALUE (time_identifier) = build_int_2 (0, 0);
266: IDENTIFIER_CLASS_VALUE (time_identifier) = build_int_2 (0, 1);
267: IDENTIFIER_GLOBAL_VALUE (time_identifier) = filename_times;
268: filename_times = time_identifier;
269: pop_obstacks ();
270: }
271: return time_identifier;
272: }
273:
274: #ifdef __GNUC__
275: __inline
276: #endif
277: static int
278: my_get_run_time ()
279: {
280: int old_quiet_flag = quiet_flag;
281: int this_time;
282: quiet_flag = 0;
283: this_time = get_run_time ();
284: quiet_flag = old_quiet_flag;
285: return this_time;
286: }
287:
288: /* Table indexed by tree code giving a string containing a character
289: classifying the tree code. Possibilities are
290: t, d, s, c, r, <, 1 and 2. See cp-tree.def for details. */
291:
292: #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
293:
294: char *cplus_tree_code_type[] = {
295: "x",
296: #include "cp-tree.def"
297: };
298: #undef DEFTREECODE
299:
300: /* Table indexed by tree code giving number of expression
301: operands beyond the fixed part of the node structure.
302: Not used for types or decls. */
303:
304: #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
305:
306: int cplus_tree_code_length[] = {
307: 0,
308: #include "cp-tree.def"
309: };
310: #undef DEFTREECODE
311:
312: /* Names of tree components.
313: Used for printing out the tree and error messages. */
314: #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
315:
316: char *cplus_tree_code_name[] = {
317: "@@dummy",
318: #include "cp-tree.def"
319: };
320: #undef DEFTREECODE
321:
322: /* toplev.c needs to call these. */
323:
324: void
325: lang_init ()
326: {
327: /* the beginning of the file is a new line; check for # */
328: /* With luck, we discover the real source file's name from that
329: and put it in input_filename. */
330: put_back (check_newline ());
331:
332: if (flag_cadillac)
333: cadillac_start ();
334: if (flag_gnu_xref) GNU_xref_begin (input_filename);
335: }
336:
337: void
338: lang_finish ()
339: {
340: extern int errorcount, sorrycount;
341: if (flag_gnu_xref) GNU_xref_end (errorcount+sorrycount);
342: }
343:
344: void
345: init_filename_times ()
346: {
347: this_filename_time = get_time_identifier ("<top level>");
348: if (flag_detailed_statistics)
349: {
350: header_time = 0;
351: body_time = my_get_run_time ();
352: TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time)) = body_time;
353: }
354: }
355:
356: /* Change by Bryan Boreham, Kewill, Thu Jul 27 09:46:05 1989.
357: Stuck this hack in to get the files open correctly; this is called
358: in place of init_lex if we are an unexec'd binary. */
359: void
360: reinit_lang_specific ()
361: {
362: init_filename_times ();
363: reinit_search_statistics ();
364: }
365:
366: void
367: init_lex ()
368: {
369: extern int *init_parse ();
370: extern char *(*decl_printable_name) ();
371: extern char *lang_printable_name ();
372:
373: int i;
374:
375: /* Initialize the lookahead machinery. */
376: init_spew ();
377:
378: /* Make identifier nodes long enough for the language-specific slots. */
379: set_identifier_size (sizeof (struct lang_identifier));
380: decl_printable_name = lang_printable_name;
381:
382: init_cplus_expand ();
383:
384: tree_code_type
385: = (char **) realloc (tree_code_type,
386: sizeof (char *) * LAST_CPLUS_TREE_CODE);
387: tree_code_length
388: = (int *) realloc (tree_code_length,
389: sizeof (int) * LAST_CPLUS_TREE_CODE);
390: tree_code_name
391: = (char **) realloc (tree_code_name,
392: sizeof (char *) * LAST_CPLUS_TREE_CODE);
393: bcopy (cplus_tree_code_type,
394: tree_code_type + (int) LAST_AND_UNUSED_TREE_CODE,
395: (LAST_CPLUS_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE) * sizeof (char *));
396: bcopy (cplus_tree_code_length,
397: tree_code_length + (int) LAST_AND_UNUSED_TREE_CODE,
398: (LAST_CPLUS_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE) * sizeof (int));
399: bcopy (cplus_tree_code_name,
400: tree_code_name + (int) LAST_AND_UNUSED_TREE_CODE,
401: (LAST_CPLUS_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE) * sizeof (char *));
402:
403: opname_tab = (char **)oballoc ((int)LAST_CPLUS_TREE_CODE * sizeof (char *));
404: bzero (opname_tab, (int)LAST_CPLUS_TREE_CODE * sizeof (char *));
405: assignop_tab = (char **)oballoc ((int)LAST_CPLUS_TREE_CODE * sizeof (char *));
406: bzero (assignop_tab, (int)LAST_CPLUS_TREE_CODE * sizeof (char *));
407:
408: ansi_opname[0] = get_identifier ("<invalid operator>");
1.1.1.2 ! root 409: for (i = 0; i < (int) LAST_CPLUS_TREE_CODE; i++)
1.1 root 410: {
411: ansi_opname[i] = ansi_opname[0];
412: ansi_assopname[i] = ansi_opname[0];
413: }
414:
1.1.1.2 ! root 415: ansi_opname[(int) MULT_EXPR] = get_identifier ("__ml");
! 416: IDENTIFIER_OPNAME_P (ansi_opname[(int) MULT_EXPR]) = 1;
! 417: ansi_opname[(int) INDIRECT_REF] = ansi_opname[(int) MULT_EXPR];
! 418: ansi_assopname[(int) MULT_EXPR] = get_identifier ("__aml");
! 419: IDENTIFIER_OPNAME_P (ansi_assopname[(int) MULT_EXPR]) = 1;
! 420: ansi_assopname[(int) INDIRECT_REF] = ansi_assopname[(int) MULT_EXPR];
! 421: ansi_opname[(int) TRUNC_MOD_EXPR] = get_identifier ("__md");
! 422: IDENTIFIER_OPNAME_P (ansi_opname[(int) TRUNC_MOD_EXPR]) = 1;
! 423: ansi_assopname[(int) TRUNC_MOD_EXPR] = get_identifier ("__amd");
! 424: IDENTIFIER_OPNAME_P (ansi_assopname[(int) TRUNC_MOD_EXPR]) = 1;
! 425: ansi_opname[(int) CEIL_MOD_EXPR] = ansi_opname[(int) TRUNC_MOD_EXPR];
! 426: ansi_opname[(int) FLOOR_MOD_EXPR] = ansi_opname[(int) TRUNC_MOD_EXPR];
! 427: ansi_opname[(int) ROUND_MOD_EXPR] = ansi_opname[(int) TRUNC_MOD_EXPR];
! 428: ansi_opname[(int) MINUS_EXPR] = get_identifier ("__mi");
! 429: IDENTIFIER_OPNAME_P (ansi_opname[(int) MINUS_EXPR]) = 1;
! 430: ansi_opname[(int) NEGATE_EXPR] = ansi_opname[(int) MINUS_EXPR];
! 431: ansi_assopname[(int) MINUS_EXPR] = get_identifier ("__ami");
! 432: IDENTIFIER_OPNAME_P (ansi_assopname[(int) MINUS_EXPR]) = 1;
! 433: ansi_assopname[(int) NEGATE_EXPR] = ansi_assopname[(int) MINUS_EXPR];
! 434: ansi_opname[(int) RSHIFT_EXPR] = get_identifier ("__rs");
! 435: IDENTIFIER_OPNAME_P (ansi_opname[(int) RSHIFT_EXPR]) = 1;
! 436: ansi_assopname[(int) RSHIFT_EXPR] = get_identifier ("__ars");
! 437: IDENTIFIER_OPNAME_P (ansi_assopname[(int) RSHIFT_EXPR]) = 1;
! 438: ansi_opname[(int) NE_EXPR] = get_identifier ("__ne");
! 439: IDENTIFIER_OPNAME_P (ansi_opname[(int) NE_EXPR]) = 1;
! 440: ansi_opname[(int) GT_EXPR] = get_identifier ("__gt");
! 441: IDENTIFIER_OPNAME_P (ansi_opname[(int) GT_EXPR]) = 1;
! 442: ansi_opname[(int) GE_EXPR] = get_identifier ("__ge");
! 443: IDENTIFIER_OPNAME_P (ansi_opname[(int) GE_EXPR]) = 1;
! 444: ansi_opname[(int) BIT_IOR_EXPR] = get_identifier ("__or");
! 445: IDENTIFIER_OPNAME_P (ansi_opname[(int) BIT_IOR_EXPR]) = 1;
! 446: ansi_assopname[(int) BIT_IOR_EXPR] = get_identifier ("__aor");
! 447: IDENTIFIER_OPNAME_P (ansi_assopname[(int) BIT_IOR_EXPR]) = 1;
! 448: ansi_opname[(int) TRUTH_ANDIF_EXPR] = get_identifier ("__aa");
! 449: IDENTIFIER_OPNAME_P (ansi_opname[(int) TRUTH_ANDIF_EXPR]) = 1;
! 450: ansi_opname[(int) TRUTH_NOT_EXPR] = get_identifier ("__nt");
! 451: IDENTIFIER_OPNAME_P (ansi_opname[(int) TRUTH_NOT_EXPR]) = 1;
! 452: ansi_opname[(int) PREINCREMENT_EXPR] = get_identifier ("__pp");
! 453: IDENTIFIER_OPNAME_P (ansi_opname[(int) PREINCREMENT_EXPR]) = 1;
! 454: ansi_opname[(int) POSTINCREMENT_EXPR] = ansi_opname[(int) PREINCREMENT_EXPR];
! 455: ansi_opname[(int) MODIFY_EXPR] = get_identifier ("__as");
! 456: IDENTIFIER_OPNAME_P (ansi_opname[(int) MODIFY_EXPR]) = 1;
! 457: ansi_assopname[(int) NOP_EXPR] = ansi_opname[(int) MODIFY_EXPR];
! 458: ansi_opname[(int) COMPOUND_EXPR] = get_identifier ("__cm");
! 459: IDENTIFIER_OPNAME_P (ansi_opname[(int) COMPOUND_EXPR]) = 1;
! 460: ansi_opname[(int) EXACT_DIV_EXPR] = get_identifier ("__dv");
! 461: IDENTIFIER_OPNAME_P (ansi_opname[(int) EXACT_DIV_EXPR]) = 1;
! 462: ansi_assopname[(int) EXACT_DIV_EXPR] = get_identifier ("__adv");
! 463: IDENTIFIER_OPNAME_P (ansi_assopname[(int) EXACT_DIV_EXPR]) = 1;
! 464: ansi_opname[(int) TRUNC_DIV_EXPR] = ansi_opname[(int) EXACT_DIV_EXPR];
! 465: ansi_opname[(int) CEIL_DIV_EXPR] = ansi_opname[(int) EXACT_DIV_EXPR];
! 466: ansi_opname[(int) FLOOR_DIV_EXPR] = ansi_opname[(int) EXACT_DIV_EXPR];
! 467: ansi_opname[(int) ROUND_DIV_EXPR] = ansi_opname[(int) EXACT_DIV_EXPR];
! 468: ansi_opname[(int) PLUS_EXPR] = get_identifier ("__pl");
! 469: ansi_assopname[(int) TRUNC_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR];
! 470: ansi_assopname[(int) CEIL_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR];
! 471: ansi_assopname[(int) FLOOR_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR];
! 472: ansi_assopname[(int) ROUND_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR];
! 473: ansi_opname[(int) PLUS_EXPR] = get_identifier ("__pl");
! 474: IDENTIFIER_OPNAME_P (ansi_opname[(int) PLUS_EXPR]) = 1;
! 475: ansi_assopname[(int) PLUS_EXPR] = get_identifier ("__apl");
! 476: IDENTIFIER_OPNAME_P (ansi_assopname[(int) PLUS_EXPR]) = 1;
! 477: ansi_opname[(int) CONVERT_EXPR] = ansi_opname[(int) PLUS_EXPR];
! 478: ansi_assopname[(int) CONVERT_EXPR] = ansi_assopname[(int) PLUS_EXPR];
! 479: ansi_opname[(int) LSHIFT_EXPR] = get_identifier ("__ls");
! 480: IDENTIFIER_OPNAME_P (ansi_opname[(int) LSHIFT_EXPR]) = 1;
! 481: ansi_assopname[(int) LSHIFT_EXPR] = get_identifier ("__als");
! 482: IDENTIFIER_OPNAME_P (ansi_assopname[(int) LSHIFT_EXPR]) = 1;
! 483: ansi_opname[(int) EQ_EXPR] = get_identifier ("__eq");
! 484: IDENTIFIER_OPNAME_P (ansi_opname[(int) EQ_EXPR]) = 1;
! 485: ansi_opname[(int) LT_EXPR] = get_identifier ("__lt");
! 486: IDENTIFIER_OPNAME_P (ansi_opname[(int) LT_EXPR]) = 1;
! 487: ansi_opname[(int) LE_EXPR] = get_identifier ("__le");
! 488: IDENTIFIER_OPNAME_P (ansi_opname[(int) LE_EXPR]) = 1;
! 489: ansi_opname[(int) BIT_AND_EXPR] = get_identifier ("__ad");
! 490: IDENTIFIER_OPNAME_P (ansi_opname[(int) BIT_AND_EXPR]) = 1;
! 491: ansi_assopname[(int) BIT_AND_EXPR] = get_identifier ("__aad");
! 492: IDENTIFIER_OPNAME_P (ansi_assopname[(int) BIT_AND_EXPR]) = 1;
! 493: ansi_opname[(int) ADDR_EXPR] = ansi_opname[(int) BIT_AND_EXPR];
! 494: ansi_assopname[(int) ADDR_EXPR] = ansi_assopname[(int) BIT_AND_EXPR];
! 495: ansi_opname[(int) BIT_XOR_EXPR] = get_identifier ("__er");
! 496: IDENTIFIER_OPNAME_P (ansi_opname[(int) BIT_XOR_EXPR]) = 1;
! 497: ansi_assopname[(int) BIT_XOR_EXPR] = get_identifier ("__aer");
! 498: IDENTIFIER_OPNAME_P (ansi_assopname[(int) BIT_XOR_EXPR]) = 1;
! 499: ansi_opname[(int) TRUTH_ORIF_EXPR] = get_identifier ("__oo");
! 500: IDENTIFIER_OPNAME_P (ansi_opname[(int) TRUTH_ORIF_EXPR]) = 1;
! 501: ansi_opname[(int) BIT_NOT_EXPR] = get_identifier ("__co");
! 502: IDENTIFIER_OPNAME_P (ansi_opname[(int) BIT_NOT_EXPR]) = 1;
! 503: ansi_opname[(int) PREDECREMENT_EXPR] = get_identifier ("__mm");
! 504: IDENTIFIER_OPNAME_P (ansi_opname[(int) PREDECREMENT_EXPR]) = 1;
! 505: ansi_opname[(int) POSTDECREMENT_EXPR] = ansi_opname[(int) PREDECREMENT_EXPR];
! 506: ansi_opname[(int) COMPONENT_REF] = get_identifier ("__rf");
! 507: IDENTIFIER_OPNAME_P (ansi_opname[(int) COMPONENT_REF]) = 1;
! 508: ansi_opname[(int) MEMBER_REF] = get_identifier ("__rm");
! 509: IDENTIFIER_OPNAME_P (ansi_opname[(int) MEMBER_REF]) = 1;
! 510: ansi_opname[(int) CALL_EXPR] = get_identifier ("__cl");
! 511: IDENTIFIER_OPNAME_P (ansi_opname[(int) CALL_EXPR]) = 1;
! 512: ansi_opname[(int) ARRAY_REF] = get_identifier ("__vc");
! 513: IDENTIFIER_OPNAME_P (ansi_opname[(int) ARRAY_REF]) = 1;
! 514: ansi_opname[(int) NEW_EXPR] = get_identifier ("__nw");
! 515: IDENTIFIER_OPNAME_P (ansi_opname[(int) NEW_EXPR]) = 1;
! 516: ansi_opname[(int) DELETE_EXPR] = get_identifier ("__dl");
! 517: IDENTIFIER_OPNAME_P (ansi_opname[(int) DELETE_EXPR]) = 1;
! 518: ansi_opname[(int) TYPE_EXPR] = get_identifier ("__op");
! 519: IDENTIFIER_OPNAME_P (ansi_opname[(int) TYPE_EXPR]) = 1;
1.1 root 520:
521: /* This is not true: these operators are not defined in ANSI,
522: but we need them anyway. */
1.1.1.2 ! root 523: ansi_opname[(int) MIN_EXPR] = get_identifier ("__mn");
! 524: IDENTIFIER_OPNAME_P (ansi_opname[(int) MIN_EXPR]) = 1;
! 525: ansi_opname[(int) MAX_EXPR] = get_identifier ("__mx");
! 526: IDENTIFIER_OPNAME_P (ansi_opname[(int) MAX_EXPR]) = 1;
! 527: ansi_opname[(int) COND_EXPR] = get_identifier ("__cn");
! 528: IDENTIFIER_OPNAME_P (ansi_opname[(int) COND_EXPR]) = 1;
! 529: ansi_opname[(int) METHOD_CALL_EXPR] = get_identifier ("__wr");
! 530: IDENTIFIER_OPNAME_P (ansi_opname[(int) METHOD_CALL_EXPR]) = 1;
1.1 root 531:
532: init_method ();
533: gcc_obstack_init (&inline_text_obstack);
534: inline_text_firstobj = (char *) obstack_alloc (&inline_text_obstack, 0);
535:
536: /* Start it at 0, because check_newline is called at the very beginning
537: and will increment it to 1. */
538: lineno = 0;
539: current_function_decl = NULL;
540:
541: maxtoken = 40;
542: token_buffer = (char *) xmalloc (maxtoken + 2);
543: max_wide = 40;
544: wide_buffer = (int *) xmalloc (max_wide + 1);
545:
546: ridpointers[(int) RID_INT] = get_identifier ("int");
547: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_INT],
548: build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]));
549: ridpointers[(int) RID_CHAR] = get_identifier ("char");
550: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_CHAR],
551: build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]));
552: ridpointers[(int) RID_VOID] = get_identifier ("void");
553: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VOID],
554: build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]));
555: ridpointers[(int) RID_FLOAT] = get_identifier ("float");
556: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_FLOAT],
557: build_tree_list (NULL_TREE, ridpointers[(int) RID_FLOAT]));
558: ridpointers[(int) RID_DOUBLE] = get_identifier ("double");
559: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_DOUBLE],
560: build_tree_list (NULL_TREE, ridpointers[(int) RID_DOUBLE]));
561: ridpointers[(int) RID_SHORT] = get_identifier ("short");
562: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_SHORT],
563: build_tree_list (NULL_TREE, ridpointers[(int) RID_SHORT]));
564: ridpointers[(int) RID_LONG] = get_identifier ("long");
565: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_LONG],
566: build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]));
567: ridpointers[(int) RID_UNSIGNED] = get_identifier ("unsigned");
568: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_UNSIGNED],
569: build_tree_list (NULL_TREE, ridpointers[(int) RID_UNSIGNED]));
570: ridpointers[(int) RID_SIGNED] = get_identifier ("signed");
571: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_SIGNED],
572: build_tree_list (NULL_TREE, ridpointers[(int) RID_SIGNED]));
573: ridpointers[(int) RID_INLINE] = get_identifier ("inline");
574: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_INLINE],
575: build_tree_list (NULL_TREE, ridpointers[(int) RID_INLINE]));
576: ridpointers[(int) RID_CONST] = get_identifier ("const");
577: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_CONST],
578: build_tree_list (NULL_TREE, ridpointers[(int) RID_CONST]));
579: ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile");
580: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VOLATILE],
581: build_tree_list (NULL_TREE, ridpointers[(int) RID_VOLATILE]));
582: ridpointers[(int) RID_AUTO] = get_identifier ("auto");
583: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_AUTO],
584: build_tree_list (NULL_TREE, ridpointers[(int) RID_AUTO]));
585: ridpointers[(int) RID_STATIC] = get_identifier ("static");
586: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_STATIC],
587: build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]));
588: ridpointers[(int) RID_EXTERN] = get_identifier ("extern");
589: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_EXTERN],
590: build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]));
591: ridpointers[(int) RID_TYPEDEF] = get_identifier ("typedef");
592: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_TYPEDEF],
593: build_tree_list (NULL_TREE, ridpointers[(int) RID_TYPEDEF]));
594: ridpointers[(int) RID_REGISTER] = get_identifier ("register");
595: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_REGISTER],
596: build_tree_list (NULL_TREE, ridpointers[(int) RID_REGISTER]));
597:
598: /* C++ extensions. These are probably not correctly named. */
599: class_type_node = build_int_2 (class_type, 0);
600: TREE_TYPE (class_type_node) = class_type_node;
601: ridpointers[(int) RID_CLASS] = class_type_node;
602:
603: record_type_node = build_int_2 (record_type, 0);
604: TREE_TYPE (record_type_node) = record_type_node;
605: ridpointers[(int) RID_RECORD] = record_type_node;
606:
607: union_type_node = build_int_2 (union_type, 0);
608: TREE_TYPE (union_type_node) = union_type_node;
609: ridpointers[(int) RID_UNION] = union_type_node;
610:
611: enum_type_node = build_int_2 (enum_type, 0);
612: TREE_TYPE (enum_type_node) = enum_type_node;
613: ridpointers[(int) RID_ENUM] = enum_type_node;
614:
615: ridpointers[(int) RID_VIRTUAL] = get_identifier ("virtual");
616: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VIRTUAL],
617: build_tree_list (NULL_TREE, ridpointers[(int) RID_VIRTUAL]));
618: ridpointers[(int) RID_FRIEND] = get_identifier ("friend");
619: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_FRIEND],
620: build_tree_list (NULL_TREE, ridpointers[(int) RID_FRIEND]));
621:
622: ridpointers[(int) RID_PUBLIC] = get_identifier ("public");
623: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_PUBLIC],
624: build_tree_list (NULL_TREE, ridpointers[(int) RID_PUBLIC]));
625: ridpointers[(int) RID_PRIVATE] = get_identifier ("private");
626: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_PRIVATE],
627: build_tree_list (NULL_TREE, ridpointers[(int) RID_PRIVATE]));
628: ridpointers[(int) RID_PROTECTED] = get_identifier ("protected");
629: SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_PROTECTED],
630: build_tree_list (NULL_TREE, ridpointers[(int) RID_PROTECTED]));
631:
632: /* Exception handling extensions. */
633: exception_type_node = build_int_2 (exception_type, 0);
634: TREE_TYPE (exception_type_node) = exception_type_node;
635: ridpointers[(int) RID_EXCEPTION] = exception_type_node;
636:
637: opname_tab[(int) COMPONENT_REF] = "->";
638: opname_tab[(int) MEMBER_REF] = "->*";
639: opname_tab[(int) METHOD_CALL_EXPR] = "->()";
640: opname_tab[(int) INDIRECT_REF] = "(unary *)";
641: opname_tab[(int) ARRAY_REF] = "[]";
642: opname_tab[(int) MODIFY_EXPR] = "=";
643: opname_tab[(int) NEW_EXPR] = "new";
644: opname_tab[(int) DELETE_EXPR] = "delete";
645: opname_tab[(int) COND_EXPR] = "... ? ... : ...";
646: opname_tab[(int) CALL_EXPR] = "()";
647: opname_tab[(int) PLUS_EXPR] = "+";
648: opname_tab[(int) MINUS_EXPR] = "-";
649: opname_tab[(int) MULT_EXPR] = "*";
650: opname_tab[(int) TRUNC_DIV_EXPR] = "/";
651: opname_tab[(int) CEIL_DIV_EXPR] = "(ceiling /)";
652: opname_tab[(int) FLOOR_DIV_EXPR] = "(floor /)";
653: opname_tab[(int) ROUND_DIV_EXPR] = "(round /)";
654: opname_tab[(int) TRUNC_MOD_EXPR] = "%";
655: opname_tab[(int) CEIL_MOD_EXPR] = "(ceiling %)";
656: opname_tab[(int) FLOOR_MOD_EXPR] = "(floor %)";
657: opname_tab[(int) ROUND_MOD_EXPR] = "(round %)";
658: opname_tab[(int) NEGATE_EXPR] = "-";
659: opname_tab[(int) MIN_EXPR] = "<?";
660: opname_tab[(int) MAX_EXPR] = ">?";
661: opname_tab[(int) ABS_EXPR] = "abs";
662: opname_tab[(int) FFS_EXPR] = "ffs";
663: opname_tab[(int) LSHIFT_EXPR] = "<<";
664: opname_tab[(int) RSHIFT_EXPR] = ">>";
665: opname_tab[(int) BIT_IOR_EXPR] = "|";
666: opname_tab[(int) BIT_XOR_EXPR] = "^";
667: opname_tab[(int) BIT_AND_EXPR] = "&";
668: opname_tab[(int) BIT_ANDTC_EXPR] = "&~";
669: opname_tab[(int) BIT_NOT_EXPR] = "~";
670: opname_tab[(int) TRUTH_ANDIF_EXPR] = "&&";
671: opname_tab[(int) TRUTH_ORIF_EXPR] = "||";
672: opname_tab[(int) TRUTH_AND_EXPR] = "strict &&";
673: opname_tab[(int) TRUTH_OR_EXPR] = "strict ||";
674: opname_tab[(int) TRUTH_NOT_EXPR] = "!";
675: opname_tab[(int) LT_EXPR] = "<";
676: opname_tab[(int) LE_EXPR] = "<=";
677: opname_tab[(int) GT_EXPR] = ">";
678: opname_tab[(int) GE_EXPR] = ">=";
679: opname_tab[(int) EQ_EXPR] = "==";
680: opname_tab[(int) NE_EXPR] = "!=";
681: opname_tab[(int) IN_EXPR] = "in";
682: opname_tab[(int) SET_LE_EXPR] = "subset";
683: opname_tab[(int) CARD_EXPR] = "#";
684: opname_tab[(int) RANGE_EXPR] = "..";
685: opname_tab[(int) CONVERT_EXPR] = "(unary +)";
686: opname_tab[(int) ADDR_EXPR] = "(unary &)";
687: opname_tab[(int) PREDECREMENT_EXPR] = "--";
688: opname_tab[(int) PREINCREMENT_EXPR] = "++";
689: opname_tab[(int) POSTDECREMENT_EXPR] = "--";
690: opname_tab[(int) POSTINCREMENT_EXPR] = "++";
691: opname_tab[(int) COMPOUND_EXPR] = ",";
692:
693: assignop_tab[(int) NOP_EXPR] = "=";
694: assignop_tab[(int) PLUS_EXPR] = "+=";
695: assignop_tab[(int) CONVERT_EXPR] = "+=";
696: assignop_tab[(int) MINUS_EXPR] = "-=";
697: assignop_tab[(int) NEGATE_EXPR] = "-=";
698: assignop_tab[(int) MULT_EXPR] = "*=";
699: assignop_tab[(int) INDIRECT_REF] = "*=";
700: assignop_tab[(int) TRUNC_DIV_EXPR] = "/=";
701: assignop_tab[(int) EXACT_DIV_EXPR] = "(exact /=)";
702: assignop_tab[(int) CEIL_DIV_EXPR] = "(ceiling /=)";
703: assignop_tab[(int) FLOOR_DIV_EXPR] = "(floor /=)";
704: assignop_tab[(int) ROUND_DIV_EXPR] = "(round /=)";
705: assignop_tab[(int) TRUNC_MOD_EXPR] = "%=";
706: assignop_tab[(int) CEIL_MOD_EXPR] = "(ceiling %=)";
707: assignop_tab[(int) FLOOR_MOD_EXPR] = "(floor %=)";
708: assignop_tab[(int) ROUND_MOD_EXPR] = "(round %=)";
709: assignop_tab[(int) MIN_EXPR] = "<?=";
710: assignop_tab[(int) MAX_EXPR] = ">?=";
711: assignop_tab[(int) LSHIFT_EXPR] = "<<=";
712: assignop_tab[(int) RSHIFT_EXPR] = ">>=";
713: assignop_tab[(int) BIT_IOR_EXPR] = "|=";
714: assignop_tab[(int) BIT_XOR_EXPR] = "^=";
715: assignop_tab[(int) BIT_AND_EXPR] = "&=";
716: assignop_tab[(int) ADDR_EXPR] = "&=";
717:
718: init_filename_times ();
719:
720: #define UNSET_RESERVED_WORD(STRING) \
721: do { is_reserved_word (STRING, sizeof (STRING) - 1)->name = ""; } while (0)
722:
723: if (flag_ansi_exceptions)
724: flag_handle_exceptions = 2;
725:
726: if (!flag_ansi_exceptions)
727: {
728: UNSET_RESERVED_WORD ("catch");
729: }
730:
731: if (! flag_handle_exceptions)
732: {
733: /* Easiest way to not recognize exception
1.1.1.2 ! root 734: handling extensions... */
1.1 root 735: UNSET_RESERVED_WORD ("all");
736: UNSET_RESERVED_WORD ("except");
737: UNSET_RESERVED_WORD ("exception");
738: UNSET_RESERVED_WORD ("raise");
739: UNSET_RESERVED_WORD ("raises");
740: UNSET_RESERVED_WORD ("reraise");
741: UNSET_RESERVED_WORD ("try");
742: UNSET_RESERVED_WORD ("throw");
743: }
744: else if (flag_ansi_exceptions)
745: {
746: /* Easiest way to not recognize exception
1.1.1.2 ! root 747: handling extensions... */
1.1 root 748: UNSET_RESERVED_WORD ("exception");
749: UNSET_RESERVED_WORD ("all");
750: UNSET_RESERVED_WORD ("except");
751: UNSET_RESERVED_WORD ("raise");
752: UNSET_RESERVED_WORD ("raises");
753: UNSET_RESERVED_WORD ("reraise");
754: is_reserved_word ("try", sizeof ("try") - 1)->token = ANSI_TRY;
755: is_reserved_word ("throw", sizeof ("throw") - 1)->token = ANSI_THROW;
756: }
757: if (! (flag_gc || flag_dossier))
758: {
759: UNSET_RESERVED_WORD ("classof");
760: UNSET_RESERVED_WORD ("headof");
761: }
762: if (flag_no_asm)
763: UNSET_RESERVED_WORD ("asm");
764: if (flag_no_asm || flag_traditional)
765: UNSET_RESERVED_WORD ("typeof");
766: #ifndef SOS
767: UNSET_RESERVED_WORD ("dynamic");
768: #endif
769:
770: token_count = init_parse ();
771: interface_unknown = 1;
772: }
773:
774: void
775: reinit_parse_for_function ()
776: {
777: current_base_init_list = NULL_TREE;
778: current_member_init_list = NULL_TREE;
779: }
780:
781: /* Functions and data structures for #pragma interface.
782:
783: `#pragma implementation' means that the main file being compiled
784: is considered to implement (provide) the classes that appear in
785: its main body. I.e., if this is file "foo.cc", and class `bar'
786: is defined in "foo.cc", then we say that "foo.cc implements bar".
787:
788: All main input files "implement" themselves automagically.
789:
790: `#pragma interface' means that unless this file (of the form "foo.h"
791: is not presently being included by file "foo.cc", the
792: CLASSTYPE_INTERFACE_ONLY bit gets set. The effect is that none
793: of the vtables nor any of the inline functions defined in foo.h
794: will ever be output.
795:
796: There are cases when we want to link files such as "defs.h" and
797: "main.cc". In this case, we give "defs.h" a `#pragma interface',
798: and "main.cc" has `#pragma implementation "defs.h"'. */
799:
800: struct impl_files
801: {
802: char *filename;
803: struct impl_files *next;
804: };
805:
806: static struct impl_files *impl_file_chain;
807:
808: /* Helper function to load global variables with interface
809: information. */
810: void
811: extract_interface_info ()
812: {
813: tree fileinfo = get_time_identifier (input_filename);
814: fileinfo = IDENTIFIER_CLASS_VALUE (fileinfo);
815: interface_only = TREE_INT_CST_LOW (fileinfo);
816: interface_unknown = TREE_INT_CST_HIGH (fileinfo);
817: }
818:
819: /* Return nonzero if S and T are not considered part of an
820: INTERFACE/IMPLEMENTATION pair. Otherwise, return 0. */
821: static int
822: interface_strcmp (s)
823: char *s;
824: {
825: /* Set the interface/implementation bits for this scope. */
826: struct impl_files *ifiles;
827: char *s1;
828:
829: s = FILE_NAME_NONDIRECTORY (s);
830:
831: for (ifiles = impl_file_chain; ifiles; ifiles = ifiles->next)
832: {
833: char *t1 = ifiles->filename;
834: s1 = s;
835:
836: if (*s1 != *t1 || *s1 == 0)
837: continue;
838:
839: while (*s1 == *t1 && *s1 != 0)
840: s1++, t1++;
841:
842: /* A match. */
843: if (*s1 == *t1)
844: return 0;
845:
846: /* Don't get faked out by xxx.yyy.cc vs xxx.zzz.cc. */
847: if (strchr (s1, '.') || strchr (t1, '.'))
848: continue;
849:
850: if (*s1 == '\0' || s1[-1] != '.' || t1[-1] != '.')
851: continue;
852:
853: /* A match. */
854: return 0;
855: }
856:
857: /* No matches. */
858: return 1;
859: }
860:
861: void
862: set_typedecl_interface_info (prev, vars)
863: tree prev, vars;
864: {
865: tree id = get_time_identifier (DECL_SOURCE_FILE (vars));
866: tree fileinfo = IDENTIFIER_CLASS_VALUE (id);
867: tree type = TREE_TYPE (vars);
868:
869: CLASSTYPE_INTERFACE_ONLY (type) = TREE_INT_CST_LOW (fileinfo)
870: = interface_strcmp (DECL_SOURCE_FILE (vars));
871: }
872:
873: void
874: set_vardecl_interface_info (prev, vars)
875: tree prev, vars;
876: {
877: tree type = DECL_CONTEXT (vars);
878:
879: if (CLASSTYPE_INTERFACE_UNKNOWN (type) == 0)
880: {
881: if (CLASSTYPE_INTERFACE_ONLY (type))
882: set_typedecl_interface_info (prev, TYPE_NAME (type));
883: TREE_EXTERNAL (vars) = CLASSTYPE_INTERFACE_ONLY (type);
884: TREE_PUBLIC (vars) = ! CLASSTYPE_INTERFACE_ONLY (type);
885: CLASSTYPE_VTABLE_NEEDS_WRITING (type) |= TREE_PUBLIC (vars);
886: }
887: }
888:
889: /* Called from the top level: if there are any pending inlines to
890: do, set up to process them now. */
891: void
892: do_pending_inlines ()
893: {
894: struct pending_inline *prev = 0, *tail;
895: struct pending_inline *t;
896:
897: /* Reverse the pending inline functions, since
898: they were cons'd instead of appended. */
899:
900: for (t = pending_inlines; t; t = tail)
901: {
902: t->deja_vu = 1;
903: tail = t->next;
904: t->next = prev;
905: prev = t;
906: }
907: /* Reset to zero so that if the inline functions we are currently
908: processing define inline functions of their own, that is handled
909: correctly. ??? This hasn't been checked in a while. */
910: pending_inlines = 0;
911:
912: /* Now start processing the first inline function. */
913: t = prev;
914: assert ((t->parm_vec == NULL_TREE) == (t->bindings == NULL_TREE));
915: if (t->parm_vec)
916: push_template_decls (t->parm_vec, t->bindings, 0);
917: if (t->len > 0)
918: {
919: feed_input (t->buf, t->len, t->can_free ? &inline_text_obstack : 0);
920: lineno = t->lineno;
921: if (input_filename != t->filename)
922: {
923: input_filename = t->filename;
924: /* Get interface/implementation back in sync. */
925: extract_interface_info ();
926: }
927: yychar = PRE_PARSED_FUNCTION_DECL;
928: }
929: /* Pass back a handle on the rest of the inline functions, so that they
930: can be processed later. */
931: yylval.ttype = build_tree_list ((tree) t, t->fndecl);
932: if (flag_default_inline && t->fndecl
933: /* If we're working from a template, don't change
934: the `inline' state. */
935: && t->parm_vec == NULL_TREE)
936: TREE_INLINE (t->fndecl) = 1;
937: DECL_PENDING_INLINE_INFO (t->fndecl) = 0;
938: }
939:
940: extern struct pending_input *to_be_restored;
941:
942: void
943: process_next_inline (t)
944: tree t;
945: {
946: struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t);
947: assert ((i->parm_vec == NULL_TREE) == (i->bindings == NULL_TREE));
948: if (i->parm_vec)
949: pop_template_decls (i->parm_vec, i->bindings, 0);
950: i = i->next;
951: if (yychar == YYEMPTY)
952: yychar = yylex ();
953: if (yychar != END_OF_SAVED_INPUT)
954: {
955: error ("parse error at end of saved function text");
956: /* restore_pending_input will abort unless yychar is either
957: * END_OF_SAVED_INPUT or YYEMPTY; since we already know we're
958: * hosed, feed back YYEMPTY.
959: */
960: yychar = YYEMPTY;
961: }
962: else
963: yychar = YYEMPTY;
964: restore_pending_input (to_be_restored);
965: to_be_restored = 0;
966: if (i && i->fndecl != NULL_TREE)
967: {
968: assert ((i->parm_vec == NULL_TREE) == (i->bindings == NULL_TREE));
969: if (i->parm_vec)
970: push_template_decls (i->parm_vec, i->bindings, 0);
971: feed_input (i->buf, i->len, i->can_free ? &inline_text_obstack : 0);
972: lineno = i->lineno;
973: input_filename = i->filename;
974: yychar = PRE_PARSED_FUNCTION_DECL;
975: yylval.ttype = build_tree_list ((tree) i, i->fndecl);
976: if (flag_default_inline
977: /* If we're working from a template, don't change
978: the `inline' state. */
979: && i->parm_vec == NULL_TREE)
980: TREE_INLINE (i->fndecl) = 1;
981: DECL_PENDING_INLINE_INFO (i->fndecl) = 0;
982: }
983: extract_interface_info ();
984: }
985:
986: /* Since inline methods can refer to text which has not yet been seen,
987: we store the text of the method in a structure which is placed in the
988: DECL_PENDING_INLINE_INFO field of the FUNCTION_DECL.
989: After parsing the body of the class definition, the FUNCTION_DECL's are
990: scanned to see which ones have this field set. Those are then digested
991: one at a time.
992:
993: This function's FUNCTION_DECL will have a bit set in its common so
994: that we know to watch out for it. */
995:
996: void
997: consume_string (this_obstack)
998: register struct obstack *this_obstack;
999: {
1000: register char c;
1001: do
1002: {
1003: c = getch ();
1004: if (c == '\\')
1005: {
1006: obstack_1grow (this_obstack, c);
1007: c = getch ();
1008: obstack_1grow (this_obstack, c);
1009: continue;
1010: }
1011: if (c == '\n')
1012: {
1013: if (pedantic)
1014: warning ("ANSI C forbids newline in string constant");
1015: lineno++;
1016: }
1017: obstack_1grow (this_obstack, c);
1018: }
1019: while (c != '\"');
1020: }
1021:
1022: static int nextchar = -1;
1023: static int nextyychar = YYEMPTY;
1024: static YYSTYPE nextyylval;
1025: static tree nextlastiddecl;
1026:
1027: struct pending_input {
1028: int nextchar, yychar, nextyychar, eof;
1029: YYSTYPE yylval, nextyylval;
1030: struct obstack token_obstack;
1031: int first_token;
1032: };
1033:
1034: struct pending_input *
1035: save_pending_input ()
1036: {
1037: struct pending_input *p;
1038: p = (struct pending_input *) xmalloc (sizeof (struct pending_input));
1039: p->nextchar = nextchar;
1040: p->yychar = yychar;
1041: p->nextyychar = nextyychar;
1042: p->yylval = yylval;
1043: p->nextyylval = nextyylval;
1044: p->eof = end_of_file;
1045: yychar = nextyychar = YYEMPTY;
1046: nextchar = -1;
1047: p->first_token = first_token;
1048: p->token_obstack = token_obstack;
1049:
1050: first_token = 0;
1051: gcc_obstack_init (&token_obstack);
1052: end_of_file = 0;
1053: return p;
1054: }
1055:
1056: void
1057: restore_pending_input (p)
1058: struct pending_input *p;
1059: {
1060: assert (nextchar == -1);
1061: nextchar = p->nextchar;
1062: assert (yychar == YYEMPTY || yychar == END_OF_SAVED_INPUT);
1063: yychar = p->yychar;
1064: assert (nextyychar == YYEMPTY);
1065: nextyychar = p->nextyychar;
1066: yylval = p->yylval;
1067: nextyylval = p->nextyylval;
1068: first_token = p->first_token;
1069: obstack_free (&token_obstack, (char *) 0);
1070: token_obstack = p->token_obstack;
1071: end_of_file = p->eof;
1072: free (p);
1073: }
1074:
1075: /* Return next non-whitespace input character, which may come
1076: from `finput', or from `nextchar'. */
1077: static int
1078: yynextch ()
1079: {
1080: int c;
1081:
1082: if (nextchar >= 0)
1083: {
1084: c = nextchar;
1085: nextchar = -1;
1086: }
1087: else c = getch ();
1088: return skip_white_space (c);
1089: }
1090:
1091: /* Unget character CH from the input stream.
1092: If RESCAN is non-zero, then we want to `see' this
1093: character as the next input token. */
1094: void
1095: yyungetc (ch, rescan)
1096: int ch;
1097: int rescan;
1098: {
1099: /* Unget a character from the input stream. */
1100: if (yychar == YYEMPTY || rescan == 0)
1101: {
1102: if (nextchar >= 0)
1103: put_back (nextchar);
1104: nextchar = ch;
1105: }
1106: else
1107: {
1108: assert (nextyychar == YYEMPTY);
1109: nextyychar = yychar;
1110: nextyylval = yylval;
1111: yychar = ch;
1112: }
1113: }
1114:
1115: /* This function stores away the text for an inline function that should
1116: be processed later. It decides how much later, and may need to move
1117: the info between obstacks; therefore, the caller should not refer to
1118: the T parameter after calling this function.
1119:
1120: This function also stores the list of template-parameter bindings that
1121: will be needed for expanding the template, if any. */
1122:
1123: static void
1124: store_pending_inline (decl, t)
1125: tree decl;
1126: struct pending_inline *t;
1127: {
1128: extern int processing_template_defn;
1129: int delay_to_eof = 0;
1130: struct pending_inline **inlines;
1131:
1132: t->fndecl = decl;
1133: /* Default: compile right away, and no extra bindings are needed. */
1134: t->parm_vec = t->bindings = 0;
1135: if (processing_template_defn)
1136: {
1137: tree type = current_class_type;
1138: /* Assumption: In this (possibly) nested class sequence, only
1139: one name will have template parms. */
1140: while (type)
1141: {
1142: tree decl = TYPE_NAME (type);
1143: tree tmpl = IDENTIFIER_TEMPLATE (DECL_NAME (decl));
1144: if (tmpl)
1145: {
1146: t->parm_vec = DECL_TEMPLATE_INFO (TREE_PURPOSE (tmpl))->parm_vec;
1147: t->bindings = TREE_VALUE (tmpl);
1148: }
1149: type = DECL_CONTEXT (decl);
1150: }
1151: if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
1152: || TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE)
1153: {
1154: if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
1155: assert (TYPE_MAX_VALUE (TREE_TYPE (decl)) == current_class_type);
1156:
1157: /* Inline functions can be compiled immediately. Other functions
1158: will be output separately, so if we're in interface-only mode,
1159: punt them now, or output them now if we're doing implementations
1160: and we know no overrides will exist. Otherwise, we delay until
1161: end-of-file, to see if the definition is really required. */
1162: if (TREE_INLINE (decl))
1163: /* delay_to_eof == 0 */;
1164: else if (current_class_type && !interface_unknown)
1165: {
1166: if (interface_only)
1167: {
1168: #if 0
1169: print_node_brief (stderr, "\ndiscarding text for ", decl, 0);
1170: #endif
1171: if (t->can_free)
1172: obstack_free (&inline_text_obstack, t->buf);
1173: DECL_PENDING_INLINE_INFO (decl) = 0;
1174: return;
1175: }
1176: }
1177: /* Don't delay the processing of virtual functions. */
1178: else if (DECL_VINDEX (decl) == NULL_TREE)
1179: delay_to_eof = 1;
1180: }
1181: else
1182: abort ();
1183: }
1184:
1185: if (delay_to_eof)
1186: {
1187: extern struct pending_inline *pending_template_expansions;
1188:
1189: if (t->can_free)
1190: {
1191: char *free_to = t->buf;
1192: t->buf = (char *) obstack_copy (&permanent_obstack, t->buf,
1193: t->len + 1);
1194: t = (struct pending_inline *) obstack_copy (&permanent_obstack, t,
1195: sizeof (*t));
1196: obstack_free (&inline_text_obstack, free_to);
1197: }
1198: inlines = &pending_template_expansions;
1199: t->can_free = 0;
1200: }
1201: else
1202: {
1203: inlines = &pending_inlines;
1204: DECL_PENDING_INLINE_INFO (decl) = t;
1205: }
1206:
1207: /* Because we use obstacks, we must process these in precise order. */
1208: t->next = *inlines;
1209: *inlines = t;
1210: }
1211:
1212: void reinit_parse_for_block ();
1213:
1214: void
1215: reinit_parse_for_method (yychar, decl)
1216: int yychar;
1217: tree decl;
1218: {
1219: int len;
1220: int starting_lineno = lineno;
1221: char *starting_filename = input_filename;
1222:
1223: reinit_parse_for_block (yychar, &inline_text_obstack, 0);
1224:
1225: len = obstack_object_size (&inline_text_obstack);
1226: current_base_init_list = NULL_TREE;
1227: current_member_init_list = NULL_TREE;
1228: if (decl == void_type_node
1229: || (current_class_type && TYPE_REDEFINED (current_class_type)))
1230: {
1231: /* Happens when we get two declarations of the same
1232: function in the same scope. */
1233: char *buf = obstack_finish (&inline_text_obstack);
1234: obstack_free (&inline_text_obstack, buf);
1235: return;
1236: }
1237: else
1238: {
1239: struct pending_inline *t;
1240: char *buf = obstack_finish (&inline_text_obstack);
1241:
1242: t = (struct pending_inline *) obstack_alloc (&inline_text_obstack,
1243: sizeof (struct pending_inline));
1244: t->buf = buf;
1245: t->len = len;
1246: t->lineno = starting_lineno;
1247: t->filename = starting_filename;
1248: t->token = YYEMPTY;
1249: t->can_free = 1;
1250: t->deja_vu = 0;
1251: store_pending_inline (decl, t);
1252: }
1253: }
1254:
1255: /* Consume a block -- actually, a method or template definition beginning
1256: with `:' or `{' -- and save it away on the specified obstack.
1257:
1258: Argument IS_TEMPLATE indicates which set of error messages should be
1259: output if something goes wrong. This should really be cleaned up somehow,
1260: without loss of clarity. */
1261: void
1262: reinit_parse_for_block (yychar, obstackp, is_template)
1263: int yychar;
1264: struct obstack *obstackp;
1265: int is_template;
1266: {
1267: register int c = 0;
1268: int blev = 1;
1269: int starting_lineno = lineno;
1270: char *starting_filename = input_filename;
1271: int len;
1272: int look_for_semicolon = 0;
1273:
1274: if (yychar == '{')
1275: obstack_1grow (obstackp, '{');
1276: else if (yychar == '=')
1277: {
1278: look_for_semicolon = 1;
1279: }
1280: else
1281: {
1282: if (yychar != ':' && (yychar != RETURN || is_template))
1283: {
1284: yyerror (is_template
1285: ? "parse error in template specification"
1286: : "parse error in method specification");
1287: yychar = '{';
1288: }
1289: obstack_1grow (obstackp, yychar);
1290: while (c >= 0)
1291: {
1292: int this_lineno = lineno;
1293:
1294: c = yynextch ();
1295:
1296: /* Don't lose our cool if there are lots of comments. */
1297: if (lineno == this_lineno)
1298: ;
1299: else if (lineno - this_lineno < 10 /* + strlen (input_filename) */)
1300: {
1301: int i;
1302: for (i = lineno - this_lineno; i > 0; i--)
1303: obstack_1grow (obstackp, '\n');
1304: }
1305: else
1306: {
1307: char buf[12];
1308: sprintf (buf, "\n# %d \"", lineno);
1309: len = strlen (buf);
1310: obstack_grow (obstackp, buf, len);
1311:
1312: len = strlen (input_filename);
1313: obstack_grow (obstackp, input_filename, len);
1314: obstack_1grow (obstackp, '\"');
1315: obstack_1grow (obstackp, '\n');
1316: }
1317:
1318: /* strings must be read differently than text. */
1319: if (c == '\"')
1320: {
1321: obstack_1grow (obstackp, c);
1322: consume_string (obstackp);
1323: c = yynextch ();
1324: }
1325: while (c > ' ') /* ASCII dependent! */
1326: {
1327: obstack_1grow (obstackp, c);
1328: if (c == '{') goto main_loop;
1329: if (c == '\"')
1330: consume_string (obstackp);
1331: if (c == ';')
1332: {
1333: error (is_template
1334: ? "template body missing"
1335: : "function body for constructor missing");
1336: obstack_1grow (obstackp, '{');
1337: obstack_1grow (obstackp, '}');
1338: len += 2;
1339: goto done;
1340: }
1341: c = getch ();
1342: }
1343: if (c == '\n')
1344: lineno++;
1345: obstack_1grow (obstackp, c);
1346: }
1347: if (c == EOF)
1348: {
1349: error_with_file_and_line (starting_filename,
1350: starting_lineno,
1351: "end of file read inside definition");
1352: }
1353: }
1354:
1355: main_loop:
1356: while (c >= 0)
1357: {
1358: int this_lineno = lineno;
1359:
1360: c = skip_white_space (getch ());
1361:
1362: /* Don't lose our cool if there are lots of comments. */
1363: if (lineno - this_lineno)
1364: if (lineno - this_lineno == 1)
1365: obstack_1grow (obstackp, '\n');
1366: else
1367: {
1368: char buf[12];
1369: sprintf (buf, "\n# %d \"", lineno);
1370: len = strlen (buf);
1371: obstack_grow (obstackp, buf, len);
1372:
1373: len = strlen (input_filename);
1374: obstack_grow (obstackp, input_filename, len);
1375: obstack_1grow (obstackp, '\"');
1376: obstack_1grow (obstackp, '\n');
1377: }
1378:
1379: while (c > ' ')
1380: {
1381: obstack_1grow (obstackp, c);
1382: if (c == '{') blev++;
1383: else if (c == '}')
1384: {
1385: blev--;
1386: if (blev == 0 && !look_for_semicolon)
1387: goto done;
1388: }
1389: else if (c == '\"')
1390: consume_string (obstackp);
1391: else if (c == ';' && look_for_semicolon && blev == 0)
1392: goto done;
1393: c = getch ();
1394: }
1395: if (c == '\n')
1396: lineno++;
1397: obstack_1grow (obstackp, c);
1398: }
1399: done:
1400: obstack_1grow (obstackp, '\0');
1401: }
1402:
1403: /* Build a default function named NAME for type TYPE.
1404: KIND says what to build.
1405:
1406: When KIND == 0, build default destructor.
1407: When KIND == 1, build virtual destructor.
1408: When KIND == 2, build default constructor.
1409: When KIND == 3, build default X(const X&) constructor.
1410: When KIND == 4, build default X(X&) constructor. */
1411:
1412: tree
1413: cons_up_default_function (type, name, kind)
1414: tree type, name;
1415: int kind;
1416: {
1417: extern tree void_list_node, constructor_name ();
1418: int len;
1419: tree declspecs = NULL_TREE;
1420: tree fn, args;
1421: tree argtype;
1422:
1423: name = constructor_name (name);
1424: switch (kind)
1425: {
1426: /* Destructors. */
1427: case 1:
1428: declspecs = build_decl_list (NULL_TREE, ridpointers [(int) RID_VIRTUAL]);
1429: /* Fall through... */
1430: case 0:
1431: name = build_parse_node (BIT_NOT_EXPR, name);
1432: /* Fall through... */
1433: case 2:
1434: /* Default constructor. */
1435: args = void_list_node;
1436: break;
1437:
1438: case 3:
1439: type = build_type_variant (type, 1, 0);
1440: /* Fall through... */
1441: case 4:
1442: argtype = build_reference_type (type);
1443: args = tree_cons (NULL_TREE,
1444: build_tree_list (hash_tree_chain (argtype, NULL_TREE),
1445: get_identifier ("arg")),
1446: void_list_node);
1447: break;
1448:
1449: default:
1450: abort ();
1451: }
1452:
1453: fn = start_method (declspecs,
1454: build_parse_node (CALL_EXPR, name, args, NULL_TREE),
1455: NULL_TREE);
1456: if (fn == void_type_node)
1457: return fn;
1458:
1459: current_base_init_list = NULL_TREE;
1460: current_member_init_list = NULL_TREE;
1461:
1462: len = 3;
1463:
1464: {
1465: struct pending_inline *t;
1466:
1467: t = (struct pending_inline *) obstack_alloc (&inline_text_obstack,
1468: sizeof (struct pending_inline));
1469: t->buf = default_def;
1470: t->len = len;
1471: t->lineno = lineno;
1472: t->filename = input_filename;
1473: t->token = YYEMPTY;
1474: t->can_free = 0;
1475: t->deja_vu = 0;
1476: store_pending_inline (fn, t);
1477: /* We make this declaration private (static in the C sense). */
1478: TREE_PUBLIC (fn) = 0;
1479: }
1480: finish_method (fn);
1481: DECL_CLASS_CONTEXT (fn) = type;
1482: /* Show that this function was generated by the compiler. */
1483: DECL_IGNORED_P (fn) = 1;
1484: return fn;
1485: }
1486:
1487: /* Heuristic to tell whether the user is missing a semicolon
1488: after a struct or enum declaration. Emit an error message
1489: if we know the user has blown it. */
1490: void
1491: check_for_missing_semicolon (type)
1492: tree type;
1493: {
1494: if (yychar < 0)
1495: yychar = yylex ();
1496:
1497: if (yychar > 255
1498: && yychar != IDENTIFIER
1499: && yychar != TYPENAME)
1500: {
1501: if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)))
1502: error ("semicolon missing after %s declaration",
1503: TREE_CODE (type) == ENUMERAL_TYPE ? "enum" : "struct");
1504: else
1505: error ("semicolon missing after declaration of `%s'",
1506: TYPE_NAME_STRING (type));
1507: shadow_tag (build_tree_list (0, type));
1508: }
1509: /* Could probably also hack cases where class { ... } f (); appears. */
1510: clear_anon_tags ();
1511: }
1512:
1513: void
1514: note_got_semicolon (type)
1515: tree type;
1516: {
1517: if (TREE_CODE_CLASS (TREE_CODE (type)) != 't')
1518: abort ();
1519: if (IS_AGGR_TYPE (type))
1520: CLASSTYPE_GOT_SEMICOLON (type) = 1;
1521: }
1522:
1523: void
1524: note_list_got_semicolon (declspecs)
1525: tree declspecs;
1526: {
1527: tree link;
1528:
1529: for (link = declspecs; link; link = TREE_CHAIN (link))
1530: {
1531: tree type = TREE_VALUE (link);
1532: if (TREE_CODE_CLASS (TREE_CODE (type)) == 't')
1533: note_got_semicolon (type);
1534: }
1535: clear_anon_tags ();
1536: }
1537:
1538: /* If C is not whitespace, return C.
1539: Otherwise skip whitespace and return first nonwhite char read. */
1540:
1541: static int
1542: skip_white_space (c)
1543: register int c;
1544: {
1545: for (;;)
1546: {
1547: switch (c)
1548: {
1549: case '\n':
1550: c = check_newline ();
1551: break;
1552:
1553: case ' ':
1554: case '\t':
1555: case '\f':
1556: case '\r':
1557: case '\v':
1558: case '\b':
1559: do
1560: c = getch ();
1561: while (c == ' ' || c == '\t');
1562: break;
1563:
1564: case '\\':
1565: c = getch ();
1566: if (c == '\n')
1567: lineno++;
1568: else
1569: error ("stray '\\' in program");
1570: c = getch ();
1571: break;
1572:
1573: default:
1574: return (c);
1575: }
1576: }
1577: }
1578:
1579:
1580:
1581: /* Make the token buffer longer, preserving the data in it.
1582: P should point to just beyond the last valid character in the old buffer.
1583: The value we return is a pointer to the new buffer
1584: at a place corresponding to P. */
1585:
1586: static char *
1587: extend_token_buffer (p)
1588: char *p;
1589: {
1590: int offset = p - token_buffer;
1591:
1592: maxtoken = maxtoken * 2 + 10;
1593: token_buffer = (char *) xrealloc (token_buffer, maxtoken + 2);
1594:
1595: return token_buffer + offset;
1596: }
1597:
1598: static int
1599: get_last_nonwhite_on_line ()
1600: {
1601: register int c;
1602:
1603: /* Is this the last nonwhite stuff on the line? */
1604: if (nextchar >= 0)
1605: c = nextchar, nextchar = -1;
1606: else
1607: c = getch ();
1608:
1609: while (c == ' ' || c == '\t')
1610: c = getch ();
1611: return c;
1612: }
1613:
1614: /* At the beginning of a line, increment the line number
1615: and process any #-directive on this line.
1616: If the line is a #-directive, read the entire line and return a newline.
1617: Otherwise, return the line's first non-whitespace character. */
1618:
1619: int
1620: check_newline ()
1621: {
1622: register int c;
1623: register int token;
1624:
1625: lineno++;
1626:
1627: /* Read first nonwhite char on the line. */
1628:
1629: do
1630: c = getch ();
1631: while (c == ' ' || c == '\t');
1632:
1633: if (c != '#')
1634: {
1635: /* If not #, return it so caller will use it. */
1636: return c;
1637: }
1638:
1639: /* Read first nonwhite char after the `#'. */
1640:
1641: do
1642: c = getch ();
1643: while (c == ' ' || c == '\t');
1644:
1645: /* If a letter follows, then if the word here is `line', skip
1646: it and ignore it; otherwise, ignore the line, with an error
1647: if the word isn't `pragma'. */
1648:
1649: if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
1650: {
1651: if (c == 'p')
1652: {
1653: if (getch () == 'r'
1654: && getch () == 'a'
1655: && getch () == 'g'
1656: && getch () == 'm'
1657: && getch () == 'a')
1658: {
1659: /* Read first nonwhite char after the `#pragma'. */
1660:
1661: do
1662: c = getch ();
1663: while (c == ' ' || c == '\t');
1664:
1665: if (c == 'v'
1666: && getch () == 't'
1667: && getch () == 'a'
1668: && getch () == 'b'
1669: && getch () == 'l'
1670: && getch () == 'e'
1671: && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
1672: {
1673: extern tree pending_vtables;
1674:
1675: /* More follows: it must be a string constant (class name). */
1676: token = real_yylex ();
1677: if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
1678: {
1679: error ("invalid #pragma vtable");
1680: goto skipline;
1681: }
1682: if (write_virtuals != 2)
1683: {
1684: warning ("use `+e2' option to enable #pragma vtable");
1685: goto skipline;
1686: }
1687: pending_vtables = perm_tree_cons (NULL_TREE, get_identifier (TREE_STRING_POINTER (yylval.ttype)), pending_vtables);
1688: if (nextchar < 0)
1689: nextchar = getch ();
1690: c = nextchar;
1691: if (c != '\n')
1692: warning ("trailing characters ignored");
1693: }
1694: else if (c == 'u'
1695: && getch () == 'n'
1696: && getch () == 'i'
1697: && getch () == 't'
1698: && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
1699: {
1700: /* More follows: it must be a string constant (unit name). */
1701: token = real_yylex ();
1702: if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
1703: {
1704: error ("invalid #pragma unit");
1705: goto skipline;
1706: }
1707: current_unit_name = get_identifier (TREE_STRING_POINTER (yylval.ttype));
1708: current_unit_language = current_lang_name;
1709: if (nextchar < 0)
1710: nextchar = getch ();
1711: c = nextchar;
1712: if (c != '\n')
1713: warning ("trailing characters ignored");
1714: }
1715: else if (c == 'i')
1716: {
1717: tree fileinfo = IDENTIFIER_CLASS_VALUE (get_time_identifier (input_filename));
1718: c = getch ();
1719:
1720: if (c == 'n'
1721: && getch () == 't'
1722: && getch () == 'e'
1723: && getch () == 'r'
1724: && getch () == 'f'
1725: && getch () == 'a'
1726: && getch () == 'c'
1727: && getch () == 'e'
1728: && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
1729: {
1730: /* read to newline. */
1731: while (c != '\n')
1732: c = getch ();
1733:
1734: write_virtuals = 3;
1735:
1736: if (impl_file_chain == 0)
1737: {
1738: char *filename;
1739: tree fi;
1740:
1741: /* If this is zero at this point, then we are
1742: auto-implementing. */
1743: if (main_input_filename == 0)
1744: main_input_filename = input_filename;
1745:
1746: filename = FILE_NAME_NONDIRECTORY (main_input_filename);
1747: fi = get_time_identifier (filename);
1748: fi = IDENTIFIER_CLASS_VALUE (fi);
1749: TREE_INT_CST_LOW (fi) = 0;
1750: TREE_INT_CST_HIGH (fi) = 1;
1751: /* Get default. */
1752: impl_file_chain = (struct impl_files *)permalloc (sizeof (struct impl_files));
1753: impl_file_chain->filename = filename;
1754: impl_file_chain->next = 0;
1755: }
1756:
1757: interface_only = interface_strcmp (input_filename);
1758: interface_unknown = 0;
1759: TREE_INT_CST_LOW (fileinfo) = interface_only;
1760: TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
1761: }
1762: else if (c == 'm'
1763: && getch () == 'p'
1764: && getch () == 'l'
1765: && getch () == 'e'
1766: && getch () == 'm'
1767: && getch () == 'e'
1768: && getch () == 'n'
1769: && getch () == 't'
1770: && getch () == 'a'
1771: && getch () == 't'
1772: && getch () == 'i'
1773: && getch () == 'o'
1774: && getch () == 'n'
1775: && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
1776: {
1777: char *main_filename = main_input_filename ? main_input_filename : input_filename;
1778: char *tmp;
1779:
1780: while (c == ' ' || c == '\t')
1781: c = getch ();
1782: if (c != '\n')
1783: {
1784: put_back (c);
1785: token = real_yylex ();
1786: if (token != STRING
1787: || TREE_CODE (yylval.ttype) != STRING_CST)
1788: {
1789: error ("invalid `#pragma implementation'");
1790: goto skipline;
1791: }
1792: main_filename = TREE_STRING_POINTER (yylval.ttype);
1793: }
1794: main_filename = FILE_NAME_NONDIRECTORY (main_filename);
1795:
1796: /* read to newline. */
1797: while (c != '\n')
1798: c = getch ();
1799:
1800: if (write_virtuals == 3)
1801: {
1802: struct impl_files *ifiles = impl_file_chain;
1803: while (ifiles)
1804: {
1805: if (! strcmp (ifiles->filename, main_filename))
1806: break;
1807: ifiles = ifiles->next;
1808: }
1809: if (ifiles == 0)
1810: {
1811: ifiles = (struct impl_files*) permalloc (sizeof (struct impl_files));
1812: ifiles->filename = main_filename;
1813: ifiles->next = impl_file_chain;
1814: impl_file_chain = ifiles;
1815: }
1816: }
1817: else if (main_input_filename == input_filename
1818: || ! strcmp (input_filename, main_filename))
1819: {
1820: write_virtuals = 3;
1821: if (impl_file_chain == 0)
1822: {
1823: impl_file_chain = (struct impl_files*) permalloc (sizeof (struct impl_files));
1824: impl_file_chain->filename = main_filename;
1825: impl_file_chain->next = 0;
1826: }
1827: }
1828: else
1829: error ("`#pragma implementation' can only appear at top-level");
1830: interface_only = 0;
1831: /* We make this non-zero so that we infer decl linkage
1832: in the impl file only for variables first declared
1833: in the interface file. */
1834: interface_unknown = 1;
1835: TREE_INT_CST_LOW (fileinfo) = interface_only;
1836: TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
1837: }
1838: }
1839: }
1840: goto skipline;
1841: }
1842: else if (c == 'd')
1843: {
1844: if (getch () == 'e'
1845: && getch () == 'f'
1846: && getch () == 'i'
1847: && getch () == 'n'
1848: && getch () == 'e'
1849: && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
1850: {
1851: #ifdef DWARF_DEBUGGING_INFO
1852: if ((debug_info_level == DINFO_LEVEL_VERBOSE)
1853: && (write_symbols == DWARF_DEBUG))
1854: dwarfout_define (lineno, get_directive_line (finput));
1855: #endif /* DWARF_DEBUGGING_INFO */
1856: goto skipline;
1857: }
1858: }
1859: else if (c == 'u')
1860: {
1861: if (getch () == 'n'
1862: && getch () == 'd'
1863: && getch () == 'e'
1864: && getch () == 'f'
1865: && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
1866: {
1867: #ifdef DWARF_DEBUGGING_INFO
1868: if ((debug_info_level == DINFO_LEVEL_VERBOSE)
1869: && (write_symbols == DWARF_DEBUG))
1870: dwarfout_undef (lineno, get_directive_line (finput));
1871: #endif /* DWARF_DEBUGGING_INFO */
1872: goto skipline;
1873: }
1874: }
1875: else if (c == 'l')
1876: {
1877: if (getch () == 'i'
1878: && getch () == 'n'
1879: && getch () == 'e'
1880: && ((c = getch ()) == ' ' || c == '\t'))
1881: goto linenum;
1882: }
1883: else if (c == 'i')
1884: {
1885: if (getch () == 'd'
1886: && getch () == 'e'
1887: && getch () == 'n'
1888: && getch () == 't'
1889: && ((c = getch ()) == ' ' || c == '\t'))
1890: {
1891: /* Conditionally used. */
1892: extern FILE *asm_out_file;
1893:
1894: if (pedantic)
1895: error ("ANSI C does not allow #ident");
1896:
1897: /* Here we have just seen `#ident '.
1898: A string constant should follow. */
1899:
1900: while (c == ' ' || c == '\t')
1901: c = getch ();
1902:
1903: /* If no argument, ignore the line. */
1904: if (c == '\n')
1905: return c;
1906:
1907: put_back (c);
1908: token = real_yylex ();
1909: if (token != STRING
1910: || TREE_CODE (yylval.ttype) != STRING_CST)
1911: {
1912: error ("invalid #ident");
1913: goto skipline;
1914: }
1915:
1916: #ifdef ASM_OUTPUT_IDENT
1917: ASM_OUTPUT_IDENT (asm_out_file, TREE_STRING_POINTER (yylval.ttype));
1918: #endif
1919:
1920: /* Skip the rest of this line. */
1921: goto skipline;
1922: }
1923: }
1924: else if (c == 'n')
1925: {
1926: if (getch () == 'e'
1927: && getch () == 'w'
1928: && getch () == 'w'
1929: && getch () == 'o'
1930: && getch () == 'r'
1931: && getch () == 'l'
1932: && getch () == 'd'
1933: && ((c = getch ()) == ' ' || c == '\t'))
1934: {
1935: /* Used to test incremental compilation. */
1936: sorry ("#pragma newworld");
1937: goto skipline;
1938: }
1939: }
1940: error ("undefined or invalid # directive");
1941: goto skipline;
1942: }
1943:
1944: linenum:
1945: /* Here we have either `#line' or `# <nonletter>'.
1946: In either case, it should be a line number; a digit should follow. */
1947:
1948: while (c == ' ' || c == '\t')
1949: c = getch ();
1950:
1951: /* If the # is the only nonwhite char on the line,
1952: just ignore it. Check the new newline. */
1953: if (c == '\n')
1954: return c;
1955:
1956: /* Something follows the #; read a token. */
1957:
1958: put_back (c);
1959: token = real_yylex ();
1960:
1961: if (token == CONSTANT
1962: && TREE_CODE (yylval.ttype) == INTEGER_CST)
1963: {
1964: int old_lineno = lineno;
1965: int used_up = 0;
1966: /* subtract one, because it is the following line that
1967: gets the specified number */
1968:
1969: int l = TREE_INT_CST_LOW (yylval.ttype) - 1;
1970: c = get_last_nonwhite_on_line ();
1971: if (c == '\n')
1972: {
1973: /* No more: store the line number and check following line. */
1974: lineno = l;
1975: return c;
1976: }
1977: put_back (c);
1978:
1979: /* More follows: it must be a string constant (filename). */
1980:
1981: token = real_yylex ();
1982: if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
1983: {
1984: error ("invalid #line");
1985: goto skipline;
1986: }
1987:
1988: /* Changing files again. This means currently collected time
1989: is charged against header time, and body time starts back
1990: at 0. */
1991: if (flag_detailed_statistics)
1992: {
1993: int this_time = my_get_run_time ();
1994: tree time_identifier = get_time_identifier (TREE_STRING_POINTER (yylval.ttype));
1995: header_time += this_time - body_time;
1996: TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time))
1997: += this_time - body_time;
1998: this_filename_time = time_identifier;
1999: body_time = this_time;
2000: }
2001:
2002: if (flag_cadillac)
2003: cadillac_note_source ();
2004:
2005: input_filename
2006: = (char *) permalloc (TREE_STRING_LENGTH (yylval.ttype) + 1);
2007: strcpy (input_filename, TREE_STRING_POINTER (yylval.ttype));
2008: lineno = l;
2009: GNU_xref_file (input_filename);
2010:
2011: /* Each change of file name
2012: reinitializes whether we are now in a system header. */
2013: in_system_header = 0;
2014:
2015: if (main_input_filename == 0)
2016: {
2017: struct impl_files *ifiles = impl_file_chain;
2018:
2019: if (ifiles)
2020: {
2021: while (ifiles->next)
2022: ifiles = ifiles->next;
2023: ifiles->filename = FILE_NAME_NONDIRECTORY (input_filename);
2024: }
2025:
2026: main_input_filename = input_filename;
2027: if (write_virtuals == 3)
2028: walk_vtables (set_typedecl_interface_info, set_vardecl_interface_info);
2029: }
2030:
2031: extract_interface_info ();
2032:
2033: c = get_last_nonwhite_on_line ();
2034: if (c == '\n')
2035: {
2036: if (flag_cadillac)
2037: cadillac_switch_source (-1);
2038: return c;
2039: }
2040: put_back (c);
2041:
2042: token = real_yylex ();
2043: used_up = 0;
2044:
2045: /* `1' after file name means entering new file.
2046: `2' after file name means just left a file. */
2047:
2048: if (token == CONSTANT
2049: && TREE_CODE (yylval.ttype) == INTEGER_CST)
2050: {
2051: if (TREE_INT_CST_LOW (yylval.ttype) == 1)
2052: {
2053: /* Pushing to a new file. */
2054: struct file_stack *p
2055: = (struct file_stack *) xmalloc (sizeof (struct file_stack));
2056: input_file_stack->line = old_lineno;
2057: p->next = input_file_stack;
2058: p->name = input_filename;
2059: input_file_stack = p;
2060: input_file_stack_tick++;
2061: #ifdef DWARF_DEBUGGING_INFO
2062: if (debug_info_level == DINFO_LEVEL_VERBOSE
2063: && write_symbols == DWARF_DEBUG)
2064: dwarfout_start_new_source_file (input_filename);
2065: #endif /* DWARF_DEBUGGING_INFO */
2066:
2067: used_up = 1;
2068: if (flag_cadillac)
2069: cadillac_push_source ();
2070: }
2071: else if (TREE_INT_CST_LOW (yylval.ttype) == 2)
2072: {
2073: /* Popping out of a file. */
2074: if (input_file_stack->next)
2075: {
2076: struct file_stack *p = input_file_stack;
2077:
2078: if (flag_cadillac)
2079: cadillac_pop_source ();
2080:
2081: input_file_stack = p->next;
2082: free (p);
2083: input_file_stack_tick++;
2084: #ifdef DWARF_DEBUGGING_INFO
2085: if (debug_info_level == DINFO_LEVEL_VERBOSE
2086: && write_symbols == DWARF_DEBUG)
2087: dwarfout_resume_previous_source_file (input_file_stack->line);
2088: #endif /* DWARF_DEBUGGING_INFO */
2089: }
2090: else
2091: error ("#-lines for entering and leaving files don't match");
2092:
2093: used_up = 1;
2094: }
2095: }
2096: else if (flag_cadillac)
2097: cadillac_switch_source (-1);
2098:
2099: /* If we have handled a `1' or a `2',
2100: see if there is another number to read. */
2101: if (used_up)
2102: {
2103: c = get_last_nonwhite_on_line ();
2104: if (c == '\n')
2105: {
2106: if (flag_cadillac)
2107: cadillac_switch_source (-1);
2108: return c;
2109: }
2110: put_back (c);
2111:
2112: token = real_yylex ();
2113: used_up = 0;
2114: }
2115:
2116: /* `3' after file name means this is a system header file. */
2117:
2118: if (token == CONSTANT
2119: && TREE_CODE (yylval.ttype) == INTEGER_CST
2120: && TREE_INT_CST_LOW (yylval.ttype) == 3)
2121: in_system_header = 1;
2122:
2123: /* If NEXTCHAR is not end of line, we don't care what it is. */
2124: if (nextchar == '\n')
2125: return '\n';
2126: }
2127: else
2128: error ("invalid #-line");
2129:
2130: /* skip the rest of this line. */
2131: skipline:
2132: if (c == '\n')
2133: return c;
2134: while ((c = getch ()) != EOF && c != '\n');
2135: return c;
2136: }
2137:
2138: #if 0
2139: #define isalnum(char) (char >= 'a' ? char <= 'z' : char >= '0' ? char <= '9' || (char >= 'A' && char <= 'Z') : 0)
2140: #define isdigit(char) (char >= '0' && char <= '9')
2141: #else
2142: #include <ctype.h>
2143: #endif
2144:
2145: #define ENDFILE -1 /* token that represents end-of-file */
2146:
2147: static int
2148: readescape ()
2149: {
2150: register int c = getch ();
2151: register unsigned count;
2152: register int code;
2153: unsigned firstdig;
2154:
2155: switch (c)
2156: {
2157: case 'x':
2158: code = 0;
2159: count = 0;
2160: while (1)
2161: {
2162: c = getch ();
2163: if (! isxdigit (c))
2164: {
2165: put_back (c);
2166: break;
2167: }
2168: code *= 16;
2169: if (c >= 'a' && c <= 'f')
2170: code += c - 'a' + 10;
2171: if (c >= 'A' && c <= 'F')
2172: code += c - 'A' + 10;
2173: if (c >= '0' && c <= '9')
2174: code += c - '0';
2175: if (count == 0)
2176: firstdig = code;
2177: count++;
2178: }
2179: if (count == 0)
2180: error ("\\x used with no following hex digits");
2181: else if ((count - 1) * 4 >= TYPE_PRECISION (integer_type_node)
2182: || ((1 << (TYPE_PRECISION (integer_type_node) - (count - 1) * 4))
2183: <= firstdig))
2184: warning ("hex escape out of range");
2185: return code;
2186:
2187: case '0': case '1': case '2': case '3': case '4':
2188: case '5': case '6': case '7':
2189: code = 0;
2190: count = 0;
2191: while ((c <= '7') && (c >= '0') && (count++ < 3))
2192: {
2193: code = (code * 8) + (c - '0');
2194: c = getch ();
2195: }
2196: put_back (c);
2197: return code;
2198:
2199: case '\\': case '\'': case '"':
2200: return c;
2201:
2202: case '\n':
2203: lineno++;
2204: return -1;
2205:
2206: case 'n':
2207: return TARGET_NEWLINE;
2208:
2209: case 't':
2210: return TARGET_TAB;
2211:
2212: case 'r':
2213: return TARGET_CR;
2214:
2215: case 'f':
2216: return TARGET_FF;
2217:
2218: case 'b':
2219: return TARGET_BS;
2220:
2221: case 'a':
2222: return TARGET_BELL;
2223:
2224: case 'v':
2225: return TARGET_VT;
2226:
2227: case 'E':
2228: return 033;
2229:
2230: case '?':
2231: /* `\(', etc, are used at beginning of line to avoid confusing Emacs. */
2232: case '(':
2233: case '{':
2234: case '[':
2235: return c;
2236: }
2237: if (c >= 040 && c <= 0177)
2238: warning ("unknown escape sequence `\\%c'", c);
2239: else
2240: warning ("unknown escape sequence: `\\' followed by char code 0x%x", c);
2241: return c;
2242: }
2243:
2244: /* Value is 1 if we should try to make the next identifier look like a
2245: typename (when it may be a local variable or a class variable).
2246: Value is 0 if we treat this name in a default fashion.
2247: Value is -1 if we must not see a type name. */
2248: int looking_for_typename = 0;
2249:
2250: void
2251: dont_see_typename ()
2252: {
2253: looking_for_typename = -1;
2254: if (yychar == TYPENAME || yychar == PTYPENAME)
2255: {
2256: yychar = IDENTIFIER;
2257: lastiddecl = 0;
2258: }
2259: }
2260:
2261: #ifdef __GNUC__
2262: extern __inline int identifier_type ();
2263: __inline
2264: #endif
2265: int
2266: identifier_type (decl)
2267: tree decl;
2268: {
2269: if (TREE_CODE (decl) == TEMPLATE_DECL
2270: && DECL_TEMPLATE_IS_CLASS (decl))
2271: return PTYPENAME;
2272: if (TREE_CODE (decl) != TYPE_DECL)
2273: return IDENTIFIER;
2274: return TYPENAME;
2275: }
2276:
2277: void
2278: see_typename ()
2279: {
2280: looking_for_typename = 0;
2281: if (yychar == IDENTIFIER)
2282: {
2283: lastiddecl = lookup_name (yylval.ttype, -1);
2284: if (lastiddecl == 0)
2285: {
2286: if (flag_labels_ok)
2287: lastiddecl = IDENTIFIER_LABEL_VALUE (yylval.ttype);
2288: }
2289: else
2290: yychar = identifier_type (lastiddecl);
2291: }
2292: }
2293:
2294: tree do_identifier (token)
2295: register tree token;
2296: {
2297: register tree id = lastiddecl;
2298:
2299: if (yychar == YYEMPTY)
2300: yychar = yylex ();
2301: /* Scope class declarations before global
2302: declarations. */
2303: if (id == IDENTIFIER_GLOBAL_VALUE (token)
2304: && current_class_type != 0
2305: && TYPE_SIZE (current_class_type) == 0
2306: && TREE_CODE (current_class_type) != UNINSTANTIATED_P_TYPE)
2307: {
2308: /* Could be from one of the base classes. */
2309: tree field = lookup_field (current_class_type, token, 1);
2310: if (field == 0)
2311: ;
2312: else if (field == error_mark_node)
2313: /* We have already generated the error message.
2314: But we still want to return this value. */
2315: id = lookup_field (current_class_type, token, 0);
2316: else if (TREE_CODE (field) == VAR_DECL
2317: || TREE_CODE (field) == CONST_DECL)
2318: id = field;
2319: else if (TREE_CODE (field) != FIELD_DECL)
2320: abort ();
2321: else
2322: {
2323: error_with_decl (field, "invalid use of member `%s' from base class `%s'",
2324: TYPE_NAME_STRING (DECL_FIELD_CONTEXT (field)));
2325: id = error_mark_node;
2326: return id;
2327: }
2328: }
2329:
2330: if (!id || id == error_mark_node)
2331: {
2332: if (yychar == '(' || yychar == LEFT_RIGHT)
2333: {
2334: id = implicitly_declare (token);
2335: }
2336: else if (current_function_decl == 0)
2337: {
2338: error ("`%s' undeclared, outside of functions",
2339: IDENTIFIER_POINTER (token));
2340: id = error_mark_node;
2341: }
2342: else
2343: {
2344: if (IDENTIFIER_GLOBAL_VALUE (token) != error_mark_node
2345: || IDENTIFIER_ERROR_LOCUS (token) != current_function_decl)
2346: {
2347: extern int undeclared_variable_notice;
2348:
2349: error ("`%s' undeclared (first use this function)",
2350: IDENTIFIER_POINTER (token));
2351:
2352: if (! undeclared_variable_notice)
2353: {
2354: error ("(Each undeclared identifier is reported only once");
2355: error ("for each function it appears in.)");
2356: undeclared_variable_notice = 1;
2357: }
2358: }
2359: id = error_mark_node;
2360: /* Prevent repeated error messages. */
2361: IDENTIFIER_GLOBAL_VALUE (token) = error_mark_node;
2362: SET_IDENTIFIER_ERROR_LOCUS (token, current_function_decl);
2363: }
2364: }
2365: /* TREE_USED is set in `hack_identifier'. */
2366: if (TREE_CODE (id) == CONST_DECL)
2367: {
2368: if (IDENTIFIER_CLASS_VALUE (token) == id)
2369: {
2370: /* Check visibility. */
2371: enum visibility_type visibility
2372: = compute_visibility (TYPE_BINFO (current_class_type), id);
2373: if (visibility == visibility_private)
2374: error_with_decl (id, "enum `%s' is private");
2375: /* protected is OK, since it's an enum of `this'. */
2376: }
2377: id = DECL_INITIAL (id);
2378: }
2379: else id = hack_identifier (id, token, yychar);
2380: return id;
2381: }
2382:
2383: tree
2384: identifier_typedecl_value (node)
2385: tree node;
2386: {
2387: tree t, type;
2388: type = IDENTIFIER_TYPE_VALUE (node);
2389: if (type == NULL_TREE)
2390: return NULL_TREE;
2391: #define do(X) \
2392: { \
2393: t = (X); \
2394: if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type) \
2395: return t; \
2396: }
2397: do (IDENTIFIER_LOCAL_VALUE (node));
2398: do (IDENTIFIER_CLASS_VALUE (node));
2399: do (IDENTIFIER_GLOBAL_VALUE (node));
2400: #undef do
2401: /* Will this one ever happen? */
2402: if (TYPE_NAME (type))
2403: return TYPE_NAME (type);
2404: abort ();
2405: }
2406:
2407: struct try_type
2408: {
2409: tree *node_var;
2410: char unsigned_flag;
2411: char long_flag;
2412: char long_long_flag;
2413: };
2414:
2415: struct try_type type_sequence[] =
2416: {
2417: { &integer_type_node, 0, 0, 0},
2418: { &unsigned_type_node, 1, 0, 0},
2419: { &long_integer_type_node, 0, 1, 0},
2420: { &long_unsigned_type_node, 1, 1, 0},
2421: { &long_long_integer_type_node, 0, 1, 1},
2422: { &long_long_unsigned_type_node, 1, 1, 1}
2423: };
2424:
2425: int
2426: real_yylex ()
2427: {
2428: tree tmp;
2429: register int c;
2430: register int value;
2431: int wide_flag = 0;
2432: int dollar_seen = 0;
2433: static tree typename_scope_in_progress;
2434:
2435: relex:
2436: if (nextchar >= 0)
2437: c = nextchar, nextchar = -1;
2438: else
2439: c = getch ();
2440:
2441: /* Effectively do c = skip_white_space (c)
2442: but do it faster in the usual cases. */
2443: while (1)
2444: switch (c)
2445: {
2446: case ' ':
2447: case '\t':
2448: case '\f':
2449: case '\r':
2450: case '\v':
2451: case '\b':
2452: c = getch ();
2453: break;
2454:
2455: case '\n':
2456: case '/':
2457: case '\\':
2458: c = skip_white_space (c);
2459: default:
2460: goto found_nonwhite;
2461: }
2462: found_nonwhite:
2463:
2464: token_buffer[0] = c;
2465: token_buffer[1] = 0;
2466:
2467: /* yylloc.first_line = lineno; */
2468:
2469: reswitch:
2470: switch (c)
2471: {
2472: case EOF:
2473: token_buffer[0] = '\0';
2474: end_of_file = 1;
2475: if (input_redirected ())
2476: value = END_OF_SAVED_INPUT;
2477: else if (do_pending_expansions ())
2478: /* this will set yychar for us */
2479: return yychar;
2480: else
2481: value = ENDFILE;
2482: break;
2483:
2484: case '$':
2485: if (dollars_in_ident)
2486: {
2487: dollar_seen = 1;
2488: goto letter;
2489: }
2490: value = '$';
2491: goto done;
2492:
2493: case 'L':
2494: /* Capital L may start a wide-string or wide-character constant. */
2495: {
2496: register int c = getch ();
2497: if (c == '\'')
2498: {
2499: wide_flag = 1;
2500: goto char_constant;
2501: }
2502: if (c == '"')
2503: {
2504: wide_flag = 1;
2505: goto string_constant;
2506: }
2507: put_back (c);
2508: }
2509:
2510: case 'A': case 'B': case 'C': case 'D': case 'E':
2511: case 'F': case 'G': case 'H': case 'I': case 'J':
2512: case 'K': case 'M': case 'N': case 'O':
2513: case 'P': case 'Q': case 'R': case 'S': case 'T':
2514: case 'U': case 'V': case 'W': case 'X': case 'Y':
2515: case 'Z':
2516: case 'a': case 'b': case 'c': case 'd': case 'e':
2517: case 'f': case 'g': case 'h': case 'i': case 'j':
2518: case 'k': case 'l': case 'm': case 'n': case 'o':
2519: case 'p': case 'q': case 'r': case 's': case 't':
2520: case 'u': case 'v': case 'w': case 'x': case 'y':
2521: case 'z':
2522: case '_':
2523: letter:
2524: {
2525: register char *p;
2526:
2527: p = token_buffer;
2528: if (input == 0)
2529: {
2530: /* We know that `token_buffer' can hold at least on char,
2531: so we install C immediately.
2532: We may have to read the value in `putback_char', so call
2533: `getch' once. */
2534: *p++ = c;
2535: c = getch ();
2536:
2537: /* Make this run fast. We know that we are reading straight
2538: from FINPUT in this case (since identifiers cannot straddle
2539: input sources. */
2540: while (isalnum (c) || (c == '_') || c == '$')
2541: {
2542: if (p >= token_buffer + maxtoken)
2543: p = extend_token_buffer (p);
2544: if (c == '$' && ! dollars_in_ident)
2545: break;
2546:
2547: *p++ = c;
2548: c = getc (finput);
2549: }
2550: }
2551: else
2552: {
2553: /* We know that `token_buffer' can hold at least on char,
2554: so we install C immediately. */
2555: *p++ = c;
2556: c = getch ();
2557:
2558: while (isalnum (c) || (c == '_') || c == '$')
2559: {
2560: if (p >= token_buffer + maxtoken)
2561: p = extend_token_buffer (p);
2562: if (c == '$' && ! dollars_in_ident)
2563: break;
2564:
2565: *p++ = c;
2566: c = getch ();
2567: }
2568: }
2569:
2570: *p = 0;
2571: nextchar = c;
2572:
2573: value = IDENTIFIER;
2574: yylval.itype = 0;
2575:
2576: /* Try to recognize a keyword. Uses minimum-perfect hash function */
2577:
2578: {
2579: register struct resword *ptr;
2580:
2581: if (ptr = is_reserved_word (token_buffer, p - token_buffer))
2582: {
2583: if (ptr->rid)
2584: {
2585: tree old_ttype = ridpointers[(int) ptr->rid];
2586:
2587: /* If this provides a type for us, then revert lexical
2588: state to standard state. */
2589: if (TREE_CODE (old_ttype) == IDENTIFIER_NODE
2590: && IDENTIFIER_GLOBAL_VALUE (old_ttype) != 0
2591: && TREE_CODE (IDENTIFIER_GLOBAL_VALUE (old_ttype)) == TYPE_DECL)
2592: looking_for_typename = 0;
2593: else if (ptr->token == AGGR || ptr->token == ENUM)
2594: looking_for_typename = 1;
2595:
2596: /* Check if this is a language-type declaration.
2597: Just glimpse the next non-white character. */
2598: nextchar = skip_white_space (nextchar);
2599: if (nextchar == '"')
2600: {
2601: /* We are looking at a string. Complain
2602: if the token before the string is no `extern'.
2603:
2604: Could cheat some memory by placing this string
2605: on the temporary_, instead of the saveable_
2606: obstack. */
2607:
2608: if (ptr->rid != RID_EXTERN)
2609: error ("invalid modifier `%s' for language string",
2610: ptr->name);
2611: real_yylex ();
2612: value = EXTERN_LANG_STRING;
2613: yylval.ttype = get_identifier (TREE_STRING_POINTER (yylval.ttype));
2614: break;
2615: }
2616: if (ptr->token == VISSPEC)
2617: {
2618: switch (ptr->rid)
2619: {
2620: case RID_PUBLIC:
2621: yylval.itype = visibility_public;
2622: break;
2623: case RID_PRIVATE:
2624: yylval.itype = visibility_private;
2625: break;
2626: case RID_PROTECTED:
2627: yylval.itype = visibility_protected;
2628: break;
2629: default:
2630: abort ();
2631: }
2632: }
2633: else
2634: yylval.ttype = old_ttype;
2635: }
2636: value = (int) ptr->token;
2637: }
2638: }
2639:
2640: /* If we did not find a keyword, look for an identifier
2641: (or a typename). */
2642:
2643: if (value == IDENTIFIER || value == TYPESPEC)
2644: GNU_xref_ref (current_function_decl, token_buffer);
2645:
2646: if (value == IDENTIFIER)
2647: {
2648: tmp = get_identifier (token_buffer);
2649:
2650: #ifndef VMS
2651: /* Make sure that user does not collide with our internal
2652: naming scheme. */
2653: if (JOINER == '$'
2654: && dollar_seen
2655: && (THIS_NAME_P (tmp)
2656: || VPTR_NAME_P (tmp)
2657: || DESTRUCTOR_NAME_P (tmp)
2658: || WRAPPER_OR_ANTI_WRAPPER_NAME_P (tmp)
2659: || VTABLE_NAME_P (tmp)
2660: || TEMP_NAME_P (tmp)
2661: || ANON_AGGRNAME_P (tmp)
2662: || ANON_PARMNAME_P (tmp)))
2663: warning ("identifier name `%s' conflicts with GNU C++ internal naming strategy",
2664: token_buffer);
2665: #endif
2666:
2667: yylval.ttype = tmp;
2668: }
2669: if (value == NEW && ! global_bindings_p ())
2670: {
2671: looking_for_typename = 1;
2672: value = NEW;
2673: goto done;
2674: }
2675: }
2676: break;
2677:
2678: case '.':
2679: {
2680: register int c1 = getch ();
2681: token_buffer[0] = c;
2682: token_buffer[1] = c1;
2683: if (c1 == '*')
2684: {
2685: value = DOT_STAR;
2686: token_buffer[2] = 0;
2687: goto done;
2688: }
2689: if (c1 == '.')
2690: {
2691: c1 = getch ();
2692: if (c1 == '.')
2693: {
2694: token_buffer[2] = c1;
2695: token_buffer[3] = 0;
2696: value = ELLIPSIS;
2697: goto done;
2698: }
2699: nextchar = c1;
2700: token_buffer[2] = '\0';
2701: value = RANGE;
2702: goto done;
2703: }
2704: if (isdigit (c1))
2705: {
2706: put_back (c1);
2707: goto resume_numerical_scan;
2708: }
2709: nextchar = c1;
2710: value = '.';
2711: token_buffer[1] = 0;
2712: goto done;
2713: }
2714: case '0': case '1':
2715: /* Optimize for most frequent case. */
2716: {
2717: register int c1 = getch ();
2718: if (! isalnum (c1) && c1 != '.')
2719: {
2720: /* Terminate string. */
2721: token_buffer[0] = c;
2722: token_buffer[1] = 0;
2723: if (c == '0')
2724: yylval.ttype = integer_zero_node;
2725: else
2726: yylval.ttype = integer_one_node;
2727: nextchar = c1;
2728: value = CONSTANT;
2729: goto done;
2730: }
2731: put_back (c1);
2732: }
2733: /* fall through... */
2734: case '2': case '3': case '4':
2735: case '5': case '6': case '7': case '8': case '9':
2736: resume_numerical_scan:
2737: {
2738: register char *p;
2739: int base = 10;
2740: int count = 0;
2741: int largest_digit = 0;
2742: int numdigits = 0;
2743: /* for multi-precision arithmetic,
2744: we store only 8 live bits in each short,
2745: giving us 64 bits of reliable precision */
2746: short shorts[8];
2747: int overflow = 0;
2748:
2749: enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS} floatflag
2750: = NOT_FLOAT;
2751:
2752: p = token_buffer;
2753: *p++ = c;
2754:
2755: for (count = 0; count < 8; count++)
2756: shorts[count] = 0;
2757:
2758: if (c == '0')
2759: {
2760: *p++ = (c = getch ());
2761: if ((c == 'x') || (c == 'X'))
2762: {
2763: base = 16;
2764: *p++ = (c = getch ());
2765: }
2766: /* Leading 0 forces octal unless the 0 is the only digit. */
2767: else if (c >= '0' && c <= '9')
2768: {
2769: base = 8;
2770: numdigits++;
2771: }
2772: else
2773: numdigits++;
2774: }
2775:
2776: /* Read all the digits-and-decimal-points. */
2777:
2778: while (c == '.'
2779: || (isalnum (c) && (c != 'l') && (c != 'L')
2780: && (c != 'u') && (c != 'U')
2781: && (floatflag == NOT_FLOAT || ((c != 'f') && (c != 'F')))))
2782: {
2783: if (c == '.')
2784: {
2785: if (base == 16)
2786: error ("floating constant may not be in radix 16");
2787: if (floatflag == AFTER_POINT)
2788: {
2789: error ("malformed floating constant");
2790: floatflag = TOO_MANY_POINTS;
2791: }
2792: else
2793: floatflag = AFTER_POINT;
2794:
2795: base = 10;
2796: *p++ = c = getch ();
2797: /* Accept '.' as the start of a floating-point number
2798: only when it is followed by a digit.
2799: Otherwise, unread the following non-digit
2800: and use the '.' as a structural token. */
2801: if (p == token_buffer + 2 && !isdigit (c))
2802: {
2803: if (c == '.')
2804: {
2805: c = getch ();
2806: if (c == '.')
2807: {
2808: *p++ = '.';
2809: *p = '\0';
2810: value = ELLIPSIS;
2811: goto done;
2812: }
2813: nextchar = c;
2814: token_buffer[2] = '\0';
2815: value = RANGE;
2816: goto done;
2817: }
2818: nextchar = c;
2819: token_buffer[1] = '\0';
2820: value = '.';
2821: goto done;
2822: }
2823: }
2824: else
2825: {
2826: /* It is not a decimal point.
2827: It should be a digit (perhaps a hex digit). */
2828:
2829: if (isdigit (c))
2830: {
2831: c = c - '0';
2832: }
2833: else if (base <= 10)
2834: {
2835: if ((c&~040) == 'E')
2836: {
2837: base = 10;
2838: floatflag = AFTER_POINT;
2839: break; /* start of exponent */
2840: }
2841: error ("nondigits in number and not hexadecimal");
2842: c = 0;
2843: }
2844: else if (c >= 'a')
2845: {
2846: c = c - 'a' + 10;
2847: }
2848: else
2849: {
2850: c = c - 'A' + 10;
2851: }
2852: if (c >= largest_digit)
2853: largest_digit = c;
2854: numdigits++;
2855:
2856: for (count = 0; count < 8; count++)
2857: {
2858: shorts[count] *= base;
2859: if (count)
2860: {
2861: shorts[count] += (shorts[count-1] >> 8);
2862: shorts[count-1] &= (1<<8)-1;
2863: }
2864: else shorts[0] += c;
2865: }
2866:
2867: if (shorts[7] >= 1<<8
2868: || shorts[7] < - (1 << 8))
2869: overflow = TRUE;
2870:
2871: if (p >= token_buffer + maxtoken - 3)
2872: p = extend_token_buffer (p);
2873: *p++ = (c = getch ());
2874: }
2875: }
2876:
2877: if (numdigits == 0)
2878: error ("numeric constant with no digits");
2879:
2880: if (largest_digit >= base)
2881: error ("numeric constant contains digits beyond the radix");
2882:
2883: /* Remove terminating char from the token buffer and delimit the string */
2884: *--p = 0;
2885:
2886: if (floatflag != NOT_FLOAT)
2887: {
2888: tree type = double_type_node;
2889: char f_seen = 0;
2890: char l_seen = 0;
2891: REAL_VALUE_TYPE value;
2892: jmp_buf handler;
2893:
2894: /* Read explicit exponent if any, and put it in tokenbuf. */
2895:
2896: if ((c == 'e') || (c == 'E'))
2897: {
2898: if (p >= token_buffer + maxtoken - 3)
2899: p = extend_token_buffer (p);
2900: *p++ = c;
2901: c = getch ();
2902: if ((c == '+') || (c == '-'))
2903: {
2904: *p++ = c;
2905: c = getch ();
2906: }
2907: if (! isdigit (c))
2908: error ("floating constant exponent has no digits");
2909: while (isdigit (c))
2910: {
2911: if (p >= token_buffer + maxtoken - 3)
2912: p = extend_token_buffer (p);
2913: *p++ = c;
2914: c = getch ();
2915: }
2916: }
2917:
2918: *p = 0;
2919: errno = 0;
2920:
2921: /* Convert string to a double, checking for overflow. */
2922: if (setjmp (handler))
2923: {
2924: error ("floating constant out of range");
2925: value = dconst0;
2926: }
2927: else
2928: {
2929: set_float_handler (handler);
2930: value = REAL_VALUE_ATOF (token_buffer);
2931: set_float_handler (0);
2932: }
2933: #ifdef ERANGE
2934: if (errno == ERANGE && !flag_traditional)
2935: {
2936: char *p1 = token_buffer;
2937: /* Check for "0.0" and variants;
2938: Sunos 4 spuriously returns ERANGE for them. */
2939: while (*p1 == '0') p1++;
2940: if (*p1 == '.')
2941: {
2942: p1++;
2943: while (*p1 == '0') p1++;
2944: }
2945: if (*p1 == 'e' || *p1 == 'E')
2946: {
2947: /* with significand==0, ignore the exponent */
2948: p1++;
2949: while (*p1 != 0) p1++;
2950: }
2951: /* ERANGE is also reported for underflow,
2952: so test the value to distinguish overflow from that. */
2953: if (*p1 != 0 && (value > 1.0 || value < -1.0))
2954: warning ("floating point number exceeds range of `double'");
2955: }
2956: #endif
2957:
2958: /* Read the suffixes to choose a data type. */
2959: while (1)
2960: {
2961: if (c == 'f' || c == 'F')
2962: {
2963: if (f_seen)
2964: error ("two `f's in floating constant");
2965: f_seen = 1;
2966: type = float_type_node;
2967: value = REAL_VALUE_TRUNCATE (TYPE_MODE (type), value);
2968: }
2969: else if (c == 'l' || c == 'L')
2970: {
2971: if (l_seen)
2972: error ("two `l's in floating constant");
2973: l_seen = 1;
2974: type = long_double_type_node;
2975: }
2976: else
2977: {
2978: if (isalnum (c))
2979: {
2980: error ("garbage at end of number");
2981: while (isalnum (c))
2982: {
2983: if (p >= token_buffer + maxtoken - 3)
2984: p = extend_token_buffer (p);
2985: *p++ = c;
2986: c = getch ();
2987: }
2988: }
2989: break;
2990: }
2991: if (p >= token_buffer + maxtoken - 3)
2992: p = extend_token_buffer (p);
2993: *p++ = c;
2994: c = getch ();
2995: }
2996:
2997: /* Create a node with determined type and value. */
2998: yylval.ttype = build_real (type, value);
2999:
3000: put_back (c);
3001: *p = 0;
3002: }
3003: else
3004: {
3005: tree type;
3006: int spec_unsigned = 0;
3007: int spec_long = 0;
3008: int spec_long_long = 0;
3009:
3010: while (1)
3011: {
3012: if (c == 'u' || c == 'U')
3013: {
3014: if (spec_unsigned)
3015: error ("two `u's in integer constant");
3016: spec_unsigned = 1;
3017: }
3018: else if (c == 'l' || c == 'L')
3019: {
3020: if (spec_long)
3021: {
3022: if (spec_long_long)
3023: error ("three `l's in integer constant");
3024: else if (pedantic)
3025: pedwarn ("ANSI C forbids long long integer constants");
3026: spec_long_long = 1;
3027: }
3028: spec_long = 1;
3029: }
3030: else
3031: {
3032: if (isalnum (c))
3033: {
3034: error ("garbage at end of number");
3035: while (isalnum (c))
3036: {
3037: if (p >= token_buffer + maxtoken - 3)
3038: p = extend_token_buffer (p);
3039: *p++ = c;
3040: c = getch ();
3041: }
3042: }
3043: break;
3044: }
3045: if (p >= token_buffer + maxtoken - 3)
3046: p = extend_token_buffer (p);
3047: *p++ = c;
3048: c = getch ();
3049: }
3050:
3051: put_back (c);
3052:
3053: if ((overflow || shorts[7] || shorts[6] || shorts[5] || shorts[4])
3054: && !spec_long_long)
3055: warning ("integer constant out of range");
3056:
3057: /* If it won't fit in a signed long long, make it unsigned.
3058: We can't distinguish based on the tree node because
3059: any integer constant fits any long long type. */
3060: if (shorts[7] >= (1<<8))
3061: spec_unsigned = 1;
3062:
3063: /* This is simplified by the fact that our constant
3064: is always positive. */
3065: yylval.ttype
3066: = (build_int_2
3067: ((((long)shorts[3]<<24) + ((long)shorts[2]<<16)
3068: + ((long)shorts[1]<<8) + (long)shorts[0]),
3069: (spec_long_long
3070: ? (((long)shorts[7]<<24) + ((long)shorts[6]<<16)
3071: + ((long)shorts[5]<<8) + (long)shorts[4])
3072: : 0)));
3073:
3074: #if 0
3075: /* Find the first allowable type that the value fits in. */
3076: type = 0;
3077: for (i = 0; i < sizeof (type_sequence) / sizeof (type_sequence[0]);
3078: i++)
3079: if (!(spec_long && !type_sequence[i].long_flag)
3080: && !(spec_long_long && !type_sequence[i].long_long_flag)
3081: && !(spec_unsigned && !type_sequence[i].unsigned_flag)
3082: /* A hex or octal constant traditionally is unsigned. */
3083: && !(base != 10 && flag_traditional
3084: && !type_sequence[i].unsigned_flag)
3085: /* A decimal constant can't be unsigned int
3086: unless explicitly specified. */
3087: && !(base == 10 && !spec_unsigned
3088: && *type_sequence[i].node_var == unsigned_type_node))
3089: if (int_fits_type_p (yylval.ttype, *type_sequence[i].node_var))
3090: {
3091: type = *type_sequence[i].node_var;
3092: break;
3093: }
3094: if (flag_traditional && type == long_unsigned_type_node
3095: && !spec_unsigned)
3096: type = long_integer_type_node;
3097:
3098: if (type == 0)
3099: {
3100: type = long_long_integer_type_node;
3101: warning ("integer constant out of range");
3102: }
3103:
3104: /* Warn about some cases where the type of a given constant
3105: changes from traditional C to ANSI C. */
3106: if (warn_traditional)
3107: {
3108: tree other_type = 0;
3109:
3110: /* This computation is the same as the previous one
3111: except that flag_traditional is used backwards. */
3112: for (i = 0; i < sizeof (type_sequence) / sizeof (type_sequence[0]);
3113: i++)
3114: if (!(spec_long && !type_sequence[i].long_flag)
3115: && !(spec_long_long && !type_sequence[i].long_long_flag)
3116: && !(spec_unsigned && !type_sequence[i].unsigned_flag)
3117: /* A hex or octal constant traditionally is unsigned. */
3118: && !(base != 10 && !flag_traditional
3119: && !type_sequence[i].unsigned_flag)
3120: /* A decimal constant can't be unsigned int
3121: unless explicitly specified. */
3122: && !(base == 10 && !spec_unsigned
3123: && *type_sequence[i].node_var == unsigned_type_node))
3124: if (int_fits_type_p (yylval.ttype, *type_sequence[i].node_var))
3125: {
3126: other_type = *type_sequence[i].node_var;
3127: break;
3128: }
3129: if (!flag_traditional && type == long_unsigned_type_node
3130: && !spec_unsigned)
3131: type = long_integer_type_node;
3132:
3133: if (other_type != 0 && other_type != type)
3134: {
3135: if (flag_traditional)
3136: warning ("type of integer constant would be different without -traditional");
3137: else
3138: warning ("type of integer constant would be different with -traditional");
3139: }
3140: }
3141:
3142: #else /* 1 */
3143: if (!spec_long && !spec_unsigned
3144: && !(flag_traditional && base != 10)
3145: && int_fits_type_p (yylval.ttype, integer_type_node))
3146: {
3147: #if 0
3148: if (warn_traditional && base != 10)
3149: warning ("small nondecimal constant becomes signed in ANSI C");
3150: #endif
3151: type = integer_type_node;
3152: }
3153: else if (!spec_long && (base != 10 || spec_unsigned)
3154: && int_fits_type_p (yylval.ttype, unsigned_type_node))
3155: {
3156: /* Nondecimal constants try unsigned even in traditional C. */
3157: type = unsigned_type_node;
3158: }
3159:
3160: else if (!spec_unsigned && !spec_long_long
3161: && int_fits_type_p (yylval.ttype, long_integer_type_node))
3162: type = long_integer_type_node;
3163:
3164: else if (! spec_long_long
3165: && int_fits_type_p (yylval.ttype,
3166: long_unsigned_type_node))
3167: {
3168: #if 0
3169: if (warn_traditional && !spec_unsigned)
3170: warning ("large integer constant becomes unsigned in ANSI C");
3171: #endif
3172: if (flag_traditional && !spec_unsigned)
3173: type = long_integer_type_node;
3174: else
3175: type = long_unsigned_type_node;
3176: }
3177:
3178: else if (! spec_unsigned
3179: && int_fits_type_p (yylval.ttype,
3180: long_long_integer_type_node))
3181: type = long_long_integer_type_node;
3182:
3183: else if (int_fits_type_p (yylval.ttype,
3184: long_long_unsigned_type_node))
3185: {
3186: #if 0
3187: if (warn_traditional && !spec_unsigned)
3188: warning ("large nondecimal constant is unsigned in ANSI C");
3189: #endif
3190:
3191: if (flag_traditional && !spec_unsigned)
3192: type = long_long_integer_type_node;
3193: else
3194: type = long_long_unsigned_type_node;
3195: }
3196:
3197: else
3198: {
3199: type = long_long_integer_type_node;
3200: warning ("integer constant out of range");
3201: }
3202: #endif
3203:
3204: TREE_TYPE (yylval.ttype) = type;
3205: *p = 0;
3206: }
3207:
3208: value = CONSTANT; break;
3209: }
3210:
3211: case '\'':
3212: char_constant:
3213: {
3214: register int result = 0;
3215: register num_chars = 0;
3216: unsigned width = TYPE_PRECISION (char_type_node);
3217: int max_chars;
3218:
3219: if (wide_flag) width = TYPE_PRECISION (integer_type_node);
3220:
3221: max_chars = TYPE_PRECISION (integer_type_node) / width;
3222:
3223: while (1)
3224: {
3225: tryagain:
3226:
3227: c = getch ();
3228:
3229: if (c == '\'' || c == EOF)
3230: break;
3231:
3232: if (c == '\\')
3233: {
3234: c = readescape ();
3235: if (c < 0)
3236: goto tryagain;
3237: if (width < HOST_BITS_PER_INT
3238: && (unsigned) c >= (1 << width))
3239: warning ("escape sequence out of range for character");
3240: }
3241: else if (c == '\n')
3242: {
3243: if (pedantic)
3244: warning ("ANSI C forbids newline in character constant");
3245: lineno++;
3246: }
3247:
3248: num_chars++;
3249: if (num_chars > maxtoken - 4)
3250: extend_token_buffer (token_buffer);
3251:
3252: token_buffer[num_chars] = c;
3253:
3254: /* Merge character into result; ignore excess chars. */
3255: if (num_chars < max_chars + 1)
3256: {
3257: if (width < HOST_BITS_PER_INT)
3258: result = (result << width) | (c & ((1 << width) - 1));
3259: else
3260: result = c;
3261: }
3262: }
3263:
3264: token_buffer[num_chars + 1] = '\'';
3265: token_buffer[num_chars + 2] = 0;
3266:
3267: if (c != '\'')
3268: error ("malformatted character constant");
3269: else if (num_chars == 0)
3270: error ("empty character constant");
3271: else if (num_chars > max_chars)
3272: {
3273: num_chars = max_chars;
3274: error ("character constant too long");
3275: }
3276: else if (num_chars != 1 && ! flag_traditional)
3277: warning ("multi-character character constant");
3278:
3279: /* If char type is signed, sign-extend the constant. */
3280: if (! wide_flag)
3281: {
3282: int num_bits = num_chars * width;
3283: if (TREE_UNSIGNED (char_type_node)
3284: || ((result >> (num_bits - 1)) & 1) == 0)
3285: yylval.ttype
3286: = build_int_2 (result & ((unsigned) ~0
3287: >> (HOST_BITS_PER_INT - num_bits)),
3288: 0);
3289: else
3290: yylval.ttype
3291: = build_int_2 (result | ~((unsigned) ~0
3292: >> (HOST_BITS_PER_INT - num_bits)),
3293: -1);
3294: TREE_TYPE (yylval.ttype) = char_type_node;
3295: }
3296: else
3297: {
3298: yylval.ttype = build_int_2 (result, 0);
3299: TREE_TYPE (yylval.ttype) = integer_type_node;
3300: }
3301: value = CONSTANT; break;
3302: }
3303:
3304: case '"':
3305: string_constant:
3306: {
3307: int *widep;
3308: register char *p;
3309:
3310: c = getch ();
3311: p = token_buffer + 1;
3312:
3313: if (wide_flag)
3314: widep = wide_buffer;
3315:
3316: while (c != '"' && c >= 0)
3317: {
3318: if (c == '\\')
3319: {
3320: c = readescape ();
3321: if (c < 0)
3322: goto skipnewline;
3323: if (!wide_flag && c >= (1 << BITS_PER_UNIT))
3324: warning ("escape sequence out of range for character");
3325: }
3326: else if (c == '\n')
3327: {
3328: if (pedantic)
3329: warning ("ANSI C forbids newline in string constant");
3330: lineno++;
3331: }
3332:
3333: /* Store the char in C into the appropriate buffer. */
3334:
3335: if (wide_flag)
3336: {
3337: if (widep == wide_buffer + max_wide)
3338: {
3339: int n = widep - wide_buffer;
3340: max_wide *= 2;
3341: wide_buffer = (int *) xrealloc (wide_buffer, max_wide + 1);
3342: widep = wide_buffer + n;
3343: }
3344: *widep++ = c;
3345: }
3346: else
3347: {
3348: if (p == token_buffer + maxtoken)
3349: p = extend_token_buffer (p);
3350: *p++ = c;
3351: }
3352:
3353: skipnewline:
3354: c = getch ();
3355: if (c == EOF) {
3356: error("Unterminated string");
3357: break;
3358: }
3359: }
3360:
3361: /* We have read the entire constant.
3362: Construct a STRING_CST for the result. */
3363:
3364: if (wide_flag)
3365: {
3366: /* If this is a L"..." wide-string, make a vector
3367: of the ints in wide_buffer. */
3368: *widep = 0;
3369: /* We have not implemented the case where `int'
3370: on the target and on the execution machine differ in size. */
3371: assert (TYPE_PRECISION (integer_type_node) == sizeof (int) * BITS_PER_UNIT);
3372: yylval.ttype = build_string ((widep - wide_buffer + 1) * sizeof (int),
3373: (char *)wide_buffer);
3374: TREE_TYPE (yylval.ttype) = int_array_type_node;
3375: }
3376: else
3377: {
3378: *p = 0;
3379: yylval.ttype = build_string (p - token_buffer, token_buffer + 1);
3380: TREE_TYPE (yylval.ttype) = char_array_type_node;
3381: }
3382:
3383: *p++ = '"';
3384: *p = 0;
3385:
3386: value = STRING; break;
3387: }
3388:
3389: case '+':
3390: case '-':
3391: case '&':
3392: case '|':
3393: case '<':
3394: case '>':
3395: case '*':
3396: case '/':
3397: case '%':
3398: case '^':
3399: case '!':
3400: case '=':
3401: {
3402: register int c1;
3403:
3404: combine:
3405:
3406: switch (c)
3407: {
3408: case '+':
3409: yylval.code = PLUS_EXPR; break;
3410: case '-':
3411: yylval.code = MINUS_EXPR; break;
3412: case '&':
3413: yylval.code = BIT_AND_EXPR; break;
3414: case '|':
3415: yylval.code = BIT_IOR_EXPR; break;
3416: case '*':
3417: yylval.code = MULT_EXPR; break;
3418: case '/':
3419: yylval.code = TRUNC_DIV_EXPR; break;
3420: case '%':
3421: yylval.code = TRUNC_MOD_EXPR; break;
3422: case '^':
3423: yylval.code = BIT_XOR_EXPR; break;
3424: case LSHIFT:
3425: yylval.code = LSHIFT_EXPR; break;
3426: case RSHIFT:
3427: yylval.code = RSHIFT_EXPR; break;
3428: case '<':
3429: yylval.code = LT_EXPR; break;
3430: case '>':
3431: yylval.code = GT_EXPR; break;
3432: }
3433:
3434: token_buffer[1] = c1 = getch ();
3435: token_buffer[2] = 0;
3436:
3437: if (c1 == '=')
3438: {
3439: switch (c)
3440: {
3441: case '<':
3442: value = ARITHCOMPARE; yylval.code = LE_EXPR; goto done;
3443: case '>':
3444: value = ARITHCOMPARE; yylval.code = GE_EXPR; goto done;
3445: case '!':
3446: value = EQCOMPARE; yylval.code = NE_EXPR; goto done;
3447: case '=':
3448: value = EQCOMPARE; yylval.code = EQ_EXPR; goto done;
3449: }
3450: value = ASSIGN; goto done;
3451: }
3452: else if (c == c1)
3453: switch (c)
3454: {
3455: case '+':
3456: value = PLUSPLUS; goto done;
3457: case '-':
3458: value = MINUSMINUS; goto done;
3459: case '&':
3460: value = ANDAND; goto done;
3461: case '|':
3462: value = OROR; goto done;
3463: case '<':
3464: c = LSHIFT;
3465: goto combine;
3466: case '>':
3467: c = RSHIFT;
3468: goto combine;
3469: }
3470: else if ((c == '-') && (c1 == '>'))
3471: {
3472: nextchar = skip_white_space (getch ());
3473: if (nextchar == '(')
3474: {
3475: int next_c = skip_white_space (getch ());
3476: if (next_c == ')')
3477: {
3478: nextchar = -1;
3479: value = POINTSAT_LEFT_RIGHT;
3480: goto done;
3481: }
3482: put_back (next_c);
3483: }
3484: if (nextchar == '*')
3485: {
3486: nextchar = -1;
3487: value = POINTSAT_STAR;
3488: }
3489: else
3490: value = POINTSAT;
3491: goto done;
3492: }
3493: else if (c1 == '?' && (c == '<' || c == '>'))
3494: {
3495: token_buffer[3] = 0;
3496:
3497: c1 = getch ();
3498: yylval.code = (c == '<' ? MIN_EXPR : MAX_EXPR);
3499: if (c1 == '=')
3500: {
3501: /* <?= or >?= expression. */
3502: token_buffer[2] = c1;
3503: value = ASSIGN;
3504: }
3505: else
3506: {
3507: value = MIN_MAX;
3508: nextchar = c1;
3509: }
3510: if (pedantic)
3511: error ("use of `operator %s' is not standard C++",
3512: token_buffer);
3513: goto done;
3514: }
3515:
3516: nextchar = c1;
3517: token_buffer[1] = 0;
3518:
3519: value = c;
3520: goto done;
3521: }
3522:
3523: case ':':
3524: c = getch ();
3525: if (c == ':')
3526: {
3527: token_buffer[1] = ':';
3528: token_buffer[2] = '\0';
3529: value = SCOPE;
3530: yylval.itype = 1;
3531: }
3532: else
3533: {
3534: nextchar = c;
3535: value = ':';
3536: }
3537: break;
3538:
3539: case 0:
3540: /* Don't make yyparse think this is eof. */
3541: value = 1;
3542: break;
3543:
3544: case '(':
3545: /* try, weakly, to handle casts to pointers to functions. */
3546: nextchar = skip_white_space (getch ());
3547: if (nextchar == '*')
3548: {
3549: int next_c = skip_white_space (getch ());
3550: if (next_c == ')')
3551: {
3552: nextchar = -1;
3553: yylval.ttype = build1 (INDIRECT_REF, 0, 0);
3554: value = PAREN_STAR_PAREN;
3555: }
3556: else
3557: {
3558: put_back (next_c);
3559: value = c;
3560: }
3561: }
3562: else if (nextchar == ')')
3563: {
3564: nextchar = -1;
3565: yylval.ttype = NULL_TREE;
3566: value = LEFT_RIGHT;
3567: }
3568: else value = c;
3569: break;
3570:
3571: default:
3572: value = c;
3573: }
3574:
3575: done:
3576: /* yylloc.last_line = lineno; */
3577: #ifdef GATHER_STATISTICS
3578: token_count[value] += 1;
3579: #endif
3580:
3581: return value;
3582: }
3583:
3584: typedef enum
3585: {
3586: d_kind, t_kind, s_kind, r_kind, e_kind, c_kind,
3587: id_kind, op_id_kind, perm_list_kind, temp_list_kind,
3588: vec_kind, x_kind, lang_decl, lang_type, all_kinds
3589: } tree_node_kind;
3590: extern int tree_node_counts[];
3591: extern int tree_node_sizes[];
3592: extern char *tree_node_kind_names[];
3593:
3594: /* Place to save freed lang_decls which were allocated on the
3595: permanent_obstack. @@ Not currently used. */
3596: tree free_lang_decl_chain;
3597:
3598: tree
3599: build_lang_decl (code, name, type)
3600: enum tree_code code;
3601: tree name;
3602: tree type;
3603: {
3604: register tree t = build_decl (code, name, type);
3605: struct obstack *obstack = current_obstack;
3606: register int i = sizeof (struct lang_decl) / sizeof (int);
3607: register int *pi;
3608:
3609: if (! TREE_PERMANENT (t))
3610: obstack = saveable_obstack;
3611: else
3612: /* Could be that saveable is permanent and current is not. */
3613: obstack = &permanent_obstack;
3614:
3615: if (free_lang_decl_chain && obstack == &permanent_obstack)
3616: {
3617: pi = (int *)free_lang_decl_chain;
3618: free_lang_decl_chain = TREE_CHAIN (free_lang_decl_chain);
3619: }
3620: else
3621: pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl));
3622:
3623: while (i > 0)
3624: pi[--i] = 0;
3625:
3626: DECL_LANG_SPECIFIC (t) = (struct lang_decl *) pi;
3627: LANG_DECL_PERMANENT ((struct lang_decl *) pi)
3628: = obstack == &permanent_obstack;
3629: assert (LANG_DECL_PERMANENT ((struct lang_decl *) pi)
3630: == TREE_PERMANENT (t));
3631: DECL_MAIN_VARIANT (t) = t;
3632: if (current_lang_name == lang_name_cplusplus)
3633: {
3634: DECL_LANGUAGE (t) = lang_cplusplus;
3635:
3636: #ifndef NO_AUTO_OVERLOAD
3637: if (code == FUNCTION_DECL && name != 0
3638: && ! (IDENTIFIER_LENGTH (name) == 4
3639: && IDENTIFIER_POINTER (name)[0] == 'm'
3640: && strcmp (IDENTIFIER_POINTER (name), "main") == 0)
3641: && ! (IDENTIFIER_LENGTH (name) > 10
3642: && IDENTIFIER_POINTER (name)[0] == '_'
3643: && IDENTIFIER_POINTER (name)[1] == '_'
3644: && strncmp (IDENTIFIER_POINTER (name)+2, "builtin_", 8) == 0))
3645: TREE_OVERLOADED (name) = 1;
3646: #endif
3647: }
3648: else if (current_lang_name == lang_name_c)
3649: DECL_LANGUAGE (t) = lang_c;
3650: else abort ();
3651:
1.1.1.2 ! root 3652: #if 0 /* not yet, should get fixed properly later */
! 3653: if (code == TYPE_DECL)
! 3654: {
! 3655: tree id;
! 3656: id = get_identifier (build_overload_name (type, 1, 1));
! 3657: DECL_ASSEMBLER_NAME (t) = id;
! 3658: }
! 3659:
! 3660: #endif
1.1 root 3661: #ifdef GATHER_STATISTICS
3662: tree_node_counts[(int)lang_decl] += 1;
3663: tree_node_sizes[(int)lang_decl] += sizeof(struct lang_decl);
3664: #endif
3665:
3666: return t;
3667: }
3668:
3669: tree
3670: build_lang_field_decl (code, name, type)
3671: enum tree_code code;
3672: tree name;
3673: tree type;
3674: {
3675: extern struct obstack *current_obstack, *saveable_obstack;
3676: register tree t = build_decl (code, name, type);
3677: struct obstack *obstack = current_obstack;
3678: register int i = sizeof (struct lang_decl_flags) / sizeof (int);
3679: register int *pi;
1.1.1.2 ! root 3680: #if 0 /* not yet, should get fixed properly later */
! 3681:
! 3682: if (code == TYPE_DECL)
! 3683: {
! 3684: tree id;
! 3685: id = get_identifier (build_overload_name (type, 1, 1));
! 3686: DECL_ASSEMBLER_NAME (t) = id;
! 3687: }
! 3688: #endif
1.1 root 3689:
3690: if (! TREE_PERMANENT (t))
3691: obstack = saveable_obstack;
3692: else
3693: assert (obstack == &permanent_obstack);
3694:
3695: pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl_flags));
3696: while (i > 0)
3697: pi[--i] = 0;
3698:
3699: DECL_LANG_SPECIFIC (t) = (struct lang_decl *) pi;
3700: return t;
3701: }
3702:
3703: void
3704: copy_lang_decl (node)
3705: tree node;
3706: {
3707: int size;
3708: int *pi;
3709:
3710: if (TREE_CODE (node) == FIELD_DECL)
3711: size = sizeof (struct lang_decl_flags);
3712: else
3713: size = sizeof (struct lang_decl);
3714: pi = (int *)obstack_alloc (&permanent_obstack, size);
3715: bcopy (DECL_LANG_SPECIFIC (node), pi, size);
3716: DECL_LANG_SPECIFIC (node) = (struct lang_decl *)pi;
3717: }
3718:
3719: tree
3720: make_lang_type (code)
3721: enum tree_code code;
3722: {
3723: extern struct obstack *current_obstack, *saveable_obstack;
3724: register tree t = make_node (code);
3725: struct obstack *obstack = current_obstack;
3726: register int i = sizeof (struct lang_type) / sizeof (int);
3727: register int *pi;
3728:
3729: /* Set up some flags that give proper default behavior. */
3730: IS_AGGR_TYPE (t) = 1;
3731:
3732: if (! TREE_PERMANENT (t))
3733: obstack = saveable_obstack;
3734: else
3735: assert (obstack == &permanent_obstack);
3736:
3737: pi = (int *) obstack_alloc (obstack, sizeof (struct lang_type));
3738: while (i > 0)
3739: pi[--i] = 0;
3740:
3741: TYPE_LANG_SPECIFIC (t) = (struct lang_type *) pi;
3742: CLASSTYPE_AS_LIST (t) = build_tree_list (NULL_TREE, t);
3743: CLASSTYPE_INTERFACE_UNKNOWN (t) = interface_unknown;
3744: CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
3745: CLASSTYPE_VBASE_SIZE (t) = integer_zero_node;
3746: TYPE_BINFO (t) = make_binfo (integer_zero_node, t, 0, 0, 0);
3747: CLASSTYPE_BINFO_AS_LIST (t) = build_tree_list (NULL_TREE, TYPE_BINFO (t));
3748:
3749: /* Make sure this is laid out, for ease of use later.
3750: In the presence of parse errors, the normal was of assuring
3751: this might not ever get executed, so we lay it out *immediately*. */
3752: build_pointer_type (t);
3753:
3754: #ifdef GATHER_STATISTICS
3755: tree_node_counts[(int)lang_type] += 1;
3756: tree_node_sizes[(int)lang_type] += sizeof(struct lang_type);
3757: #endif
3758:
3759: return t;
3760: }
3761:
3762: void
3763: copy_decl_lang_specific (decl)
3764: tree decl;
3765: {
3766: extern struct obstack *current_obstack, *saveable_obstack;
3767: register int *old = (int *)DECL_LANG_SPECIFIC (decl);
3768: struct obstack *obstack = current_obstack;
3769: register int i = sizeof (struct lang_decl) / sizeof (int);
3770: register int *pi;
3771:
3772: if (! TREE_PERMANENT (decl))
3773: obstack = saveable_obstack;
3774: else
3775: assert (obstack == &permanent_obstack);
3776:
3777: pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl));
3778: while (i-- > 0)
3779: pi[i] = old[i];
3780:
3781: DECL_LANG_SPECIFIC (decl) = (struct lang_decl *) pi;
3782:
3783: #ifdef GATHER_STATISTICS
3784: tree_node_counts[(int)lang_decl] += 1;
3785: tree_node_sizes[(int)lang_decl] += sizeof(struct lang_decl);
3786: #endif
3787: }
3788:
3789: void
3790: dump_time_statistics ()
3791: {
3792: register tree prev = 0, decl, next;
3793: int this_time = my_get_run_time ();
3794: TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time))
3795: += this_time - body_time;
3796:
3797: fprintf (stderr, "\n******\n");
3798: print_time ("header files (total)", header_time);
3799: print_time ("main file (total)", this_time - body_time);
3800: fprintf (stderr, "ratio = %g : 1\n",
3801: (double)header_time / (double)(this_time - body_time));
3802: fprintf (stderr, "\n******\n");
3803:
3804: for (decl = filename_times; decl; decl = next)
3805: {
3806: next = IDENTIFIER_GLOBAL_VALUE (decl);
3807: IDENTIFIER_GLOBAL_VALUE (decl) = prev;
3808: prev = decl;
3809: }
3810:
3811: for (decl = prev; decl; decl = IDENTIFIER_GLOBAL_VALUE (decl))
3812: print_time (IDENTIFIER_POINTER (decl),
3813: TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (decl)));
3814: }
3815:
3816: void
3817: compiler_error (s, v, v2)
3818: char *s;
3819: int v, v2; /* @@also used as pointer */
3820: {
3821: char buf[1024];
3822: sprintf (buf, s, v, v2);
3823: error_with_file_and_line (input_filename, lineno, "%s (compiler error)", buf);
3824: }
3825:
3826: void
3827: compiler_error_with_decl (decl, s)
3828: tree decl;
3829: char *s;
3830: {
3831: char *name;
3832: count_error (0);
3833:
3834: report_error_function (0);
3835:
3836: if (TREE_CODE (decl) == PARM_DECL)
3837: fprintf (stderr, "%s:%d: ",
3838: DECL_SOURCE_FILE (DECL_CONTEXT (decl)),
3839: DECL_SOURCE_LINE (DECL_CONTEXT (decl)));
3840: else
3841: fprintf (stderr, "%s:%d: ",
3842: DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
3843:
3844: name = lang_printable_name (decl);
3845: if (name)
3846: fprintf (stderr, s, name);
3847: else
3848: fprintf (stderr, s, "((anonymous))");
3849: fprintf (stderr, " (compiler error)\n");
3850: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.