1 /*
2 * Sparse c2xml
3 *
4 * Dumps the parse tree as an xml document
5 *
6 * Copyright (C) 2007 Rob Taylor
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 */
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <assert.h>
32 #include <libxml/parser.h>
33 #include <libxml/tree.h>
34
35 #include "expression.h"
36 #include "parse.h"
37 #include "scope.h"
38 #include "symbol.h"
39
40 static xmlDocPtr doc = NULL; /* document pointer */
41 static xmlNodePtr root_node = NULL;/* root node pointer */
42 static int idcount = 0;
43
44 static void examine_symbol(struct symbol *sym, xmlNodePtr node);
45
newProp(xmlNodePtr node,const char * name,const char * value)46 static xmlAttrPtr newProp(xmlNodePtr node, const char *name, const char *value)
47 {
48 return xmlNewProp(node, BAD_CAST name, BAD_CAST value);
49 }
50
newNumProp(xmlNodePtr node,const char * name,int value)51 static xmlAttrPtr newNumProp(xmlNodePtr node, const char *name, int value)
52 {
53 char buf[256];
54 snprintf(buf, 256, "%d", value);
55 return newProp(node, name, buf);
56 }
57
newIdProp(xmlNodePtr node,const char * name,unsigned int id)58 static xmlAttrPtr newIdProp(xmlNodePtr node, const char *name, unsigned int id)
59 {
60 char buf[256];
61 snprintf(buf, 256, "_%d", id);
62 return newProp(node, name, buf);
63 }
64
new_sym_node(struct symbol * sym,const char * name,xmlNodePtr parent)65 static xmlNodePtr new_sym_node(struct symbol *sym, const char *name, xmlNodePtr parent)
66 {
67 xmlNodePtr node;
68 const char *ident = show_ident(sym->ident);
69
70 assert(name != NULL);
71 assert(sym != NULL);
72 assert(parent != NULL);
73
74 node = xmlNewChild(parent, NULL, BAD_CAST "symbol", NULL);
75
76 newProp(node, "type", name);
77
78 newIdProp(node, "id", idcount);
79
80 if (sym->ident && ident)
81 newProp(node, "ident", ident);
82 newProp(node, "file", stream_name(sym->pos.stream));
83
84 newNumProp(node, "start-line", sym->pos.line);
85 newNumProp(node, "start-col", sym->pos.pos);
86
87 if (sym->endpos.type) {
88 newNumProp(node, "end-line", sym->endpos.line);
89 newNumProp(node, "end-col", sym->endpos.pos);
90 if (sym->pos.stream != sym->endpos.stream)
91 newProp(node, "end-file", stream_name(sym->endpos.stream));
92 }
93 sym->aux = node;
94
95 idcount++;
96
97 return node;
98 }
99
examine_members(struct symbol_list * list,xmlNodePtr node)100 static inline void examine_members(struct symbol_list *list, xmlNodePtr node)
101 {
102 struct symbol *sym;
103
104 FOR_EACH_PTR(list, sym) {
105 examine_symbol(sym, node);
106 } END_FOR_EACH_PTR(sym);
107 }
108
examine_modifiers(struct symbol * sym,xmlNodePtr node)109 static void examine_modifiers(struct symbol *sym, xmlNodePtr node)
110 {
111 const char *modifiers[] = {
112 "auto",
113 "register",
114 "static",
115 "extern",
116 "const",
117 "volatile",
118 "signed",
119 "unsigned",
120 "char",
121 "short",
122 "long",
123 "long-long",
124 "typedef",
125 NULL,
126 NULL,
127 NULL,
128 NULL,
129 NULL,
130 "inline",
131 "addressable",
132 "nocast",
133 "noderef",
134 "accessed",
135 "toplevel",
136 "label",
137 "assigned",
138 "type-type",
139 "safe",
140 "user-type",
141 "force",
142 "explicitly-signed",
143 "bitwise"};
144
145 int i;
146
147 if (sym->namespace != NS_SYMBOL)
148 return;
149
150 /*iterate over the 32 bit bitfield*/
151 for (i=0; i < 32; i++) {
152 if ((sym->ctype.modifiers & 1<<i) && modifiers[i])
153 newProp(node, modifiers[i], "1");
154 }
155 }
156
157 static void
examine_layout(struct symbol * sym,xmlNodePtr node)158 examine_layout(struct symbol *sym, xmlNodePtr node)
159 {
160 examine_symbol_type(sym);
161
162 newNumProp(node, "bit-size", sym->bit_size);
163 newNumProp(node, "alignment", sym->ctype.alignment);
164 newNumProp(node, "offset", sym->offset);
165 if (is_bitfield_type(sym)) {
166 newNumProp(node, "bit-offset", sym->bit_offset);
167 }
168 }
169
examine_symbol(struct symbol * sym,xmlNodePtr node)170 static void examine_symbol(struct symbol *sym, xmlNodePtr node)
171 {
172 xmlNodePtr child = NULL;
173 const char *base;
174 int array_size;
175
176 if (!sym)
177 return;
178 if (sym->aux) /*already visited */
179 return;
180
181 if (sym->ident && sym->ident->reserved)
182 return;
183
184 child = new_sym_node(sym, get_type_name(sym->type), node);
185 examine_modifiers(sym, child);
186 examine_layout(sym, child);
187
188 if (sym->ctype.base_type) {
189 if ((base = builtin_typename(sym->ctype.base_type)) == NULL) {
190 if (!sym->ctype.base_type->aux) {
191 examine_symbol(sym->ctype.base_type, root_node);
192 }
193 xmlNewProp(child, BAD_CAST "base-type",
194 xmlGetProp((xmlNodePtr)sym->ctype.base_type->aux, BAD_CAST "id"));
195 } else {
196 newProp(child, "base-type-builtin", base);
197 }
198 }
199 if (sym->array_size) {
200 /* TODO: modify get_expression_value to give error return */
201 array_size = get_expression_value(sym->array_size);
202 newNumProp(child, "array-size", array_size);
203 }
204
205
206 switch (sym->type) {
207 case SYM_STRUCT:
208 case SYM_UNION:
209 examine_members(sym->symbol_list, child);
210 break;
211 case SYM_FN:
212 examine_members(sym->arguments, child);
213 break;
214 case SYM_UNINITIALIZED:
215 newProp(child, "base-type-builtin", builtin_typename(sym));
216 break;
217 default:
218 break;
219 }
220 return;
221 }
222
get_expansion_end(struct token * token)223 static struct position *get_expansion_end (struct token *token)
224 {
225 struct token *p1, *p2;
226
227 for (p1=NULL, p2=NULL;
228 !eof_token(token);
229 p2 = p1, p1 = token, token = token->next);
230
231 if (p2)
232 return &(p2->pos);
233 else
234 return NULL;
235 }
236
examine_macro(struct symbol * sym,xmlNodePtr node)237 static void examine_macro(struct symbol *sym, xmlNodePtr node)
238 {
239 struct position *pos;
240
241 /* this should probably go in the main codebase*/
242 pos = get_expansion_end(sym->expansion);
243 if (pos)
244 sym->endpos = *pos;
245 else
246 sym->endpos = sym->pos;
247
248 new_sym_node(sym, "macro", node);
249 }
250
examine_namespace(struct symbol * sym)251 static void examine_namespace(struct symbol *sym)
252 {
253 if (sym->ident && sym->ident->reserved)
254 return;
255
256 switch(sym->namespace) {
257 case NS_MACRO:
258 examine_macro(sym, root_node);
259 break;
260 case NS_TYPEDEF:
261 case NS_STRUCT:
262 case NS_SYMBOL:
263 examine_symbol(sym, root_node);
264 break;
265 case NS_NONE:
266 case NS_LABEL:
267 case NS_ITERATOR:
268 case NS_UNDEF:
269 case NS_PREPROCESSOR:
270 case NS_KEYWORD:
271 break;
272 default:
273 die("Unrecognised namespace type %d",sym->namespace);
274 }
275
276 }
277
get_stream_id(const char * name)278 static int get_stream_id (const char *name)
279 {
280 int i;
281 for (i=0; i<input_stream_nr; i++) {
282 if (strcmp(name, stream_name(i))==0)
283 return i;
284 }
285 return -1;
286 }
287
examine_symbol_list(const char * file,struct symbol_list * list)288 static inline void examine_symbol_list(const char *file, struct symbol_list *list)
289 {
290 struct symbol *sym;
291 int stream_id = get_stream_id (file);
292
293 if (!list)
294 return;
295 FOR_EACH_PTR(list, sym) {
296 if (sym->pos.stream == stream_id)
297 examine_namespace(sym);
298 } END_FOR_EACH_PTR(sym);
299 }
300
main(int argc,char ** argv)301 int main(int argc, char **argv)
302 {
303 struct string_list *filelist = NULL;
304 struct symbol_list *symlist = NULL;
305 char *file;
306
307 doc = xmlNewDoc(BAD_CAST "1.0");
308 root_node = xmlNewNode(NULL, BAD_CAST "parse");
309 xmlDocSetRootElement(doc, root_node);
310
311 /* - A DTD is probably unnecessary for something like this
312
313 dtd = xmlCreateIntSubset(doc, "parse", "http://www.kernel.org/pub/software/devel/sparse/parse.dtd" NULL, "parse.dtd");
314
315 ns = xmlNewNs (root_node, "http://www.kernel.org/pub/software/devel/sparse/parse.dtd", NULL);
316
317 xmlSetNs(root_node, ns);
318 */
319 symlist = sparse_initialize(argc, argv, &filelist);
320
321 FOR_EACH_PTR(filelist, file) {
322 examine_symbol_list(file, symlist);
323 sparse_keep_tokens(file);
324 examine_symbol_list(file, file_scope->symbols);
325 examine_symbol_list(file, global_scope->symbols);
326 } END_FOR_EACH_PTR(file);
327
328
329 xmlSaveFormatFileEnc("-", doc, "UTF-8", 1);
330 xmlFreeDoc(doc);
331 xmlCleanupParser();
332
333 return 0;
334 }
335