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++) {