📄 c-aux-info.c
字号:
/* Generate information regarding function declarations and definitions based on information stored in GCC's tree structure. This code implements the -aux-info option. Copyright (C) 1989, 1991, 1994, 1995, 1997 Free Software Foundation, Inc. Contributed by Ron Guilmette (rfg@segfault.us.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, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA. */#include "config.h"#include <stdio.h>#include "flags.h"#include "tree.h"#include "c-tree.h"extern char *xmalloc ();enum formals_style_enum { ansi, k_and_r_names, k_and_r_decls};typedef enum formals_style_enum formals_style;static char *data_type;static char *concat PROTO((char *, char *));static char *concat3 PROTO((char *, char *, char *));static char *affix_data_type PROTO((char *));static char *gen_formal_list_for_type PROTO((tree, formals_style));static int deserves_ellipsis PROTO((tree));static char *gen_formal_list_for_func_def PROTO((tree, formals_style));static char *gen_type PROTO((char *, tree, formals_style));static char *gen_decl PROTO((tree, int, formals_style));/* Take two strings and mash them together into a newly allocated area. */static char *concat (s1, s2) char *s1; char *s2;{ int size1, size2; char *ret_val; if (!s1) s1 = ""; if (!s2) s2 = ""; size1 = strlen (s1); size2 = strlen (s2); ret_val = xmalloc (size1 + size2 + 1); strcpy (ret_val, s1); strcpy (&ret_val[size1], s2); return ret_val;}/* Take three strings and mash them together into a newly allocated area. */static char *concat3 (s1, s2, s3) char *s1; char *s2; char *s3;{ int size1, size2, size3; char *ret_val; if (!s1) s1 = ""; if (!s2) s2 = ""; if (!s3) s3 = ""; size1 = strlen (s1); size2 = strlen (s2); size3 = strlen (s3); ret_val = xmalloc (size1 + size2 + size3 + 1); strcpy (ret_val, s1); strcpy (&ret_val[size1], s2); strcpy (&ret_val[size1+size2], s3); return ret_val;}/* Given a string representing an entire type or an entire declaration which only lacks the actual "data-type" specifier (at its left end), affix the data-type specifier to the left end of the given type specification or object declaration. Because of C language weirdness, the data-type specifier (which normally goes in at the very left end) may have to be slipped in just to the right of any leading "const" or "volatile" qualifiers (there may be more than one). Actually this may not be strictly necessary because it seems that GCC (at least) accepts `<data-type> const foo;' and treats it the same as `const <data-type> foo;' but people are accustomed to seeing `const char *foo;' and *not* `char const *foo;' so we try to create types that look as expected. */static char *affix_data_type (type_or_decl) char *type_or_decl;{ char *p = type_or_decl; char *qualifiers_then_data_type; char saved; /* Skip as many leading const's or volatile's as there are. */ for (;;) { if (!strncmp (p, "volatile ", 9)) { p += 9; continue; } if (!strncmp (p, "const ", 6)) { p += 6; continue; } break; } /* p now points to the place where we can insert the data type. We have to add a blank after the data-type of course. */ if (p == type_or_decl) return concat3 (data_type, " ", type_or_decl); saved = *p; *p = '\0'; qualifiers_then_data_type = concat (type_or_decl, data_type); *p = saved; return concat3 (qualifiers_then_data_type, " ", p);}/* Given a tree node which represents some "function type", generate the source code version of a formal parameter list (of some given style) for this function type. Return the whole formal parameter list (including a pair of surrounding parens) as a string. Note that if the style we are currently aiming for is non-ansi, then we just return a pair of empty parens here. */static char *gen_formal_list_for_type (fntype, style) tree fntype; formals_style style;{ char *formal_list = ""; tree formal_type; if (style != ansi) return "()"; formal_type = TYPE_ARG_TYPES (fntype); while (formal_type && TREE_VALUE (formal_type) != void_type_node) { char *this_type; if (*formal_list) formal_list = concat (formal_list, ", "); this_type = gen_type ("", TREE_VALUE (formal_type), ansi); formal_list = ((strlen (this_type)) ? concat (formal_list, affix_data_type (this_type)) : concat (formal_list, data_type)); formal_type = TREE_CHAIN (formal_type); } /* If we got to here, then we are trying to generate an ANSI style formal parameters list. New style prototyped ANSI formal parameter lists should in theory always contain some stuff between the opening and closing parens, even if it is only "void". The brutal truth though is that there is lots of old K&R code out there which contains declarations of "pointer-to-function" parameters and these almost never have fully specified formal parameter lists associated with them. That is, the pointer-to-function parameters are declared with just empty parameter lists. In cases such as these, protoize should really insert *something* into the vacant parameter lists, but what? It has no basis on which to insert anything in particular. Here, we make life easy for protoize by trying to distinguish between K&R empty parameter lists and new-style prototyped parameter lists that actually contain "void". In the latter case we (obviously) want to output the "void" verbatim, and that what we do. In the former case, we do our best to give protoize something nice to insert. This "something nice" should be something that is still valid (when re-compiled) but something that can clearly indicate to the user that more typing information (for the parameter list) should be added (by hand) at some convenient moment. The string chosen here is a comment with question marks in it. */ if (!*formal_list) { if (TYPE_ARG_TYPES (fntype)) /* assert (TREE_VALUE (TYPE_ARG_TYPES (fntype)) == void_type_node); */ formal_list = "void"; else formal_list = "/* ??? */"; } else { /* If there were at least some parameters, and if the formals-types-list petered out to a NULL (i.e. without being terminated by a void_type_node) then we need to tack on an ellipsis. */ if (!formal_type) formal_list = concat (formal_list, ", ..."); } return concat3 (" (", formal_list, ")");}/* For the generation of an ANSI prototype for a function definition, we have to look at the formal parameter list of the function's own "type" to determine if the function's formal parameter list should end with an ellipsis. Given a tree node, the following function will return non-zero if the "function type" parameter list should end with an ellipsis. */static intdeserves_ellipsis (fntype) tree fntype;{ tree formal_type; formal_type = TYPE_ARG_TYPES (fntype); while (formal_type && TREE_VALUE (formal_type) != void_type_node) formal_type = TREE_CHAIN (formal_type); /* If there were at least some parameters, and if the formals-types-list petered out to a NULL (i.e. without being terminated by a void_type_node) then we need to tack on an ellipsis. */ return (!formal_type && TYPE_ARG_TYPES (fntype));}/* Generate a parameter list for a function definition (in some given style). Note that this routine has to be separate (and different) from the code that generates the prototype parameter lists for function declarations, because in the case of a function declaration, all we have to go on is a tree node representing the function's own "function type". This can tell us the types of all of the formal parameters for the function, but it cannot tell us the actual *names* of each of the formal parameters. We need to output those parameter names for each function definition. This routine gets a pointer to a tree node which represents the actual declaration of the given function, and this DECL node has a list of formal parameter (variable) declarations attached to it. These formal parameter (variable) declaration nodes give us the actual names of the formal parameters for the given function definition. This routine returns a string which is the source form for the entire function formal parameter list. */static char *gen_formal_list_for_func_def (fndecl, style) tree fndecl; formals_style style;{ char *formal_list = ""; tree formal_decl; formal_decl = DECL_ARGUMENTS (fndecl); while (formal_decl) { char *this_formal; if (*formal_list && ((style == ansi) || (style == k_and_r_names))) formal_list = concat (formal_list, ", "); this_formal = gen_decl (formal_decl, 0, style); if (style == k_and_r_decls) formal_list = concat3 (formal_list, this_formal, "; "); else formal_list = concat (formal_list, this_formal); formal_decl = TREE_CHAIN (formal_decl); } if (style == ansi) { if (!DECL_ARGUMENTS (fndecl)) formal_list = concat (formal_list, "void"); if (deserves_ellipsis (TREE_TYPE (fndecl))) formal_list = concat (formal_list, ", ..."); } if ((style == ansi) || (style == k_and_r_names)) formal_list = concat3 (" (", formal_list, ")"); return formal_list;}/* Generate a string which is the source code form for a given type (t). This routine is ugly and complex because the C syntax for declarations is ugly and complex. This routine is straightforward so long as *no* pointer types, array types, or function types are involved. In the simple cases, this routine will return the (string) value which was passed in as the "ret_val" argument. Usually, this starts out either as an empty string, or as the name of the declared item (i.e. the formal function parameter variable).
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -