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