Annotation of GNUtools/cc/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 cp-parse.c and cp-spew.c.  */
        !            24: 
        !            25: #include "config.h"
        !            26: #include <stdio.h>
        !            27: #include "input.h"
        !            28: #include "tree.h"
        !            29: #include "cp-lex.h"
        !            30: #ifdef OBJCPLUS
        !            31: #include "obcp-parse.h"
        !            32: #else
        !            33: #include "cp-parse.h"
        !            34: #endif
        !            35: #include "cp-tree.h"
        !            36: #include "flags.h"
        !            37: #include "obstack.h"
        !            38: 
        !            39: /* This takes a token stream that hasn't decided much about types and
        !            40:    tries to figure out as much as it can, with excessive lookahead and
        !            41:    backtracking. */
        !            42: 
        !            43: /* fifo of tokens recognized and available to parser. */
        !            44: struct token  {
        !            45:   /* The values for YYCHAR will fit in a short.  */
        !            46:   short                yychar;
        !            47:   short                end_of_file;
        !            48:   YYSTYPE      yylval;
        !            49: };
        !            50: 
        !            51: static int do_aggr ();
        !            52: static struct token frob_identifier ();
        !            53: static struct token hack_scope ();
        !            54: static tree hack_ptype ();
        !            55: static tree hack_more_ids ();
        !            56: 
        !            57: /* From cp-lex.c: */
        !            58: /* the declaration found for the last IDENTIFIER token read in.
        !            59:    yylex must look this up to detect typedefs, which get token type TYPENAME,
        !            60:    so it is left around in case the identifier is not a typedef but is
        !            61:    used in a context which makes it a reference to a variable.  */
        !            62: extern tree lastiddecl;                /* let our brains leak out here too */
        !            63: extern int     yychar;         /*  the lookahead symbol                */
        !            64: extern YYSTYPE yylval;         /*  the semantic value of the           */
        !            65:                                /*  lookahead symbol                    */
        !            66: extern int end_of_file;
        !            67: 
        !            68: struct obstack token_obstack;
        !            69: int first_token;
        !            70:   
        !            71: #ifdef SPEW_DEBUG
        !            72: int spew_debug = 0;
        !            73: static unsigned int yylex_ctr = 0;
        !            74: static int debug_yychar ();
        !            75: #endif
        !            76: 
        !            77: static char follows_typename[END_OF_SAVED_INPUT+1];
        !            78: static char follows_identifier[END_OF_SAVED_INPUT+1];
        !            79: 
        !            80: /* This is a hack!!! TEMPLATE_TYPE_SEEN_BEFORE_SCOPE consists of the name
        !            81:  * of the last template_type parsed in cp-parse.y if it is followed by a
        !            82:  * scope operator.  It will be reset inside the next invocation of yylex().
        !            83:  * This is used for recognizing nested types inside templates.
        !            84:  * - [email protected] */
        !            85: tree template_type_seen_before_scope;
        !            86: 
        !            87: /* Initialize token_obstack. Called once, from init_lex.  */
        !            88: void
        !            89: init_spew ()
        !            90: {
        !            91:   static char *chars_following_identifier = ".+-|/%^!?:";
        !            92:   short *ps;
        !            93:   static short toks_follow_ids[] =
        !            94:     { ASSIGN, RANGE, OROR, ANDAND, MIN_MAX, EQCOMPARE,
        !            95:       ARITHCOMPARE, LSHIFT, RSHIFT, UNARY, PLUSPLUS, MINUSMINUS, POINTSAT,
        !            96:       POINTSAT_STAR, DOT_STAR, CONSTANT, STRING, SIZEOF, ENUM, IF,
        !            97:       ELSE, WHILE, DO, FOR, SWITCH, CASE, DEFAULT, BREAK, CONTINUE,
        !            98:       RETURN, GOTO, ASM_KEYWORD, GCC_ASM_KEYWORD, TYPEOF, ALIGNOF, HEADOF,
        !            99:       CLASSOF, ATTRIBUTE, AGGR, VISSPEC, DELETE, RAISE, RERAISE, TRY, EXCEPT,
        !           100:       CATCH, THROW, ANSI_TRY, ANSI_THROW, DYNAMIC_CAST, TYPEID,
        !           101:       EXTERN_LANG_STRING, ALL, END_OF_SAVED_INPUT, -1 };
        !           102:   static short toks_follow_types[] =
        !           103:     { IDENTIFIER, TYPENAME, SCOPED_TYPENAME, SCSPEC, TYPESPEC, TYPE_QUAL,
        !           104:       ELLIPSIS, THIS, OPERATOR, TEMPLATE, SCOPE, START_DECLARATOR,
        !           105:       TYPENAME_COLON, PAREN_STAR_PAREN, TYPENAME_ELLIPSIS, PTYPENAME,
        !           106:       PRE_PARSED_FUNCTION_DECL, PRE_PARSED_CLASS_DECL, -1 };
        !           107: 
        !           108:   gcc_obstack_init(&token_obstack);
        !           109: 
        !           110:   /* Initialize the arrays saying what tokens are definitely
        !           111:      (or possibly) valid following typenames and identifiers.  */
        !           112:   while (*chars_following_identifier)
        !           113:     follows_identifier[*chars_following_identifier++] = 1;
        !           114:   for (ps = toks_follow_ids; *ps != -1; ps++)
        !           115:     follows_identifier[*ps] = 1;
        !           116:   for (ps = toks_follow_types; *ps != -1; ps++)
        !           117:     follows_typename[*ps] = 1;
        !           118: }
        !           119: 
        !           120: #ifdef SPEW_DEBUG
        !           121: /* Use functions for debugging...  */
        !           122: 
        !           123: /* Return the number of tokens available on the fifo. */
        !           124: static int
        !           125: num_tokens ()
        !           126: {
        !           127:   return (obstack_object_size(&token_obstack)/sizeof(struct token))
        !           128:     - first_token;
        !           129: }
        !           130: 
        !           131: /* Fetch the token N down the line from the head of the fifo. */
        !           132: static struct token*
        !           133: nth_token (n)
        !           134:      int n;
        !           135: {
        !           136:   /* could just have this do slurp_ implicitly, but this way is easier
        !           137:    * to debug... */
        !           138:   my_friendly_assert (n < num_tokens(), 298);
        !           139:   return ((struct token*)obstack_base(&token_obstack))+n+first_token;
        !           140: }
        !           141: 
        !           142: /* Add a token to the token fifo. */
        !           143: static void
        !           144: add_token (t)
        !           145:      struct token* t;
        !           146: {
        !           147:   obstack_grow(&token_obstack,t,sizeof (struct token));
        !           148: }
        !           149: 
        !           150: /* Consume the next token out of the fifo.  */
        !           151: static void
        !           152: consume_token()
        !           153: {
        !           154:   if (num_tokens() == 1)
        !           155:     {
        !           156:       obstack_free(&token_obstack, obstack_base (&token_obstack));
        !           157:       first_token = 0;
        !           158:     }
        !           159:   else
        !           160:     first_token++;
        !           161: }
        !           162: 
        !           163: #else
        !           164: /* ...otherwise use macros.  */
        !           165: 
        !           166: #define num_tokens() \
        !           167:   ((obstack_object_size(&token_obstack)/sizeof(struct token)) - first_token)
        !           168: 
        !           169: #define nth_token(N) \
        !           170:   (((struct token*)obstack_base(&token_obstack))+(N)+first_token)
        !           171: 
        !           172: #define add_token(T) obstack_grow(&token_obstack, (T), sizeof (struct token))
        !           173: 
        !           174: #define consume_token() \
        !           175:   (num_tokens() == 1                                                   \
        !           176:    ? (obstack_free (&token_obstack, obstack_base (&token_obstack)),    \
        !           177:       (first_token = 0))                                               \
        !           178:    : first_token++)
        !           179: #endif
        !           180: 
        !           181: /* Pull in enough tokens from real_yylex that the queue is N long.  */
        !           182: 
        !           183: static void
        !           184: scan_tokens (n)
        !           185:      int n;
        !           186: {
        !           187:   int i;
        !           188:   struct token *tmp;
        !           189: 
        !           190:   /* We cannot read past certain tokens, so make sure we don't.  */
        !           191:   i = num_tokens ();
        !           192:   if (i > n)
        !           193:     return;
        !           194:   while (i-- > 0)
        !           195:     {
        !           196:       tmp = nth_token (i);
        !           197:       /* Never read past these characters: they might separate
        !           198:         the current input stream from one we save away later.  */
        !           199:       if (tmp->yychar == '{' || tmp->yychar == ':' || tmp->yychar == ';')
        !           200:        goto pad_tokens;
        !           201:     }
        !           202: 
        !           203:   while (num_tokens() <= n)
        !           204:     {
        !           205:       obstack_blank(&token_obstack,sizeof (struct token));
        !           206:       tmp = ((struct token *)obstack_next_free (&token_obstack))-1;
        !           207:       tmp->yychar = real_yylex();
        !           208:       tmp->end_of_file = end_of_file;
        !           209:       tmp->yylval = yylval;
        !           210:       end_of_file = 0;
        !           211:       if (tmp->yychar == '{'
        !           212:          || tmp->yychar == ':'
        !           213:          || tmp->yychar == ';')
        !           214:        {
        !           215:        pad_tokens:
        !           216:          while (num_tokens () <= n)
        !           217:            {
        !           218:              obstack_blank(&token_obstack,sizeof (struct token));
        !           219:              tmp = ((struct token *)obstack_next_free (&token_obstack))-1;
        !           220:              tmp->yychar = EMPTY;
        !           221:              tmp->end_of_file = 0;
        !           222:            }
        !           223:        }
        !           224:     }
        !           225: }
        !           226: 
        !           227: /* Create room for N tokens at the front of the fifo.  This is used
        !           228:    to insert new tokens into the stream ahead of the current token.  */
        !           229: 
        !           230: static void
        !           231: shift_tokens (n)
        !           232:      int n;
        !           233: {
        !           234:   if (first_token >= n)
        !           235:     first_token -= n;
        !           236:   else
        !           237:     {
        !           238:       int old_token_count = num_tokens ();
        !           239:       char *tmp;
        !           240: 
        !           241:       obstack_blank (&token_obstack, (n-first_token) * sizeof (struct token));
        !           242:       if (old_token_count)
        !           243:        {
        !           244:          tmp = (char *)alloca ((num_tokens () + (n-first_token))
        !           245:                                * sizeof (struct token));
        !           246:          /* This move does not rely on the system being able to handle
        !           247:             overlapping moves.  */
        !           248:          bcopy (nth_token (0), tmp, old_token_count * sizeof (struct token));
        !           249:          bcopy (tmp, nth_token (n), old_token_count * sizeof (struct token));
        !           250:        }
        !           251:       first_token = 0;
        !           252:     }
        !           253: }
        !           254: 
        !           255: static int
        !           256: probe_obstack (h, obj, nlevels)
        !           257:      struct obstack *h;
        !           258:      tree obj;
        !           259:      unsigned int nlevels;
        !           260: {
        !           261:   register struct _obstack_chunk*  lp; /* below addr of any objects in this chunk */
        !           262:   register struct _obstack_chunk*  plp;        /* point to previous chunk if any */
        !           263: 
        !           264:   lp = (h)->chunk;
        !           265:   /* We use >= rather than > since the object cannot be exactly at
        !           266:      the beginning of the chunk but might be an empty object exactly
        !           267:      at the end of an adjacent chunk. */
        !           268:   for (; nlevels != 0 && lp != 0 && ((tree)lp >= obj || (tree)lp->limit < obj);
        !           269:        nlevels -= 1)
        !           270:     {
        !           271:       plp = lp->prev;
        !           272:       lp = plp;      
        !           273:     }
        !           274:   return nlevels != 0 && lp != 0;
        !           275: }
        !           276: 
        !           277: /* from cp-lex.c: */
        !           278: /* Value is 1 if we should try to make the next identifier look like a
        !           279:    typename (when it may be a local variable or a class variable).
        !           280:    Value is 0 if we treat this name in a default fashion.
        !           281:    Value is -1 if we must not see a type name.  */
        !           282: extern int looking_for_typename;
        !           283: 
        !           284: extern struct obstack *current_obstack, *saveable_obstack;
        !           285: 
        !           286: int
        !           287: yylex()
        !           288: {
        !           289:   struct token tmp_token;
        !           290:   tree trrr;
        !           291: 
        !           292:  retry:
        !           293: #ifdef SPEW_DEBUG
        !           294:   if (spew_debug)
        !           295:   {
        !           296:     yylex_ctr ++;
        !           297:     fprintf(stderr, "\t\t## %d ##",yylex_ctr);
        !           298:   }
        !           299: #endif
        !           300:   
        !           301:   /* This is a kludge for recognizing nested types in templates */
        !           302:   if (template_type_seen_before_scope)
        !           303:     {
        !           304:       shift_tokens (2);                /* Sync in hack_more_ids (yes, it's ugly) */
        !           305:       nth_token (1)->yychar = SCOPE;
        !           306:       yylval.ttype = hack_more_ids (0, template_type_seen_before_scope);
        !           307:       template_type_seen_before_scope = 0;
        !           308:       if (!yylval.ttype)
        !           309:        {
        !           310:          /* Sync back again, leaving SCOPE on the token stream, because we
        !           311:           * failed to substitute the original SCOPE token with a
        !           312:           * SCOPED_TYPENAME.  See rule "template_type" in cp-parse.y */
        !           313:          consume_token ();
        !           314:        }
        !           315:       else
        !           316:        {
        !           317:          yychar = SCOPED_TYPENAME;
        !           318: #ifdef SPEW_DEBUG    
        !           319:          if (spew_debug)
        !           320:            debug_yychar(yychar);
        !           321: #endif
        !           322:          return yychar;
        !           323:        }
        !           324:     }
        !           325: 
        !           326:   /* if we've got tokens, send them */
        !           327:   if (num_tokens())
        !           328:     {
        !           329:       tmp_token= *nth_token(0);
        !           330: 
        !           331:       /* TMP_TOKEN.YYLVAL.TTYPE may have been allocated on the wrong obstack.
        !           332:         If we don't find it in CURRENT_OBSTACK's current or immediately
        !           333:         previous chunk, assume it was and copy it to the current obstack.  */
        !           334:       if ((tmp_token.yychar == CONSTANT
        !           335:           || tmp_token.yychar == STRING)
        !           336:          && ! TREE_PERMANENT (tmp_token.yylval.ttype)
        !           337:          && ! probe_obstack (current_obstack, tmp_token.yylval.ttype, 2)
        !           338:          && ! probe_obstack (saveable_obstack, tmp_token.yylval.ttype, 2))
        !           339:        tmp_token.yylval.ttype = copy_node (tmp_token.yylval.ttype);
        !           340:     }
        !           341:   else
        !           342:     {
        !           343:       /* if not, grab the next one and think about it */
        !           344:       tmp_token.yychar = real_yylex ();
        !           345:       tmp_token.yylval = yylval;
        !           346:       tmp_token.end_of_file = end_of_file;
        !           347:       add_token(&tmp_token);
        !           348:     }
        !           349: 
        !           350:   /* many tokens just need to be returned. At first glance, all we
        !           351:    * have to do is send them back up, but some of them are needed to
        !           352:    * figure out local context. */
        !           353:   switch(tmp_token.yychar)
        !           354:     {
        !           355:     case EMPTY:
        !           356:       /* This is a lexical no-op.  */
        !           357:       consume_token ();
        !           358: #ifdef SPEW_DEBUG    
        !           359:       if (spew_debug)
        !           360:        debug_yychar (tmp_token.yychar);
        !           361: #endif
        !           362:       goto retry;
        !           363: 
        !           364:     case IDENTIFIER:
        !           365:       /* Note: this calls arbitrate_lookup.  */
        !           366:       trrr = lookup_name (tmp_token.yylval.ttype, -2);
        !           367:       if (trrr)
        !           368:        {
        !           369:          tmp_token.yychar = identifier_type (trrr);
        !           370:          switch (tmp_token.yychar)
        !           371:            {
        !           372:            case TYPENAME:
        !           373:              lastiddecl = identifier_typedecl_value (tmp_token.yylval.ttype);
        !           374:              if (lastiddecl == NULL_TREE)
        !           375:                lastiddecl = trrr;
        !           376:              break;
        !           377:            case IDENTIFIER:
        !           378:              lastiddecl = trrr;
        !           379:              break;
        !           380:            case PTYPENAME:
        !           381:              /* This is for cases like
        !           382:                    template<class A> X<A>::operator[] ...
        !           383:                 since "X" is (presumably) a PTYPENAME; we might want to
        !           384:                 avoid seeing the entire thing as a type name, but X<A>
        !           385:                 must be one.
        !           386: 
        !           387:                 It might not work right if the thing after the ::
        !           388:                 can be a typename nested in X<A>, but I don't think the
        !           389:                 PT code would be up to dealing with that anyways.  --KR  */
        !           390:              if (looking_for_typename == -1)
        !           391:                {
        !           392:                  scan_tokens (2);
        !           393:                  if (nth_token(1)->yychar == '<')
        !           394:                    looking_for_typename = 0;
        !           395:                }
        !           396:              break;
        !           397:            default:
        !           398:              my_friendly_abort (101);
        !           399:            }
        !           400:        }
        !           401:       else
        !           402:        lastiddecl = trrr;
        !           403:       /* and fall through to... */
        !           404:     case TYPENAME:
        !           405:     case PTYPENAME:
        !           406:       /* if (new_token) add_token (&tmp_token); */
        !           407:       *nth_token(0) = tmp_token;
        !           408:       tmp_token = frob_identifier ();
        !           409:       if (looking_for_typename < 0)
        !           410:        {
        !           411:          tmp_token.yychar = IDENTIFIER;
        !           412:          lastiddecl = 0;
        !           413:          looking_for_typename = 0;
        !           414:        }
        !           415:       else if (lastiddecl && TREE_CODE (lastiddecl) == TYPE_DECL)
        !           416:        {
        !           417:          scan_tokens (2);
        !           418:          if (nth_token(0)->yychar == IDENTIFIER
        !           419:              && nth_token (1)->yychar != SCOPE)
        !           420:            looking_for_typename = -1;
        !           421:          else
        !           422:            looking_for_typename = 0;
        !           423:          goto finish_typename_processing;
        !           424:        }
        !           425:       else
        !           426:        looking_for_typename = 0;
        !           427:       break;
        !           428: 
        !           429:     case TYPESPEC:
        !           430:     case SCSPEC:
        !           431:       consume_token ();
        !           432:     finish_typename_processing:
        !           433:       /* Now see if we should insert a START_DECLARATOR token.
        !           434:          Here are the cases caught:
        !           435: 
        !           436:         typespec ( * ID ) (    // ptr to function
        !           437:         typespec ( & ID ) (    // ref to function
        !           438:         typespec ( * ID ) [    // array of pointers
        !           439:         typespec ( & ID ) [    // array of references
        !           440: 
        !           441:         This is a terrible kludge.  */
        !           442: 
        !           443:       scan_tokens (2);
        !           444:       if (nth_token (0)->yychar == '('
        !           445:          && (nth_token (1)->yychar == '*'
        !           446:              || nth_token (1)->yychar == '&'))
        !           447:        {
        !           448:          scan_tokens (5);
        !           449:          if (nth_token (3)->yychar == ')'
        !           450:              && (nth_token (4)->yychar == '('
        !           451:                  || nth_token (4)->yychar == '['
        !           452:                  || nth_token (4)->yychar == LEFT_RIGHT)
        !           453:              && (nth_token (2)->yychar == IDENTIFIER
        !           454:                  || nth_token (2)->yychar == TYPENAME))
        !           455:            {
        !           456:              shift_tokens (1);
        !           457:              nth_token (0)->yychar = START_DECLARATOR;
        !           458:            }
        !           459:        }
        !           460:       /* Extend to handle:
        !           461: 
        !           462:         typespec (ID::* qf)(   // ptr to member function
        !           463:         typespec (ID::* qf)[   // array of ptr to member functions
        !           464: 
        !           465:         */
        !           466:       if (nth_token (0)->yychar == '('
        !           467:          && (nth_token (1)->yychar == IDENTIFIER
        !           468:              || nth_token (1)->yychar == TYPENAME))
        !           469:        {
        !           470:          scan_tokens (7);
        !           471:          if (nth_token (2)->yychar == SCOPE
        !           472:              && nth_token (3)->yychar == '*'
        !           473:              && (nth_token (4)->yychar == IDENTIFIER
        !           474:                  || nth_token (4)->yychar == TYPENAME)
        !           475:              && nth_token (5)->yychar == ')'
        !           476:              && (nth_token (6)->yychar == '('
        !           477:                  || nth_token (6)->yychar == '['
        !           478:                  || nth_token (6)->yychar == LEFT_RIGHT))
        !           479:            {
        !           480:              shift_tokens (1);
        !           481:              nth_token (0)->yychar = START_DECLARATOR;
        !           482:            }
        !           483:        }
        !           484:       break;
        !           485: 
        !           486: #if 0
        !           487:     case '(':
        !           488:       /* Handle casts.  We are looking for one of:
        !           489:          `( TYPENAME' followed by `)', or
        !           490:         `( TYPENAME *' followed by one of `[,*,&,)', or
        !           491:         `( TYPENAME &' followed by one of `[,*,&,)', or
        !           492:         `( TYPENAME [' followed by `]'.  We are punting
        !           493:         generality on scanning casts to array types.  */
        !           494:       scan_tokens (4);
        !           495:       if (nth_token (1)->yychar == IDENTIFIER)
        !           496:        {
        !           497:          tree type = identifier_typedecl_value (nth_token (1)->yylval.ttype);
        !           498:          if (type)
        !           499:            switch (nth_token (2)->yychar)
        !           500:              {
        !           501:              default:
        !           502:                break;
        !           503:              }
        !           504:        }
        !           505:       break;
        !           506: 
        !           507:     case SCOPE:
        !           508:       /* if (new_token) add_token (&tmp_token); */
        !           509:       *nth_token(0) = tmp_token;
        !           510:       tmp_token = hack_scope ();
        !           511:       break;
        !           512: #endif
        !           513: 
        !           514:     case AGGR:
        !           515:       *nth_token(0) = tmp_token;
        !           516:       do_aggr ();
        !           517:       /* fall through to output... */
        !           518:     case ENUM:
        !           519:       /* Set this again, in case we are rescanning.  */
        !           520:       looking_for_typename = 1;
        !           521:       /* fall through... */
        !           522:     default:
        !           523: #ifdef SPEW_DEBUG    
        !           524:       if (spew_debug)
        !           525:        debug_yychar(tmp_token.yychar);
        !           526: #endif
        !           527:       consume_token();
        !           528:       yylval = tmp_token.yylval;
        !           529:       yychar = tmp_token.yychar;
        !           530:       end_of_file = tmp_token.end_of_file;
        !           531:       return tmp_token.yychar;
        !           532:     }
        !           533: 
        !           534:   if (tmp_token.yychar == SCOPED_TYPENAME)
        !           535:     {
        !           536: #if 0
        !           537:       tree t2 = resolve_scope_to_name (NULL_TREE, tmp_token.yylval.ttype);
        !           538:       if (t2 != NULL_TREE)
        !           539:        {
        !           540:          tmp_token.yylval.ttype = t2;
        !           541:          tmp_token.yychar = TYPENAME;
        !           542:        }
        !           543:       else
        !           544:        {
        !           545:          /* unwind? */
        !           546:        }
        !           547:     }
        !           548:   else
        !           549:     {
        !           550:       /* couldn't get here, as is... */
        !           551: #endif
        !           552:       tmp_token.yychar = TYPENAME;
        !           553:     }
        !           554: 
        !           555:   yylval = tmp_token.yylval;
        !           556:   yychar = tmp_token.yychar;
        !           557:   end_of_file = tmp_token.end_of_file;
        !           558: #ifdef SPEW_DEBUG    
        !           559:   if (spew_debug)
        !           560:     debug_yychar(yychar);
        !           561: #endif
        !           562: /*  consume_token(); */ /* already eaten by frob_identifier?... */
        !           563:   return yychar;
        !           564: }
        !           565: 
        !           566: /* token[0] == AGGR (struct/union/enum)
        !           567:  * thus, token[1] is either a TYPENAME or a TYPENAME_DEFN
        !           568:  * if token[2] == '{' or ':' then it's TYPENAME_DEFN
        !           569:  */
        !           570: static int
        !           571: do_aggr ()
        !           572: {
        !           573:   int yc1, yc2;
        !           574:   
        !           575:   scan_tokens (2);
        !           576:   yc1 = nth_token (1)->yychar;
        !           577:   if (yc1 != TYPENAME && yc1 != IDENTIFIER && yc1 != PTYPENAME)
        !           578:     return 0;
        !           579:   yc2 = nth_token (2)->yychar;
        !           580:   if (yc2 == '{' || yc2 == ':')
        !           581:     {
        !           582:       switch (yc1)
        !           583:        {
        !           584:        case TYPENAME:
        !           585:          nth_token (1)->yychar = TYPENAME_DEFN;
        !           586:          break;
        !           587:        case PTYPENAME:
        !           588:          nth_token (1)->yychar = PTYPENAME_DEFN;
        !           589:          break;
        !           590:        case IDENTIFIER:
        !           591:          nth_token (1)->yychar = IDENTIFIER_DEFN;
        !           592:          break;
        !           593:        default:
        !           594:          my_friendly_abort (102);
        !           595:        }
        !           596:     }
        !           597:   return 0;
        !           598: }  
        !           599: 
        !           600: static struct token
        !           601: frob_identifier ()
        !           602: {
        !           603:   /* we could have a type, if it is followed by :: (if so, suck it all up); */
        !           604:   /* we could have a ptypename; */
        !           605:   /* we could have a normal identifier. */
        !           606:   tree t1;
        !           607:   struct token rt;
        !           608:   
        !           609:   scan_tokens(1);
        !           610:   rt = *nth_token(0);
        !           611: 
        !           612: #if 0
        !           613:   if (nth_token(1)->yychar == '<')
        !           614:     {
        !           615:       t1 = hack_ptype();       /* suck up the whole thing */
        !           616:       if (t1)
        !           617:        {
        !           618:          rt.yylval.ttype = t1;
        !           619:          rt.yychar = TYPENAME;
        !           620:          *nth_token(0) = rt;
        !           621:        }
        !           622:       /* else fall out bottom */
        !           623:     }  
        !           624: #endif
        !           625: 
        !           626:   if (nth_token(1)->yychar == SCOPE)
        !           627:     {
        !           628: #if 0
        !           629:       t1 = hack_more_ids(0);
        !           630:       if (t1 && TREE_CODE(t1) == SCOPE_REF)
        !           631: #else
        !           632:       t1 = hack_more_ids(0, nth_token (0)->yylval.ttype);
        !           633:       if (t1)
        !           634: #endif
        !           635:        {
        !           636:          rt.yylval.ttype = t1;
        !           637:          rt.yychar = SCOPED_TYPENAME ;
        !           638:          return rt;
        !           639:        }
        !           640:       else
        !           641:        {
        !           642:          /* deal with types (enums?) in classes... */
        !           643:          struct token *tok;
        !           644:          tree ta, tb;
        !           645:          scan_tokens(3);
        !           646: 
        !           647:          /* Have to check for a type conversion operator
        !           648:             to a nested type.  */
        !           649:          if (nth_token (2)->yychar == OPERATOR)
        !           650:            tok = nth_token (3);
        !           651:          else
        !           652:            tok = nth_token(2);
        !           653: 
        !           654:          if (tok->yychar == IDENTIFIER || tok->yychar == TYPENAME)
        !           655:            {
        !           656:              ta = build_parse_node (SCOPE_REF,
        !           657:                                     nth_token(0)->yylval.ttype,
        !           658:                                     tok->yylval.ttype);
        !           659:              tb = resolve_scope_to_name (NULL_TREE, ta);
        !           660: 
        !           661:              if (tb != NULL_TREE)
        !           662:                {
        !           663:                  if (nth_token (2)->yychar == OPERATOR)
        !           664:                    {
        !           665:                      /* Have to keep these tokens around
        !           666:                         so we can finish parsing the declaration.
        !           667:                         What do we do for
        !           668: 
        !           669:                         int foo::operator bar::baz (); 
        !           670: 
        !           671:                         where bar is a nested class in foo?  */
        !           672:                      nth_token (3)->yychar = TYPENAME;
        !           673:                      nth_token (3)->yylval.ttype = tb;
        !           674:                    }
        !           675:                  else
        !           676:                    {
        !           677:                      consume_token (); /* base type */
        !           678:                      consume_token (); /* SCOPE */
        !           679:                      consume_token (); /* member type */
        !           680:                      rt.yychar = TYPENAME;
        !           681:                      rt.yylval.ttype = tb;
        !           682:                      rt.end_of_file = tok->end_of_file;
        !           683:                      return rt;
        !           684:                    }
        !           685:                  
        !           686:                }
        !           687:            }      
        !           688:          /* else fall out bottom */
        !           689:        }
        !           690:     }
        !           691:             
        !           692:   consume_token();
        !           693:   return rt;
        !           694: }
        !           695: 
        !           696: /* When this function is called, nth_token(0) is the current
        !           697:    token we are scanning.  This means that the next token we'll
        !           698:    scan is nth_token (1).  Usually the next token we'll scan
        !           699:    is nth_token (0) (and the current token is in [yylval,yychar]).  */
        !           700: tree
        !           701: arbitrate_lookup (name, exp_decl, type_decl)
        !           702:      tree name, exp_decl, type_decl;
        !           703: {
        !           704:   int ch;
        !           705:   tree t;
        !           706:   char *assume;
        !           707: 
        !           708:   scan_tokens (3);
        !           709:   ch = nth_token (1)->yychar;
        !           710: 
        !           711:   switch (ch)
        !           712:     {
        !           713:     case '(':
        !           714:     case LEFT_RIGHT:
        !           715:       /* If we guessed wrong here, `build_functional_cast' can fix it.  */
        !           716:       return type_decl;
        !           717: 
        !           718:     case '=':
        !           719:       if (global_bindings_p ())
        !           720:        /* Probably a default parameter.  */
        !           721:        return type_decl;
        !           722:       /* Probably not an initialization.  */
        !           723:       return exp_decl;
        !           724: 
        !           725:     case '[':
        !           726:       /* This needs special help because an expression inside the
        !           727:         brackets means nothing.  */
        !           728:       {
        !           729:        int i;
        !           730: 
        !           731:        for (i = 0; i < 42; i++)
        !           732:          {
        !           733:            int ith_yychar;
        !           734: 
        !           735:            scan_tokens (3+i);
        !           736:            ith_yychar = nth_token (2+i)->yychar;
        !           737: 
        !           738:            /* If we hit an undefined identifier, assume
        !           739:               the decl in arbitration is its type specifier.  */
        !           740:            if (ith_yychar == IDENTIFIER
        !           741:                && lookup_name (nth_token (2+i)->yylval.ttype, 0) == 0)
        !           742:              return type_decl;
        !           743:            else if (ith_yychar == ']')
        !           744:              {
        !           745:                /* There are only a few things we expect after a ']'
        !           746:                   in a declarator.  */
        !           747:                i += 1;
        !           748:                scan_tokens (4+i);
        !           749:                ith_yychar = nth_token (2+i)->yychar;
        !           750: 
        !           751:                /* These are inconclusive.  */
        !           752:                if (ith_yychar == LEFT_RIGHT
        !           753:                    || ith_yychar == '('
        !           754:                    || ith_yychar == '['
        !           755:                    || ith_yychar == ',')
        !           756:                  continue;
        !           757:                /* stmt or decl?  We'll probably never know.  */
        !           758:                else if (ith_yychar == ';')
        !           759:                  goto warn_ambiguous;
        !           760: 
        !           761:                if (ith_yychar == '=')
        !           762:                  {
        !           763:                    if (nth_token (3+i)->yychar == '{')
        !           764:                      return type_decl;
        !           765:                    continue;
        !           766:                  }
        !           767: 
        !           768:                /* Whatever it is, it looks like we're processing an expr.  */
        !           769:                return exp_decl;
        !           770:              }
        !           771:          }
        !           772:        goto warn_ambiguous;
        !           773:       }
        !           774: 
        !           775:     case ',':
        !           776:     case ';':
        !           777:     case '&':
        !           778:     case '<':
        !           779:     case '*':
        !           780:     case ']':
        !           781:     case ')':
        !           782:     case '>':
        !           783:       /* see if the next token looks like it wants to be part
        !           784:         of a declaration list or an expression list.  */
        !           785:       {
        !           786:        int i;
        !           787: 
        !           788:        /* Some heuristics: if we are inside a function definition,
        !           789:           prefer the local declaration.  */
        !           790:        if (! global_bindings_p ())
        !           791:          {
        !           792:            if (IDENTIFIER_LOCAL_VALUE (name) == exp_decl)
        !           793:              return exp_decl;
        !           794:            if (IDENTIFIER_LOCAL_VALUE (name) != type_decl
        !           795:                && IDENTIFIER_CLASS_VALUE (name) == exp_decl)
        !           796:              return exp_decl;
        !           797:          }
        !           798:        /* If these symbols follow in a list, we know it's a list of
        !           799:           expressions.  */
        !           800:        if (follows_identifier[nth_token (2)->yychar])
        !           801:          return exp_decl;
        !           802: 
        !           803:        /* If we see a id&, or id&) the we are probably in an argument list. */
        !           804:        if (ch=='&'
        !           805:            && (nth_token (2)->yychar == ',' || nth_token (2)->yychar == ')'))
        !           806:          return type_decl;
        !           807: 
        !           808:        /* Look for the first identifier or other distinguishing token
        !           809:           we find in the next several tokens.  */
        !           810:        for (i = 0; i < 42; i++)
        !           811:          {
        !           812:            int ith_yychar;
        !           813: 
        !           814:            scan_tokens (3+i);
        !           815:            ith_yychar = nth_token (2+i)->yychar;
        !           816: 
        !           817:            if (ith_yychar == IDENTIFIER)
        !           818:              {
        !           819:                tree as_type = lookup_name (nth_token (2+i)->yylval.ttype, 1);
        !           820:                if (as_type && TREE_CODE (as_type) != TYPE_DECL)
        !           821:                  return exp_decl;
        !           822:                /* An undeclared identifier or a typename means we're
        !           823:                   probably looking at a typename.  */
        !           824:                return type_decl;
        !           825:              }
        !           826:            else if (ith_yychar == EMPTY
        !           827:                     || follows_identifier[ith_yychar])
        !           828:              return exp_decl;
        !           829:            else if (follows_typename[ith_yychar])
        !           830:              return type_decl;
        !           831:            /* stmt or decl?  We'll probably never know.  */
        !           832:            else if (ith_yychar == ';')
        !           833:              goto warn_ambiguous;
        !           834:          }
        !           835:        goto warn_ambiguous;
        !           836:       }
        !           837: 
        !           838:     default:
        !           839:       if (follows_identifier[ch])
        !           840:        return exp_decl;
        !           841:       if (follows_typename[ch])
        !           842:        return type_decl;
        !           843: 
        !           844:       /* Fall through...  */
        !           845:     warn_ambiguous:
        !           846:       if (ch == '[')
        !           847:        {
        !           848:          assume = "expression";
        !           849:          t = exp_decl;
        !           850:        }
        !           851:       else
        !           852:        {
        !           853:          assume = "type";
        !           854:          t = type_decl;
        !           855:        }
        !           856: 
        !           857:       warning ("name `%s' could be type or expression; compiler assuming %s",
        !           858:               IDENTIFIER_POINTER (DECL_NAME (t)), assume);
        !           859:       return t;
        !           860:     }
        !           861: }
        !           862: 
        !           863: /* now returns decl_node */
        !           864: 
        !           865: #if 0
        !           866: static tree
        !           867: hack_ptype()
        !           868: {
        !           869:   /* when we get here, we know that [0] is a ptype and [1] is '<'.
        !           870:    * now we loop over simple parameters. */
        !           871:   struct token this_param;
        !           872:   int n = 2;
        !           873:   tree tplist = 0;
        !           874:   tree tc;
        !           875:   scan_tokens(n+1);
        !           876:   
        !           877:   while((this_param = *nth_token(n)).yychar != '>')
        !           878:     {
        !           879:       /* if it is a type, add it to the list */
        !           880:       tree thistype;
        !           881:     
        !           882:       switch(this_param.yychar)
        !           883:        {
        !           884:        case IDENTIFIER:
        !           885:        case TYPENAME:
        !           886:        case TYPESPEC:
        !           887:          break;
        !           888:        default:
        !           889:          return 0;
        !           890:        }
        !           891: 
        !           892:       thistype = this_param.yylval.ttype;
        !           893:       thistype = lookup_name(thistype, 1);
        !           894:       thistype = TREE_TYPE (thistype);
        !           895:         
        !           896:       if (tplist)
        !           897:        tplist = chainon (tplist, build_tree_list (NULL_TREE, thistype));
        !           898:       else
        !           899:        tplist = build_tree_list(NULL_TREE, thistype);
        !           900:     
        !           901:     
        !           902:       /* then suck up the comma */
        !           903:       n++;
        !           904:       scan_tokens(n+1);
        !           905:       this_param = *nth_token(n);
        !           906:       if (this_param.yychar == ',')
        !           907:        {
        !           908:          n++;
        !           909:          scan_tokens(n+1);
        !           910:          continue;
        !           911:        }
        !           912:       if (this_param.yychar == '>')
        !           913:        break;
        !           914:       return 0;
        !           915:     }
        !           916: 
        !           917:   /* once we're done, lookup_template_class -> identifier */
        !           918:   tc = lookup_template_class (nth_token(0)->yylval.ttype,tplist);
        !           919:   /* then lookup_name on that to get a type, if there is one */
        !           920:   tc = lookup_name (tc, 1);
        !           921:   if (tc)
        !           922:     {
        !           923:       int i;
        !           924:       /* don't actually eat the trailing '>'... we can replace it! */
        !           925:       for (i=0; i<n; i++)
        !           926:        consume_token();
        !           927:       /*    IDENTIFIER_TYPE_VALUE (DECL_NAME (tc)) = */
        !           928:       return DECL_NAME (tc);
        !           929:     }
        !           930:   return NULL_TREE;
        !           931: }
        !           932: #endif
        !           933: 
        !           934: #if 0
        !           935: static tree
        !           936: hack_more_ids (n)
        !           937:      int n;
        !           938: {
        !           939:   /*
        !           940:    * The recursion should probably do consume_tokens(), since once we've started
        !           941:    * down an IDENTIFIER SCOPE ... chain, we don't need to back-track - we just
        !           942:    * get as much as we can, make SCOPE_REF's out of it, and return it.
        !           943:    */
        !           944:   struct token this_iter, this2_iter;
        !           945:   int tmp_y;
        !           946:   
        !           947:   scan_tokens(n+1);
        !           948:   this_iter = *nth_token(n);
        !           949: 
        !           950:   tmp_y = nth_token(n)->yychar;
        !           951:   if (tmp_y == IDENTIFIER || tmp_y == TYPENAME)
        !           952:     {
        !           953:       scan_tokens(n+2+2);
        !           954:       if (nth_token(n+1)->yychar == SCOPE)
        !           955:        {
        !           956:          if (nth_token(n+1+2)->yychar == SCOPE)
        !           957:            {
        !           958:              tree hmi;
        !           959:        
        !           960:              consume_token();  /* last IDENTIFIER (this_iter) */
        !           961:              consume_token();  /* last SCOPE */
        !           962:              this2_iter = *nth_token(n);
        !           963:        
        !           964:              hmi = hack_more_ids (n);
        !           965:        
        !           966:              if (hmi)
        !           967:                return build_parse_node (SCOPE_REF, this_iter.yylval.ttype, hmi);
        !           968:              consume_token(); /* last IDENTIFIER (this2_iter) */
        !           969:              return build_parse_node (SCOPE_REF, this_iter.yylval.ttype,
        !           970:                                       this2_iter.yylval.ttype);
        !           971:            }
        !           972:          else
        !           973:            {
        !           974:              /* consume_token();       */      /* last IDENTIFIER */
        !           975:              /* leave whatever else we got */
        !           976:              /* return this_iter.yylval.ttype; */
        !           977:              return NULL_TREE;
        !           978:            }
        !           979:        }
        !           980:     }
        !           981:   return NULL_TREE;            /* @@ may need to backtrack */
        !           982: }
        !           983: #else
        !           984: /* [email protected] says:  I didn't understand how the code above was intended
        !           985:  * to work, so I rewrote it (also changed the interface a bit).  This code
        !           986:  * dives down an IDENTIFIER/TYPENAME SCOPE ... chain as long as the parsed
        !           987:  * type prefix constitutes recognizable (by resolve_scope_to_name) types.
        !           988:  * Interface changed like this:
        !           989:  * 1. Takes an extra argument containing the name of the the type recognized
        !           990:  *    so far.
        !           991:  * 2. Now returns the name of the type instead of a SCOPE_REF. */
        !           992: static tree
        !           993: hack_more_ids(n, outer)
        !           994:   int n;
        !           995:   tree outer;
        !           996: {
        !           997:   int ch;
        !           998:   tree type, val;
        !           999: 
        !          1000:   scan_tokens (n + 2);
        !          1001:   if (nth_token (n + 1)->yychar != SCOPE
        !          1002:       || ((ch = nth_token (n + 2)->yychar) != IDENTIFIER && ch != TYPENAME))
        !          1003:     return NULL_TREE;
        !          1004:   val = build_parse_node (SCOPE_REF, outer, nth_token (n + 2)->yylval.ttype);
        !          1005:   type = resolve_scope_to_name (NULL_TREE, val);
        !          1006:   if (type == NULL_TREE)
        !          1007:     return NULL_TREE;
        !          1008:   consume_token ();
        !          1009:   consume_token ();
        !          1010:   val = hack_more_ids (n, type);
        !          1011:   if (! val)
        !          1012:     consume_token ();
        !          1013:   return val ? val : type;
        !          1014: }
        !          1015: #endif
        !          1016: 
        !          1017: #if 0
        !          1018: static struct token
        !          1019: hack_scope ()
        !          1020: {
        !          1021:   /* we've got a :: - what follows is either a global var or a type. */
        !          1022:   /* hmm, template names can be in the global scope too... */
        !          1023:   tree t1;
        !          1024:   struct token rt;
        !          1025:   
        !          1026:   scan_tokens(1);
        !          1027:   if (nth_token(1)->yychar == IDENTIFIER)
        !          1028:     {
        !          1029:       /* @@ this is probably not right, but doesn't get hit yet */
        !          1030:       t1 = build_parse_node (SCOPE_REF,
        !          1031:                             NULL_TREE, /* to get "global" scope */
        !          1032:                             hack_more_ids(0)); /* do some prefetching */
        !          1033:       rt.yylval.ttype = t1;
        !          1034:       rt.yychar =              /*SCOPED_*/TYPENAME;
        !          1035:       return rt;
        !          1036:     }
        !          1037:   else
        !          1038:     {
        !          1039:       rt = *nth_token(0);
        !          1040:       consume_token();
        !          1041:       return rt;
        !          1042:     }
        !          1043: }
        !          1044: #endif
        !          1045:   
        !          1046: /*
        !          1047:  * Generations:
        !          1048:  *     
        !          1049:  * PINST: PTYPE { saved_arg_count = arg_count($1) }
        !          1050:  *        '<' { arg_c = 0; } PARGS '>'
        !          1051:  *        ;
        !          1052:  * PARG: TYPE
        !          1053:  *       | VALUE
        !          1054:  *       ;
        !          1055:  * (of course the arg counting doesn't work for recursion... Do it right.)
        !          1056:  * PARGS: PARG { assert(arg_c == saved_arg_count); }
        !          1057:  *        | PARG ',' PARGS     { arg_c++; }
        !          1058:  *        ;
        !          1059:  * ATYPE: PINST
        !          1060:  *        | TYPEID
        !          1061:  *        ;
        !          1062:  * TYPE: ATYPE
        !          1063:  *       | ATYPE { basetype = $1; } '::' TYPEKIDS
        !          1064:  *       ;
        !          1065:  * TYPEKIDS: TYPE { assert ($1 is a member of basetype); }
        !          1066:  *       | TYPEKIDS { basetype += $1} TYPE { assert( $3 is in basetype ); }
        !          1067:  *       ;
        !          1068:  *
        !          1069:  *
        !          1070:  * state0: ; ATYPE
        !          1071:  *     TYPE '<': ac = args($0), base = CALL state1, state3     
        !          1072:  *     TYPE '::': base=$0, state3
        !          1073:  *     else return TYPE
        !          1074:  * state1: ; begin PARGS
        !          1075:  *     if(ac < list length) punt
        !          1076:  *     PARG ",": add to list, state1
        !          1077:  *     PARG ">": add to list, return
        !          1078:  *     else unravel
        !          1079:  * state3: ; begin TYPEKIDS
        !          1080:  *     TYPE: 
        !          1081:  */
        !          1082:   
        !          1083:   
        !          1084: #ifdef SPEW_DEBUG    
        !          1085: /* debug_yychar takes a yychar (token number) value and prints its name. */
        !          1086: static int
        !          1087: debug_yychar (yy)
        !          1088:      int yy;
        !          1089: {
        !          1090:   /* In cp-parse.y: */
        !          1091:   extern char *debug_yytranslate ();
        !          1092:   
        !          1093:   int i;
        !          1094:   
        !          1095:   if(yy<256) {
        !          1096:     fprintf (stderr, "<%d: %c >\n", yy, yy);
        !          1097:     return 0;
        !          1098:   }
        !          1099:   fprintf (stderr, "<%d:%s>\n", yy, debug_yytranslate (yy));
        !          1100:   return 1;
        !          1101: }
        !          1102: 
        !          1103: #endif
        !          1104: 
        !          1105: #ifdef OBJCPLUS
        !          1106: /* Search the lookahead tokens for protocol qualifiers and change them into
        !          1107:    ordinary identifiers.  */
        !          1108: void
        !          1109: forget_saved_protocol_qualifiers ()
        !          1110: {
        !          1111:  
        !          1112:   int i;
        !          1113:   struct token *tmp;
        !          1114: 
        !          1115:   i = num_tokens ();
        !          1116:   while (i-- > 0)
        !          1117:     {
        !          1118:       tmp = nth_token (i);
        !          1119:       if (tmp->yychar == TYPE_QUAL
        !          1120:          && TREE_CODE (tmp->yylval.ttype) == IDENTIFIER_NODE)
        !          1121:        {
        !          1122:          char *name = IDENTIFIER_POINTER (tmp->yylval.ttype);
        !          1123:          if (strcmp (name, "in") == 0
        !          1124:              || strcmp (name, "out") == 0
        !          1125:              || strcmp (name, "inout") == 0
        !          1126:              || strcmp (name, "bycopy") == 0
        !          1127:              || strcmp (name, "oneway") == 0)
        !          1128:            tmp->yychar = IDENTIFIER;
        !          1129:        }
        !          1130:     }
        !          1131: }
        !          1132: #endif

unix.superglobalmegacorp.com

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