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