|
|
1.1 root 1: /* Type Analyzer for GNU C++. 1.1.1.2 ! root 2: Copyright (C) 1987, 89, 92, 93, 94, 1995 Free Software Foundation, Inc. 1.1 root 3: Hacked... nay, bludgeoned... by Mark Eichin ([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 1.1.1.2 ! root 19: the Free Software Foundation, 59 Temple Place - Suite 330, ! 20: Boston, MA 02111-1307, USA. */ 1.1 root 21: 22: 23: /* This file is the type analyzer for GNU C++. To debug it, define SPEW_DEBUG 24: when compiling parse.c and spew.c. */ 25: 26: #include "config.h" 27: #include <stdio.h> 28: #include "input.h" 29: #include "tree.h" 30: #include "lex.h" 31: #include "parse.h" 32: #include "cp-tree.h" 33: #include "flags.h" 34: #include "obstack.h" 35: 36: /* This takes a token stream that hasn't decided much about types and 37: tries to figure out as much as it can, with excessive lookahead and 38: backtracking. */ 39: 40: /* fifo of tokens recognized and available to parser. */ 41: struct token { 42: /* The values for YYCHAR will fit in a short. */ 43: short yychar; 44: short end_of_file; 45: YYSTYPE yylval; 46: }; 47: 48: static int do_aggr (); 49: 50: /* From lex.c: */ 51: /* the declaration found for the last IDENTIFIER token read in. 52: yylex must look this up to detect typedefs, which get token type TYPENAME, 53: so it is left around in case the identifier is not a typedef but is 54: used in a context which makes it a reference to a variable. */ 55: extern tree lastiddecl; /* let our brains leak out here too */ 56: extern int yychar; /* the lookahead symbol */ 57: extern YYSTYPE yylval; /* the semantic value of the */ 58: /* lookahead symbol */ 59: extern int end_of_file; 60: 61: struct obstack token_obstack; 62: int first_token; 63: 64: #ifdef SPEW_DEBUG 65: int spew_debug = 0; 66: static unsigned int yylex_ctr = 0; 67: static int debug_yychar (); 68: #endif 69: 70: /* Initialize token_obstack. Called once, from init_lex. */ 71: void 72: init_spew () 73: { 74: gcc_obstack_init(&token_obstack); 75: } 76: 77: #ifdef SPEW_DEBUG 78: /* Use functions for debugging... */ 79: 80: /* Return the number of tokens available on the fifo. */ 81: static int 82: num_tokens () 83: { 84: return (obstack_object_size(&token_obstack)/sizeof(struct token)) 85: - first_token; 86: } 87: 88: /* Fetch the token N down the line from the head of the fifo. */ 89: static struct token* 90: nth_token (n) 91: int n; 92: { 93: /* could just have this do slurp_ implicitly, but this way is easier 94: * to debug... */ 95: my_friendly_assert (n < num_tokens(), 298); 96: return ((struct token*)obstack_base(&token_obstack))+n+first_token; 97: } 98: 99: /* Add a token to the token fifo. */ 100: static void 101: add_token (t) 102: struct token* t; 103: { 104: obstack_grow(&token_obstack,t,sizeof (struct token)); 105: } 106: 107: /* Consume the next token out of the fifo. */ 108: static void 109: consume_token() 110: { 111: if (num_tokens() == 1) 112: { 113: obstack_free(&token_obstack, obstack_base (&token_obstack)); 114: first_token = 0; 115: } 116: else 117: first_token++; 118: } 119: 120: #else 121: /* ...otherwise use macros. */ 122: 123: #define num_tokens() \ 124: ((obstack_object_size(&token_obstack)/sizeof(struct token)) - first_token) 125: 126: #define nth_token(N) \ 127: (((struct token*)obstack_base(&token_obstack))+(N)+first_token) 128: 129: #define add_token(T) obstack_grow(&token_obstack, (T), sizeof (struct token)) 130: 131: #define consume_token() \ 132: (num_tokens() == 1 \ 133: ? (obstack_free (&token_obstack, obstack_base (&token_obstack)), \ 134: (first_token = 0)) \ 135: : first_token++) 136: #endif 137: 138: /* Pull in enough tokens from real_yylex that the queue is N long beyond 139: the current token. */ 140: 141: static void 142: scan_tokens (n) 143: int n; 144: { 145: int i; 146: struct token *tmp; 147: 148: /* We cannot read past certain tokens, so make sure we don't. */ 149: i = num_tokens (); 150: if (i > n) 151: return; 152: while (i-- > 0) 153: { 154: tmp = nth_token (i); 155: /* Never read past these characters: they might separate 156: the current input stream from one we save away later. */ 157: if (tmp->yychar == '{' || tmp->yychar == ':' || tmp->yychar == ';') 158: goto pad_tokens; 159: } 160: 161: while (num_tokens() <= n) 162: { 163: obstack_blank(&token_obstack,sizeof (struct token)); 164: tmp = ((struct token *)obstack_next_free (&token_obstack))-1; 165: tmp->yychar = real_yylex(); 166: tmp->end_of_file = end_of_file; 167: tmp->yylval = yylval; 168: end_of_file = 0; 169: if (tmp->yychar == '{' 170: || tmp->yychar == ':' 171: || tmp->yychar == ';') 172: { 173: pad_tokens: 174: while (num_tokens () <= n) 175: { 176: obstack_blank(&token_obstack,sizeof (struct token)); 177: tmp = ((struct token *)obstack_next_free (&token_obstack))-1; 178: tmp->yychar = EMPTY; 179: tmp->end_of_file = 0; 180: } 181: } 182: } 183: } 184: 185: /* Create room for N tokens at the front of the fifo. This is used 186: to insert new tokens into the stream ahead of the current token. */ 187: 188: static void 189: shift_tokens (n) 190: int n; 191: { 192: if (first_token >= n) 193: first_token -= n; 194: else 195: { 196: int old_token_count = num_tokens (); 197: char *tmp; 198: 199: obstack_blank (&token_obstack, (n-first_token) * sizeof (struct token)); 200: if (old_token_count) 201: { 202: tmp = (char *)alloca ((num_tokens () + (n-first_token)) 203: * sizeof (struct token)); 204: /* This move does not rely on the system being able to handle 205: overlapping moves. */ 206: bcopy ((char *) nth_token (0), tmp, 207: old_token_count * sizeof (struct token)); 208: bcopy (tmp, (char *) nth_token (n), 209: old_token_count * sizeof (struct token)); 210: } 211: first_token = 0; 212: } 213: } 214: 215: static int 216: probe_obstack (h, obj, nlevels) 217: struct obstack *h; 218: tree obj; 219: unsigned int nlevels; 220: { 221: register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */ 222: register struct _obstack_chunk* plp; /* point to previous chunk if any */ 223: 224: lp = (h)->chunk; 225: /* We use >= rather than > since the object cannot be exactly at 226: the beginning of the chunk but might be an empty object exactly 227: at the end of an adjacent chunk. */ 228: for (; nlevels != 0 && lp != 0 && ((tree)lp >= obj || (tree)lp->limit < obj); 229: nlevels -= 1) 230: { 231: plp = lp->prev; 232: lp = plp; 233: } 234: return nlevels != 0 && lp != 0; 235: } 236: 237: /* from lex.c: */ 238: /* Value is 1 (or 2) if we should try to make the next identifier look like 239: a typename (when it may be a local variable or a class variable). 240: Value is 0 if we treat this name in a default fashion. */ 241: extern int looking_for_typename; 242: int looking_for_template; 243: 244: extern struct obstack *current_obstack, *saveable_obstack; 245: tree got_scope; 1.1.1.2 ! root 246: tree got_object; ! 247: ! 248: int ! 249: peekyylex() ! 250: { ! 251: scan_tokens (0); ! 252: return nth_token (0)->yychar; ! 253: } 1.1 root 254: 255: int 256: yylex() 257: { 258: struct token tmp_token; 259: tree trrr; 260: 261: retry: 262: #ifdef SPEW_DEBUG 263: if (spew_debug) 264: { 265: yylex_ctr ++; 266: fprintf(stderr, "\t\t## %d ##",yylex_ctr); 267: } 268: #endif 269: 270: /* if we've got tokens, send them */ 271: if (num_tokens()) 272: { 273: tmp_token= *nth_token(0); 274: 275: /* TMP_TOKEN.YYLVAL.TTYPE may have been allocated on the wrong obstack. 276: If we don't find it in CURRENT_OBSTACK's current or immediately 277: previous chunk, assume it was and copy it to the current obstack. */ 278: if ((tmp_token.yychar == CONSTANT 279: || tmp_token.yychar == STRING) 280: && ! TREE_PERMANENT (tmp_token.yylval.ttype) 281: && ! probe_obstack (current_obstack, tmp_token.yylval.ttype, 2) 282: && ! probe_obstack (saveable_obstack, tmp_token.yylval.ttype, 2)) 283: tmp_token.yylval.ttype = copy_node (tmp_token.yylval.ttype); 284: } 285: else 286: { 287: /* if not, grab the next one and think about it */ 288: tmp_token.yychar = real_yylex (); 289: tmp_token.yylval = yylval; 290: tmp_token.end_of_file = end_of_file; 291: add_token(&tmp_token); 292: } 293: 294: /* many tokens just need to be returned. At first glance, all we 295: * have to do is send them back up, but some of them are needed to 296: * figure out local context. */ 297: switch(tmp_token.yychar) 298: { 299: case EMPTY: 300: /* This is a lexical no-op. */ 301: consume_token (); 302: #ifdef SPEW_DEBUG 303: if (spew_debug) 304: debug_yychar (tmp_token.yychar); 305: #endif 306: goto retry; 307: 308: case IDENTIFIER: 309: scan_tokens (1); 310: if (nth_token (1)->yychar == SCOPE) 311: /* Don't interfere with the setting from an 'aggr' prefix. */ 312: looking_for_typename++; 313: else if (nth_token (1)->yychar == '<') 314: looking_for_template = 1; 315: 316: trrr = lookup_name (tmp_token.yylval.ttype, -2); 317: 318: if (trrr) 319: { 320: tmp_token.yychar = identifier_type (trrr); 321: switch (tmp_token.yychar) 322: { 323: case TYPENAME: 324: lastiddecl = identifier_typedecl_value (tmp_token.yylval.ttype); 325: if (lastiddecl != trrr) 326: { 327: lastiddecl = trrr; 1.1.1.2 ! root 328: if (got_scope || got_object) 1.1 root 329: tmp_token.yylval.ttype = DECL_NESTED_TYPENAME (trrr); 330: } 331: break; 332: case IDENTIFIER: 333: lastiddecl = trrr; 334: break; 335: case PTYPENAME: 336: lastiddecl = NULL_TREE; 337: break; 1.1.1.2 ! root 338: case NSNAME: ! 339: lastiddecl = trrr; ! 340: if (got_scope || got_object) ! 341: tmp_token.yylval.ttype = trrr; ! 342: break; 1.1 root 343: default: 344: my_friendly_abort (101); 345: } 346: } 347: else 348: lastiddecl = trrr; 349: got_scope = NULL_TREE; 350: /* and fall through to... */ 1.1.1.2 ! root 351: case IDENTIFIER_DEFN: 1.1 root 352: case TYPENAME: 1.1.1.2 ! root 353: case TYPENAME_DEFN: 1.1 root 354: case PTYPENAME: 1.1.1.2 ! root 355: case PTYPENAME_DEFN: 1.1 root 356: consume_token (); 357: if (looking_for_typename > 0) 358: looking_for_typename--; 359: looking_for_template = 0; 360: break; 361: 362: case SCSPEC: 363: /* do_aggr needs to check if the previous token was RID_FRIEND, 364: so just increment first_token instead of calling consume_token. */ 365: first_token++; 366: break; 367: case TYPESPEC: 368: consume_token (); 369: break; 370: 371: case AGGR: 372: *nth_token(0) = tmp_token; 373: do_aggr (); 374: /* fall through to output... */ 375: case ENUM: 376: /* Set this again, in case we are rescanning. */ 377: looking_for_typename = 1; 378: /* fall through... */ 379: default: 380: consume_token(); 381: } 382: 383: yylval = tmp_token.yylval; 384: yychar = tmp_token.yychar; 385: end_of_file = tmp_token.end_of_file; 386: #ifdef SPEW_DEBUG 387: if (spew_debug) 388: debug_yychar(yychar); 389: #endif 390: return yychar; 391: } 392: 393: /* token[0] == AGGR (struct/union/enum) 394: * Thus, token[1] is either a TYPENAME or a TYPENAME_DEFN. 395: * If token[2] == '{' or ':' then it's TYPENAME_DEFN. 396: * It's also a definition if it's a forward declaration (as in 'struct Foo;') 397: * which we can tell lf token[2] == ';' *and* token[-1] != FRIEND. 398: */ 399: static int 400: do_aggr () 401: { 402: int yc1, yc2; 403: 404: scan_tokens (2); 405: yc1 = nth_token (1)->yychar; 406: if (yc1 != TYPENAME && yc1 != IDENTIFIER && yc1 != PTYPENAME) 407: return 0; 408: yc2 = nth_token (2)->yychar; 409: if (yc2 == ';') 410: { 411: /* It's a forward declaration iff we were not preceded by 'friend'. */ 412: if (first_token > 0 && nth_token (-1)->yychar == SCSPEC 413: && nth_token (-1)->yylval.ttype == ridpointers[(int) RID_FRIEND]) 414: return 0; 415: } 416: else if (yc2 != '{' && yc2 != ':') 417: return 0; 418: 419: switch (yc1) 420: { 421: case TYPENAME: 422: nth_token (1)->yychar = TYPENAME_DEFN; 423: break; 424: case PTYPENAME: 425: nth_token (1)->yychar = PTYPENAME_DEFN; 426: break; 427: case IDENTIFIER: 428: nth_token (1)->yychar = IDENTIFIER_DEFN; 429: break; 430: default: 431: my_friendly_abort (102); 432: } 433: return 0; 434: } 435: 436: #ifdef SPEW_DEBUG 437: /* debug_yychar takes a yychar (token number) value and prints its name. */ 438: static int 439: debug_yychar (yy) 440: int yy; 441: { 442: /* In parse.y: */ 443: extern char *debug_yytranslate (); 444: 445: int i; 446: 447: if(yy<256) { 448: fprintf (stderr, "<%d: %c >\n", yy, yy); 449: return 0; 450: } 451: fprintf (stderr, "<%d:%s>\n", yy, debug_yytranslate (yy)); 452: return 1; 453: } 454: 455: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.