dxref.c
1 /*
2 dxref - a tiny cross referencer using DWARF2-XML
3 Copyright (C) 2003, 2004, by gondow@jaist.ac.jp, All rights reserved.
4 $Id: dxref.c,v 1.13 2004/01/20 14:22:10 gondow Exp gondow $
5 */
6 /* ======================================================================== */
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <assert.h>
10 #include <string.h>
11 #include <unistd.h>
12
13 #include <libxml/parser.h>
14 #include <libxml/xpath.h>
15 #include <libxml/tree.h>
16 #include <libxml/debugXML.h>
17
18 #define BUFLEN 8192
19
20 #define TARGET_MAIN "target=\"main\""
21 #define TARGET_SRC "target=\"src\""
22 #define COMM_BEGIN "<font color=\"red\">/* "
23 #define COMM_END " */</font>"
24
25 #define DEFAULT_DIR "./HTML/"
26 #define WORKING_DIR "./HTML/dxref.files/"
27 #if 0
28 #define XREF_MAIN "dxref_main.html"
29 #endif
30 #define XREF_INFO "dxref_info.html"
31 #define XREF_MACINFO "dxref_macinfo.html"
32 #define XREF_INDEX "dxref_index.html"
33 #define XREF_STRUCTS1 "dxref_structs1.html"
34 #define XREF_STRUCTS2 "dxref_structs2.html"
35 #define XREF_UNIONS1 "dxref_unions1.html"
36 #define XREF_UNIONS2 "dxref_unions2.html"
37 #define XREF_TYPEDEFS1 "dxref_typedefs1.html"
38 #define XREF_TYPEDEFS2 "dxref_typedefs2.html"
39 #define XREF_ENUM_TAGS1 "dxref_enum_tags1.html"
40 #define XREF_ENUM_TAGS2 "dxref_enum_tags2.html"
41 #define XREF_ENUM_CONSTS1 "dxref_enum_consts1.html"
42 #define XREF_ENUM_CONSTS2 "dxref_enum_consts2.html"
43 #define XREF_LABELS1 "dxref_labels1.html"
44 #define XREF_LABELS2 "dxref_labels2.html"
45 #define XREF_FUNCTIONS1 "dxref_functions1.html"
46 #define XREF_FUNCTIONS2 "dxref_functions2.html"
47 #define XREF_VARIABLES1 "dxref_variables1.html"
48 #define XREF_VARIABLES2 "dxref_variables2.html"
49 #define XREF_MACROS1 "dxref_macros1.html"
50 #define XREF_MACROS2 "dxref_macros2.html"
51 #define XREF_MACROS3 "dxref_macros3.html"
52 #define XREF_FILES1 "dxref_files1.html"
53 #define XREF_FILES2 "dxref_files2.html"
54
55 /* ====================================================================== */
56 static struct {
57 int src2html;
58 int num_files;
59 char **files;
60 int verbose;
61 } args = {
62 0, /* src2html */
63 0, /* num_files */
64 NULL,/* files */
65 0 /* verbose */
66 };
67
68 struct comp_unit {
69 char *info_offset;
70 unsigned long info_offset2;
71 char *macinfo_offset;
72 char *line_offset;
73 int n_file;
74 struct file *file; /* array */
75 int n_line;
76 struct line *line; /* array */
77 };
78
79 struct file {
80 char *filename;
81 char *pathname;
82 };
83
84 struct line {
85 unsigned long addr;
86 int line;
87 struct file *file;
88 };
89
90 struct abbrev_entry {
91 int number;
92 char *upper_bound_form;
93 };
94 /* ====================================================================== */
95 static xmlDocPtr xml_doc = NULL;
96 static xmlNodePtr xml_root = NULL;
97 static int indent_depth = 0;
98 static int n_comp_unit;
99 static struct comp_unit *comp_unit;
100 static struct abbrev_entry *abbrev_table;
101 static int eval_xpath_debug = 0;
102 /* ====================================================================== */
103 static void *emalloc (size_t size);
104 static void print_usage (void);
105 static void process_args (int argc, char *argv []);
106 static void init (void);
107 static void final (void);
108 static int count_children (xmlNodePtr node, char *tag);
109 static xmlNodePtr search_sibling (xmlNodePtr node, char *tag);
110 static char **create_dir_table (xmlNodePtr node);
111 static void delete_dir_table (char **dir_table);
112 static struct file *create_file_table (xmlNodePtr node, char **dir_table,
113 int *n_file);
114 static struct line *create_line_table (xmlNodePtr node,
115 struct file *file_table, int *n_line);
116 static void create_comp_unit_table (void);
117 static void create_abbrev_table (void);
118 static void do_src2html (void);
119
120 static char *href_info (char *id, char *title);
121 static char *href_info2 (char *id, char *title, char *title2);
122 static char *href_macinfo (char *id, char *title);
123 static char *href_macinfo2 (char *id, char *title, char *title2);
124 static char *href_src1 (char *pathname, char *line, char *title);
125 static char *href_src2 (char *pathname, char *line, char *title);
126 static char *a_name (char *id);
127
128 static xmlNodeSetPtr eval_xpath (char *xpath, xmlNodePtr from,
129 void **free_p, int *num);
130 static inline char *get_child (char *elem, char *name, char *attr,
131 xmlNodePtr from);
132 static inline char *get_tag (char *name, char *attr, xmlNodePtr from);
133 static inline char *get_attr (char *name, char *attr, xmlNodePtr from);
134 static inline char *get_attr_value (char *xpath, xmlNodePtr from);
135 static inline char *get_attr_value_ref (char *name, xmlNodePtr from);
136 static inline char *get_attr_desc (char *xpath, xmlNodePtr from);
137
138 static char *get_type (xmlNodePtr node);
139 static char *get_params (xmlNodePtr node);
140 static char *get_subscript (xmlNodePtr node);
141 static int get_comp_unit (xmlNodePtr node);
142 static char *get_filename_by_char (int n_comp, char *file_num);
143 static char *get_filename_by_node (xmlNodePtr node, char *file_num);
144 static char *get_filename_by_int (int n_comp, int file_num);
145 static char *get_pathname_by_char (int n_comp, char *file_num);
146 static char *get_pathname_by_node (xmlNodePtr node, char *file_num);
147 static char *get_pathname_by_int (int n_comp, int file_num);
148 static char *get_line (char *line);
149 static char *get_name (char *name);
150
151 static char *type_to_string (xmlNodePtr node);
152 static char *base_type_to_string (xmlNodePtr node);
153 static char *array_type_to_string (xmlNodePtr node);
154 static char *ptr_type_to_string (xmlNodePtr node);
155 static char *func_type_to_string (xmlNodePtr node);
156 static char *volatile_to_string (xmlNodePtr node);
157 static char *const_to_string (xmlNodePtr node);
158 static char *struct_union_to_string (xmlNodePtr node, char *which);
159 static char *struct_to_string (xmlNodePtr node);
160 static char *union_to_string (xmlNodePtr node);
161 static char *typedef_to_string (xmlNodePtr node);
162 static char *enum_to_string (xmlNodePtr node);
163 static char *enum_constants_to_string (xmlNodePtr node);
164 static char *members_to_string (xmlNodePtr node);
165
166 static void visit_all_children (xmlNodePtr node, FILE *fp);
167 static void output_indent (FILE *fp);
168 static void output_debug_info_top (void);
169 static void output_debug_info (xmlNodePtr node, FILE *fp);
170 static void output_compile_unit (xmlNodePtr node, FILE *fp);
171 static void output_subprogram (xmlNodePtr node, FILE *fp);
172 static void output_lexical_block (xmlNodePtr node, FILE *fp);
173 static void output_variable (xmlNodePtr node, FILE *fp);
174 static void output_label (xmlNodePtr node, FILE *fp);
175 static void output_typedef (xmlNodePtr node, FILE *fp);
176 static void output_enum (xmlNodePtr node, FILE *fp);
177 static void output_enum_constants (xmlNodePtr node, FILE *fp,
178 char *pathname, char *line);
179 static void output_struct_union (xmlNodePtr node, FILE *fp, char *which);
180 static void output_struct (xmlNodePtr node, FILE *fp);
181 static void output_union (xmlNodePtr node, FILE *fp);
182 static void output_members (xmlNodePtr node, FILE *fp);
183
184 static void output_all_structs (void);
185 static void output_all_unions (void);
186
187 static void output_all_typedefs (void);
188 static void output_all_enums (void);
189 static void output_all_labels (void);
190 static void output_all_functions (void);
191 static void output_all_variables (void);
192 static void output_all_files (void);
193
194 static char *get_macinfo_id (void);
195 static void output_all_macros (void);
196 /* ====================================================================== */
197 static void *
198 emalloc (size_t size)
199 {
200 void *p = malloc (size);
201 if (p == NULL) perror ("malloc");
202 return p;
203 }
204
205 static void
206 print_usage (void)
207 {
208 fprintf (stderr,
209 "usage : dxref [options] file.xml\n"
210 "options:\n"
211 " --src2html translate sources to htmls\n"
212 " --verbose tells what is being doing\n"
213 " --help prints this usage\n"
214 );
215 }
216
217 static void
218 process_args (int argc, char *argv [])
219 {
220 int i;
221 char *s;
222
223 for (i = 1; i < argc; i++) {
224 if (argv [i][0] != '-') { /* filenames */
225 args.files = &argv [i];
226 args.num_files = argc - i;
227 break;
228 } else if (!strcmp (argv [i], "--src2html")) {
229 args.src2html = 1;
230 } else if (!strcmp (argv [i], "--verbose")) {
231 args.verbose = 1;
232 } else if (!strcmp (argv [i], "--help")) {
233 print_usage ();
234 exit (1);
235 } else {
236 /* unknown option */
237 fprintf (stderr, "unknown option: %s\n", argv [i]);
238 print_usage ();
239 exit (1);
240 }
241 }
242
243 if (args.num_files <= 0) {
244 print_usage ();
245 exit (1);
246 }
247 }
248
249 static void
250 init (void)
251 {
252 char *xml;
253
254 assert (args.num_files >= 1);
255 xml = args.files [0]; /* currently, only one file is processed */
256 xmlDoValidityCheckingDefaultValue = 1;
257 xmlSubstituteEntitiesDefault (1); /* to substitute entity refs. (<) */
258
259 if (!strcmp (".gz", xml + strlen (xml) -3)) { /* gzipped file */
260 FILE *fp;
261 char buf[BUFLEN], *gunzip_file;
262 int ret;
263
264 gunzip_file = tmpnam (NULL);
265 snprintf (buf, sizeof (buf), "gunzip -c %s > %s", xml, gunzip_file);
266 ret = system (buf);
267 if (ret == -1) {
268 perror ("system"); exit (1);
269 }
270 fp = fopen (gunzip_file, "r");
271 xml_doc = xmlParseFile(gunzip_file);
272 unlink (gunzip_file);
273 } else { /* not gzipped file */
274 xml_doc = xmlParseFile(xml);
275 }
276 xml_root = xmlDocGetRootElement (xml_doc);
277 xmlXPathInit();
278 mkdir (DEFAULT_DIR, 0755);
279 mkdir (WORKING_DIR, 0755);
280 create_comp_unit_table ();
281 create_abbrev_table ();
282
283 /* must be after create_comp_unit_table (); */
284 if (args.src2html) do_src2html ();
285 }
286
287 static void
288 final (void)
289 {
290 system ("dxref.csh");
291 }
292
293 static int
294 count_children (xmlNodePtr node, char *tag)
295 {
296 int n = 0;
297 xmlNodePtr child;
298
299 for (child = node->children; child != NULL; child = child->next) {
300 if (child->type == XML_ELEMENT_NODE && !strcmp (child->name, tag))
301 n++;
302 }
303 return n;
304 }
305
306 static xmlNodePtr
307 search_sibling (xmlNodePtr node, char *tag)
308 {
309 while (node != NULL) {
310 if (node->type == XML_ELEMENT_NODE && !strcmp (node->name, tag))
311 return node;
312 node = node->next;
313 }
314 return NULL; /* not found */
315 }
316
317 static char **
318 create_dir_table (xmlNodePtr node)
319 {
320 int i, n_dir;
321 xmlNodePtr child;
322 char **dir_table;
323
324 assert (node != NULL);
325 assert (node->type == XML_ELEMENT_NODE);
326 assert (!strcmp (node->name, "include_directories"));
327
328 n_dir = count_children (node, "directory");
329 /* +1 for 1-origin, +1 for NULL-termination */
330 dir_table = emalloc (sizeof (char *) * (n_dir + 2));
331 dir_table [0] = "!!!not used entry";
332 i = 1;
333 for (child = node->children; child != NULL; child = child->next) {
334 if (child->type == XML_ELEMENT_NODE
335 && !strcmp (child->name, "directory"))
336 dir_table [i++] = xmlNodeGetContent (child);
337 }
338 dir_table [i] = NULL;
339
340 return dir_table;
341 }
342
343 static void
344 delete_dir_table (char **dir_table)
345 {
346 int i;
347
348 if (dir_table == NULL)
349 return;
350
351 for (i = 1; dir_table [i] != NULL; i++) {
352 xmlFree (dir_table [i]);
353 }
354 free (dir_table);
355 }
356
357 static struct file *
358 create_file_table (xmlNodePtr node, char **dir_table, int *n_file)
359 {
360 int i;
361 struct file *file_table;
362 xmlNodePtr child;
363 char buf [BUFLEN];
364
365 *n_file = count_children (node, "file");
366 /* +1 for 1-origin */
367 file_table = emalloc (sizeof (struct file) * *n_file + 1);
368
369 file_table [0].filename = "!!!unused entry";
370 file_table [0].pathname = "!!!unused entry";
371 i = 1;
372 for (child = node->children; child != NULL; child = child->next) {
373 if (child->type == XML_ELEMENT_NODE && !strcmp (child->name, "file")) {
374 char *dir_index = xmlGetProp (child, "directory");
375 int d = atoi (dir_index);
376 xmlFree (dir_index);
377
378 file_table [i].filename = xmlNodeGetContent (child);
379
380 if (d == 0) {
381 file_table [i].pathname = file_table [i].filename;
382 } else {
383 snprintf (buf, sizeof (buf), "%s/%s",
384 dir_table [d], file_table [i].filename);
385 file_table [i].pathname = strdup (buf);
386 }
387 i++;
388 }
389 }
390 assert (i == *n_file + 1);
391 return file_table;
392 }
393
394 static struct line *
395 create_line_table (xmlNodePtr node, struct file *file_table, int *n_line)
396 {
397 int i;
398 struct line *line_table;
399 xmlNodePtr child;
400
401 *n_line = count_children (node, "line");
402 line_table = emalloc (sizeof (struct line) * *n_line);
403
404 i = 0;
405 for (child = node->children; child != NULL; child = child->next) {
406 if (child->type == XML_ELEMENT_NODE && !strcmp (child->name, "line")) {
407 char *addr = xmlGetProp (child, "address");
408 char *line = xmlGetProp (child, "line");
409 char *file = xmlGetProp (child, "file");
410
411 line_table [i].addr = atoll (addr);
412 line_table [i].line = atoi (line);
413 line_table [i].file = &file_table [atoi (file)];
414
415 xmlFree (addr);
416 xmlFree (line);
417 xmlFree (file);
418 i++;
419 }
420 }
421 assert (i == *n_line);
422 return line_table;
423 }
424
425 static void
426 create_comp_unit_table (void)
427 {
428 int i;
429 char *xpath = "//section[@name='.debug_info']/tag[@name='DW_TAG_compile_unit']";
430 void *free_p;
431
432 xmlNodeSetPtr result = eval_xpath (xpath, xml_root, &free_p,
433 &n_comp_unit);
434 assert (n_comp_unit >= 1);
435 comp_unit = emalloc (sizeof (struct comp_unit) * n_comp_unit);
436
437 /* store debug line info. etc for each compilation_unit */
438 for (i = 0; i < n_comp_unit; i++) {
439 xmlNodePtr node = result->nodeTab [i];
440 char **dir_table;
441 xmlNodePtr line_node, line_node2;
442 char buf [BUFLEN];
443 xmlAttrPtr attr;
444 int ret;
445
446 char *info_offset = xmlGetProp (node, "offset");
447 char *macro_info = get_attr_value ("DW_AT_macro_info", node);
448 char *stmt_list = get_attr_value ("DW_AT_stmt_list", node);
449
450 assert (info_offset != NULL);
451 assert (macro_info != NULL);
452 assert (stmt_list != NULL);
453
454 comp_unit [i].info_offset = info_offset;
455 ret = sscanf (info_offset, "info:%ld", &comp_unit [i].info_offset2);
456 if (ret != 1)
457 fprintf (stderr, "info_offset = %s\n", info_offset);
458 assert (ret == 1);
459 snprintf (buf, sizeof (buf), "macinfo:%s", macro_info);
460 comp_unit [i].macinfo_offset = strdup (buf);
461 snprintf (buf, sizeof (buf), "line:%s", stmt_list);
462 comp_unit [i].line_offset = strdup (buf);
463
464 attr = xmlGetID (xml_doc, comp_unit [i].line_offset);
465 assert (attr != NULL);
466 line_node = attr->parent;
467
468 line_node2 = search_sibling (line_node, "include_directories");
469 if (line_node2 == NULL) { /* no directory info. */
470 dir_table = NULL;
471 } else {
472 line_node = line_node2;
473 dir_table = create_dir_table (line_node);
474 }
475 line_node = search_sibling (line_node, "file_names");
476 assert (node != NULL);
477 comp_unit [i].file = create_file_table (line_node, dir_table,
478 &comp_unit [i].n_file);
479 delete_dir_table (dir_table);
480 #if 1
481 comp_unit [i].line = NULL;
482 #else
483 /* currently, dxref does not use `comp_unit [i].line', so
484 I commented out the following. */
485 line_node = search_sibling (line_node, "lines");
486 assert (node != NULL);
487 comp_unit [i].line = create_line_table (line_node, comp_unit [i].file,
488 &comp_unit [i].n_line);
489 #endif
490 xmlFree (macro_info);
491 xmlFree (stmt_list);
492 }
493 }
494
495 static void
496 create_abbrev_table (void)
497 {
498 int i, n;
499 char *xpath = "//section[@name='.debug_abbrev']/tag_abbrev"
500 "[@name='DW_TAG_subrange_type']/"
501 "attribute_abbrev[@name='DW_AT_upper_bound']";
502 void *free_p;
503 xmlNodeSetPtr result = eval_xpath (xpath, xml_root, &free_p, &n);
504
505 abbrev_table = emalloc (sizeof (struct abbrev_entry) * (n + 1));
506 for (i = 0; i < n; i++) {
507 xmlNodePtr node = result->nodeTab [i];
508 char *number = xmlGetProp (node->parent, "number");
509 abbrev_table [i].number = atoi (number);
510 xmlFree (number);
511 abbrev_table [i].upper_bound_form = xmlGetProp (node, "type");
512 }
513 abbrev_table [n].number = -1; /* sentinel */
514 abbrev_table [n].upper_bound_form = NULL;
515 free (free_p);
516 }
517
518 static void
519 do_src2html (void)
520 {
521 int i, j, ret;
522 char buf [BUFLEN];
523
524 if (args.verbose) printf ("translating sources to htmls\n");
525 for (i = 0; i < n_comp_unit; i++) {
526 for (j = 1; j <= comp_unit [i].n_file; j++) {
527 snprintf (buf, sizeof (buf), "PATH=.:$PATH; src2html %s",
528 comp_unit [i].file [j].pathname);
529 ret = system (buf);
530 if (ret == -1) { perror ("system"); exit (1); }
531 }
532 }
533 }
534
535 static char *
536 href_info (char *id, char *title)
537 {
538 static char buf [BUFLEN];
539 snprintf (buf, sizeof (buf), "<a href=\"" XREF_INFO "#%s\" "
540 TARGET_MAIN ">%s</a>", id, title);
541 return buf;
542 }
543
544 static char *
545 href_info2 (char *id, char *title, char *title2)
546 {
547 static char buf [BUFLEN];
548 snprintf (buf, sizeof (buf), "<a href=\"" XREF_INFO "#%s\" "
549 TARGET_MAIN ">%s %s</a>", id, title, title2);
550 return buf;
551 }
552
553 static char *
554 href_macinfo (char *id, char *title)
555 {
556 static char buf [BUFLEN];
557 snprintf (buf, sizeof (buf), "<a href=\"" XREF_MACINFO "#%s\" "
558 TARGET_MAIN ">%s</a>", id, title);
559 return buf;
560 }
561
562 static char *
563 href_macinfo2 (char *id, char *title, char *title2)
564 {
565 static char buf [BUFLEN];
566 snprintf (buf, sizeof (buf), "<a href=\"" XREF_MACINFO "#%s\" "
567 TARGET_MAIN ">%s %s</a>", id, title, title2);
568 return buf;
569 }
570
571 static char *
572 href_src1 (char *pathname, char *line, char *title)
573 {
574 static char buf [BUFLEN];
575 snprintf (buf, sizeof (buf), "<a href=\"./%s.html#%s\" "
576 TARGET_SRC ">%s</a>", pathname, line, title);
577 return buf;
578 }
579
580 static char *
581 href_src2 (char *pathname, char *line, char *title)
582 {
583 static char buf [BUFLEN];
584 snprintf (buf, sizeof (buf),
585 "<a href=\"./%s.html#%s\" " TARGET_SRC ">%s:%s</a>",
586 pathname, line, title, line);
587 return buf;
588 }
589
590 static char *
591 a_name (char *id)
592 {
593 static char buf [BUFLEN];
594 snprintf (buf, sizeof (buf), "<a name=\"%s\"/>", id);
595 return buf;
596 }
597
598 static xmlNodeSetPtr
599 eval_xpath (char *xpath, xmlNodePtr from, void **free_p, int *num)
600 {
601 xmlXPathObjectPtr result;
602 xmlXPathContextPtr context;
603
604 context = xmlXPathNewContext(xml_doc);
605 assert (context != NULL);
606 context->node = from;
607 result = xmlXPathEval (xpath, context);
608 xmlXPathFreeContext (context);
609 #if 0
610 if (args.verbose)
611 xmlXPathDebugDumpObject (stdout, result, 0);
612 #endif
613 if (num != NULL)
614 *num = xmlXPathNodeSetGetLength (result->nodesetval);
615 *free_p = result;
616 return result->nodesetval;
617 }
618
619 static inline char *
620 get_child (char *elem, char *name, char *attr, xmlNodePtr from)
621 {
622 int i;
623 xmlNodePtr node;
624 char *attr_name;
625
626 assert (from->children != NULL);
627 for (node = from->children; node != NULL; node = node->next) {
628 if (node->type != XML_ELEMENT_NODE) continue;
629 if (strcmp (node->name, elem)) continue;
630 attr_name = xmlGetProp (node, "name");
631 if (strcmp (attr_name, name)) {
632 xmlFree (attr_name);
633 continue;
634 }
635 xmlFree (attr_name);
636 if (*attr == '@') {
637 attr++;
638 return xmlGetProp (node, attr);
639 } else {
640 xmlNodePtr child;
641 for (child = node->children; child != NULL; child = child->next) {
642 if (child->type != XML_ELEMENT_NODE) continue;
643 if (strcmp (child->name, attr)) continue;
644 return xmlNodeGetContent (child);
645 }
646 return NULL;
647 }
648 }
649 return NULL;
650 }
651
652 static inline char *
653 get_tag (char *name, char *attr, xmlNodePtr from)
654 {
655 return get_child ("tag", name, attr, from);
656 }
657
658 static inline char *
659 get_attr (char *name, char *attr, xmlNodePtr from)
660 {
661 return get_child ("attribute", name, attr, from);
662 }
663
664 static inline char *
665 get_attr_value (char *name, xmlNodePtr from)
666 {
667 return get_attr (name, "@value", from);
668 }
669
670 static inline char *
671 get_attr_value_ref (char *name, xmlNodePtr from)
672 {
673 return get_attr (name, "@value_ref", from);
674 }
675
676 static inline char *
677 get_attr_desc (char *name, xmlNodePtr from)
678 {
679 return get_attr (name, "description", from);
680 }
681
682 static char *
683 get_type (xmlNodePtr node)
684 {
685 char *type;
686 char *type_id;
687
688 type_id = get_attr_value_ref ("DW_AT_type", node);
689 if (type_id == NULL) {
690 type = strdup ("void %s");
691 } else {
692 xmlAttrPtr list = xmlGetID (xml_doc, type_id);
693 assert (list != NULL);
694 type = type_to_string (list->parent);
695 }
696 xmlFree (type_id);
697 return type;
698 }
699
700 static char *
701 get_params (xmlNodePtr node)
702 {
703 char *attr, *xpath;
704 char buf [BUFLEN] = {'\0'};
705 xmlNodeSetPtr result;
706 int i, n;
707 void *free_p;
708
709 assert (node->type == XML_ELEMENT_NODE);
710 assert (!strcmp (node->name, "tag"));
711 attr = xmlGetProp (node, "name");
712 assert (!strcmp (attr, "DW_TAG_subroutine_type")
713 || !strcmp (attr, "DW_TAG_subprogram"));
714 xmlFree (attr);
715
716 xpath = "tag[@name='DW_TAG_unspecified_parameters'"
717 " or @name='DW_TAG_formal_parameter']";
718 result = eval_xpath (xpath, node, &free_p, &n);
719
720 for (i = 0; i < n; i++) {
721 xmlNodePtr child = result->nodeTab [i];
722 char *attr = xmlGetProp (child, "name");
723 if (!strcmp (attr, "DW_TAG_unspecified_parameters")) {
724 strncat (buf, (i == 0 ? "" : ", ..."), sizeof (buf));
725 } else if (!strcmp (attr, "DW_TAG_formal_parameter")) {
726 char buf2 [BUFLEN];
727 char *type = get_type (child);
728 char *name = get_attr_value ("DW_AT_name", child);
729 snprintf (buf2, sizeof (buf2), type, (name == NULL ? "" : name));
730 if (i != 0) strncat (buf, ", ", sizeof (buf));
731 strncat (buf, buf2, sizeof (buf));
732 free (type);
733 xmlFree (name);
734 } else {
735 assert (0); exit (1);
736 }
737 xmlFree (attr);
738 }
739
740 free (free_p);
741
742 if (n == 0)
743 snprintf (buf, sizeof (buf), "void");
744 return strdup (buf);
745 }
746
747 static char *
748 get_subscript (xmlNodePtr node)
749 {
750 /* Note: A DW_AT_upper_bound's value means 2 possibilities:
751 (1) the maximum index value (e.g., 9 for 'int a[10]').
752 (2) the pointer to the (artificial) DW_TAG_variable that
753 holds an expression value for the array size.
754 Problem here is that artificial DW_TAG_variable does not
755 have a name, just a location. */
756 int i;
757 char buf [BUFLEN];
758 char *ret, *form = NULL;
759 char *abbrev_num = get_tag ("DW_TAG_subrange_type",
760 "@abbrev_number", node);
761 if (abbrev_num == NULL) {
762 /* we cannot found the corresponding abbrev.
763 this might be a bug, but now just ignore it. */
764 return strdup ("");
765 }
766
767 for (i = 0; abbrev_table [i].number != -1; i++) {
768 if (abbrev_table [i].number == atoi (abbrev_num)) {
769 form = abbrev_table [i].upper_bound_form;
770 break;
771 }
772 }
773
774 xmlFree (abbrev_num);
775
776 if (form == NULL) {
777 ret = strdup (""); /* no subscript information */
778 } else if (!strncmp (form, "DW_FORM_ref", 11)) {
779 ret = "<em>exp</em>";
780 } else if (!strncmp (form, "DW_FORM_data", 12)) {
781 xmlNodePtr child, child2;
782 char *upper_bound = NULL;
783 char *attr;
784
785 for (child = node->children; child != NULL; child = child->next) {
786 if (child->type != XML_ELEMENT_NODE) continue;
787 if (strcmp (child->name, "tag")) continue;
788 attr = xmlGetProp (child, "name");
789 if (strcmp (attr, "DW_TAG_subrange_type")) {
790 xmlFree (attr);
791 continue;
792 }
793 xmlFree (attr);
794
795 for (child2 = child->children; child2 != NULL;
796 child2 = child2->next) {
797 if (child2->type != XML_ELEMENT_NODE) continue;
798 if (strcmp (child2->name, "attribute")) continue;
799 attr = xmlGetProp (child2, "name");
800 if (strcmp (attr, "DW_AT_upper_bound")) {
801 xmlFree (attr);
802 continue;
803 }
804 xmlFree (attr);
805 upper_bound = xmlGetProp (child2, "value");
806 break;
807 }
808 }
809 assert (upper_bound != NULL);
810 snprintf (buf, sizeof (buf), "%d", atoi (upper_bound) + 1);
811 xmlFree (upper_bound);
812 ret = buf;
813 } else {
814 assert (0); exit (1);
815 }
816 return strdup (ret);
817 }
818
819
820 static int
821 get_comp_unit (xmlNodePtr node)
822 {
823 int i, ret;
824 char *offset = xmlGetProp (node, "offset");
825 unsigned long offset2;
826
827 assert (offset != NULL);
828 ret = sscanf (offset, "info:%ld", &offset2);
829 assert (ret == 1);
830
831 for (i = 0; i < n_comp_unit; i++) {
832 if (offset2 < comp_unit [i].info_offset2)
833 break;
834 }
835 return i - 1;
836 }
837
838 static char *
839 get_filename_by_char (int n_comp, char *file_num)
840 {
841 if (file_num == NULL) {
842 return "??";
843 } else {
844 return get_filename_by_int (n_comp, atoi (file_num));
845 }
846 }
847
848 static char *
849 get_filename_by_node (xmlNodePtr node, char *file_num)
850 {
851 if (file_num == NULL) {
852 return "??";
853 } else {
854 int n_comp = get_comp_unit (node);
855 return get_filename_by_int (n_comp, atoi (file_num));
856 }
857 }
858
859 static char *
860 get_filename_by_int (int n_comp, int file_num)
861 {
862 assert (0 <= n_comp && n_comp < n_comp_unit);
863 assert (0 <= file_num && file_num <= comp_unit [n_comp].n_file);
864 if (file_num > 0) {
865 return comp_unit [n_comp].file [file_num].filename;
866 } else {
867 return "??";
868 }
869 }
870
871 static char *
872 get_pathname_by_char (int n_comp, char *file_num)
873 {
874 if (file_num == NULL) {
875 return "??";
876 } else {
877 return get_pathname_by_int (n_comp, atoi (file_num));
878 }
879 }
880
881 static char *
882 get_pathname_by_node (xmlNodePtr node, char *file_num)
883 {
884 if (file_num == NULL) {
885 return "??";
886 } else {
887 int n_comp = get_comp_unit (node);
888 return get_pathname_by_int (n_comp, atoi (file_num));
889 }
890 }
891
892 static char *
893 get_pathname_by_int (int n_comp, int file_num)
894 {
895 assert (0 <= n_comp && n_comp < n_comp_unit);
896 assert (0 <= file_num && file_num <= comp_unit [n_comp].n_file);
897 if (file_num > 0) {
898 return comp_unit [n_comp].file [file_num].pathname;
899 } else {
900 return "??";
901 }
902 }
903
904 static char *
905 get_line (char *line)
906 {
907 return (line == NULL ? "??" : line);
908 }
909
910 static char *
911 get_name (char *name)
912 {
913 return (name == NULL ? "??" : name);
914 }
915
916 static char *
917 type_to_string (xmlNodePtr node)
918 {
919 char *attr, *ret;
920 assert (node->type == XML_ELEMENT_NODE);
921 assert (!strcmp (node->name, "tag"));
922
923 attr = xmlGetProp (node, "name");
924
925 if (!strcmp (attr, "DW_TAG_array_type")) {
926 ret = array_type_to_string (node);
927 } else if (!strcmp (attr, "DW_TAG_base_type")) {
928 ret = base_type_to_string (node);
929 } else if (!strcmp (attr, "DW_TAG_pointer_type")) {
930 ret = ptr_type_to_string (node);
931 } else if (!strcmp (attr, "DW_TAG_subroutine_type")) {
932 ret = func_type_to_string (node);
933 } else if (!strcmp (attr, "DW_TAG_const_type")) {
934 ret = const_to_string (node);
935 } else if (!strcmp (attr, "DW_TAG_volatile_type")) {
936 ret = volatile_to_string (node);
937 } else if (!strcmp (attr, "DW_TAG_structure_type")) {
938 ret = struct_to_string (node);
939 } else if (!strcmp (attr, "DW_TAG_union_type")) {
940 ret = union_to_string (node);
941 } else if (!strcmp (attr, "DW_TAG_typedef")) {
942 ret = typedef_to_string (node);
943 } else if (!strcmp (attr, "DW_TAG_enumeration_type")) {
944 ret = enum_to_string (node);
945 #if 0
946 } else if (!strcmp (attr, "DW_TAG_member")) {
947 } else if (!strcmp (attr, "DW_TAG_subrange_type")) {
948 #endif
949 } else {
950 assert (0); exit (1);
951 }
952 xmlFree (attr);
953 return ret;
954 }
955 static char *
956 base_type_to_string (xmlNodePtr node)
957 {
958 char buf [BUFLEN];
959 char *type = get_attr_value ("DW_AT_name", node);
960 if (type == NULL) {
961 snprintf (buf, sizeof (buf), "%s %%s", "void");
962 } else {
963 snprintf (buf, sizeof (buf), "%s %%s", type);
964 xmlFree (type);
965 }
966 return strdup (buf);
967 }
968
969 static char *
970 array_type_to_string (xmlNodePtr node)
971 {
972 char buf [BUFLEN], buf2 [BUFLEN];
973 #if 0
974 char *id = xmlGetProp (node, "offset");
975 #endif
976 char *type = get_type (node);
977 char *subscript = get_subscript (node);
978 snprintf (buf2, sizeof (buf2), "%%s[%s]", subscript);
979 snprintf (buf, sizeof (buf), type, buf2);
980 free (subscript);
981 free (type);
982 return strdup (buf);
983 }
984
985 static char *
986 ptr_type_to_string (xmlNodePtr node)
987 {
988 char buf [BUFLEN];
989 char *type = get_type (node);
990 snprintf (buf, sizeof (buf), type, "(*%s)");
991 free (type);
992 return strdup (buf);
993 }
994
995 static char *
996 func_type_to_string (xmlNodePtr node)
997 {
998 char buf [BUFLEN], buf2 [BUFLEN];
999 char *ret_type = get_type (node);
1000 char *params = get_params (node);
1001 snprintf (buf2, sizeof (buf2), "(%%s)(%s)", params);
1002 snprintf (buf, sizeof (buf), ret_type, buf2);
1003 free (ret_type);
1004 free (params);
1005 return strdup (buf);
1006 }
1007
1008 static char *
1009 volatile_to_string (xmlNodePtr node)
1010 {
1011 char buf [BUFLEN];
1012 char *type = get_type (node);
1013 snprintf (buf, sizeof (buf), type, "volatile %s");
1014 free (type);
1015 return strdup (buf);
1016 }
1017
1018 static char *
1019 const_to_string (xmlNodePtr node)
1020 {
1021 char buf [BUFLEN];
1022 char *type = get_type (node);
1023 snprintf (buf, sizeof (buf), type, "const %s");
1024 free (type);
1025 return strdup (buf);
1026 }
1027
1028 static char *
1029 struct_union_to_string (xmlNodePtr node, char *which)
1030 {
1031 char buf [BUFLEN];
1032 char *id = xmlGetProp (node, "offset");
1033 char *name = get_attr_value ("DW_AT_name", node);
1034 if (name == NULL) {
1035 char *members = members_to_string (node);
1036 snprintf (buf, sizeof (buf), "%s %s %%s", which, members);
1037 } else {
1038 snprintf (buf, sizeof (buf), "%s %s %%s", which, href_info (id, name));
1039 xmlFree (name);
1040 }
1041 xmlFree (id);
1042 return strdup (buf);
1043 }
1044
1045 static char *
1046 struct_to_string (xmlNodePtr node)
1047 {
1048 return struct_union_to_string (node, "struct");
1049 }
1050
1051 static char *
1052 union_to_string (xmlNodePtr node)
1053 {
1054 return struct_union_to_string (node, "union");
1055 }
1056
1057 static char *
1058 members_to_string (xmlNodePtr node)
1059 {
1060 char buf [BUFLEN] = {'\0'}, buf2 [BUFLEN], buf3 [BUFLEN];
1061 xmlNodeSetPtr result;
1062 int i, n;
1063 char *xpath = "tag[@name='DW_TAG_member']";
1064 void *free_p;
1065
1066 result = eval_xpath (xpath, node, &free_p, &n);
1067
1068 strncat (buf, "{ ", sizeof (buf));
1069
1070 for (i = 0; i < n; i++) {
1071 xmlNodePtr child = result->nodeTab [i];
1072 char *id = xmlGetProp (child, "offset");
1073 char *name = get_attr_value ("DW_AT_name", child);
1074 char *file = get_attr_value ("DW_AT_decl_file", child);
1075 char *filename = get_filename_by_node (child, file);
1076 char *pathname = get_pathname_by_node (child, file);
1077 #if 0
1078 char *line = get_line (get_attr_value ("DW_AT_decl_line", child));
1079 #endif
1080 char *type = get_type (child);
1081
1082 snprintf (buf2, sizeof (buf2), "%s", href_info (id, get_name (name)));
1083 snprintf (buf3, sizeof (buf3), type, buf2);
1084 strncat (buf, buf3, sizeof (buf));
1085 strncat (buf, "; ", sizeof (buf));
1086 xmlFree (id);
1087 xmlFree (name);
1088 xmlFree (file);
1089 free (type);
1090 }
1091 free (free_p);
1092
1093 strncat (buf, "}", sizeof (buf));
1094 return strdup (buf);
1095 }
1096
1097 static char *
1098 typedef_to_string (xmlNodePtr node)
1099 {
1100 char buf [BUFLEN];
1101 char *id = xmlGetProp (node, "offset");
1102 char *name = get_attr_value ("DW_AT_name", node);
1103 snprintf (buf, sizeof (buf), "%s %%s", href_info (id, get_name (name)));
1104 xmlFree (id);
1105 xmlFree (name);
1106 return strdup (buf);
1107 }
1108
1109 static char *
1110 enum_to_string (xmlNodePtr node)
1111 {
1112 char buf [BUFLEN];
1113 char *id = xmlGetProp (node, "offset");
1114 char *name = get_attr_value ("DW_AT_name", node);
1115 if (name == NULL) {
1116 char * enum_constants = enum_constants_to_string (node);
1117 snprintf (buf, sizeof (buf), "enum %s %%s", enum_constants);
1118 } else {
1119 snprintf (buf, sizeof (buf), "enum %s %%s", href_info (id, name));
1120 }
1121 xmlFree (id);
1122 xmlFree (name);
1123 return strdup (buf);
1124 }
1125
1126 static char *
1127 enum_constants_to_string (xmlNodePtr node)
1128 {
1129 char buf [BUFLEN] = {'\0'}, buf2 [BUFLEN];
1130 xmlNodeSetPtr result;
1131 int i, n;
1132 char *xpath = "tag[@name='DW_TAG_enumerator']";
1133 void *free_p;
1134
1135 result = eval_xpath (xpath, node, &free_p, &n);
1136 strncat (buf, "{ ", sizeof (buf));
1137
1138 for (i = 0; i < n; i++) {
1139 xmlNodePtr child = result->nodeTab [i];
1140 char *id = xmlGetProp (child, "offset");
1141 char *name = get_attr_value ("DW_AT_name", child);
1142 char *value = get_attr_value ("DW_AT_const_value", child);
1143
1144 snprintf (buf2, sizeof (buf2),
1145 "%s = %s, ", href_info (id, get_name (name)), value);
1146 strncat (buf, buf2, sizeof (buf));
1147 xmlFree (id);
1148 xmlFree (name);
1149 xmlFree (value);
1150 }
1151
1152 free (free_p);
1153 strncat (buf, "}", sizeof (buf));
1154 return strdup (buf);
1155 }
1156
1157 static void
1158 output_indent (FILE *fp)
1159 {
1160 fprintf (fp, "%*s", indent_depth*4, "");
1161 }
1162
1163 static void
1164 visit_all_children (xmlNodePtr node, FILE *fp)
1165 {
1166 xmlNodePtr child;
1167 for (child = node->children; child != NULL; child = child->next) {
1168 if (child->type != XML_ELEMENT_NODE || strcmp (child->name, "tag"))
1169 continue;
1170 output_debug_info (child, fp);
1171 }
1172 }
1173
1174 static void
1175 output_debug_info_top (void)
1176 {
1177 FILE *fp;
1178 xmlNodeSetPtr result;
1179 xmlNodePtr node, child;
1180 void *free_p;
1181
1182 if (args.verbose) printf ("processing .debug_info\n");
1183 result = eval_xpath ("//section[@name='.debug_info']",
1184 xml_root, &free_p, NULL);
1185 assert (xmlXPathNodeSetGetLength (result) == 1);
1186 node = result->nodeTab [0];
1187 assert (node->type == XML_ELEMENT_NODE);
1188 assert (!strcmp (node->name, "section"));
1189
1190 fp = fopen (WORKING_DIR XREF_INFO, "w");
1191 if (fp == NULL) {
1192 perror ("fopen (info)"); exit (1);
1193 }
1194 visit_all_children (node, fp);
1195 free (free_p);
1196 fclose (fp);
1197 }
1198
1199 static void
1200 output_debug_info (xmlNodePtr node, FILE *fp)
1201 {
1202 char *attr;
1203 assert (node->type == XML_ELEMENT_NODE);
1204 assert (!strcmp (node->name, "tag"));
1205 attr = xmlGetProp (node, "name");
1206 if (args.verbose) printf ("\tprocessing %s\n", attr);
1207
1208 if (!strcmp (attr, "DW_TAG_compile_unit")) {
1209 output_compile_unit (node, fp);
1210 } else if (!strcmp (attr, "DW_TAG_subprogram")) {
1211 output_subprogram (node, fp);
1212 } else if (!strcmp (attr, "DW_TAG_lexical_block")) {
1213 output_lexical_block (node, fp);
1214 } else if (!strcmp (attr, "DW_TAG_variable")) {
1215 output_variable (node, fp);
1216 } else if (!strcmp (attr, "DW_TAG_label")) {
1217 output_label (node, fp);
1218 } else if (!strcmp (attr, "DW_TAG_typedef")) {
1219 output_typedef (node, fp);
1220 } else if (!strcmp (attr, "DW_TAG_structure_type")) {
1221 output_struct (node, fp);
1222 } else if (!strcmp (attr, "DW_TAG_union_type")) {
1223 output_union (node, fp);
1224 } else if (!strcmp (attr, "DW_TAG_enumeration_type")) {
1225 output_enum (node, fp);
1226 #if 0
1227 } else if (!strcmp (attr, "DW_TAG_array_type")
1228 || !strcmp (attr, "DW_TAG_base_type")
1229 || !strcmp (attr, "DW_TAG_const_type")
1230 || !strcmp (attr, "DW_TAG_pointer_type")
1231 || !strcmp (attr, "DW_TAG_subroutine_type")
1232 || !strcmp (attr, "DW_TAG_volatile_type")
1233 || !strcmp (attr, "DW_TAG_member")
1234 || !strcmp (attr, "DW_TAG_subrange_type")
1235 || !strcmp (attr, "DW_TAG_constant")
1236 || !strcmp (attr, "DW_TAG_enumerator")
1237 || !strcmp (attr, "DW_TAG_formal_parameter")
1238 || !strcmp (attr, "DW_TAG_unspecified_parameters")) {
1239 visit_all_children (node, fp);
1240 #endif
1241 } else {
1242 /*
1243 just ignore for the following tags, not appearing in ANSI C:
1244 DW_TAG_access_declaration DW_TAG_catch_block
1245 DW_TAG_class_type DW_TAG_common_block
1246 DW_TAG_common_inclusion DW_TAG_entry_point
1247 DW_TAG_file_type DW_TAG_friend
1248 DW_TAG_imported_declaration DW_TAG_inheritance
1249 DW_TAG_inlined_subroutine DW_TAG_module
1250 DW_TAG_namelist DW_TAG_namelist_item
1251 DW_TAG_packed_type DW_TAG_ptr_to_member_type
1252 DW_TAG_reference_type DW_TAG_set_type
1253 DW_TAG_string_type
1254 DW_TAG_template_type_param DW_TAG_template_value_param
1255 DW_TAG_thrown_type DW_TAG_try_block
1256 DW_TAG_variant DW_TAG_variant_part DW_TAG_with_stmt
1257 and other vender-specific extentions.
1258 */
1259 }
1260 xmlFree (attr);
1261 }
1262
1263 static void
1264 output_compile_unit (xmlNodePtr node, FILE *fp)
1265 {
1266 char *id = xmlGetProp (node, "offset");
1267 char *filename = get_attr_value ("DW_AT_name", node);
1268 char *comp_dir = get_attr_value ("DW_AT_comp_dir", node);
1269 char *high_pc = get_attr_value ("DW_AT_high_pc", node);
1270 char *low_pc = get_attr_value ("DW_AT_low_pc", node);
1271 char *producer = get_attr_value ("DW_AT_producer", node);
1272
1273 fprintf (fp,
1274 "</pre><hr/>\n"
1275 "<h1>%s --- %s, 0x%x-0x%x, %s</h1><a name=\"%s\"/>\n"
1276 "<hr/><pre>\n",
1277 href_src1 (filename, "top", filename), comp_dir,
1278 atoi (low_pc), atoi (high_pc), producer, id);
1279 visit_all_children (node, fp);
1280
1281 xmlFree (id);
1282 xmlFree (filename);
1283 xmlFree (comp_dir);
1284 xmlFree (high_pc);
1285 xmlFree (low_pc);
1286 xmlFree (producer);
1287 }
1288
1289 static void
1290 output_subprogram (xmlNodePtr node, FILE *fp)
1291 {
1292 char buf [BUFLEN], buf2 [BUFLEN];
1293 char *id = xmlGetProp (node, "offset");
1294 char *funcname = get_attr_value ("DW_AT_name", node);
1295 char *file = get_attr_value ("DW_AT_decl_file", node);
1296 char *filename = get_filename_by_node (node, file);
1297 char *pathname = get_pathname_by_node (node, file);
1298 char *line = get_attr_value ("DW_AT_decl_line", node);
1299 char *line2 = get_line (line);
1300 char *high_pc = get_attr_value ("DW_AT_high_pc", node);
1301 char *low_pc = get_attr_value ("DW_AT_low_pc", node);
1302 char *external = get_attr_value ("DW_AT_external", node);
1303 char *declaration = get_attr_value ("DW_AT_declaration", node);
1304 char *abst_origin = get_attr_value ("DW_AT_abstract_origin", node);
1305 char *inlined = get_attr_desc ("DW_AT_inline", node);
1306 char *ret_type = get_type (node);
1307 char *params = get_params (node);
1308
1309 int is_extern = (declaration != NULL) && strcmp (declaration, "0");
1310
1311 /* skip this entry because this is a concrete code for inlined func */
1312 if (abst_origin != NULL)
1313 goto output_subprogram_exit;
1314
1315 snprintf (buf2, sizeof (buf2), "%%s (%s)", params);
1316 snprintf (buf, sizeof (buf), ret_type, buf2);
1317 free (ret_type);
1318 free (params);
1319
1320 snprintf (buf2, sizeof (buf2),
1321 "%s<a name=\"%s\"/>",
1322 href_src1 (pathname, line2, get_name (funcname)), id);
1323
1324 if (inlined == NULL)
1325 inlined = "";
1326
1327 output_indent (fp);
1328 if (low_pc != NULL && high_pc != NULL) {
1329 fprintf (fp, COMM_BEGIN "0x%x-0x%x, %s %s" COMM_END "\n",
1330 atoi (low_pc), atoi (high_pc),
1331 href_src2 (pathname, line2, filename), inlined);
1332 } else {
1333 fprintf (fp, COMM_BEGIN "%s %s" COMM_END "\n",
1334 href_src2 (pathname, line2, filename), inlined);
1335 }
1336
1337 output_indent (fp);
1338 if (external == NULL || strcmp (external, "1"))
1339 fprintf (fp, "static ");
1340 if (is_extern)
1341 fprintf (fp, "extern ");
1342 fprintf (fp, buf, buf2);
1343
1344 if (is_extern) {
1345 fprintf (fp, ";\n");
1346 } else {
1347 fprintf (fp, "\n{\n");
1348 indent_depth++;
1349 visit_all_children (node, fp);
1350 indent_depth--;
1351 fprintf (fp, "}\n", buf);
1352 }
1353
1354 output_subprogram_exit:
1355 xmlFree (id);
1356 xmlFree (funcname);
1357 xmlFree (file);
1358 xmlFree (line);
1359 xmlFree (high_pc);
1360 xmlFree (low_pc);
1361 xmlFree (external);
1362 xmlFree (declaration);
1363 xmlFree (abst_origin);
1364 xmlFree (inlined);
1365 }
1366
1367 static void
1368 output_lexical_block (xmlNodePtr node, FILE *fp)
1369 {
1370 char *id = xmlGetProp (node, "offset");
1371 char *high_pc = get_attr_value ("DW_AT_high_pc", node);
1372 char *low_pc = get_attr_value ("DW_AT_low_pc", node);
1373 output_indent (fp);
1374 fprintf (fp,
1375 "{ <a name=\"%s\"/><font color=\"red\">/* 0x%x-0x%x */</font>\n",
1376 id,
1377 (low_pc == NULL ? 0 : atoi (low_pc)),
1378 (low_pc == NULL ? 0 : atoi (high_pc)));
1379 indent_depth++;
1380 visit_all_children (node, fp);
1381 indent_depth--;
1382 output_indent (fp);
1383 fprintf (fp, "}\n");
1384
1385 xmlFree (id);
1386 xmlFree (high_pc);
1387 xmlFree (low_pc);
1388 }
1389
1390 static void
1391 output_variable (xmlNodePtr node, FILE *fp)
1392 {
1393 char buf [BUFLEN], loc [BUFLEN];
1394 int offset, reg, is_auto = 0;
1395 unsigned long addr;
1396 char *id = xmlGetProp (node, "offset");
1397 char *varname = get_attr_value ("DW_AT_name", node);
1398 char *file = get_attr_value ("DW_AT_decl_file", node);
1399 char *filename = get_filename_by_node (node, file);
1400 char *pathname = get_pathname_by_node (node, file);
1401 char *line = get_attr_value ("DW_AT_decl_line", node);
1402 char *line2 = get_line (line);
1403 char *external = get_attr_value ("DW_AT_external", node);
1404 char *type = get_type (node);
1405 char *location = get_attr_desc ("DW_AT_location", node);
1406 char *declaration = get_attr_value ("DW_AT_declaration", node);
1407
1408 snprintf (buf, sizeof (buf), "%s%s",
1409 href_src1 (pathname, line2, get_name (varname)), a_name (id));
1410
1411 if (location == NULL) {
1412 snprintf (loc, sizeof (loc), "??");
1413 } else if (sscanf (location, "DW_OP_fbreg: %d", &offset) == 1) {
1414 /* allocated on stack */
1415 is_auto = 1;
1416 snprintf (loc, sizeof (loc), "%%fp+(%d)", offset);
1417 } else if (sscanf (location, "DW_OP_addr: %u", &addr) == 1) {
1418 /* allocated on data */
1419 snprintf (loc, sizeof (loc), "0x%x", addr);
1420 } else if (sscanf (location, "DW_OP_reg%d", ®) == 1) {
1421 /* allocated on registers */
1422 is_auto = 1;
1423 snprintf (loc, sizeof (loc), "%%r%d", reg);
1424 } else {
1425 /* unknown description, so print it as it is. */
1426 snprintf (loc, sizeof (loc), "%s", location);
1427 #if 0
1428 fprintf (stderr, "unknown description (%s)\n", location);
1429 assert (0);
1430 #endif
1431 }
1432
1433 output_indent (fp);
1434 if (!is_auto && (external == NULL || strcmp (external, "1")))
1435 fprintf (fp, "static ");
1436 if (declaration != NULL && strcmp (declaration, "0"))
1437 fprintf (fp, "extern ");
1438 fprintf (fp, type, buf);
1439 free (type);
1440 fprintf (fp, "; " COMM_BEGIN "%s, %s" COMM_END,
1441 loc, href_src2 (pathname, line2, filename));
1442 fprintf (fp, "\n");
1443
1444 xmlFree (id);
1445 xmlFree (varname);
1446 xmlFree (file);
1447 xmlFree (line);
1448 xmlFree (external);
1449 xmlFree (location);
1450 xmlFree (declaration);
1451 }
1452
1453 static void
1454 output_label (xmlNodePtr node, FILE *fp)
1455 {
1456 char *id = xmlGetProp (node, "offset");
1457 char *labelname = get_attr_value ("DW_AT_name", node);
1458 char *file = get_attr_value ("DW_AT_decl_file", node);
1459 char *filename = get_filename_by_node (node, file);
1460 char *pathname = get_pathname_by_node (node, file);
1461 char *line = get_attr_value ("DW_AT_decl_line", node);
1462 char *low_pc = get_attr_value ("DW_AT_low_pc", node);
1463
1464 output_indent (fp);
1465 fprintf (fp, "%s%s:",
1466 href_src1 (pathname, get_line (line), get_name (labelname)),
1467 a_name (id));
1468 fprintf (fp, " " COMM_BEGIN "0x%x, %s" COMM_END,
1469 atoi (low_pc),
1470 href_src2 (pathname, get_line (line), filename));
1471 fprintf (fp, "\n");
1472
1473 xmlFree (id);
1474 xmlFree (labelname);
1475 xmlFree (file);
1476 xmlFree (line);
1477 xmlFree (low_pc);
1478 }
1479
1480 static void
1481 output_typedef (xmlNodePtr node, FILE *fp)
1482 {
1483 char buf [BUFLEN], loc [BUFLEN];
1484 char *id = xmlGetProp (node, "offset");
1485 char *typename = get_attr_value ("DW_AT_name", node);
1486 char *file = get_attr_value ("DW_AT_decl_file", node);
1487 char *filename = get_filename_by_node (node, file);
1488 char *pathname = get_pathname_by_node (node, file);
1489 char *line = get_attr_value ("DW_AT_decl_line", node);
1490 char *type = get_type (node);
1491
1492 snprintf (buf, sizeof (buf), "%s%s",
1493 href_src1 (pathname, get_line (line), get_name (typename)),
1494 a_name (id));
1495 output_indent (fp);
1496 fprintf (fp, "typedef ");
1497 fprintf (fp, type, buf);
1498 free (type);
1499 fprintf (fp, "; ");
1500 fprintf (fp, " " COMM_BEGIN "%s" COMM_END,
1501 href_src2 (pathname, get_line (line), filename));
1502 fprintf (fp, "\n");
1503
1504 xmlFree (id);
1505 xmlFree (typename);
1506 xmlFree (file);
1507 xmlFree (line);
1508 }
1509
1510 static void
1511 output_enum (xmlNodePtr node, FILE *fp)
1512 {
1513 char *id = xmlGetProp (node, "offset");
1514 char *enumname = get_attr_value ("DW_AT_name", node);
1515 char *file = get_attr_value ("DW_AT_decl_file", node);
1516 char *filename = get_filename_by_node (node, file);
1517 char *pathname = get_pathname_by_node (node, file);
1518 char *line = get_attr_value ("DW_AT_decl_line", node);
1519 char *line2 = get_line (line);
1520
1521 output_indent (fp);
1522 fprintf (fp, "enum %s%s " COMM_BEGIN "%s" COMM_END " ",
1523 (enumname == NULL ? "" : href_src1 (pathname, line2, enumname)),
1524 a_name (id), href_src2 (pathname, line2, filename));
1525 output_enum_constants (node, fp, pathname, line2);
1526 fprintf (fp, ";\n");
1527
1528 xmlFree (id);
1529 xmlFree (enumname);
1530 xmlFree (file);
1531 xmlFree (line);
1532 }
1533
1534 static void
1535 output_enum_constants (xmlNodePtr node, FILE *fp, char *pathname, char *line)
1536 {
1537 xmlNodeSetPtr result;
1538 int i, n;
1539 char *xpath = "tag[@name='DW_TAG_enumerator']";
1540 void *free_p;
1541
1542 result = eval_xpath (xpath, node, &free_p, &n);
1543
1544 if (n == 0) return;
1545
1546 output_indent (fp);
1547 fprintf (fp, "{\n");
1548 indent_depth++;
1549
1550 for (i = 0; i < n; i++) {
1551 xmlNodePtr child = result->nodeTab [i];
1552 char *id = xmlGetProp (child, "offset");
1553 char *name = get_attr_value ("DW_AT_name", child);
1554 char *value = get_attr_value ("DW_AT_const_value", child);
1555
1556 output_indent (fp);
1557 fprintf (fp, "%s = %s,%s\n",
1558 href_src1 (pathname, line, name), value, a_name (id));
1559 xmlFree (id);
1560 xmlFree (name);
1561 xmlFree (value);
1562 }
1563 free (free_p);
1564 indent_depth--;
1565 output_indent (fp);
1566 fprintf (fp, "}");
1567 }
1568
1569 static void
1570 output_struct_union (xmlNodePtr node, FILE *fp, char *which)
1571 {
1572 char *id = xmlGetProp (node, "offset");
1573 char *tagname = get_attr_value ("DW_AT_name", node);
1574 char *file = get_attr_value ("DW_AT_decl_file", node);
1575 char *filename = get_filename_by_node (node, file);
1576 char *pathname = get_pathname_by_node (node, file);
1577 char *line = get_attr_value ("DW_AT_decl_line", node);
1578 char *line2 = get_line (line);
1579 char *size = get_attr_value ("DW_AT_byte_size", node);
1580
1581 output_indent (fp);
1582 fprintf (fp, "%s %s%s " COMM_BEGIN "%s" COMM_END " ", which,
1583 (tagname == NULL ? "" : href_src1 (pathname, line2, tagname)),
1584 a_name (id), href_src2 (pathname, line2, filename));
1585 output_members (node, fp);
1586 fprintf (fp, ";\n");
1587
1588 xmlFree (id);
1589 xmlFree (tagname);
1590 xmlFree (file);
1591 xmlFree (line);
1592 xmlFree (size);
1593 }
1594
1595 static void
1596 output_struct (xmlNodePtr node, FILE *fp)
1597 {
1598 output_struct_union (node, fp, "struct");
1599 }
1600
1601 static void
1602 output_union (xmlNodePtr node, FILE *fp)
1603 {
1604 output_struct_union (node, fp, "union");
1605 }
1606
1607 static void
1608 output_members (xmlNodePtr node, FILE *fp)
1609 {
1610 xmlNodeSetPtr result;
1611 int i, n;
1612 char *xpath = "tag[@name='DW_TAG_member']";
1613 void *free_p;
1614
1615 result = eval_xpath (xpath, node, &free_p, &n);
1616
1617 if (n == 0) return;
1618
1619 output_indent (fp);
1620 fprintf (fp, "{\n");
1621 indent_depth++;
1622
1623 for (i = 0; i < n; i++) {
1624 char buf [BUFLEN];
1625 xmlNodePtr child = result->nodeTab [i];
1626 char *id = xmlGetProp (child, "offset");
1627 char *name = get_attr_value ("DW_AT_name", child);
1628 char *value = get_attr_value ("DW_AT_const_value", child);
1629 char *file = get_attr_value ("DW_AT_decl_file", child);
1630 char *filename = get_filename_by_node (child, file);
1631 char *pathname = get_pathname_by_node (child, file);
1632 char *line = get_attr_value ("DW_AT_decl_line", child);
1633 char *line2 = get_line (line);
1634 char *location = get_attr_desc ("DW_AT_data_member_location", child);
1635 char *type = get_type (child);
1636
1637 snprintf (buf, sizeof (buf), "%s%s",
1638 href_src1 (pathname, line2, get_name (name)), a_name (id));
1639 output_indent (fp);
1640 fprintf (fp, type, buf);
1641
1642 if (location == NULL) {
1643 fprintf (fp, "; " COMM_BEGIN "%s" COMM_END "\n",
1644 href_src2 (pathname, line2, filename));
1645 } else {
1646 int offset;
1647 if (sscanf (location, "DW_OP_plus_uconst: %d", &offset) != 1) {
1648 fprintf (stderr, "unknown description (%s)\n", location);
1649 assert (0);
1650 }
1651 fprintf (fp, "; " COMM_BEGIN "%d, %s" COMM_END "\n",
1652 offset, href_src2 (pathname, line2, filename));
1653 }
1654
1655 free (type);
1656 xmlFree (id);
1657 xmlFree (name);
1658 xmlFree (value);
1659 xmlFree (file);
1660 xmlFree (line);
1661 xmlFree (location);
1662 }
1663 free (free_p);
1664 indent_depth--;
1665 output_indent (fp);
1666 fprintf (fp, "}");
1667 }
1668
1669 static void
1670 output_all_structs (void)
1671 {
1672 FILE *fp1, *fp2;
1673 xmlNodeSetPtr result;
1674 int n, i;
1675 void *free_p;
1676 char *work1 = WORKING_DIR XREF_STRUCTS1;
1677 char *work2 = WORKING_DIR XREF_STRUCTS2;
1678
1679 if (args.verbose) printf ("processing all structures\n");
1680 fp1 = fopen (work1, "w");
1681 if (fp1 == NULL) { perror ("fopen(structs1)"); exit (1); }
1682 fp2 = fopen (work2, "w");
1683 if (fp2 == NULL) { perror ("fopen(structs2)"); exit (1); }
1684
1685 result = eval_xpath ("//tag[@name='DW_TAG_structure_type']",
1686 xml_root, &free_p, &n);
1687
1688 for (i = 0; i < n; i++) {
1689 xmlNodePtr node = result->nodeTab [i];
1690 char *id = xmlGetProp (node, "offset");
1691 char *tagname = get_attr_value ("DW_AT_name", node);
1692 char *file = get_attr_value ("DW_AT_decl_file", node);
1693 char *filename = get_filename_by_node (node, file);
1694 char *pathname = get_pathname_by_node (node, file);
1695 char *line = get_attr_value ("DW_AT_decl_line", node);
1696 char *line2 = get_line (line);
1697
1698 if (tagname == NULL) goto loop_continue;
1699 fprintf (fp1, "%s @ struct %s; " COMM_BEGIN "%s" COMM_END "\n",
1700 tagname, href_info (id, tagname),
1701 href_src2 (pathname, line2, filename));
1702
1703 if (file == NULL) goto loop_continue;
1704 fprintf (fp2, "%s %s @ " COMM_BEGIN "%s" COMM_END " struct %s;\n",
1705 filename, line2,
1706 href_src2 (pathname, line2, filename),
1707 href_info (id, tagname));
1708
1709 loop_continue:
1710 xmlFree (id);
1711 xmlFree (tagname);
1712 xmlFree (file);
1713 xmlFree (line);
1714 }
1715 free (free_p);
1716 fclose (fp1);
1717 fclose (fp2);
1718 }
1719
1720 static void
1721 output_all_unions (void)
1722 {
1723 FILE *fp1, *fp2;
1724 xmlNodeSetPtr result;
1725 int n, i;
1726 void *free_p;
1727 char *work1 = WORKING_DIR XREF_UNIONS1;
1728 char *work2 = WORKING_DIR XREF_UNIONS2;
1729
1730 if (args.verbose) printf ("processing all unions\n");
1731 fp1 = fopen (work1, "w");
1732 if (fp1 == NULL) { perror ("fopen(unions1)"); exit (1); }
1733 fp2 = fopen (work2, "w");
1734 if (fp2 == NULL) { perror ("fopen(unions2)"); exit (1); }
1735
1736 result = eval_xpath ("//tag[@name='DW_TAG_union_type']",
1737 xml_root, &free_p, &n);
1738
1739 for (i = 0; i < n; i++) {
1740 xmlNodePtr node = result->nodeTab [i];
1741 char *id = xmlGetProp (node, "offset");
1742 char *tagname = get_attr_value ("DW_AT_name", node);
1743 char *file = get_attr_value ("DW_AT_decl_file", node);
1744 char *filename = get_filename_by_node (node, file);
1745 char *pathname = get_pathname_by_node (node, file);
1746 char *line = get_attr_value ("DW_AT_decl_line", node);
1747 char *line2 = get_line (line2);
1748
1749 if (tagname == NULL) goto loop_continue;
1750 fprintf (fp1, "%s @ union %s; " COMM_BEGIN "%s" COMM_END "\n",
1751 tagname, href_info (id, tagname),
1752 href_src2 (pathname, line2, filename));
1753 if (file == NULL) goto loop_continue;
1754 fprintf (fp2, "%s %s @ " COMM_BEGIN "%s" COMM_END " union %s;\n",
1755 filename, line2,
1756 href_src2 (pathname, line2, filename),
1757 href_info (id, tagname));
1758
1759 loop_continue:
1760 xmlFree (id);
1761 xmlFree (tagname);
1762 xmlFree (file);
1763 xmlFree (line);
1764 }
1765 free (free_p);
1766 fclose (fp1);
1767 fclose (fp2);
1768 }
1769
1770 static void
1771 output_all_typedefs (void)
1772 {
1773 FILE *fp1, *fp2;
1774 xmlNodeSetPtr result;
1775 int n, i;
1776 void *free_p;
1777 char *work1 = WORKING_DIR XREF_TYPEDEFS1;
1778 char *work2 = WORKING_DIR XREF_TYPEDEFS2;
1779
1780 if (args.verbose) printf ("processing all typedefs\n");
1781 fp1 = fopen (work1, "w");
1782 if (fp1 == NULL) { perror ("fopen(tdefs1)"); exit (1); }
1783 fp2 = fopen (work2, "w");
1784 if (fp2 == NULL) { perror ("fopen(tdefs2)"); exit (1); }
1785
1786 result = eval_xpath ("//tag[@name='DW_TAG_typedef']",
1787 xml_root, &free_p, &n);
1788
1789 for (i = 0; i < n; i++) {
1790 xmlNodePtr node = result->nodeTab [i];
1791 char *id = xmlGetProp (node, "offset");
1792 char *name = get_attr_value ("DW_AT_name", node);
1793 char *file = get_attr_value ("DW_AT_decl_file", node);
1794 char *filename = get_filename_by_node (node, file);
1795 char *pathname = get_pathname_by_node (node, file);
1796 char *line = get_attr_value ("DW_AT_decl_line", node);
1797 char *line2 = get_line (line);
1798
1799 if (name == NULL) goto loop_continue;
1800 fprintf (fp1, "%s @ typedef %s; " COMM_BEGIN "%s" COMM_END "\n",
1801 name, href_info (id, name),
1802 href_src2 (pathname, line2, filename));
1803 if (file == NULL) goto loop_continue;
1804 fprintf (fp2, "%s %s @ " COMM_BEGIN "%s" COMM_END " union %s;\n",
1805 filename, line2,
1806 href_src2 (pathname, line2, filename),
1807 href_info (id, name));
1808
1809 loop_continue:
1810 xmlFree (id);
1811 xmlFree (name);
1812 xmlFree (file);
1813 xmlFree (line);
1814 }
1815 free (free_p);
1816 fclose (fp1);
1817 fclose (fp2);
1818 }
1819
1820 static void
1821 output_all_enum_tags (void)
1822 {
1823 FILE *fp1, *fp2;
1824 xmlNodeSetPtr result;
1825 int n, i;
1826 void *free_p;
1827 char *work1 = WORKING_DIR XREF_ENUM_TAGS1;
1828 char *work2 = WORKING_DIR XREF_ENUM_TAGS2;
1829
1830 if (args.verbose) printf ("processing all enum tags\n");
1831 fp1 = fopen (work1, "w");
1832 if (fp1 == NULL) { perror ("fopen(etags1)"); exit (1); }
1833 fp2 = fopen (work2, "w");
1834 if (fp2 == NULL) { perror ("fopen(etags2)"); exit (1); }
1835
1836 result = eval_xpath ("//tag[@name='DW_TAG_enumeration_type']",
1837 xml_root, &free_p, &n);
1838
1839 for (i = 0; i < n; i++) {
1840 xmlNodePtr node = result->nodeTab [i];
1841 char *id = xmlGetProp (node, "offset");
1842 char *name = get_attr_value ("DW_AT_name", node);
1843 char *file = get_attr_value ("DW_AT_decl_file", node);
1844 char *filename = get_filename_by_node (node, file);
1845 char *pathname = get_pathname_by_node (node, file);
1846 char *line = get_attr_value ("DW_AT_decl_line", node);
1847 char *line2 = get_line (line);
1848
1849 if (name == NULL) goto loop_continue;
1850 fprintf (fp1, "%s @ enum %s; " COMM_BEGIN "%s" COMM_END "\n",
1851 name, href_info (id, name),
1852 href_src2 (pathname, line2, filename));
1853 if (file == NULL) goto loop_continue;
1854 fprintf (fp2, "%s %s @ " COMM_BEGIN "%s" COMM_END " enum %s;\n",
1855 filename, line2,
1856 href_src2 (pathname, line2, filename),
1857 href_info (id, name));
1858
1859 loop_continue:
1860 xmlFree (id);
1861 xmlFree (name);
1862 xmlFree (file);
1863 xmlFree (line);
1864 }
1865 free (free_p);
1866 fclose (fp1);
1867 fclose (fp2);
1868 }
1869
1870 static void
1871 output_all_enum_consts (void)
1872 {
1873 FILE *fp1, *fp2;
1874 xmlNodeSetPtr result;
1875 int n, i;
1876 void *free_p;
1877 char *work1 = WORKING_DIR XREF_ENUM_CONSTS1;
1878 char *work2 = WORKING_DIR XREF_ENUM_CONSTS2;
1879
1880 if (args.verbose) printf ("processing all enum constants\n");
1881 fp1 = fopen (work1, "w");
1882 if (fp1 == NULL) { perror ("fopen(econs1)"); exit (1); }
1883 fp2 = fopen (work2, "w");
1884 if (fp2 == NULL) { perror ("fopen(econs2)"); exit (1); }
1885
1886 result = eval_xpath ("//tag[@name='DW_TAG_enumerator']",
1887 xml_root, &free_p, &n);
1888
1889 for (i = 0; i < n; i++) {
1890 xmlNodePtr node = result->nodeTab [i];
1891 char *id = xmlGetProp (node, "offset");
1892 char *name = get_attr_value ("DW_AT_name", node);
1893 char *file = get_attr_value ("DW_AT_decl_file", node->parent);
1894 char *filename = get_filename_by_node (node, file);
1895 char *pathname = get_pathname_by_node (node, file);
1896 char *line = get_attr_value ("DW_AT_decl_line", node->parent);
1897 char *line2 = get_line (line);
1898
1899 if (name == NULL) goto loop_continue;
1900 fprintf (fp1, "%s @ %s; " COMM_BEGIN "%s" COMM_END "\n",
1901 name, href_info (id, name),
1902 href_src2 (pathname, line2, filename));
1903 if (file == NULL) goto loop_continue;
1904 fprintf (fp2, "%s %s @ " COMM_BEGIN "%s" COMM_END " %s;\n",
1905 filename, line2,
1906 href_src2 (pathname, line2, filename),
1907 href_info (id, name));
1908
1909 loop_continue:
1910 xmlFree (id);
1911 xmlFree (name);
1912 xmlFree (file);
1913 xmlFree (line);
1914 }
1915 free (free_p);
1916 fclose (fp1);
1917 fclose (fp2);
1918 }
1919
1920 static void
1921 output_all_labels (void)
1922 {
1923 FILE *fp1, *fp2;
1924 xmlNodeSetPtr result;
1925 int n, i;
1926 void *free_p;
1927 char *work1 = WORKING_DIR XREF_LABELS1;
1928 char *work2 = WORKING_DIR XREF_LABELS2;
1929
1930 if (args.verbose) printf ("processing all labels\n");
1931 fp1 = fopen (work1, "w");
1932 if (fp1 == NULL) { perror ("fopen(labels1)"); exit (1); }
1933 fp2 = fopen (work2, "w");
1934 if (fp2 == NULL) { perror ("fopen(labels2)"); exit (1); }
1935
1936 result = eval_xpath ("//tag[@name='DW_TAG_label']",
1937 xml_root, &free_p, &n);
1938
1939 for (i = 0; i < n; i++) {
1940 xmlNodePtr node = result->nodeTab [i];
1941 char *id = xmlGetProp (node, "offset");
1942 char *name = get_attr_value ("DW_AT_name", node);
1943 char *file = get_attr_value ("DW_AT_decl_file", node);
1944 char *filename = get_filename_by_node (node, file);
1945 char *pathname = get_pathname_by_node (node, file);
1946 char *line = get_attr_value ("DW_AT_decl_line", node);
1947 char *line2 = get_line (line);
1948
1949 if (name == NULL) goto loop_continue;
1950 fprintf (fp1, "%s @ %s: " COMM_BEGIN "%s" COMM_END "\n",
1951 name, href_info (id, name),
1952 href_src2 (pathname, line2, filename));
1953 if (file == NULL) goto loop_continue;
1954 fprintf (fp2, "%s %s @ " COMM_BEGIN "%s" COMM_END " %s:\n",
1955 filename, line2, href_src2 (pathname, line2, filename),
1956 href_info (id, name));
1957
1958 loop_continue:
1959 xmlFree (id);
1960 xmlFree (name);
1961 xmlFree (file);
1962 xmlFree (line);
1963 }
1964 free (free_p);
1965 fclose (fp1);
1966 fclose (fp2);
1967 }
1968
1969 static void
1970 output_all_functions (void)
1971 {
1972 FILE *fp1, *fp2;
1973 xmlNodeSetPtr result;
1974 int n, i;
1975 void *free_p;
1976 char *work1 = WORKING_DIR XREF_FUNCTIONS1;
1977 char *work2 = WORKING_DIR XREF_FUNCTIONS2;
1978
1979 if (args.verbose) printf ("processing all functions\n");
1980 fp1 = fopen (work1, "w");
1981 if (fp1 == NULL) { perror ("fopen(funcs1)"); exit (1); }
1982 fp2 = fopen (work2, "w");
1983 if (fp2 == NULL) { perror ("fopen(funcs2)"); exit (1); }
1984
1985 result = eval_xpath ("//tag[@name='DW_TAG_subprogram']",
1986 xml_root, &free_p, &n);
1987
1988 for (i = 0; i < n; i++) {
1989 char buf [BUFLEN], buf2 [BUFLEN];
1990 xmlNodePtr node = result->nodeTab [i];
1991 char *id = xmlGetProp (node, "offset");
1992 char *name = get_attr_value ("DW_AT_name", node);
1993 char *file = get_attr_value ("DW_AT_decl_file", node);
1994 char *filename = get_filename_by_node (node, file);
1995 char *pathname = get_pathname_by_node (node, file);
1996 char *line = get_attr_value ("DW_AT_decl_line", node);
1997 char *line2 = get_line (line);
1998 char *ret_type = get_type (node);
1999 char *params = get_params (node);
2000 char *external = get_attr_value ("DW_AT_external", node);
2001
2002 if (name == NULL) goto loop_continue;
2003
2004 snprintf (buf2, sizeof (buf2), "%%s (%s)", params);
2005 snprintf (buf, sizeof (buf), ret_type, buf2);
2006 free (ret_type);
2007 free (params);
2008
2009 fprintf (fp1, "%s @ ", name);
2010 if (external != NULL && !strcmp (external, "0"))
2011 fprintf (fp1, "static ");
2012 snprintf (buf2, sizeof (buf2), "%s", href_info (id, name));
2013 fprintf (fp1, buf, buf2);
2014 fprintf (fp1, "; " COMM_BEGIN "%s" COMM_END "\n",
2015 href_src2 (pathname, line2, filename));
2016
2017 if (file == NULL) goto loop_continue;
2018
2019 fprintf (fp2, "%s %s @ ", filename, pathname);
2020 fprintf (fp2, COMM_BEGIN "%s" COMM_END " ",
2021 href_src2 (pathname, line2, filename));
2022 if (external != NULL && !strcmp (external, "0"))
2023 fprintf (fp2, "static ");
2024 snprintf (buf2, sizeof (buf2), "%s", href_info (id, name));
2025 fprintf (fp2, buf, buf2);
2026 fprintf (fp2, ";\n");
2027
2028 loop_continue:
2029 xmlFree (id);
2030 xmlFree (name);
2031 xmlFree (file);
2032 xmlFree (line);
2033 xmlFree (external);
2034 }
2035 free (free_p);
2036 fclose (fp1);
2037 fclose (fp2);
2038 }
2039
2040 static void
2041 output_all_variables (void)
2042 {
2043 FILE *fp1, *fp2;
2044 xmlNodeSetPtr result;
2045 int n, i;
2046 void *free_p;
2047 char *work1 = WORKING_DIR XREF_VARIABLES1;
2048 char *work2 = WORKING_DIR XREF_VARIABLES2;
2049
2050 if (args.verbose) printf ("processing all variables\n");
2051 fp1 = fopen (work1, "w");
2052 if (fp1 == NULL) { perror ("fopen(vars1)"); exit (1); }
2053 fp2 = fopen (work2, "w");
2054 if (fp2 == NULL) { perror ("fopen(vars2)"); exit (1); }
2055
2056 result = eval_xpath ("//tag[@name='DW_TAG_variable']",
2057 xml_root, &free_p, &n);
2058
2059 for (i = 0; i < n; i++) {
2060 char buf [BUFLEN];
2061 xmlNodePtr node = result->nodeTab [i];
2062 char *id = xmlGetProp (node, "offset");
2063 char *name = get_attr_value ("DW_AT_name", node);
2064 char *file = get_attr_value ("DW_AT_decl_file", node);
2065 char *filename = get_filename_by_node (node, file);
2066 char *pathname = get_pathname_by_node (node, file);
2067 char *line = get_attr_value ("DW_AT_decl_line", node);
2068 char *line2 = get_line (line);
2069 char *type = get_type (node);
2070 char *external = get_attr_value ("DW_AT_external", node);
2071
2072 if (name == NULL) goto loop_continue;
2073
2074 fprintf (fp1, "%s @ ", name);
2075 if (external != NULL && !strcmp (external, "0"))
2076 fprintf (fp1, "static ");
2077 snprintf (buf, sizeof (buf), "%s", href_info (id, name));
2078 fprintf (fp1, type, buf);
2079 fprintf (fp1, "; " COMM_BEGIN "%s" COMM_END "\n",
2080 href_src2 (pathname, line2, filename));
2081
2082 if (file == NULL) goto loop_continue;
2083
2084 fprintf (fp2, "%s %s @ ", filename, line2);
2085 fprintf (fp2, COMM_BEGIN "%s" COMM_END " ",
2086 href_src2 (pathname, line2, filename));
2087 if (external != NULL && !strcmp (external, "0"))
2088 fprintf (fp2, "static ");
2089 snprintf (buf, sizeof (buf), "%s", href_info (id, name));
2090 fprintf (fp2, type, buf);
2091 fprintf (fp2, ";\n");
2092
2093 loop_continue:
2094 xmlFree (id);
2095 xmlFree (name);
2096 xmlFree (file);
2097 xmlFree (line);
2098 xmlFree (external);
2099 free (type);
2100 }
2101 free (free_p);
2102 fclose (fp1);
2103 fclose (fp2);
2104 }
2105
2106 static void
2107 output_all_files (void)
2108 {
2109 FILE *fp1;
2110 xmlNodeSetPtr result;
2111 int n, i;
2112 void *free_p;
2113 char *work1 = WORKING_DIR XREF_FILES1;
2114
2115 if (args.verbose) printf ("processing all files\n");
2116 fp1 = fopen (work1, "w");
2117 if (fp1 == NULL) { perror ("fopen(files1)"); exit (1); }
2118
2119 result = eval_xpath ("//tag[@name='DW_TAG_compile_unit']",
2120 xml_root, &free_p, &n);
2121
2122 for (i = 0; i < n; i++) {
2123 xmlNodePtr node = result->nodeTab [i];
2124 char *id = xmlGetProp (node, "offset");
2125 char *name = get_attr_value ("DW_AT_name", node);
2126
2127 if (name == NULL) goto loop_continue;
2128
2129 fprintf (fp1, "%s @ %s", name, href_info (id, name));
2130 fprintf (fp1, " " COMM_BEGIN "%s" COMM_END "\n",
2131 href_src1 (name, "top", name));
2132
2133 loop_continue:
2134 xmlFree (id);
2135 xmlFree (name);
2136 }
2137 free (free_p);
2138 fclose (fp1);
2139 }
2140
2141 static char *
2142 get_macinfo_id (void)
2143 {
2144 static char buf [BUFLEN];
2145 static int counter = 0;
2146 snprintf (buf, sizeof (buf), "MACINFOID%d", counter++);
2147 return buf;
2148 }
2149
2150 static void
2151 output_all_macros (void)
2152 {
2153 FILE *fp1, *fp2, *fp3, *fp4;
2154 xmlNodeSetPtr result;
2155 int n, i;
2156 int curr_comp_unit = -1;
2157 void *free_p;
2158 char *work1 = WORKING_DIR XREF_MACROS1;
2159 char *work2 = WORKING_DIR XREF_MACROS2;
2160 char *work3 = WORKING_DIR XREF_MACROS3;
2161 char *work4 = WORKING_DIR XREF_MACINFO;
2162
2163 enum { STACK_SIZE = 1024 };
2164 int file_stack [STACK_SIZE], sp = 0;
2165
2166 if (args.verbose) printf ("processing all macros\n");
2167 fp1 = fopen (work1, "w");
2168 if (fp1 == NULL) { perror ("fopen(macros1)"); exit (1); }
2169 fp2 = fopen (work2, "w");
2170 if (fp2 == NULL) { perror ("fopen(macros2)"); exit (1); }
2171 fp3 = fopen (work3, "w");
2172 if (fp3 == NULL) { perror ("fopen(macros3)"); exit (1); }
2173 fp4 = fopen (work4, "w");
2174 if (fp4 == NULL) { perror ("fopen(macros4)"); exit (1); }
2175
2176 result = eval_xpath ("//section[@name='.debug_macinfo']/*",
2177 xml_root, &free_p, &n);
2178 /* for font-lock sanity */
2179
2180 for (i = 0; i < n; i++) {
2181 char buf [BUFLEN];
2182 xmlNodePtr node = result->nodeTab [i];
2183
2184 if (node->type != XML_ELEMENT_NODE) continue;
2185
2186 if (!strcmp (node->name, "start_file")) {
2187 char *line = xmlGetProp (node, "line");
2188 char *file_num = xmlGetProp (node, "file_index");
2189 char *filename, *pathname;
2190 if (sp >= STACK_SIZE) {
2191 fprintf (stderr, "file stack overflow\n");
2192 exit (1);
2193 }
2194 if (sp == 0) {
2195 int j;
2196 char *offset = xmlGetProp (node, "offset");
2197 assert (offset != NULL);
2198
2199 if (strcmp (line, "0")) {
2200 if (line == NULL) line = "(null)";
2201 printf ("line = %s, offset = %s\n", line, offset);
2202 }
2203 assert (!strcmp (line, "0"));
2204
2205 for (j = 0; j < n_comp_unit; j++) {
2206 if (!strcmp (offset, comp_unit [j].macinfo_offset)) {
2207 curr_comp_unit = j;
2208 break;
2209 }
2210 }
2211 /* not found, so skip this comp_unit */
2212 if (j >= n_comp_unit) {
2213 while (1) {
2214 char *line;
2215 i++;
2216 if (i >= n) break;
2217 node = result->nodeTab [i];
2218 if (strcmp (node->name, "start_file"))
2219 continue;
2220 line = xmlGetProp (node, "line");
2221 if (strcmp (line, "0")) {
2222 xmlFree (line);
2223 continue;
2224 }
2225 xmlFree (line);
2226 break;
2227 }
2228 #if 0
2229 xmlAttrPtr attr;
2230 unsigned long offset2;
2231 sscanf (offset, "macinfo:%ld", &offset2);
2232 for (j = 0; j < n_comp_unit; j++) {
2233 if (offset2 > comp_unit [j].macinfo_offset2)
2234 break;
2235 }
2236 attr = xmlGetID (xml_doc, comp_unit [i].macinfo_offset);
2237 assert (attr != NULL);
2238 node = attr->parent;
2239 #endif
2240 i--;
2241 goto start_file_exit;
2242 }
2243 }
2244 assert (file_num != NULL);
2245 file_stack [sp++] = atoi (file_num);
2246 filename = get_filename_by_int (curr_comp_unit,
2247 file_stack [sp - 1]);
2248 pathname = get_pathname_by_int (curr_comp_unit,
2249 file_stack [sp - 1]);
2250
2251 if (sp < 2) {
2252 fprintf (fp4, "<hr><h1>%s, %s</h1><hr>",
2253 filename, pathname);
2254 } else {
2255 char *id = get_macinfo_id ();
2256 char *filename2 = get_filename_by_int (curr_comp_unit,
2257 file_stack [sp - 2]);
2258 char *pathname2 = get_pathname_by_int (curr_comp_unit,
2259 file_stack [sp - 2]);
2260 fprintf (fp1,
2261 "%s @ #include %s " COMM_BEGIN "%s" COMM_END "\n",
2262 filename, href_macinfo (id, filename),
2263 href_src2 (pathname2, line, filename2));
2264 fprintf (fp2,
2265 "a%s @ #include %s " COMM_BEGIN "%s" COMM_END "\n",
2266 filename, href_macinfo (id, filename),
2267 href_src2 (pathname2, line, filename2));
2268 fprintf (fp3,
2269 "%s %s @ " COMM_BEGIN "%s" COMM_END " #include %s\n",
2270 filename, line,
2271 href_src2 (pathname2, line, filename2),
2272 href_macinfo (id, filename));
2273 fprintf (fp4,
2274 "%s#include %s " COMM_BEGIN "%s" COMM_END "\n",
2275 a_name (id), href_src1 (pathname2, line, filename),
2276 href_src2 (pathname2, line, filename2));
2277 }
2278
2279 start_file_exit:
2280 xmlFree (line);
2281 xmlFree (file_num);
2282 } else if (!strcmp (node->name, "end_file")) {
2283 char *filename = get_filename_by_int (curr_comp_unit,
2284 file_stack [sp - 1]);
2285 if (sp < 0) {
2286 fprintf (stderr, "file stack underflow\n");
2287 exit (1);
2288 }
2289 sp--;
2290 } else if (!strcmp (node->name, "define_func")
2291 || !strcmp (node->name, "define_normal")) {
2292 char *id = get_macinfo_id ();
2293 char *line = xmlGetProp (node, "line");
2294 char *line2 = get_line (line);
2295 char *name = xmlGetProp (node, "name");
2296 char *filename = get_filename_by_int (curr_comp_unit,
2297 file_stack [sp - 1]);
2298 char *pathname = get_pathname_by_int (curr_comp_unit,
2299 file_stack [sp - 1]);
2300 char *body = xmlGetProp (node, "body");
2301 char *signature = xmlGetProp (node, "signature");
2302
2303 fprintf (fp1, "%s @ #define %s " COMM_BEGIN "%s" COMM_END "\n",
2304 name, href_macinfo (id, signature),
2305 href_src2 (pathname, line2, filename));
2306 fprintf (fp2, "d%s @ #define %s " COMM_BEGIN "%s" COMM_END "\n",
2307 name, href_macinfo (id, signature),
2308 href_src2 (pathname, line2, filename));
2309 fprintf (fp3, "%s %s @ " COMM_BEGIN "%s" COMM_END " #define %s\n",
2310 filename, line2, href_src2 (pathname, line2, filename),
2311 href_macinfo (id, signature));
2312 fprintf (fp4, "%s#define %s %s " COMM_BEGIN "%s" COMM_END "\n",
2313 a_name (id),
2314 href_src1 (pathname, line2, signature),
2315 body,
2316 href_src2 (pathname, line2, filename));
2317
2318 xmlFree (line);
2319 xmlFree (name);
2320 xmlFree (body);
2321 xmlFree (signature);
2322 } else if (!strcmp (node->name, "undef")) {
2323 char *id = get_macinfo_id ();
2324 char *line = xmlGetProp (node, "line");
2325 char *line2 = get_line (line);
2326 char *name = xmlGetProp (node, "name");
2327 char *filename = get_filename_by_int (curr_comp_unit,
2328 file_stack [sp - 1]);
2329 char *pathname = get_pathname_by_int (curr_comp_unit,
2330 file_stack [sp - 1]);
2331
2332 fprintf (fp1, "%s @ #undef %s " COMM_BEGIN "%s" COMM_END "\n",
2333 name, href_macinfo (id, name),
2334 href_src2 (pathname, line2, filename));
2335 fprintf (fp2, "u%s @ #undef %s " COMM_BEGIN "%s" COMM_END "\n",
2336 name, href_macinfo (id, name),
2337 href_src2 (pathname, line2, filename));
2338 fprintf (fp3, "%s %s @ " COMM_BEGIN "%s" COMM_END " #undef %s\n",
2339 filename, line2, href_src2 (pathname, line2, filename),
2340 href_macinfo (id, name));
2341 fprintf (fp4, "%s#undef %s " COMM_BEGIN "%s" COMM_END "\n",
2342 a_name (id),
2343 href_src1 (pathname, line2, name),
2344 href_src2 (pathname, line2, filename));
2345
2346 xmlFree (line);
2347 xmlFree (name);
2348 }
2349 }
2350
2351 free (free_p);
2352 fclose (fp1);
2353 fclose (fp2);
2354 fclose (fp3);
2355 fclose (fp4);
2356 }
2357 /* ====================================================================== */
2358 int
2359 main (int argc, char *argv [])
2360 {
2361 if (argc <= 1) {
2362 print_usage ();
2363 exit (1);
2364 }
2365 process_args (argc, argv);
2366 init ();
2367
2368 output_debug_info_top ();
2369 output_all_structs ();
2370 output_all_unions ();
2371 output_all_typedefs ();
2372 output_all_enum_tags ();
2373 output_all_enum_consts ();
2374 output_all_labels ();
2375 output_all_functions ();
2376 output_all_variables ();
2377 output_all_files ();
2378 output_all_macros ();
2379
2380 final ();
2381 return 0;
2382 }
2383 /* ====================================================================== */