Re: Finding all typedefs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, 27 Jul 2007 18:08:31 -0400 Pavel Roskin wrote:

> Hello!
> 
> I'm trying to write a wrapper around GNU indent to make the output
> result satisfy checkpatch.pl.  Unfortunately, GNU indent is bad at
> recognizing types if they are just bare words defined by typedef.  Such
> types should be supplied using the "-T" option to indent.
> 
> I would prefer to rely on sparse for finding all typedefs, since it's
> better at parsing C code than any script I could write.
> 
> Is there any way to make sparse dump all type names declared with a
> typedef?  I don't see any of the programs in sparse sources do anything
> like that.  I think c2xml could be a good candidate, as it outputs the
> symbol, but it doesn't give any indication that it's a typedef-defined
> type:
> 
> $ make C=2 CHECK=/home/proski/src/sparse/c2xml |grep foo_t
>   <symbol type="node" id="_29" ident="foo_t"
> file="/home/proski/src/at76/at76_usb.c" start-line="41" start-col="13"
> end-line="41" end-col="18" bit-size="32" alignment="4" offset="0"
> base-type-builtin="int"/>
> 
> Another nice thing would be to have a list of labels.  Although they are
> easier to find by scripts, I would prefer to find them in the same run.

I asked Linus about 3 years ago for something that would dump
global data sizes.  It's attached (updated to recent sparse;
it also has '-keywords' to warn about using C++ keywords, but you
can ignore/delete that part).  It may be fixable to do what you want,
although I have no info on sparse symbol struct contents.
Or maybe Josh et al can do what you want rather easily... :)


use:
make C=2 CF=-list-symbols arch/i386/kernel/smp.o

gives:
arch/i386/kernel/smp.c:107:1: struct tlb_state [addressable] [toplevel] per_cpu__cpu_tlbstate: compound size 128, alignment 128
arch/i386/kernel/smp.c:247:18: struct cpumask_t static [addressable] [toplevel] [usertype] flush_cpumask: compound size 4, alignment 4
arch/i386/kernel/smp.c:248:25: struct mm_struct *static [toplevel] [assigned] flush_mm: compound size 4, alignment 4
arch/i386/kernel/smp.c:250:8: struct spinlock_t static [addressable] [toplevel] [usertype] tlbstate_lock: compound size 8, alignment 4
arch/i386/kernel/smp.c:450:1: char static const [toplevel] __kstrtab_flush_tlb_page[0]: compound size 15, alignment 1
arch/i386/kernel/smp.c:450:1: struct kernel_symbol static const [toplevel] __ksymtab_flush_tlb_page: compound size 8, alignment 4
arch/i386/kernel/smp.c:481:8: struct spinlock_t static [addressable] [toplevel] [usertype] call_lock: compound size 8, alignment 4
arch/i386/kernel/smp.c:501:32: struct call_data_struct *static [toplevel] [assigned] call_data: compound size 4, alignment 4
arch/i386/kernel/smp.c:698:16: struct smp_ops [addressable] [toplevel] smp_ops: compound size 28, alignment 4


---
~Randy
From: Randy Dunlap <rdunlap@xxxxxxxxxxxx>
with help from Linus.

sparse additions to:
- check for C/C++ keywords: usage: -keywords
- print all global data symbols and their sizes: usage: -list-symbols
  Example of -list-symbols:
  make C=2 CF="-list-symbols" arch/x86_64/kernel/smpboot.o
  arch/x86_64/kernel/smpboot.c:90:20: struct cpuinfo_x86 [addressable] [toplevel] [assigned] cpu_data[8]: compound size 1344, alignment 64

Signed-off-by: Randy Dunlap <rdunlap@xxxxxxxxxxxx>
---
 lib.c    |   31 +++++++++++++++++++++++++++++++
 sparse.c |   47 ++++++++++++++++++++++++++++++++++++++++++++++-
 symbol.c |   33 ++++++++++++++++++++++++++++++---
 3 files changed, 107 insertions(+), 4 deletions(-)

--- sparse-2007-07-24.orig/sparse.c
+++ sparse-2007-07-24/sparse.c
@@ -20,6 +20,7 @@
 #include "allocate.h"
 #include "token.h"
 #include "parse.h"
+#include "scope.h"
 #include "symbol.h"
 #include "expression.h"
 #include "linearize.h"
@@ -273,6 +274,42 @@ static void check_symbols(struct symbol_
 	} END_FOR_EACH_PTR(sym);
 }
 
+extern int list_symbols;
+
+static void list_all_symbols(struct symbol_list *list)
+{
+	struct symbol *sym;
+
+	FOR_EACH_PTR(list, sym) {
+		/* Only show arrays, structures, unions, enums, & typedefs */
+		if (!(sym->namespace & (NS_STRUCT | NS_TYPEDEF | NS_SYMBOL)))
+			continue;
+		/* Only show types we actually examined (ie used) */
+		if (!sym->bit_size)
+			continue;
+		if (sym->type == SYM_FN || sym->type == SYM_ENUM)
+			continue;
+		if (!sym->ctype.base_type)
+			continue;
+		if (sym->ctype.base_type->type == SYM_FN)
+			continue;
+		if (sym->ctype.base_type->type == SYM_ENUM)
+			continue;
+		if (sym->ctype.base_type->type == SYM_BASETYPE)
+			continue;
+		/* Don't show unnamed types */
+		if (!sym->ident)
+			continue;
+		///printf("%s: size %u, alignment %lu\n",
+		///info(sym->pos, "%s (0x%x:base 0x%x): compound size %u, alignment %lu",
+		info(sym->pos, "%s: compound size %u, alignment %lu",
+			show_typename(sym), ///sym->type,
+			///sym->ctype.base_type->type,
+			sym->bit_size >> 3,
+			sym->ctype.alignment);
+	} END_FOR_EACH_PTR(sym);
+}
+
 int main(int argc, char **argv)
 {
 	struct string_list *filelist = NULL;
@@ -281,7 +318,15 @@ int main(int argc, char **argv)
 	// Expand, linearize and show it.
 	check_symbols(sparse_initialize(argc, argv, &filelist));
 	FOR_EACH_PTR_NOTAG(filelist, file) {
-		check_symbols(sparse(file));
+		struct symbol_list *res = sparse(file);
+
+		check_symbols(res);
+
+		// List all symbols...
+		if (list_symbols)
+			///list_all_symbols(block_scope->symbols);
+			list_all_symbols(res);
 	} END_FOR_EACH_PTR_NOTAG(file);
+
 	return 0;
 }
