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

📄 c-aux-info.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
   This routine will also return with the global variable "data_type" set to   some string value which is the "basic" data-type of the given complete type.   This "data_type" string can be concatenated onto the front of the returned   string after this routine returns to its caller.   In complicated cases involving pointer types, array types, or function   types, the C declaration syntax requires an "inside out" approach, i.e. if   you have a type which is a "pointer-to-function" type, you need to handle   the "pointer" part first, but it also has to be "innermost" (relative to   the declaration stuff for the "function" type).  Thus, is this case, you   must prepend a "(*" and append a ")" to the name of the item (i.e. formal   variable).  Then you must append and prepend the other info for the   "function type" part of the overall type.   To handle the "innermost precedence" rules of complicated C declarators, we   do the following (in this routine).  The input parameter called "ret_val"   is treated as a "seed".  Each time gen_type is called (perhaps recursively)   some additional strings may be appended or prepended (or both) to the "seed"   string.  If yet another (lower) level of the GCC tree exists for the given   type (as in the case of a pointer type, an array type, or a function type)   then the (wrapped) seed is passed to a (recursive) invocation of gen_type()   this recursive invocation may again "wrap" the (new) seed with yet more   declarator stuff, by appending, prepending (or both).  By the time the   recursion bottoms out, the "seed value" at that point will have a value   which is (almost) the complete source version of the declarator (except   for the data_type info).  Thus, this deepest "seed" value is simply passed   back up through all of the recursive calls until it is given (as the return   value) to the initial caller of the gen_type() routine.  All that remains   to do at this point is for the initial caller to prepend the "data_type"   string onto the returned "seed".  */static char *gen_type (ret_val, t, style)     char *ret_val;     tree t;     formals_style style;{  tree chain_p;  if (TYPE_NAME (t) && DECL_NAME (TYPE_NAME (t)))    data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));  else    {      switch (TREE_CODE (t))        {        case POINTER_TYPE:          if (TYPE_READONLY (t))            ret_val = concat ("const ", ret_val);          if (TYPE_VOLATILE (t))            ret_val = concat ("volatile ", ret_val);          ret_val = concat ("*", ret_val);	  if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)	    ret_val = concat3 ("(", ret_val, ")");          ret_val = gen_type (ret_val, TREE_TYPE (t), style);          return ret_val;        case ARRAY_TYPE:	  if (TYPE_SIZE (t) == 0 || TREE_CODE (TYPE_SIZE (t)) != INTEGER_CST)	    ret_val = gen_type (concat (ret_val, "[]"), TREE_TYPE (t), style);	  else if (int_size_in_bytes (t) == 0)	    ret_val = gen_type (concat (ret_val, "[0]"), TREE_TYPE (t), style);	  else	    {	      int size = (int_size_in_bytes (t) / int_size_in_bytes (TREE_TYPE (t)));	      char buff[10];	      sprintf (buff, "[%d]", size);	      ret_val = gen_type (concat (ret_val, buff),				  TREE_TYPE (t), style);	    }          break;        case FUNCTION_TYPE:          ret_val = gen_type (concat (ret_val, gen_formal_list_for_type (t, style)), TREE_TYPE (t), style);          break;        case IDENTIFIER_NODE:          data_type = IDENTIFIER_POINTER (t);          break;	/* The following three cases are complicated by the fact that a           user may do something really stupid, like creating a brand new           "anonymous" type specification in a formal argument list (or as           part of a function return type specification).  For example:		int f (enum { red, green, blue } color);	   In such cases, we have no name that we can put into the prototype	   to represent the (anonymous) type.  Thus, we have to generate the	   whole darn type specification.  Yuck!  */        case RECORD_TYPE:	  if (TYPE_NAME (t))	    data_type = IDENTIFIER_POINTER (TYPE_NAME (t));	  else	    {	      data_type = "";	      chain_p = TYPE_FIELDS (t);	      while (chain_p)		{		  data_type = concat (data_type, gen_decl (chain_p, 0, ansi));		  chain_p = TREE_CHAIN (chain_p);		  data_type = concat (data_type, "; ");		}	      data_type = concat3 ("{ ", data_type, "}");	    }	  data_type = concat ("struct ", data_type);	  break;        case UNION_TYPE:	  if (TYPE_NAME (t))	    data_type = IDENTIFIER_POINTER (TYPE_NAME (t));	  else	    {	      data_type = "";	      chain_p = TYPE_FIELDS (t);	      while (chain_p)		{		  data_type = concat (data_type, gen_decl (chain_p, 0, ansi));		  chain_p = TREE_CHAIN (chain_p);		  data_type = concat (data_type, "; ");		}	      data_type = concat3 ("{ ", data_type, "}");	    }	  data_type = concat ("union ", data_type);	  break;        case ENUMERAL_TYPE:	  if (TYPE_NAME (t))	    data_type = IDENTIFIER_POINTER (TYPE_NAME (t));	  else	    {	      data_type = "";	      chain_p = TYPE_VALUES (t);	      while (chain_p)		{		  data_type = concat (data_type,			IDENTIFIER_POINTER (TREE_PURPOSE (chain_p)));		  chain_p = TREE_CHAIN (chain_p);		  if (chain_p)		    data_type = concat (data_type, ", ");		}	      data_type = concat3 ("{ ", data_type, " }");	    }	  data_type = concat ("enum ", data_type);	  break;        case TYPE_DECL:          data_type = IDENTIFIER_POINTER (DECL_NAME (t));          break;         case INTEGER_TYPE:          data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));          /* Normally, `unsigned' is part of the deal.  Not so if it comes    	     with `const' or `volatile'.  */          if (TREE_UNSIGNED (t) && (TYPE_READONLY (t) || TYPE_VOLATILE (t)))    	    data_type = concat ("unsigned ", data_type);	  break;        case REAL_TYPE:          data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));          break;        case VOID_TYPE:          data_type = "void";          break;	case ERROR_MARK:	  data_type = "[ERROR]";	  break;        default:          abort ();        }    }  if (TYPE_READONLY (t))    ret_val = concat ("const ", ret_val);  if (TYPE_VOLATILE (t))    ret_val = concat ("volatile ", ret_val);  return ret_val;}/* Generate a string (source) representation of an entire entity declaration   (using some particular style for function types).   The given entity may be either a variable or a function.   If the "is_func_definition" parameter is non-zero, assume that the thing   we are generating a declaration for is a FUNCTION_DECL node which is   associated with a function definition.  In this case, we can assume that   an attached list of DECL nodes for function formal arguments is present.  */static char *gen_decl (decl, is_func_definition, style)     tree decl;     int is_func_definition;     formals_style style;{  char *ret_val;  if (DECL_NAME (decl))    ret_val = IDENTIFIER_POINTER (DECL_NAME (decl));  else    ret_val = "";  /* If we are just generating a list of names of formal parameters, we can     simply return the formal parameter name (with no typing information     attached to it) now.  */  if (style == k_and_r_names)    return ret_val;  /* Note that for the declaration of some entity (either a function or a     data object, like for instance a parameter) if the entity itself was     declared as either const or volatile, then const and volatile properties     are associated with just the declaration of the entity, and *not* with     the `type' of the entity.  Thus, for such declared entities, we have to     generate the qualifiers here.  */  if (TREE_THIS_VOLATILE (decl))    ret_val = concat ("volatile ", ret_val);  if (TREE_READONLY (decl))    ret_val = concat ("const ", ret_val);  data_type = "";  /* For FUNCTION_DECL nodes, there are two possible cases here.  First, if     this FUNCTION_DECL node was generated from a function "definition", then     we will have a list of DECL_NODE's, one for each of the function's formal     parameters.  In this case, we can print out not only the types of each     formal, but also each formal's name.  In the second case, this     FUNCTION_DECL node came from an actual function declaration (and *not*     a definition).  In this case, we do nothing here because the formal     argument type-list will be output later, when the "type" of the function     is added to the string we are building.  Note that the ANSI-style formal     parameter list is considered to be a (suffix) part of the "type" of the     function.  */  if (TREE_CODE (decl) == FUNCTION_DECL && is_func_definition)    {      ret_val = concat (ret_val, gen_formal_list_for_func_def (decl, ansi));      /* Since we have already added in the formals list stuff, here we don't         add the whole "type" of the function we are considering (which         would include its parameter-list info), rather, we only add in         the "type" of the "type" of the function, which is really just         the return-type of the function (and does not include the parameter         list info).  */      ret_val = gen_type (ret_val, TREE_TYPE (TREE_TYPE (decl)), style);    }  else    ret_val = gen_type (ret_val, TREE_TYPE (decl), style);  ret_val = affix_data_type (ret_val);  if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl))    ret_val = concat ("register ", ret_val);  if (TREE_PUBLIC (decl))    ret_val = concat ("extern ", ret_val);  if (TREE_CODE (decl) == FUNCTION_DECL && !TREE_PUBLIC (decl))    ret_val = concat ("static ", ret_val);  return ret_val;}extern FILE *aux_info_file;/* Generate and write a new line of info to the aux-info (.X) file.  This   routine is called once for each function declaration, and once for each   function definition (even the implicit ones).  */voidgen_aux_info_record (fndecl, is_definition, is_implicit, is_prototyped)     tree fndecl;     int is_definition;     int is_implicit;     int is_prototyped;{  if (flag_gen_aux_info)    {      static int compiled_from_record = 0;      /* Each output .X file must have a header line.  Write one now if we	 have not yet done so.  */      if (! compiled_from_record++)	{	  /* The first line tells which directory file names are relative to.	     Currently, -aux-info works only for files in the working	     directory, so just use a `.' as a placeholder for now.  */	  fprintf (aux_info_file, "/* compiled from: . */\n");	}      /* Write the actual line of auxiliary info.  */      fprintf (aux_info_file, "/* %s:%d:%c%c */ %s;",	       DECL_SOURCE_FILE (fndecl),	       DECL_SOURCE_LINE (fndecl),	       (is_implicit) ? 'I' : (is_prototyped) ? 'N' : 'O',	       (is_definition) ? 'F' : 'C',	       gen_decl (fndecl, is_definition, ansi));      /* If this is an explicit function declaration, we need to also write	 out an old-style (i.e. K&R) function header, just in case the user	 wants to run unprotoize.  */      if (is_definition)	{	  fprintf (aux_info_file, " /*%s %s*/",		   gen_formal_list_for_func_def (fndecl, k_and_r_names),		   gen_formal_list_for_func_def (fndecl, k_and_r_decls));	}      fprintf (aux_info_file, "\n");    }}

⌨️ 快捷键说明

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