aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/c2xml.c
diff options
Diffstat (limited to 'c2xml.c')
-rw-r--r--c2xml.c324
1 files changed, 324 insertions, 0 deletions
diff --git a/c2xml.c b/c2xml.c
new file mode 100644
index 00000000..62417982
--- /dev/null
+++ b/c2xml.c
@@ -0,0 +1,324 @@
+/*
+ * Sparse c2xml
+ *
+ * Dumps the parse tree as an xml document
+ *
+ * Copyright (C) 2007 Rob Taylor
+ *
+ * Licensed under the Open Software License version 1.1
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+
+#include "parse.h"
+#include "scope.h"
+#include "symbol.h"
+
+xmlDocPtr doc = NULL; /* document pointer */
+xmlNodePtr root_node = NULL;/* root node pointer */
+xmlDtdPtr dtd = NULL; /* DTD pointer */
+xmlNsPtr ns = NULL; /* namespace pointer */
+int idcount = 0;
+
+static struct symbol_list *taglist = NULL;
+
+static void examine_symbol(struct symbol *sym, xmlNodePtr node);
+
+static xmlAttrPtr newNumProp(xmlNodePtr node, const xmlChar * name, int value)
+{
+ char buf[256];
+ snprintf(buf, 256, "%d", value);
+ return xmlNewProp(node, name, buf);
+}
+
+static xmlAttrPtr newIdProp(xmlNodePtr node, const xmlChar * name, unsigned int id)
+{
+ char buf[256];
+ snprintf(buf, 256, "_%d", id);
+ return xmlNewProp(node, name, buf);
+}
+
+static xmlNodePtr new_sym_node(struct symbol *sym, const char *name, xmlNodePtr parent)
+{
+ xmlNodePtr node;
+ const char *ident = show_ident(sym->ident);
+
+ assert(name != NULL);
+ assert(sym != NULL);
+ assert(parent != NULL);
+
+ node = xmlNewChild(parent, NULL, "symbol", NULL);
+
+ xmlNewProp(node, "type", name);
+
+ newIdProp(node, "id", idcount);
+
+ if (sym->ident && ident)
+ xmlNewProp(node, "ident", ident);
+ xmlNewProp(node, "file", stream_name(sym->pos.stream));
+
+ newNumProp(node, "start-line", sym->pos.line);
+ newNumProp(node, "start-col", sym->pos.pos);
+
+ if (sym->endpos.type) {
+ newNumProp(node, "end-line", sym->endpos.line);
+ newNumProp(node, "end-col", sym->endpos.pos);
+ if (sym->pos.stream != sym->endpos.stream)
+ xmlNewProp(node, "end-file", stream_name(sym->endpos.stream));
+ }
+ sym->aux = node;
+
+ idcount++;
+
+ return node;
+}
+
+static inline void examine_members(struct symbol_list *list, xmlNodePtr node)
+{
+ struct symbol *sym;
+ xmlNodePtr child;
+ char buf[256];
+
+ FOR_EACH_PTR(list, sym) {
+ examine_symbol(sym, node);
+ } END_FOR_EACH_PTR(sym);
+}
+
+static void examine_modifiers(struct symbol *sym, xmlNodePtr node)
+{
+ const char *modifiers[] = {
+ "auto",
+ "register",
+ "static",
+ "extern",
+ "const",
+ "volatile",
+ "signed",
+ "unsigned",
+ "char",
+ "short",
+ "long",
+ "long-long",
+ "typedef",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "inline",
+ "addressable",
+ "nocast",
+ "noderef",
+ "accessed",
+ "toplevel",
+ "label",
+ "assigned",
+ "type-type",
+ "safe",
+ "user-type",
+ "force",
+ "explicitly-signed",
+ "bitwise"};
+
+ int i;
+
+ if (sym->namespace != NS_SYMBOL)
+ return;
+
+ /*iterate over the 32 bit bitfield*/
+ for (i=0; i < 32; i++) {
+ if ((sym->ctype.modifiers & 1<<i) && modifiers[i])
+ xmlNewProp(node, modifiers[i], "1");
+ }
+}
+
+static void
+examine_layout(struct symbol *sym, xmlNodePtr node)
+{
+ char buf[256];
+
+ examine_symbol_type(sym);
+
+ newNumProp(node, "bit-size", sym->bit_size);
+ newNumProp(node, "alignment", sym->ctype.alignment);
+ newNumProp(node, "offset", sym->offset);
+ if (is_bitfield_type(sym)) {
+ newNumProp(node, "bit-offset", sym->bit_offset);
+ }
+}
+
+static void examine_symbol(struct symbol *sym, xmlNodePtr node)
+{
+ xmlNodePtr child = NULL;
+ const char *base;
+ int array_size;
+ char buf[256];
+
+ if (!sym)
+ return;
+ if (sym->aux) /*already visited */
+ return;
+
+ if (sym->ident && sym->ident->reserved)
+ return;
+
+ child = new_sym_node(sym, get_type_name(sym->type), node);
+ examine_modifiers(sym, child);
+ examine_layout(sym, child);
+
+ if (sym->ctype.base_type) {
+ if ((base = builtin_typename(sym->ctype.base_type)) == NULL) {
+ if (!sym->ctype.base_type->aux) {
+ examine_symbol(sym->ctype.base_type, root_node);
+ }
+ xmlNewProp(child, "base-type",
+ xmlGetProp((xmlNodePtr)sym->ctype.base_type->aux, "id"));
+ } else {
+ xmlNewProp(child, "base-type-builtin", base);
+ }
+ }
+ if (sym->array_size) {
+ /* TODO: modify get_expression_value to give error return */
+ array_size = get_expression_value(sym->array_size);
+ newNumProp(child, "array-size", array_size);
+ }
+
+
+ switch (sym->type) {
+ case SYM_STRUCT:
+ case SYM_UNION:
+ examine_members(sym->symbol_list, child);
+ break;
+ case SYM_FN:
+ examine_members(sym->arguments, child);
+ break;
+ case SYM_UNINITIALIZED:
+ xmlNewProp(child, "base-type-builtin", builtin_typename(sym));
+ break;
+ }
+ return;
+}
+
+static struct position *get_expansion_end (struct token *token)
+{
+ struct token *p1, *p2;
+
+ for (p1=NULL, p2=NULL;
+ !eof_token(token);
+ p2 = p1, p1 = token, token = token->next);
+
+ if (p2)
+ return &(p2->pos);
+ else
+ return NULL;
+}
+
+static void examine_macro(struct symbol *sym, xmlNodePtr node)
+{
+ xmlNodePtr child;
+ struct position *pos;
+ char buf[256];
+
+ /* this should probably go in the main codebase*/
+ pos = get_expansion_end(sym->expansion);
+ if (pos)
+ sym->endpos = *pos;
+ else
+ sym->endpos = sym->pos;
+
+ child = new_sym_node(sym, "macro", node);
+}
+
+static void examine_namespace(struct symbol *sym)
+{
+ xmlChar *namespace_type = NULL;
+
+ if (sym->ident && sym->ident->reserved)
+ return;
+
+ switch(sym->namespace) {
+ case NS_MACRO:
+ examine_macro(sym, root_node);
+ break;
+ case NS_TYPEDEF:
+ case NS_STRUCT:
+ case NS_SYMBOL:
+ examine_symbol(sym, root_node);
+ break;
+ case NS_NONE:
+ case NS_LABEL:
+ case NS_ITERATOR:
+ case NS_UNDEF:
+ case NS_PREPROCESSOR:
+ case NS_KEYWORD:
+ break;
+ default:
+ die("Unrecognised namespace type %d",sym->namespace);
+ }
+
+}
+
+static int get_stream_id (const char *name)
+{
+ int i;
+ for (i=0; i<input_stream_nr; i++) {
+ if (strcmp(name, stream_name(i))==0)
+ return i;
+ }
+ return -1;
+}
+
+static inline void examine_symbol_list(const char *file, struct symbol_list *list)
+{
+ struct symbol *sym;
+ int stream_id = get_stream_id (file);
+
+ if (!list)
+ return;
+ FOR_EACH_PTR(list, sym) {
+ if (sym->pos.stream == stream_id)
+ examine_namespace(sym);
+ } END_FOR_EACH_PTR(sym);
+}
+
+int main(int argc, char **argv)
+{
+ struct string_list *filelist = NULL;
+ struct symbol_list *symlist = NULL;
+ char *file;
+
+ doc = xmlNewDoc("1.0");
+ root_node = xmlNewNode(NULL, "parse");
+ xmlDocSetRootElement(doc, root_node);
+
+/* - A DTD is probably unnecessary for something like this
+
+ dtd = xmlCreateIntSubset(doc, "parse", "http://www.kernel.org/pub/software/devel/sparse/parse.dtd" NULL, "parse.dtd");
+
+ ns = xmlNewNs (root_node, "http://www.kernel.org/pub/software/devel/sparse/parse.dtd", NULL);
+
+ xmlSetNs(root_node, ns);
+*/
+ symlist = sparse_initialize(argc, argv, &filelist);
+
+ FOR_EACH_PTR_NOTAG(filelist, file) {
+ examine_symbol_list(file, symlist);
+ sparse_keep_tokens(file);
+ examine_symbol_list(file, file_scope->symbols);
+ examine_symbol_list(file, global_scope->symbols);
+ } END_FOR_EACH_PTR_NOTAG(file);
+
+
+ xmlSaveFormatFileEnc("-", doc, "UTF-8", 1);
+ xmlFreeDoc(doc);
+ xmlCleanupParser();
+
+ return 0;
+}
+