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 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 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 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 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 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 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 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 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 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 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 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 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 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 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_NOTAG(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_NOTAG(file); 327 328 329 xmlSaveFormatFileEnc("-", doc, "UTF-8", 1); 330 xmlFreeDoc(doc); 331 xmlCleanupParser(); 332 333 return 0; 334 } 335