aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/ast-inspect.c
diff options
authorChristopher Li <sparse@chrisli.org>2010-03-30 15:50:16 -0700
committerChristopher Li <sparse@chrisli.org>2010-07-13 19:00:46 +0000
commit9291116e70fc7c8866414704515cae4c6d05722c (patch)
tree4bb5a7b49cbf355a52a7f2bf21051f9a8be54105 /ast-inspect.c
parent5e5517211f51345ea0cd62fe6953e108d0f74aed (diff)
downloadsparse-dev-9291116e70fc7c8866414704515cae4c6d05722c.tar.gz
inspect: add some example inspect for symbol and statement
This is far fro complete. It is an example how to write call back driven inspect functions. Inside each inspect call back function. It can add a child node with: ast_append_child(), or add text attribute node with ast_append_attribute() Signed-Off-By: Christopher Li <sparse@chrisli.org>
Diffstat (limited to 'ast-inspect.c')
-rw-r--r--ast-inspect.c114
1 files changed, 114 insertions, 0 deletions
diff --git a/ast-inspect.c b/ast-inspect.c
new file mode 100644
index 00000000..72f3fe08
--- /dev/null
+++ b/ast-inspect.c
@@ -0,0 +1,114 @@
+
+#include "token.h"
+#include "parse.h"
+#include "symbol.h"
+#include "ast-inspect.h"
+
+static inline void inspect_ptr_list(AstNode *node, const char *name, void (*inspect)(AstNode *))
+{
+ struct ptr_list *ptrlist = node->ptr;
+ void *ptr;
+ int i = 0;
+
+ node->text = g_strdup_printf("%s %s:", node->text, name);
+ FOR_EACH_PTR(ptrlist, ptr) {
+ char *index = g_strdup_printf("%d: ", i++);
+ ast_append_child(node, index, ptr, inspect);
+ } END_FOR_EACH_PTR(ptr);
+}
+
+
+static const char *statement_type_name(enum statement_type type)
+{
+ static const char *statement_type_name[] = {
+ [STMT_NONE] = "STMT_NONE",
+ [STMT_DECLARATION] = "STMT_DECLARATION",
+ [STMT_EXPRESSION] = "STMT_EXPRESSION",
+ [STMT_COMPOUND] = "STMT_COMPOUND",
+ [STMT_IF] = "STMT_IF",
+ [STMT_RETURN] = "STMT_RETURN",
+ [STMT_CASE] = "STMT_CASE",
+ [STMT_SWITCH] = "STMT_SWITCH",
+ [STMT_ITERATOR] = "STMT_ITERATOR",
+ [STMT_LABEL] = "STMT_LABEL",
+ [STMT_GOTO] = "STMT_GOTO",
+ [STMT_ASM] = "STMT_ASM",
+ [STMT_CONTEXT] = "STMT_CONTEXT",
+ [STMT_RANGE] = "STMT_RANGE",
+ };
+ return statement_type_name[type] ?: "UNKNOWN_STATEMENT_TYPE";
+}
+
+
+void inspect_statement(AstNode *node)
+{
+ struct statement *stmt = node->ptr;
+ node->text = g_strdup_printf("%s %s:", node->text, statement_type_name(stmt->type));
+ switch (stmt->type) {
+ case STMT_COMPOUND:
+ ast_append_child(node, "stmts:", stmt->stmts, inspect_statement_list);
+ break;
+ case STMT_IF:
+ ast_append_child(node, "if_true:", stmt->if_true, inspect_statement);
+ ast_append_child(node, "if_false:", stmt->if_false, inspect_statement);
+ default:
+ break;
+ }
+}
+
+
+void inspect_statement_list(AstNode *node)
+{
+ inspect_ptr_list(node, "statement_list", inspect_statement);
+}
+
+
+static const char *symbol_type_name(enum type type)
+{
+ static const char *type_name[] = {
+ [SYM_UNINITIALIZED] = "SYM_UNINITIALIZED",
+ [SYM_PREPROCESSOR] = "SYM_PREPROCESSOR",
+ [SYM_BASETYPE] = "SYM_BASETYPE",
+ [SYM_NODE] = "SYM_NODE",
+ [SYM_PTR] = "SYM_PTR",
+ [SYM_FN] = "SYM_FN",
+ [SYM_ARRAY] = "SYM_ARRAY",
+ [SYM_STRUCT] = "SYM_STRUCT",
+ [SYM_UNION] = "SYM_UNION",
+ [SYM_ENUM] = "SYM_ENUM",
+ [SYM_TYPEDEF] = "SYM_TYPEDEF",
+ [SYM_TYPEOF] = "SYM_TYPEOF",
+ [SYM_MEMBER] = "SYM_MEMBER",
+ [SYM_BITFIELD] = "SYM_BITFIELD",
+ [SYM_LABEL] = "SYM_LABEL",
+ [SYM_RESTRICT] = "SYM_RESTRICT",
+ [SYM_FOULED] = "SYM_FOULED",
+ [SYM_KEYWORD] = "SYM_KEYWORD",
+ [SYM_BAD] = "SYM_BAD",
+ };
+ return type_name[type] ?: "UNKNOWN_TYPE";
+}
+
+
+void inspect_symbol(AstNode *node)
+{
+ struct symbol *sym = node->ptr;
+ node->text = g_strdup_printf("%s %s: %s", node->text, symbol_type_name(sym->type),
+ show_ident(sym->ident));
+ ast_append_child(node, "ctype.base_type:", sym->ctype.base_type,inspect_symbol);
+
+ switch (sym->type) {
+ case SYM_FN:
+ ast_append_child(node, "stmt:", sym->stmt, inspect_statement);
+ break;
+ default:
+ break;
+ }
+}
+
+
+void inspect_symbol_list(AstNode *node)
+{
+ inspect_ptr_list(node, "symbol_list", inspect_symbol);
+}
+