⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cp-spew.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Type Analyzer for GNU C++.   Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.   Hacked... nay, bludgeoned... by Mark Eichin (eichin@cygnus.com)This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING.  If not, write tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  *//* This file is the type analyzer for GNU C++.  To debug it, define SPEW_DEBUG   when compiling cp-parse.c and cp-spew.c.  */#include "config.h"#include <stdio.h>#include "input.h"#include "tree.h"#include "cp-lex.h"#include "cp-parse.h"#include "cp-tree.h"#include "flags.h"#include "obstack.h"/* This takes a token stream that hasn't decided much about types and   tries to figure out as much as it can, with excessive lookahead and   backtracking. *//* fifo of tokens recognized and available to parser. */struct token  {  /* The values for YYCHAR will fit in a short.  */  short		yychar;  short		end_of_file;  YYSTYPE	yylval;};static int do_aggr ();static struct token frob_identifier ();static struct token hack_scope ();static tree hack_ptype ();static tree hack_more_ids ();/* From cp-lex.c: *//* the declaration found for the last IDENTIFIER token read in.   yylex must look this up to detect typedefs, which get token type TYPENAME,   so it is left around in case the identifier is not a typedef but is   used in a context which makes it a reference to a variable.  */extern tree lastiddecl;		/* let our brains leak out here too */extern int	yychar;		/*  the lookahead symbol		*/extern YYSTYPE	yylval;		/*  the semantic value of the		*/				/*  lookahead symbol			*/extern int end_of_file;struct obstack token_obstack;int first_token;  #ifdef SPEW_DEBUGint spew_debug = 0;static unsigned int yylex_ctr = 0;static int debug_yychar ();#endifstatic char follows_typename[END_OF_SAVED_INPUT+1];static char follows_identifier[END_OF_SAVED_INPUT+1];/* This is a hack!!! TEMPLATE_TYPE_SEEN_BEFORE_SCOPE consists of the name * of the last template_type parsed in cp-parse.y if it is followed by a * scope operator.  It will be reset inside the next invocation of yylex(). * This is used for recognizing nested types inside templates. * - niklas@appli.se */tree template_type_seen_before_scope;/* Initialize token_obstack. Called once, from init_lex.  */voidinit_spew (){  static char *chars_following_identifier = ".+-|/%^!?:";  short *ps;  static short toks_follow_ids[] =    { POINTSAT_LEFT_RIGHT, ASSIGN, RANGE, OROR, ANDAND, MIN_MAX, EQCOMPARE,      ARITHCOMPARE, LSHIFT, RSHIFT, UNARY, PLUSPLUS, MINUSMINUS, POINTSAT,      POINTSAT_STAR, DOT_STAR, CONSTANT, STRING, SIZEOF, ENUM, IF,      ELSE, WHILE, DO, FOR, SWITCH, CASE, DEFAULT, BREAK, CONTINUE,      RETURN, GOTO, ASM_KEYWORD, TYPEOF, ALIGNOF, HEADOF, CLASSOF, ATTRIBUTE,      AGGR, VISSPEC, DELETE, RAISE, RERAISE, TRY, EXCEPT, CATCH,      THROW, ANSI_TRY, ANSI_THROW, EXTERN_LANG_STRING, ALL,      END_OF_SAVED_INPUT, -1 };  static short toks_follow_types[] =    { IDENTIFIER, TYPENAME, SCOPED_TYPENAME, SCSPEC, TYPESPEC, TYPE_QUAL,      ELLIPSIS, THIS, OPERATOR, DYNAMIC, TEMPLATE, SCOPE, START_DECLARATOR,      TYPENAME_COLON, PAREN_STAR_PAREN, TYPENAME_ELLIPSIS, PTYPENAME,      PRE_PARSED_FUNCTION_DECL, PRE_PARSED_CLASS_DECL, -1 };  gcc_obstack_init(&token_obstack);  /* Initialize the arrays saying what tokens are definitely     (or possibly) valid following typenames and identifiers.  */  while (*chars_following_identifier)    follows_identifier[*chars_following_identifier++] = 1;  for (ps = toks_follow_ids; *ps != -1; ps++)    follows_identifier[*ps] = 1;  for (ps = toks_follow_types; *ps != -1; ps++)    follows_typename[*ps] = 1;}#ifdef SPEW_DEBUG/* Use functions for debugging...  *//* Return the number of tokens available on the fifo. */static intnum_tokens (){  return (obstack_object_size(&token_obstack)/sizeof(struct token))    - first_token;}/* Fetch the token N down the line from the head of the fifo. */static struct token*nth_token (n)     int n;{  /* could just have this do slurp_ implicitly, but this way is easier   * to debug... */  my_friendly_assert (n < num_tokens(), 298);  return ((struct token*)obstack_base(&token_obstack))+n+first_token;}/* Add a token to the token fifo. */static voidadd_token (t)     struct token* t;{  obstack_grow(&token_obstack,t,sizeof (struct token));}/* Consume the next token out of the fifo.  */static voidconsume_token(){  if (num_tokens() == 1)    {      obstack_free(&token_obstack, obstack_base (&token_obstack));      first_token = 0;    }  else    first_token++;}#else/* ...otherwise use macros.  */#define num_tokens() \  ((obstack_object_size(&token_obstack)/sizeof(struct token)) - first_token)#define nth_token(N) \  (((struct token*)obstack_base(&token_obstack))+(N)+first_token)#define add_token(T) obstack_grow(&token_obstack, (T), sizeof (struct token))#define consume_token() \  (num_tokens() == 1							\   ? (obstack_free (&token_obstack, obstack_base (&token_obstack)),	\      (first_token = 0))						\   : first_token++)#endif/* Pull in enough tokens from real_yylex that the queue is N long.  */static voidscan_tokens (n)     int n;{  int i;  struct token *tmp;  /* We cannot read past certain tokens, so make sure we don't.  */  i = num_tokens ();  if (i > n)    return;  while (i-- > 0)    {      tmp = nth_token (i);      /* Never read past these characters: they might separate	 the current input stream from one we save away later.  */      if (tmp->yychar == '{' || tmp->yychar == ':')	goto pad_tokens;    }  while (num_tokens() <= n)    {      obstack_blank(&token_obstack,sizeof (struct token));      tmp = ((struct token *)obstack_next_free (&token_obstack))-1;      tmp->yychar = real_yylex();      tmp->end_of_file = end_of_file;      tmp->yylval = yylval;      end_of_file = 0;      if (tmp->yychar == '{'	  || tmp->yychar == ':'	  || tmp->yychar == ';')	{	pad_tokens:	  while (num_tokens () <= n)	    {	      obstack_blank(&token_obstack,sizeof (struct token));	      tmp = ((struct token *)obstack_next_free (&token_obstack))-1;	      tmp->yychar = EMPTY;	      tmp->end_of_file = 0;	    }	}    }}/* Create room for N tokens at the front of the fifo.  This is used   to insert new tokens into the stream ahead of the current token.  */static voidshift_tokens (n)     int n;{  if (first_token >= n)    first_token -= n;  else    {      int old_token_count = num_tokens ();      char *tmp;      obstack_blank (&token_obstack, (n-first_token) * sizeof (struct token));      if (old_token_count)	{	  tmp = (char *)alloca ((num_tokens () + (n-first_token))				* sizeof (struct token));	  /* This move does not rely on the system being able to handle	     overlapping moves.  */	  bcopy (nth_token (0), tmp, old_token_count * sizeof (struct token));	  bcopy (tmp, nth_token (n), old_token_count * sizeof (struct token));	}      first_token = 0;    }}intprobe_obstack (h, obj, nlevels)     struct obstack *h;     tree obj;     unsigned int nlevels;{  register struct _obstack_chunk*  lp;	/* below addr of any objects in this chunk */  register struct _obstack_chunk*  plp;	/* point to previous chunk if any */  lp = (h)->chunk;  /* We use >= rather than > since the object cannot be exactly at     the beginning of the chunk but might be an empty object exactly     at the end of an adjacent chunk. */  for (; nlevels > 0 && lp != 0 && ((tree)lp >= obj || (tree)lp->limit < obj);       nlevels -= 1)    {      plp = lp->prev;      lp = plp;          }  return nlevels > 0 && lp != 0;}/* from cp-lex.c: *//* Value is 1 if we should try to make the next identifier look like a   typename (when it may be a local variable or a class variable).   Value is 0 if we treat this name in a default fashion.   Value is -1 if we must not see a type name.  */extern int looking_for_typename;extern struct obstack *current_obstack, *saveable_obstack;intyylex(){  struct token tmp_token;  tree trrr; retry:#ifdef SPEW_DEBUG  if (spew_debug)  {    yylex_ctr ++;    fprintf(stderr, "\t\t## %d ##",yylex_ctr);  }#endif    /* This is a kludge for recognizing nested types in templates */  if (template_type_seen_before_scope)    {      shift_tokens (2);		/* Sync in hack_more_ids (yes, it's ugly) */      nth_token (1)->yychar = SCOPE;      yylval.ttype = hack_more_ids (0, template_type_seen_before_scope);      template_type_seen_before_scope = 0;      if (!yylval.ttype)	{	  /* Sync back again, leaving SCOPE on the token stream, because we	   * failed to substitute the original SCOPE token with a	   * SCOPED_TYPENAME.  See rule "template_type" in cp-parse.y */	  consume_token ();	}      else	{	  yychar = SCOPED_TYPENAME;#ifdef SPEW_DEBUG    	  if (spew_debug)	    debug_yychar(yychar);#endif	  return yychar;	}    }  /* if we've got tokens, send them */  if (num_tokens())    {      tmp_token= *nth_token(0);      /* TMP_TOKEN.YYLVAL.TTYPE may have been allocated on the wrong obstack.	 If we don't find it in CURRENT_OBSTACK's current or immediately	 previous chunk, assume it was and copy it to the current obstack.  */      if ((tmp_token.yychar == CONSTANT	   || tmp_token.yychar == STRING)	  && ! TREE_PERMANENT (tmp_token.yylval.ttype)	  && ! probe_obstack (current_obstack, tmp_token.yylval.ttype, 2)	  && ! probe_obstack (saveable_obstack, tmp_token.yylval.ttype, 2))	tmp_token.yylval.ttype = copy_node (tmp_token.yylval.ttype);    }  else    {      /* if not, grab the next one and think about it */      tmp_token.yychar = real_yylex ();      tmp_token.yylval = yylval;      tmp_token.end_of_file = end_of_file;      add_token(&tmp_token);    }  /* many tokens just need to be returned. At first glance, all we   * have to do is send them back up, but some of them are needed to   * figure out local context. */  switch(tmp_token.yychar)    {    case EMPTY:      /* This is a lexical no-op.  */      consume_token ();#ifdef SPEW_DEBUG          if (spew_debug)	debug_yychar (tmp_token.yychar);#endif      goto retry;    case IDENTIFIER:      /* Note: this calls arbitrate_lookup.  */      trrr = lookup_name (tmp_token.yylval.ttype, -1);      if (trrr)	{	  tmp_token.yychar = identifier_type (trrr);	  switch (tmp_token.yychar)	    {	    case TYPENAME:	      lastiddecl = IDENTIFIER_TYPEDECL_VALUE (tmp_token.yylval.ttype);	      break;	    case IDENTIFIER:	      lastiddecl = trrr;	      break;	    case PTYPENAME:	      /* This is for cases like		    template<class A> X<A>::operator[] ...		 since "X" is (presumably) a PTYPENAME; we might want to		 avoid seeing the entire thing as a type name, but X<A>		 must be one.		 It might not work right if the thing after the ::		 can be a typename nested in X<A>, but I don't think the		 PT code would be up to dealing with that anyways.  --KR  */	      if (looking_for_typename == -1)		{		  scan_tokens (2);		  if (nth_token(1)->yychar == '<')		    looking_for_typename = 0;		}	      break;	    default:	      my_friendly_abort (101);	    }	}      else	lastiddecl = trrr;      /* and fall through to... */    case TYPENAME:    case PTYPENAME:      /* if (new_token) add_token (&tmp_token); */      *nth_token(0) = tmp_token;      tmp_token = frob_identifier ();      if (looking_for_typename < 0)	{	  tmp_token.yychar = IDENTIFIER;	  lastiddecl = 0;	  looking_for_typename = 0;	}      else if (lastiddecl && TREE_CODE (lastiddecl) == TYPE_DECL)	{	  scan_tokens (2);	  if (nth_token(0)->yychar == IDENTIFIER	      && nth_token (1)->yychar != SCOPE)	    looking_for_typename = -1;	  else	    looking_for_typename = 0;	  goto finish_typename_processing;	}      else	looking_for_typename = 0;      break;    case TYPESPEC:    case SCSPEC:      consume_token ();    finish_typename_processing:      /* Now see if we should insert a START_DECLARATOR token.         Here are the cases caught:	 typespec ( * ID ) (	// ptr to function	 typespec ( & ID ) (	// ref to function	 typespec ( * ID ) [	// array of pointers	 typespec ( & ID ) [	// array of references	 This is a terrible kludge.  */      scan_tokens (2);      if (nth_token (0)->yychar == '('	  && (nth_token (1)->yychar == '*'	      || nth_token (1)->yychar == '&'))	{	  scan_tokens (5);	  if (nth_token (3)->yychar == ')'	      && (nth_token (4)->yychar == '('		  || nth_token (4)->yychar == '['		  || nth_token (4)->yychar == LEFT_RIGHT)	      && (nth_token (2)->yychar == IDENTIFIER		  || nth_token (2)->yychar == TYPENAME))	    {	      shift_tokens (1);	      nth_token (0)->yychar = START_DECLARATOR;	    }	}      break;#if 0    case '(':      /* Handle casts.  We are looking for one of:         `( TYPENAME' followed by `)', or	 `( TYPENAME *' followed by one of `[,*,&,)', or	 `( TYPENAME &' followed by one of `[,*,&,)', or	 `( TYPENAME [' followed by `]'.  We are punting	 generality on scanning casts to array types.  */      scan_tokens (4);      if (nth_token (1)->yychar == IDENTIFIER)	{	  tree type = identifier_typedecl_value (nth_token (1)->yylval.ttype);	  if (type)	    switch (nth_token (2)->yychar)	      {	      default:		break;	      }	}      break;    case SCOPE:      /* if (new_token) add_token (&tmp_token); */      *nth_token(0) = tmp_token;      tmp_token = hack_scope ();      break;#endif    case AGGR:      *nth_token(0) = tmp_token;      do_aggr ();      /* fall through to output... */    case ENUM:      /* Set this again, in case we are rescanning.  */      looking_for_typename = 1;      /* fall through... */    default:#ifdef SPEW_DEBUG          if (spew_debug)	debug_yychar(tmp_token.yychar);#endif      consume_token();      yylval = tmp_token.yylval;      yychar = tmp_token.yychar;      end_of_file = tmp_token.end_of_file;      return tmp_token.yychar;    }  if (tmp_token.yychar == SCOPED_TYPENAME)    {#if 0      tree t2 = resolve_scope_to_name (NULL_TREE, tmp_token.yylval.ttype);      if (t2 != NULL_TREE)	{	  tmp_token.yylval.ttype = t2;	  tmp_token.yychar = TYPENAME;	}      else	{	  /* unwind? */	}    }  else    {      /* couldn't get here, as is... */#endif      tmp_token.yychar = TYPENAME;    }  yylval = tmp_token.yylval;  yychar = tmp_token.yychar;  end_of_file = tmp_token.end_of_file;#ifdef SPEW_DEBUG      if (spew_debug)    debug_yychar(yychar);#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -