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