Add c2xml to .gitignore
[smatch.git] / c2xml.c
blob62417982e9fcc87ee95131a71dcd265781ca6896
1 /*
2 * Sparse c2xml
4 * Dumps the parse tree as an xml document
6 * Copyright (C) 2007 Rob Taylor
8 * Licensed under the Open Software License version 1.1
9 */
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <unistd.h>
14 #include <fcntl.h>
15 #include <assert.h>
16 #include <libxml/parser.h>
17 #include <libxml/tree.h>
19 #include "parse.h"
20 #include "scope.h"
21 #include "symbol.h"
23 xmlDocPtr doc = NULL; /* document pointer */
24 xmlNodePtr root_node = NULL;/* root node pointer */
25 xmlDtdPtr dtd = NULL; /* DTD pointer */
26 xmlNsPtr ns = NULL; /* namespace pointer */
27 int idcount = 0;
29 static struct symbol_list *taglist = NULL;
31 static void examine_symbol(struct symbol *sym, xmlNodePtr node);
33 static xmlAttrPtr newNumProp(xmlNodePtr node, const xmlChar * name, int value)
35 char buf[256];
36 snprintf(buf, 256, "%d", value);
37 return xmlNewProp(node, name, buf);
40 static xmlAttrPtr newIdProp(xmlNodePtr node, const xmlChar * name, unsigned int id)
42 char buf[256];
43 snprintf(buf, 256, "_%d", id);
44 return xmlNewProp(node, name, buf);
47 static xmlNodePtr new_sym_node(struct symbol *sym, const char *name, xmlNodePtr parent)
49 xmlNodePtr node;
50 const char *ident = show_ident(sym->ident);
52 assert(name != NULL);
53 assert(sym != NULL);
54 assert(parent != NULL);
56 node = xmlNewChild(parent, NULL, "symbol", NULL);
58 xmlNewProp(node, "type", name);
60 newIdProp(node, "id", idcount);
62 if (sym->ident && ident)
63 xmlNewProp(node, "ident", ident);
64 xmlNewProp(node, "file", stream_name(sym->pos.stream));
66 newNumProp(node, "start-line", sym->pos.line);
67 newNumProp(node, "start-col", sym->pos.pos);
69 if (sym->endpos.type) {
70 newNumProp(node, "end-line", sym->endpos.line);
71 newNumProp(node, "end-col", sym->endpos.pos);
72 if (sym->pos.stream != sym->endpos.stream)
73 xmlNewProp(node, "end-file", stream_name(sym->endpos.stream));
75 sym->aux = node;
77 idcount++;
79 return node;
82 static inline void examine_members(struct symbol_list *list, xmlNodePtr node)
84 struct symbol *sym;
85 xmlNodePtr child;
86 char buf[256];
88 FOR_EACH_PTR(list, sym) {
89 examine_symbol(sym, node);
90 } END_FOR_EACH_PTR(sym);
93 static void examine_modifiers(struct symbol *sym, xmlNodePtr node)
95 const char *modifiers[] = {
96 "auto",
97 "register",
98 "static",
99 "extern",
100 "const",
101 "volatile",
102 "signed",
103 "unsigned",
104 "char",
105 "short",
106 "long",
107 "long-long",
108 "typedef",
109 NULL,
110 NULL,
111 NULL,
112 NULL,
113 NULL,
114 "inline",
115 "addressable",
116 "nocast",
117 "noderef",
118 "accessed",
119 "toplevel",
120 "label",
121 "assigned",
122 "type-type",
123 "safe",
124 "user-type",
125 "force",
126 "explicitly-signed",
127 "bitwise"};
129 int i;
131 if (sym->namespace != NS_SYMBOL)
132 return;
134 /*iterate over the 32 bit bitfield*/
135 for (i=0; i < 32; i++) {
136 if ((sym->ctype.modifiers & 1<<i) && modifiers[i])
137 xmlNewProp(node, modifiers[i], "1");
141 static void
142 examine_layout(struct symbol *sym, xmlNodePtr node)
144 char buf[256];
146 examine_symbol_type(sym);
148 newNumProp(node, "bit-size", sym->bit_size);
149 newNumProp(node, "alignment", sym->ctype.alignment);
150 newNumProp(node, "offset", sym->offset);
151 if (is_bitfield_type(sym)) {
152 newNumProp(node, "bit-offset", sym->bit_offset);
156 static void examine_symbol(struct symbol *sym, xmlNodePtr node)
158 xmlNodePtr child = NULL;
159 const char *base;
160 int array_size;
161 char buf[256];
163 if (!sym)
164 return;
165 if (sym->aux) /*already visited */
166 return;
168 if (sym->ident && sym->ident->reserved)
169 return;
171 child = new_sym_node(sym, get_type_name(sym->type), node);
172 examine_modifiers(sym, child);
173 examine_layout(sym, child);
175 if (sym->ctype.base_type) {
176 if ((base = builtin_typename(sym->ctype.base_type)) == NULL) {
177 if (!sym->ctype.base_type->aux) {
178 examine_symbol(sym->ctype.base_type, root_node);
180 xmlNewProp(child, "base-type",
181 xmlGetProp((xmlNodePtr)sym->ctype.base_type->aux, "id"));
182 } else {
183 xmlNewProp(child, "base-type-builtin", base);
186 if (sym->array_size) {
187 /* TODO: modify get_expression_value to give error return */
188 array_size = get_expression_value(sym->array_size);
189 newNumProp(child, "array-size", array_size);
193 switch (sym->type) {
194 case SYM_STRUCT:
195 case SYM_UNION:
196 examine_members(sym->symbol_list, child);
197 break;
198 case SYM_FN:
199 examine_members(sym->arguments, child);
200 break;
201 case SYM_UNINITIALIZED:
202 xmlNewProp(child, "base-type-builtin", builtin_typename(sym));
203 break;
205 return;
208 static struct position *get_expansion_end (struct token *token)
210 struct token *p1, *p2;
212 for (p1=NULL, p2=NULL;
213 !eof_token(token);
214 p2 = p1, p1 = token, token = token->next);
216 if (p2)
217 return &(p2->pos);
218 else
219 return NULL;
222 static void examine_macro(struct symbol *sym, xmlNodePtr node)
224 xmlNodePtr child;
225 struct position *pos;
226 char buf[256];
228 /* this should probably go in the main codebase*/
229 pos = get_expansion_end(sym->expansion);
230 if (pos)
231 sym->endpos = *pos;
232 else
233 sym->endpos = sym->pos;
235 child = new_sym_node(sym, "macro", node);
238 static void examine_namespace(struct symbol *sym)
240 xmlChar *namespace_type = NULL;
242 if (sym->ident && sym->ident->reserved)
243 return;
245 switch(sym->namespace) {
246 case NS_MACRO:
247 examine_macro(sym, root_node);
248 break;
249 case NS_TYPEDEF:
250 case NS_STRUCT:
251 case NS_SYMBOL:
252 examine_symbol(sym, root_node);
253 break;
254 case NS_NONE:
255 case NS_LABEL:
256 case NS_ITERATOR:
257 case NS_UNDEF:
258 case NS_PREPROCESSOR:
259 case NS_KEYWORD:
260 break;
261 default:
262 die("Unrecognised namespace type %d",sym->namespace);
267 static int get_stream_id (const char *name)
269 int i;
270 for (i=0; i<input_stream_nr; i++) {
271 if (strcmp(name, stream_name(i))==0)
272 return i;
274 return -1;
277 static inline void examine_symbol_list(const char *file, struct symbol_list *list)
279 struct symbol *sym;
280 int stream_id = get_stream_id (file);
282 if (!list)
283 return;
284 FOR_EACH_PTR(list, sym) {
285 if (sym->pos.stream == stream_id)
286 examine_namespace(sym);
287 } END_FOR_EACH_PTR(sym);
290 int main(int argc, char **argv)
292 struct string_list *filelist = NULL;
293 struct symbol_list *symlist = NULL;
294 char *file;
296 doc = xmlNewDoc("1.0");
297 root_node = xmlNewNode(NULL, "parse");
298 xmlDocSetRootElement(doc, root_node);
300 /* - A DTD is probably unnecessary for something like this
302 dtd = xmlCreateIntSubset(doc, "parse", "http://www.kernel.org/pub/software/devel/sparse/parse.dtd" NULL, "parse.dtd");
304 ns = xmlNewNs (root_node, "http://www.kernel.org/pub/software/devel/sparse/parse.dtd", NULL);
306 xmlSetNs(root_node, ns);
308 symlist = sparse_initialize(argc, argv, &filelist);
310 FOR_EACH_PTR_NOTAG(filelist, file) {
311 examine_symbol_list(file, symlist);
312 sparse_keep_tokens(file);
313 examine_symbol_list(file, file_scope->symbols);
314 examine_symbol_list(file, global_scope->symbols);
315 } END_FOR_EACH_PTR_NOTAG(file);
318 xmlSaveFormatFileEnc("-", doc, "UTF-8", 1);
319 xmlFreeDoc(doc);
320 xmlCleanupParser();
322 return 0;