--- sparse-2007-07-24.orig/lib.c
+++ sparse-2007-07-24/lib.c
@@ -213,6 +213,8 @@ int dbg_entry = 0;
 int dbg_dead = 0;
 
 int preprocess_only;
+int list_symbols = 0;
+int keywords_all = 0;
 
 #define CMDLINE_INCLUDE 20
 int cmdline_include_nr = 0;
@@ -308,6 +310,31 @@ static char **handle_switch_i(char *arg,
 	return next;
 }
 
+void handle_switch_pre(int argc, char **argv)
+{
+	char **args = argv;
+
+	for (;;) {
+		char *arg = *++args;
+		if (!arg)
+			break;
+
+		if (arg[0] == '-' && arg[1]) {
+			if (!strcmp(arg + 1, "keywords")) {
+				keywords_all = 1;
+				continue;
+			}
+		}
+	}
+}
+
+char **handle_switch_l(char *arg, char **next)
+{
+	if (!strcmp(arg, "list-symbols"))
+		list_symbols = 1;
+	return next;
+}
+
 static char **handle_switch_M(char *arg, char **next)
 {
 	if (!strcmp(arg, "MF") || !strcmp(arg,"MQ") || !strcmp(arg,"MT")) {
@@ -529,6 +556,7 @@ char **handle_switch(char *arg, char **n
 	case 'E': return handle_switch_E(arg, next);
 	case 'I': return handle_switch_I(arg, next);
 	case 'i': return handle_switch_i(arg, next);
+	case 'l': return handle_switch_l(arg, next);
 	case 'M': return handle_switch_M(arg, next);
 	case 'm': return handle_switch_m(arg, next);
 	case 'o': return handle_switch_o(arg, next);
@@ -710,6 +738,9 @@ struct symbol_list *sparse_initialize(in
 	char **args;
 	struct symbol_list *list;
 
+	// allow some switches (like "keywords") before init_symbols();
+	handle_switch_pre(argc, argv);
+
 	// Initialize symbol stream first, so that we can add defines etc
 	init_symbols();
 
--- sparse-2007-07-24.orig/symbol.c
+++ sparse-2007-07-24/symbol.c
@@ -545,7 +545,7 @@ void bind_symbol(struct symbol *sym, str
 	}
 	if (ident->reserved && (ns & (NS_TYPEDEF | NS_STRUCT | NS_LABEL | NS_SYMBOL))) {
 		sparse_error(sym->pos, "Trying to use reserved word '%s' as identifier", show_ident(ident));
-		return;
+		///return;
 	}
 	sym->namespace = ns;
 	sym->next_id = ident->symbols;
@@ -694,12 +694,13 @@ out:
  *
  * "double" == "long float", "long double" == "long long float"
  */
-static struct sym_init {
+struct sym_init {
 	const char *name;
 	struct symbol *base_type;
 	unsigned int modifiers;
 	struct symbol_op *op;
-} symbol_init_table[] = {
+};
+static struct sym_init symbol_init_table[] = {
 	/* Storage class */
 	{ "auto",	NULL,		MOD_AUTO },
 	{ "register",	NULL,		MOD_REGISTER },
@@ -727,6 +728,24 @@ static struct sym_init {
 	{ NULL,		NULL,		0 }
 };
 
+extern int keywords_all;
+const char * all_keywords[] = {
+/* more c_keywords[] */
+	"_Complex", "_Imaginary", "__thread",
+/* and cpp_keywords[] */
+	"bool", "catch", "class",
+	"complex", "__complex__", "const_cast",
+	"delete", "dynamic_cast",
+	"explicit", "export",
+	"false", "friend",
+	"mutable", "namespace", "new",
+	"operator", "private", "protected", "public",
+	"reinterpret_cast", "static_cast",
+	"template", "this", "throw",
+	"true", "try", "typeid", "typename",
+	"using", "virtual", "wchar_t",
+};
+
 static struct symbol_op constant_p_op = {
 	.evaluate = evaluate_to_integer,
 	.expand = expand_constant_p
@@ -812,6 +831,14 @@ void init_symbols(void)
 		sym->ctype.base_type = ptr->base_type;
 		sym->ctype.modifiers = ptr->modifiers;
 	}
+	if (keywords_all) {
+		int kx;
+
+		for (kx = 0; kx < sizeof(all_keywords) / sizeof(char *); kx++) {
+			struct ident *ident = built_in_ident(all_keywords [kx]);
+			ident->reserved = 1;
+		}
+	}
 
 	builtin_fn_type.variadic = 1;
 	for (ptr = eval_init_table; ptr->name; ptr++) {

[Index of Archives]     [Newbies FAQ]     [LKML]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Trinity Fuzzer Tool]

  Powered by Linux