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

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

unix.superglobalmegacorp.com

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