Hello.
This patch adds dissect.{h,c} files to the sparse distribution.
>From dissect.h:
struct reporter
{
void (*r_symdef)(struct symbol*);
void (*r_symbol)(unsigned mode, struct position*, struct
symbol*);
void (*r_member)(unsigned mode, struct position*, struct
symbol*, struct symbol*);
};
extern void dissect(struct symbol_list*, struct reporter*);
dissect() walks the output of the sparse_file() and calls reporter's
callbacks.
->r_symdef() is called when the symbol (variable or function) is defined.
->r_symbol() - when the symbol is used in any way. The 'mode' parameter
denotes how this symbol was used. It is a bitmask of possible flags:
FLAG: Code example:
U_R_VAL return VAR;
U_W_VAL VAR = 0;
U_R_PTR return *VAR;
U_W_PTR *VAR = 0;
U_R_AOF const void *... = &VAR;
U_W_AOF memset(&VAR, ...);
->r_member() tracks the use of members of structures in the same way.
This patch also adds test-dissect.c, a simple and stupid example. It
prints the 'mode' parameter in a human readable format along with the
storage info, variable's name (or struct_name.member_name), and it's
type.
The 'mode' is dumped as a 3-letter string. The first letter denotes
AOF part, 2-nd - VAL, 3-rd - PTR.
0 -> '-'
U_R_xxx -> 'r'
U_W_xxx -> 'w'
U_R_xxx | U_W_xxx -> 'm'
Example:
$ cat -n T.c
1 int var;
2
3 static void func(void)
4 {
5 int *ptr;
6
7 ptr = &var;
8 *ptr = var;
9
10 var = *++ptr;
11 }
$ ./test-dissect T.c
FILE: T.c
1:5 g def var int
3:13 s def func void ( )( ... )
5:6 l def ptr int *
7:2 l -w- ptr int *
7:9 g m-- var int
8:3 l --w ptr int *
8:9 g -r- var int
10:2 g -w- var int
10:11 l -mr ptr int *
Note that '*ptr' does not add U_R_VAL flag, this is a feature, not a bug,
even if technically wrong.
dissect() does not check the code for correctness, for example:
0 = X = Y;
gives this output:
5:6 g -w- X bad type
5:10 g -r- Y bad type
Again, X has no U_R_VAL, notabug.
Members of structures usage:
task_t *tsk;
tsk->parent->real_parent->pid++;
output:
7:2 l --r tsk struct task_struct [usertype] *
7:5 g --r task_struct.parent struct task_struct *
7:13 g --m task_struct.real_parent struct task_struct *
7:26 g -m- task_struct.pid int
dissect() tries to de-anonymize unnamed structures/unions:
1 struct T {
2 struct {
3 int x, y;
4 } m;
5 } t = {
6 { undeclared }
7 };
output:
5:3 g def t struct T
5:3 g -w- t struct T
6:2 s -w- T.m struct T:m
6:4 s -w- T:m.x int
6:4 g -r- undeclared bad type
Function calls use U_R_PTR bit:
5 func();
6 pf = func;
7 pf();
5:2 g --r func void ( )( ... )
6:2 l -w- pf void ( * )( ... )
6:7 g r-- func void ( )( ... )
7:2 l --r pf void ( * )( ... )
BUGS:
1. dissect() confuses array-in-container with pointer:
3 struct T { int ary[]; } t;
4
5 t.ary[0] = 0;
output:
5:2 l -r- t /* BUG, should be -w- */ struct T
5:3 s -w- T.ary int [0]
2. It can't detect the case when the address is taken only for writing,
eg: *(&i + 1) = 0, so U_W_AOF always implies U_R_AOF.
3. It does not support "flat" initializers without braces:
3 struct O {
4 struct I {
5 int x, y;
6 } a, b;
7 };
8
9 struct O o1 = { 1, 2, 3 };
buggy output:
9:11 l -w- o1 struct O
9:18 s -w- O.a struct I
9:21 s -w- O.b struct I
9:24 s -w- O.? bad type
This is ok:
11 struct O o2 = { { 1 }, .b = { .y = 0 } };
11:11 l -w- o2 struct O
11:18 s -w- O.a struct I
11:20 s -w- I.x int
11:30 s -w- O.b struct I
11:37 s -w- I.y int
4. test-dissect.c redefines evaluate_symbol_list(), so it can't
be linked statically with libsparse.a.
5. The implementation is far from perfect. It was really done
in "add some code + printf and see what happens" manner, without
studying the sources first. However I beleive it may be useful
for others, that is why I am posting it.
Signed-off-by: Oleg Nesterov <[EMAIL PROTECTED]>
dissect.h | 40 ++++
dissect.c | 547 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
test-dissect.c | 96 ++++++++++
Makefile | 9
4 files changed, 690 insertions(+), 2 deletions(-)
--- /dev/null 2000-01-01 03:00:00.000000000 +0300
+++ git-snapshot-20050818/dissect.h 2005-09-05 00:03:49.000000000 +0400
@@ -0,0 +1,40 @@
+#ifndef DISSECT_H
+#define DISSECT_H
+
+#include <stdio.h>
+#include "parse.h"
+#include "expression.h"
+
+#define U_SHIFT 8
+
+#define U_R_AOF 0x01
+#define U_W_AOF 0x02
+
+#define U_R_VAL 0x04
+#define U_W_VAL 0x08
+
+#define U_R_PTR (U_R_VAL << U_SHIFT)
+#define U_W_PTR (U_W_VAL << U_SHIFT)
+
+struct reporter
+{
+ void (*r_symdef)(struct symbol*);
+
+ void (*r_symbol)(unsigned, struct position*, struct symbol*);
+ void (*r_member)(unsigned, struct position*, struct symbol*, struct
symbol*);
+};
+
+extern void dissect(struct symbol_list*, struct reporter*);
+
+#define MK_IDENT(s) ({ \
+ static struct { \
+ struct ident ident; \
+ char __[sizeof(s)]; \
+ } ident = {{ \
+ .len = sizeof(s)-1, \
+ .name = s, \
+ }}; \
+ &ident.ident; \
+})
+
+#endif
--- /dev/null 2000-01-01 03:00:00.000000000 +0300
+++ git-snapshot-20050818/dissect.c 2005-09-04 23:45:27.000000000 +0400
@@ -0,0 +1,547 @@
+/*
+ * sparse/dissect.c
+ *
+ * Started by Oleg Nesterov <[EMAIL PROTECTED]>
+ *
+ * Licensed under the Open Software License version 1.1
+ */
+
+#include "dissect.h"
+
+#define U_VOID 0x00
+#define U_SELF ((1 << U_SHIFT) - 1)
+#define U_MASK (U_R_VAL | U_W_VAL | U_R_AOF)
+
+#define DO_LIST(l__, p__, expr__) \
+ do { \
+ typeof(l__->list[0]) p__; \
+ FOR_EACH_PTR(l__, p__) \
+ expr__; \
+ END_FOR_EACH_PTR(p__); \
+ } while (0)
+
+#define DO_2_LIST(l1__,l2__, p1__,p2__, expr__) \
+ do { \
+ typeof(l1__->list[0]) p1__; \
+ typeof(l2__->list[0]) p2__; \
+ PREPARE_PTR_LIST(l1__, p1__); \
+ FOR_EACH_PTR(l2__, p2__) \
+ expr__; \
+ NEXT_PTR_LIST(p1__); \
+ END_FOR_EACH_PTR(p2__); \
+ FINISH_PTR_LIST(p1__); \
+ } while (0)
+
+
+typedef unsigned usage_t;
+
+static struct reporter *reporter;
+static struct symbol *return_type;
+
+static void do_sym_list(struct symbol_list *list);
+
+static struct symbol
+ *base_type(struct symbol *sym),
+ *do_initializer(struct symbol *type, struct expression* expr),
+ *do_expression(usage_t mode, struct expression *expr),
+ *do_statement(usage_t mode, struct statement *stmt);
+
+static inline int is_ptr(struct symbol *type)
+{
+ return type->type == SYM_PTR || type->type == SYM_ARRAY;
+}
+
+static inline usage_t u_rval(usage_t mode)
+{
+ return mode & (U_R_VAL | (U_MASK << U_SHIFT))
+ ? U_R_VAL : 0;
+}
+
+static inline usage_t u_addr(usage_t mode)
+{
+ return mode = mode & U_MASK
+ ? U_R_AOF | (mode & U_W_AOF) : 0;
+}
+
+static usage_t u_lval(struct symbol *type)
+{
+ int wptr = is_ptr(type) && !(type->ctype.modifiers & MOD_CONST);
+ return wptr || type == &bad_ctype
+ ? U_W_AOF | U_R_VAL : U_R_VAL;
+}
+
+static usage_t fix_mode(struct symbol *type, usage_t mode)
+{
+ mode &= (U_SELF | (U_SELF << U_SHIFT));
+
+ switch (type->type) {
+ case SYM_BASETYPE:
+ if (!type->ctype.base_type)
+ break;
+ case SYM_ENUM:
+ case SYM_BITFIELD:
+ if (mode & U_MASK)
+ mode &= U_SELF;
+ default:
+
+ break; case SYM_FN:
+ if (mode & U_R_VAL)
+ mode |= U_R_AOF;
+ mode &= ~(U_R_VAL | U_W_AOF);
+
+ break; case SYM_ARRAY:
+ if (mode & (U_MASK << U_SHIFT))
+ mode >>= U_SHIFT;
+ else if (mode != U_W_VAL)
+ mode = u_addr(mode);
+ }
+
+ if (!(mode & U_R_AOF))
+ mode &= ~U_W_AOF;
+
+ return mode;
+}
+
+static inline struct symbol *no_member(struct ident *name)
+{
+ static struct symbol sym = {
+ .type = SYM_BAD,
+ };
+
+ sym.ctype.base_type = &bad_ctype;
+ sym.ident = name;
+
+ return &sym;
+}
+
+static struct symbol *report_member(unsigned mode, struct position *pos,
+ struct symbol *type, struct symbol *mem)
+{
+ struct symbol *ret = mem->ctype.base_type;
+
+ if (reporter->r_member)
+ reporter->r_member(fix_mode(ret, mode), pos, type, mem);
+
+ return ret;
+}
+
+static inline struct symbol *expr_symbol(struct expression *expr)
+{
+ struct symbol *sym = expr->symbol;
+
+ if (!sym) {
+ sym = lookup_symbol(expr->symbol_name, NS_SYMBOL);
+
+ if (!sym) {
+ sym = alloc_symbol(expr->pos, SYM_BAD);
+ bind_symbol(sym, expr->symbol_name, NS_SYMBOL);
+ sym->ctype.modifiers = MOD_EXTERN;
+ }
+ }
+
+ if (!sym->ctype.base_type)
+ sym->ctype.base_type = &bad_ctype;
+
+ return sym;
+}
+
+static struct symbol *report_symbol(usage_t mode, struct expression *expr)
+{
+ struct symbol *sym = expr_symbol(expr);
+// struct symbol *ret = sym->ctype.base_type;
+ struct symbol *ret = base_type(sym);
+
+ if (0 && ret->type == SYM_ENUM)
+ return report_member(mode, &expr->pos, ret, expr->symbol);
+
+ if (reporter->r_symbol)
+ reporter->r_symbol(fix_mode(ret, mode), &expr->pos, sym);
+
+ return ret;
+}
+
+static inline struct ident *mk_name(struct ident *root, struct ident *node)
+{
+ char name[256];
+
+ snprintf(name, sizeof(name), "%.*s:%.*s",
+ root ? root->len : 0, root->name,
+ node ? node->len : 0, node->name);
+
+ return built_in_ident(name);
+}
+
+static void examine_sym_node(struct symbol *node, struct ident *root)
+{
+ struct symbol *curr, *base;
+
+ if (node->examined)
+ return;
+ node->examined = 1;
+
+ for (curr = node; (base = curr->ctype.base_type); curr = base)
+ {
+ if (base->type == SYM_TYPEOF)
+ base = curr->ctype.base_type =
+ do_expression(U_VOID, base->initializer);
+
+ switch (base->type) {
+ case SYM_FN: case SYM_PTR: case SYM_ARRAY:
+ continue;
+ case SYM_STRUCT: case SYM_UNION: //case SYM_ENUM:
+ if (!base->ident && node->ident)
+ base->ident = mk_name(root, node->ident);
+ default:
+ return;
+ }
+ }
+}
+
+static struct symbol *base_type(struct symbol *sym)
+{
+ if (!sym)
+ return &bad_ctype;
+
+ if (sym->type == SYM_NODE)
+ examine_sym_node(sym, NULL);
+
+ return sym->ctype.base_type // builtin_fn_type
+ ?: &bad_ctype;
+}
+
+static struct symbol *__lookup_member(struct symbol *type, struct ident *name,
int *p_addr)
+{
+ struct symbol *node;
+ int addr = 0;
+
+ FOR_EACH_PTR(type->symbol_list, node)
+ if (!name) {
+ if (addr == *p_addr)
+ return node;
+ }
+ else if (node->ident == NULL) {
+ node = __lookup_member(node->ctype.base_type, name,
NULL);
+ if (node)
+ goto found;
+ }
+ else if (node->ident == name) {
+found:
+ if (p_addr)
+ *p_addr = addr;
+ return node;
+ }
+ addr++;
+ END_FOR_EACH_PTR(node);
+
+ return NULL;
+}
+
+static struct symbol *lookup_member(struct symbol *type, struct ident *name,
int *addr)
+{
+ struct symbol *node = __lookup_member(type, name, addr);
+
+ if (node != NULL)
+ examine_sym_node(node, type->ident);
+ else
+ node = no_member(name);
+
+ return node;
+}
+
+static struct expression *peek_preop(struct expression *expr, int op)
+{
+ do {
+ if (expr->type != EXPR_PREOP)
+ break;
+ if (expr->op == op)
+ return expr->unop;
+ if (expr->op == '(')
+ expr = expr->unop;
+ else
+ break;
+ } while (expr);
+
+ return NULL;
+}
+
+static struct symbol *do_expression(usage_t mode, struct expression *expr)
+{
+ struct symbol *ret = &int_ctype;
+
+again:
+ if (expr) switch (expr->type) {
+ default:
+ warning(expr->pos, "bad expr->type: %d", expr->type);
+
+ case EXPR_TYPE: // [struct T]; Why ???
+ case EXPR_VALUE:
+ case EXPR_FVALUE:
+
+ break; case EXPR_LABEL:
+ ret = &label_ctype;
+
+ break; case EXPR_STRING:
+ ret = &string_ctype;
+
+ break; case EXPR_STATEMENT:
+ ret = do_statement(mode, expr->statement);
+
+ break; case EXPR_SIZEOF: case EXPR_ALIGNOF: case EXPR_PTRSIZEOF:
+ do_expression(U_VOID, expr->cast_expression);
+
+ break; case EXPR_COMMA:
+ do_expression(U_VOID, expr->left);
+ ret = do_expression(mode, expr->right);
+
+ break; case EXPR_CAST: //case EXPR_IMPLIED_CAST:
+ ret = base_type(expr->cast_type);
+ do_initializer(ret, expr->cast_expression);
+
+ break; case EXPR_COMPARE: case EXPR_LOGICAL:
+ mode = u_rval(mode);
+ do_expression(mode, expr->left);
+ do_expression(mode, expr->right);
+
+ break; case EXPR_CONDITIONAL: //case EXPR_SELECT:
+ do_expression(expr->cond_true
+ ? U_R_VAL
+ : U_R_VAL | mode,
+ expr->conditional);
+ ret = do_expression(mode, expr->cond_true);
+ ret = do_expression(mode, expr->cond_false);
+
+ break; case EXPR_CALL:
+ ret = do_expression(U_R_PTR, expr->fn);
+ if (is_ptr(ret))
+ ret = ret->ctype.base_type;
+ DO_2_LIST(ret->arguments, expr->args, arg, val,
+ do_expression(u_lval(base_type(arg)), val));
+ ret = ret->type == SYM_FN ? base_type(ret)
+ : &bad_ctype;
+
+ break; case EXPR_ASSIGNMENT:
+ mode |= U_W_VAL | U_R_VAL;
+ if (expr->op == '=')
+ mode &= ~U_R_VAL;
+ ret = do_expression(mode, expr->left);
+ mode = expr->op == '='
+ ? u_lval(ret) : U_R_VAL;
+ do_expression(mode, expr->right);
+
+ break; case EXPR_BINOP: {
+ struct symbol *l, *r;
+ mode |= u_rval(mode);
+ l = do_expression(mode, expr->left);
+ r = do_expression(mode, expr->right);
+ if (expr->op != '+' && expr->op != '-')
+ ;
+ else if (!is_ptr_type(r))
+ ret = l;
+ else if (!is_ptr_type(l))
+ ret = r;
+ }
+
+ break; case EXPR_PREOP: case EXPR_POSTOP: {
+ struct expression *unop = expr->unop;
+
+ switch (expr->op) {
+ case SPECIAL_INCREMENT:
+ case SPECIAL_DECREMENT:
+ mode |= U_W_VAL | U_R_VAL;
+ default:
+ mode |= u_rval(mode);
+ case '(':
+ ret = do_expression(mode, unop);
+
+ break; case '&':
+ if ((expr = peek_preop(unop, '*')))
+ goto again;
+ ret = alloc_symbol(unop->pos, SYM_PTR);
+ ret->ctype.base_type =
+ do_expression(u_addr(mode), unop);
+
+ break; case '*':
+ if ((expr = peek_preop(unop, '&')))
+ goto again;
+ if (mode & (U_MASK << U_SHIFT))
+ mode |= U_R_VAL;
+ mode <<= U_SHIFT;
+ if (mode & (U_R_AOF << U_SHIFT))
+ mode |= U_R_VAL;
+ if (mode & (U_W_VAL << U_SHIFT))
+ mode |= U_W_AOF;
+ ret = do_expression(mode, unop);
+ ret = is_ptr(ret) ? base_type(ret)
+ : &bad_ctype;
+ }
+ }
+
+ break; case EXPR_DEREF: {
+ struct symbol *p_type;
+ usage_t p_mode;
+
+ p_mode = mode & U_SELF;
+ if (!(mode & U_MASK) && (mode & (U_MASK << U_SHIFT)))
+ p_mode = U_R_VAL;
+ p_type = do_expression(p_mode, expr->deref);
+
+ ret = report_member(mode, &expr->pos, p_type,
+ lookup_member(p_type, expr->member, NULL));
+ }
+
+ break; case EXPR_SYMBOL:
+ ret = report_symbol(mode, expr);
+ }
+
+ return ret;
+}
+
+static void do_asm_xputs(usage_t mode, struct expression_list *xputs)
+{
+ int nr = 0;
+
+ DO_LIST(xputs, expr,
+ if (++nr % 3 == 0)
+ do_expression(U_W_AOF | mode, expr));
+}
+
+static struct symbol *do_statement(usage_t mode, struct statement *stmt)
+{
+ struct symbol *ret = &void_ctype;
+
+ if (stmt) switch (stmt->type) {
+ default:
+ warning(stmt->pos, "bad stmt->type: %d", stmt->type);
+
+ case STMT_NONE:
+ case STMT_RANGE:
+ case STMT_CONTEXT:
+
+ break; case STMT_EXPRESSION:
+ ret = do_expression(mode, stmt->expression);
+
+ break; case STMT_RETURN:
+ do_expression(u_lval(return_type), stmt->expression);
+
+ break; case STMT_ASM:
+ do_expression(U_R_VAL, stmt->asm_string);
+ do_asm_xputs(U_W_VAL, stmt->asm_outputs);
+ do_asm_xputs(U_R_VAL, stmt->asm_inputs);
+
+ break; case STMT_COMPOUND: {
+ int count;
+
+ do_sym_list(stmt->syms);
+ count = statement_list_size(stmt->stmts);
+ DO_LIST(stmt->stmts, st,
+ ret = do_statement(--count ? U_VOID : mode, st));
+ }
+
+ break; case STMT_ITERATOR:
+ do_sym_list(stmt->iterator_syms);
+ do_statement(U_VOID, stmt->iterator_pre_statement);
+ do_expression(U_R_VAL, stmt->iterator_pre_condition);
+ do_statement(U_VOID, stmt->iterator_post_statement);
+ do_statement(U_VOID, stmt->iterator_statement);
+ do_expression(U_R_VAL, stmt->iterator_post_condition);
+
+ break; case STMT_IF:
+ do_expression(U_R_VAL, stmt->if_conditional);
+ do_statement(U_VOID, stmt->if_true);
+ do_statement(U_VOID, stmt->if_false);
+
+ break; case STMT_SWITCH:
+ do_expression(U_R_VAL, stmt->switch_expression);
+ do_statement(U_VOID, stmt->switch_statement);
+
+ break; case STMT_CASE:
+ do_expression(U_R_VAL, stmt->case_expression);
+ do_expression(U_R_VAL, stmt->case_to);
+ do_statement(U_VOID, stmt->case_statement);
+
+ break; case STMT_GOTO:
+ do_expression(U_R_PTR, stmt->goto_expression);
+
+ break; case STMT_LABEL:
+ do_statement(mode, stmt->label_statement);
+
+ }
+
+ return ret;
+}
+
+static struct symbol *do_initializer(struct symbol *type, struct expression*
expr)
+{
+ struct symbol *m_type;
+ struct expression *m_expr;
+ struct ident *m_name;
+ int m_addr;
+
+ if (type->type == SYM_ARRAY)
+ do_expression(U_R_VAL, type->array_size);
+
+ if (expr) switch (expr->type) {
+ default:
+ do_expression(u_lval(type), expr);
+
+ break; case EXPR_INITIALIZER:
+ m_addr = 0;
+ FOR_EACH_PTR(expr->expr_list, m_expr)
+ if(type->type == SYM_ARRAY) {
+ m_type = base_type(type);
+ if (m_expr->type == EXPR_INDEX)
+ m_expr = m_expr->idx_expression;
+ } else {
+ m_name = NULL;
+ if (m_expr->type == EXPR_IDENTIFIER) {
+ m_name = m_expr->expr_ident;
+ m_expr = m_expr->ident_expression;
+ }
+
+ m_type = report_member(U_W_VAL, &m_expr->pos,
type,
+ lookup_member(type, m_name,
&m_addr));
+ m_addr++;
+ }
+ do_initializer(m_type, m_expr);
+ END_FOR_EACH_PTR(m_expr);
+ }
+
+ return type;
+}
+
+static inline struct symbol *do_symbol(struct symbol *sym)
+{
+ struct symbol *type;
+
+ type = base_type(sym);
+
+ if (reporter->r_symdef)
+ reporter->r_symdef(sym);
+
+ switch (type->type) {
+ default:
+ if (reporter->r_symbol && sym->initializer)
+ reporter->r_symbol(U_W_VAL, &sym->pos, sym);
+ do_initializer(type, sym->initializer);
+
+ break; case SYM_FN:
+ do_sym_list(type->arguments);
+ return_type = base_type(type);
+ do_statement(U_VOID, sym->ctype.modifiers & MOD_INLINE
+ ? type->inline_stmt
+ : type->stmt);
+ }
+
+ return type;
+}
+
+static void do_sym_list(struct symbol_list *list)
+{
+ DO_LIST(list, sym, do_symbol(sym));
+}
+
+void dissect(struct symbol_list *list, struct reporter *rep)
+{
+ reporter = rep;
+ do_sym_list(list);
+}
--- /dev/null 2000-01-01 03:00:00.000000000 +0300
+++ git-snapshot-20050818/test-dissect.c 2005-09-04 23:45:39.000000000
+0400
@@ -0,0 +1,96 @@
+#include "dissect.h"
+
+static unsigned dotc_stream;
+
+static inline char storage(struct symbol *sym)
+{
+ int t = sym->type;
+ unsigned m = sym->ctype.modifiers;
+
+ if (m & MOD_INLINE || t == SYM_STRUCT || t == SYM_UNION /*|| t ==
SYM_ENUM*/)
+ return sym->pos.stream == dotc_stream ? 's' : 'g';
+
+ return (m & MOD_STATIC) ? 's' : (m & MOD_NONLOCAL) ? 'g' : 'l';
+}
+
+static inline const char *show_mode(unsigned mode)
+{
+ static char str[3];
+
+ if (mode == -1)
+ return "def";
+
+#define U(u_r) "-rwm"[(mode / u_r) & 3]
+ str[0] = U(U_R_AOF);
+ str[1] = U(U_R_VAL);
+ str[2] = U(U_R_PTR);
+#undef U
+
+ return str;
+}
+
+static void print_usage(struct position *pos, struct symbol *sym, unsigned
mode)
+{
+ static unsigned curr_stream = -1;
+
+ if (curr_stream != pos->stream) {
+ curr_stream = pos->stream;
+ printf("\nFILE: %s\n\n", stream_name(curr_stream));
+ }
+
+ printf("%4d:%-3d %c %-5.3s",
+ pos->line, pos->pos, storage(sym), show_mode(mode));
+}
+
+static void r_symbol(unsigned mode, struct position *pos, struct symbol *sym)
+{
+ print_usage(pos, sym, mode);
+
+ printf("%-32.*s %s\n",
+ sym->ident->len, sym->ident->name,
+ show_typename(sym->ctype.base_type));
+}
+
+static void r_member(unsigned mode, struct position *pos, struct symbol *sym,
struct symbol *mem)
+{
+ struct ident *ni, *si, *mi;
+
+ print_usage(pos, sym, mode);
+
+ ni = MK_IDENT("?");
+ si = sym->ident ?: ni;
+ mi = mem->ident ?: ni;
+
+ printf("%.*s.%-*.*s %s\n",
+ si->len, si->name,
+ 32-1 - si->len, mi->len, mi->name,
+ show_typename(mem->ctype.base_type));
+}
+
+static void r_symdef(struct symbol *sym)
+{
+ r_symbol(-1, &sym->pos, sym);
+}
+
+void evaluate_symbol_list(struct symbol_list *list)
+{
+ static struct reporter reporter = {
+ .r_symdef = r_symdef,
+ .r_symbol = r_symbol,
+ .r_member = r_member,
+ };
+
+ dissect(list, &reporter);
+}
+
+int main(int argc, char **argv)
+{
+ sparse_initialize(argc, argv);
+
+ while (*argv) {
+ dotc_stream = input_stream_nr;
+ sparse(argv);
+ }
+
+ return 0;
+}
--- git-snapshot-20050818/Makefile~ds 2005-08-17 23:58:51.000000000 +0400
+++ git-snapshot-20050818/Makefile 2005-09-05 00:00:58.000000000 +0400
@@ -21,7 +21,7 @@ CFLAGS += -DDEBUG
PREFIX=$(HOME)
BINDIR=$(PREFIX)/bin
-PROGRAMS=test-lexing test-parsing obfuscate check compile test-linearize
example
+PROGRAMS=test-lexing test-parsing obfuscate check compile test-linearize
test-dissect example
LIB_H= token.h parse.h lib.h symbol.h scope.h expression.h target.h \
linearize.h bitmap.h ident-list.h compat.h flow.h allocate.h \
@@ -30,7 +30,7 @@ LIB_H= token.h parse.h lib.h symbol.h
LIB_OBJS= target.o parse.o tokenize.o pre-process.o symbol.o lib.o scope.o \
expression.o show-parse.o evaluate.o expand.o inline.o linearize.o \
sort.o allocate.o compat-$(OS).o ptrlist.o \
- flow.o cse.o simplify.o memops.o liveness.o storage.o
+ flow.o cse.o simplify.o memops.o liveness.o storage.o dissect.o
LIB_FILE= libsparse.a
SLIB_FILE= libsparse.so
@@ -65,6 +65,9 @@ test-parsing: test-parsing.o $(LIBS)
test-linearize: test-linearize.o $(LIBS)
$(CC) $(LDFLAGS) -o $@ $< $(LIBS)
+test-dissect: test-dissect.o $(SLIB_FILE)
+ $(CC) $(LDFLAGS) -o $@ $< $(SLIB_FILE)
+
test-sort: test-sort.o $(LIBS)
$(CC) $(LDFLAGS) -o $@ $< $(LIBS)
@@ -108,6 +111,7 @@ target.o: $(LIB_H)
test-lexing.o: $(LIB_H)
test-parsing.o: $(LIB_H)
test-linearize.o: $(LIB_H)
+test-dissect.o: $(LIB_H) dissect.h
compile.o: $(LIB_H) compile.h
compile-i386.o: $(LIB_H) compile.h
tokenize.o: $(LIB_H)
@@ -115,6 +119,7 @@ check.o: $(LIB_H)
obfuscate.o: $(LIB_H)
example.o: $(LIB_H)
storage.o: $(LIB_H) storage.h
+dissect.o: $(LIB_H) dissect.h
compat-linux.o: compat/strtold.c compat/mmap-blob.c \
$(LIB_H)
-
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html