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>
19 #include "expression.h"
24 static xmlDocPtr doc
= NULL
; /* document pointer */
25 static xmlNodePtr root_node
= NULL
;/* root node pointer */
26 static int idcount
= 0;
28 static void examine_symbol(struct symbol
*sym
, xmlNodePtr node
);
30 static xmlAttrPtr
newProp(xmlNodePtr node
, const char *name
, const char *value
)
32 return xmlNewProp(node
, BAD_CAST name
, BAD_CAST value
);
35 static xmlAttrPtr
newNumProp(xmlNodePtr node
, const char *name
, int value
)
38 snprintf(buf
, 256, "%d", value
);
39 return newProp(node
, name
, buf
);
42 static xmlAttrPtr
newIdProp(xmlNodePtr node
, const char *name
, unsigned int id
)
45 snprintf(buf
, 256, "_%d", id
);
46 return newProp(node
, name
, buf
);
49 static xmlNodePtr
new_sym_node(struct symbol
*sym
, const char *name
, xmlNodePtr parent
)
52 const char *ident
= show_ident(sym
->ident
);
56 assert(parent
!= NULL
);
58 node
= xmlNewChild(parent
, NULL
, BAD_CAST
"symbol", NULL
);
60 newProp(node
, "type", name
);
62 newIdProp(node
, "id", idcount
);
64 if (sym
->ident
&& ident
)
65 newProp(node
, "ident", ident
);
66 newProp(node
, "file", stream_name(sym
->pos
.stream
));
68 newNumProp(node
, "start-line", sym
->pos
.line
);
69 newNumProp(node
, "start-col", sym
->pos
.pos
);
71 if (sym
->endpos
.type
) {
72 newNumProp(node
, "end-line", sym
->endpos
.line
);
73 newNumProp(node
, "end-col", sym
->endpos
.pos
);
74 if (sym
->pos
.stream
!= sym
->endpos
.stream
)
75 newProp(node
, "end-file", stream_name(sym
->endpos
.stream
));
84 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 newProp(node
, modifiers
[i
], "1");
142 examine_layout(struct symbol
*sym
, xmlNodePtr node
)
144 examine_symbol_type(sym
);
146 newNumProp(node
, "bit-size", sym
->bit_size
);
147 newNumProp(node
, "alignment", sym
->ctype
.alignment
);
148 newNumProp(node
, "offset", sym
->offset
);
149 if (is_bitfield_type(sym
)) {
150 newNumProp(node
, "bit-offset", sym
->bit_offset
);
154 static void examine_symbol(struct symbol
*sym
, xmlNodePtr node
)
156 xmlNodePtr child
= NULL
;
162 if (sym
->aux
) /*already visited */
165 if (sym
->ident
&& sym
->ident
->reserved
)
168 child
= new_sym_node(sym
, get_type_name(sym
->type
), node
);
169 examine_modifiers(sym
, child
);
170 examine_layout(sym
, child
);
172 if (sym
->ctype
.base_type
) {
173 if ((base
= builtin_typename(sym
->ctype
.base_type
)) == NULL
) {
174 if (!sym
->ctype
.base_type
->aux
) {
175 examine_symbol(sym
->ctype
.base_type
, root_node
);
177 xmlNewProp(child
, BAD_CAST
"base-type",
178 xmlGetProp((xmlNodePtr
)sym
->ctype
.base_type
->aux
, BAD_CAST
"id"));
180 newProp(child
, "base-type-builtin", base
);
183 if (sym
->array_size
) {
184 /* TODO: modify get_expression_value to give error return */
185 array_size
= get_expression_value(sym
->array_size
);
186 newNumProp(child
, "array-size", array_size
);
193 examine_members(sym
->symbol_list
, child
);
196 examine_members(sym
->arguments
, child
);
198 case SYM_UNINITIALIZED
:
199 newProp(child
, "base-type-builtin", builtin_typename(sym
));
205 static struct position
*get_expansion_end (struct token
*token
)
207 struct token
*p1
, *p2
;
209 for (p1
=NULL
, p2
=NULL
;
211 p2
= p1
, p1
= token
, token
= token
->next
);
219 static void examine_macro(struct symbol
*sym
, xmlNodePtr node
)
221 struct position
*pos
;
223 /* this should probably go in the main codebase*/
224 pos
= get_expansion_end(sym
->expansion
);
228 sym
->endpos
= sym
->pos
;
230 new_sym_node(sym
, "macro", node
);
233 static void examine_namespace(struct symbol
*sym
)
235 if (sym
->ident
&& sym
->ident
->reserved
)
238 switch(sym
->namespace) {
240 examine_macro(sym
, root_node
);
245 examine_symbol(sym
, root_node
);
251 case NS_PREPROCESSOR
:
255 die("Unrecognised namespace type %d",sym
->namespace);
260 static int get_stream_id (const char *name
)
263 for (i
=0; i
<input_stream_nr
; i
++) {
264 if (strcmp(name
, stream_name(i
))==0)
270 static inline void examine_symbol_list(const char *file
, struct symbol_list
*list
)
273 int stream_id
= get_stream_id (file
);
277 FOR_EACH_PTR(list
, sym
) {
278 if (sym
->pos
.stream
== stream_id
)
279 examine_namespace(sym
);
280 } END_FOR_EACH_PTR(sym
);
283 int main(int argc
, char **argv
)
285 struct string_list
*filelist
= NULL
;
286 struct symbol_list
*symlist
= NULL
;
289 doc
= xmlNewDoc(BAD_CAST
"1.0");
290 root_node
= xmlNewNode(NULL
, BAD_CAST
"parse");
291 xmlDocSetRootElement(doc
, root_node
);
293 /* - A DTD is probably unnecessary for something like this
295 dtd = xmlCreateIntSubset(doc, "parse", "http://www.kernel.org/pub/software/devel/sparse/parse.dtd" NULL, "parse.dtd");
297 ns = xmlNewNs (root_node, "http://www.kernel.org/pub/software/devel/sparse/parse.dtd", NULL);
299 xmlSetNs(root_node, ns);
301 symlist
= sparse_initialize(argc
, argv
, &filelist
);
303 FOR_EACH_PTR_NOTAG(filelist
, file
) {
304 examine_symbol_list(file
, symlist
);
305 sparse_keep_tokens(file
);
306 examine_symbol_list(file
, file_scope
->symbols
);
307 examine_symbol_list(file
, global_scope
->symbols
);
308 } END_FOR_EACH_PTR_NOTAG(file
);
311 xmlSaveFormatFileEnc("-", doc
, "UTF-8", 1);