Annotation of gcc/cp/spew.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.