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. (&lt;) */
  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", &reg) == 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 /* ====================================================================== */