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
16 #include <libxml/parser.h>
17 #include <libxml/tree.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 */
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
)
36 snprintf(buf
, 256, "%d", value
);
37 return xmlNewProp(node
, name
, buf
);
40 static xmlAttrPtr
newIdProp(xmlNodePtr node
, const xmlChar
* name
, unsigned int id
)
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
)
50 const char *ident
= show_ident(sym
->ident
);
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
));
82 static inline void examine_members(struct symbol_list
*list
, xmlNodePtr node
)
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
[] = {
131 if (sym
->namespace != NS_SYMBOL
)
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");
142 examine_layout(struct symbol
*sym
, xmlNodePtr node
)
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
;
165 if (sym
->aux
) /*already visited */
168 if (sym
->ident
&& sym
->ident
->reserved
)
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"));
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
);
196 examine_members(sym
->symbol_list
, child
);
199 examine_members(sym
->arguments
, child
);
201 case SYM_UNINITIALIZED
:
202 xmlNewProp(child
, "base-type-builtin", builtin_typename(sym
));
208 static struct position
*get_expansion_end (struct token
*token
)
210 struct token
*p1
, *p2
;
212 for (p1
=NULL
, p2
=NULL
;
214 p2
= p1
, p1
= token
, token
= token
->next
);
222 static void examine_macro(struct symbol
*sym
, xmlNodePtr node
)
225 struct position
*pos
;
228 /* this should probably go in the main codebase*/
229 pos
= get_expansion_end(sym
->expansion
);
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
)
245 switch(sym
->namespace) {
247 examine_macro(sym
, root_node
);
252 examine_symbol(sym
, root_node
);
258 case NS_PREPROCESSOR
:
262 die("Unrecognised namespace type %d",sym
->namespace);
267 static int get_stream_id (const char *name
)
270 for (i
=0; i
<input_stream_nr
; i
++) {
271 if (strcmp(name
, stream_name(i
))==0)
277 static inline void examine_symbol_list(const char *file
, struct symbol_list
*list
)
280 int stream_id
= get_stream_id (file
);
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
;
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);