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