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

Reply via email to