Index: objdump.c =================================================================== RCS file: /cvs/src/src/binutils/objdump.c,v retrieving revision 1.66 diff -u -r1.66 objdump.c --- objdump.c 1 May 2003 00:40:41 -0000 1.66 +++ objdump.c 2 May 2003 15:46:39 -0000 @@ -74,6 +74,7 @@ static bfd_vma start_address = (bfd_vma) -1; /* --start-address */ static bfd_vma stop_address = (bfd_vma) -1; /* --stop-address */ static int dump_debugging; /* --debugging */ +static int dump_debugging_tags; /* --debugging-tags */ static bfd_vma adjust_section_vma = 0; /* --adjust-vma */ static int file_start_context = 0; /* --file-start-context */ @@ -208,6 +209,7 @@ -S, --source Intermix source code with disassembly\n\ -s, --full-contents Display the full contents of all sections requested\n\ -g, --debugging Display debug information in object file\n\ + -e, --debugging-tags Display debug information using ctags style\n\ -G, --stabs Display (in raw form) any STABS info in the file\n\ -t, --syms Display the contents of the symbol table(s)\n\ -T, --dynamic-syms Display the contents of the dynamic symbol table\n\ @@ -266,6 +268,7 @@ {"architecture", required_argument, NULL, 'm'}, {"archive-headers", no_argument, NULL, 'a'}, {"debugging", no_argument, NULL, 'g'}, + {"debugging-tags", no_argument, NULL, 'e'}, {"demangle", optional_argument, NULL, 'C'}, {"disassemble", no_argument, NULL, 'd'}, {"disassemble-all", no_argument, NULL, 'D'}, @@ -2068,7 +2071,8 @@ } } - printf (_("\n%s: file format %s\n"), bfd_get_filename (abfd), + if (! dump_debugging_tags) + printf (_("\n%s: file format %s\n"), bfd_get_filename (abfd), abfd->xvec->name); if (dump_ar_hdrs) print_arelt_descr (stdout, abfd, TRUE); @@ -2076,7 +2080,8 @@ dump_bfd_header (abfd); if (dump_private_headers) dump_bfd_private_header (abfd); - putchar ('\n'); + if (! dump_debugging_tags) + putchar ('\n'); if (dump_section_headers) dump_headers (abfd); @@ -2106,7 +2111,8 @@ dhandle = read_debugging_info (abfd, syms, symcount); if (dhandle != NULL) { - if (! print_debugging_info (stdout, dhandle)) + if (! print_debugging_info (stdout, dhandle, abfd, syms, demangle, + dump_debugging_tags ? TRUE : FALSE)) { non_fatal (_("%s: printing debugging information failed"), bfd_get_filename (abfd)); @@ -2648,7 +2654,7 @@ bfd_init (); set_default_bfd_target (); - while ((c = getopt_long (argc, argv, "pib:m:M:VvCdDlfaHhrRtTxsSj:wE:zgG", + while ((c = getopt_long (argc, argv, "pib:m:M:VvCdDlfaHhrRtTxsSj:wE:zgeG", long_options, (int *) 0)) != EOF) { @@ -2779,6 +2785,12 @@ break; case 'g': dump_debugging = 1; + seenflag = TRUE; + break; + case 'e': + dump_debugging = 1; + dump_debugging_tags = 1; + do_demangle = TRUE; seenflag = TRUE; break; case 'G': Index: budbg.h =================================================================== RCS file: /cvs/src/src/binutils/budbg.h,v retrieving revision 1.3 diff -u -r1.3 budbg.h --- budbg.h 30 Nov 2002 08:39:41 -0000 1.3 +++ budbg.h 2 May 2003 15:46:39 -0000 @@ -32,8 +32,8 @@ /* Routine used to print generic debugging information. */ extern bfd_boolean print_debugging_info - PARAMS ((FILE *, PTR)); - + PARAMS ((FILE *, PTR, bfd *, asymbol **, PTR, bfd_boolean)); + /* Routines used to read and write stabs information. */ extern PTR start_stab Index: prdbg.c =================================================================== RCS file: /cvs/src/src/binutils/prdbg.c,v retrieving revision 1.6 diff -u -r1.6 prdbg.c --- prdbg.c 30 Nov 2002 08:39:41 -0000 1.6 +++ prdbg.c 2 May 2003 15:46:40 -0000 @@ -1,6 +1,7 @@ /* prdbg.c -- Print out generic debugging information. - Copyright 1995, 1996, 2002 Free Software Foundation, Inc. + Copyright 1995, 1996, 2002, 2003 Free Software Foundation, Inc. Written by Ian Lance Taylor . + Tags style generation written by Salvador E. Tropea This file is part of GNU Binutils. @@ -43,6 +44,15 @@ struct pr_stack *stack; /* Parameter number we are about to output. */ int parameter; + /* The following are used only by the tags code (tg_) */ + /* Name of the file we are using */ + char *filename; + /* The BFD */ + bfd *abfd; + /* The symbols table for this BFD */ + asymbol **syms; + /* Pointer to a function to demangle symbols */ + char *(*demangler) PARAMS ((bfd *, const char *)); }; /* The type stack. */ @@ -57,6 +67,13 @@ enum debug_visibility visibility; /* Name of the current method we are handling. */ const char *method; + /* The following are used only by the tags code (tg_) */ + /* Type for the container (struct, union, class, union class) */ + const char *flavor; + /* A comma separated list of parent classes */ + char *parents; + /* How many parents contains parents */ + int num_parents; }; static void indent @@ -67,6 +84,8 @@ PARAMS ((struct pr_handle *, const char *)); static bfd_boolean append_type PARAMS ((struct pr_handle *, const char *)); +static bfd_boolean append_parent + PARAMS ((struct pr_handle *, const char *)); static bfd_boolean substitute_type PARAMS ((struct pr_handle *, const char *)); static bfd_boolean indent_type @@ -77,6 +96,16 @@ PARAMS ((bfd_vma, char *, bfd_boolean, bfd_boolean)); static bfd_boolean pr_fix_visibility PARAMS ((struct pr_handle *, enum debug_visibility)); +/* Only used by tg_ code */ +static bfd_boolean tg_fix_visibility + PARAMS ((struct pr_handle *, enum debug_visibility)); +static void find_address_in_section + PARAMS ((bfd *abfd, asection *section, PTR data)); +static void translate_addresses + PARAMS ((bfd *abfd, char *addr_hex, FILE *f, asymbol **syms)); +static const char *visibility_name + PARAMS ((enum debug_visibility visibility)); + static bfd_boolean pr_start_compilation_unit PARAMS ((PTR, const char *)); static bfd_boolean pr_start_source @@ -169,6 +198,63 @@ static bfd_boolean pr_lineno PARAMS ((PTR, const char *, unsigned long, bfd_vma)); +/* Tags style replacements */ +static bfd_boolean tg_start_compilation_unit + PARAMS ((PTR, const char *)); +static bfd_boolean tg_start_source + PARAMS ((PTR, const char *)); +static bfd_boolean tg_enum_type + PARAMS ((PTR, const char *, const char **, bfd_signed_vma *)); +static bfd_boolean tg_start_struct_type + PARAMS ((PTR, const char *, unsigned int, bfd_boolean, unsigned int)); +static bfd_boolean pr_struct_field + PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility)); +static bfd_boolean tg_struct_field + PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility)); +static bfd_boolean tg_struct_field + PARAMS ((PTR, const char *, bfd_vma, bfd_vma, enum debug_visibility)); +static bfd_boolean tg_end_struct_type + PARAMS ((PTR)); +static bfd_boolean tg_start_class_type + PARAMS ((PTR, const char *, unsigned int, bfd_boolean, unsigned int, + bfd_boolean, bfd_boolean)); +static bfd_boolean tg_class_static_member + PARAMS ((PTR, const char *, const char *, enum debug_visibility)); +static bfd_boolean tg_class_baseclass + PARAMS ((PTR, bfd_vma, bfd_boolean, enum debug_visibility)); +static bfd_boolean tg_class_method_variant + PARAMS ((PTR, const char *, enum debug_visibility, bfd_boolean, bfd_boolean, + bfd_vma, bfd_boolean)); +static bfd_boolean tg_class_static_method_variant + PARAMS ((PTR, const char *, enum debug_visibility, bfd_boolean, + bfd_boolean)); +static bfd_boolean tg_end_class_type + PARAMS ((PTR)); +static bfd_boolean tg_tag_type + PARAMS ((PTR, const char *, unsigned int, enum debug_type_kind)); +static bfd_boolean tg_typdef + PARAMS ((PTR, const char *)); +static bfd_boolean tg_tag + PARAMS ((PTR, const char *)); +static bfd_boolean tg_int_constant + PARAMS ((PTR, const char *, bfd_vma)); +static bfd_boolean tg_float_constant + PARAMS ((PTR, const char *, double)); +static bfd_boolean tg_typed_constant + PARAMS ((PTR, const char *, bfd_vma)); +static bfd_boolean tg_variable + PARAMS ((PTR, const char *, enum debug_var_kind, bfd_vma)); +static bfd_boolean tg_start_function + PARAMS ((PTR, const char *, bfd_boolean)); +static bfd_boolean tg_function_parameter + PARAMS ((PTR, const char *, enum debug_parm_kind, bfd_vma)); +static bfd_boolean tg_start_block + PARAMS ((PTR, bfd_vma)); +static bfd_boolean tg_end_block + PARAMS ((PTR, bfd_vma)); +static bfd_boolean tg_lineno + PARAMS ((PTR, const char *, unsigned long, bfd_vma)); + static const struct debug_write_fns pr_fns = { pr_start_compilation_unit, @@ -217,12 +303,64 @@ pr_lineno }; +static const struct debug_write_fns tg_fns = +{ + tg_start_compilation_unit, + tg_start_source, + pr_empty_type, /* Same, push_type */ + pr_void_type, /* Same, push_type */ + pr_int_type, /* Same, push_type */ + pr_float_type, /* Same, push_type */ + pr_complex_type, /* Same, push_type */ + pr_bool_type, /* Same, push_type */ + tg_enum_type, + pr_pointer_type, /* Same, changes to pointer */ + pr_function_type, /* Same, push_type */ + pr_reference_type, /* Same, changes to reference */ + pr_range_type, /* FIXME: What's that? */ + pr_array_type, /* Same, push_type */ + pr_set_type, /* FIXME: What's that? */ + pr_offset_type, /* FIXME: What's that? */ + pr_method_type, /* Same */ + pr_const_type, /* Same, changes to const */ + pr_volatile_type, /* Same, changes to volatile */ + tg_start_struct_type, + tg_struct_field, + tg_end_struct_type, + tg_start_class_type, + tg_class_static_member, + tg_class_baseclass, + pr_class_start_method, /* Same, remmembers that's a method */ + tg_class_method_variant, + tg_class_static_method_variant, + pr_class_end_method, /* Same, forgets that's a method */ + tg_end_class_type, + pr_typedef_type, /* Same, just push type */ + tg_tag_type, + tg_typdef, + tg_tag, + tg_int_constant, /* Untested */ + tg_float_constant, /* Untested */ + tg_typed_constant, /* Untested */ + tg_variable, + tg_start_function, + tg_function_parameter, + tg_start_block, + tg_end_block, + pr_end_function, /* Same, does nothing */ + tg_lineno +}; + /* Print out the generic debugging information recorded in dhandle. */ bfd_boolean -print_debugging_info (f, dhandle) +print_debugging_info (f, dhandle, abfd, syms, demangler, as_tags) FILE *f; PTR dhandle; + bfd *abfd; + asymbol **syms; + PTR demangler; + bfd_boolean as_tags; { struct pr_handle info; @@ -230,8 +368,22 @@ info.indent = 0; info.stack = NULL; info.parameter = 0; + info.filename = NULL; + info.abfd = abfd; + info.syms = syms; + info.demangler = demangler; + + if (as_tags) + { + fputs("!_TAG_FILE_FORMAT\t2\t/extended format/\n",f); + fputs("!_TAG_FILE_SORTED\t0\t/0=unsorted, 1=sorted/\n",f); + fputs("!_TAG_PROGRAM_AUTHOR\tIan Lance Taylor, Salvador E. Tropea and others\t//\n",f); + fputs("!_TAG_PROGRAM_NAME\tobjdump\t/From GNU binutils/\n",f); + /*!_TAG_PROGRAM_VERSION 5.2.2 //*/ + } - return debug_write (dhandle, &pr_fns, (PTR) &info); + return as_tags ? debug_write (dhandle, &tg_fns, (PTR) &info) + : debug_write (dhandle, &pr_fns, (PTR) &info); } /* Indent to the current indentation level. */ @@ -311,6 +463,28 @@ return TRUE; } +/* Append a string to the parents on the top of the type stack. */ + +static bfd_boolean +append_parent (info, s) + struct pr_handle *info; + const char *s; +{ + unsigned int len; + + if (s == NULL) + return FALSE; + + assert (info->stack != NULL); + + len = info->stack->parents ? strlen (info->stack->parents) : 0; + info->stack->parents = (char *) xrealloc (info->stack->parents, + len + strlen (s) + 1); + strcpy (info->stack->parents + len, s); + + return TRUE; +} + /* We use an underscore to indicate where the name should go in a type string. This function substitutes a string for the underscore. If there is no underscore, the name follows the type. */ @@ -1894,3 +2068,1006 @@ { return TRUE; } + +/***************************************************************************** + + Tags style generation functions from here + +*****************************************************************************/ + +/* Variables for address to line translation */ +static bfd_vma pc; +static const char *filename; +static const char *functionname; +static unsigned int line; +static bfd_boolean found; + +/* Look for an address in a section. This is called via + bfd_map_over_sections. */ + +static void +find_address_in_section (abfd, section, data) + bfd *abfd; + asection *section; + PTR data; +{ + bfd_vma vma; + bfd_size_type size; + asymbol **syms = (asymbol **)data; + + if (found) + return; + + if ((bfd_get_section_flags (abfd, section) & SEC_ALLOC) == 0) + return; + + vma = bfd_get_section_vma (abfd, section); + if (pc < vma) + return; + + size = bfd_get_section_size_before_reloc (section); + if (pc >= vma + size) + return; + + found = bfd_find_nearest_line (abfd, section, syms, pc - vma, + &filename, &functionname, &line); +} + +static void +translate_addresses (abfd, addr_hex, f, syms) + bfd *abfd; + char *addr_hex; + FILE *f; + asymbol **syms; +{ + pc = bfd_scan_vma (addr_hex, NULL, 16); + found = FALSE; + bfd_map_over_sections (abfd, find_address_in_section, syms); + + if (! found) + fprintf (f, "??"); + else + //fprintf (f, "%u (%s)", line, addr_hex); + fprintf (f, "%u", line); +} + +/* Start a new compilation unit. */ + +static bfd_boolean +tg_start_compilation_unit (p, filename) + PTR p; + const char *filename ATTRIBUTE_UNUSED; +{ + struct pr_handle *info = (struct pr_handle *) p; + + fprintf(stderr, "New compilation unit: %s\n", filename); + + free (info->filename); + /* Should it be relative? best way to do it here? */ + info->filename = strdup(filename); + + return TRUE; +} + +/* Start a source file within a compilation unit. */ + +static bfd_boolean +tg_start_source (p, filename) + PTR p; + const char *filename; +{ + struct pr_handle *info = (struct pr_handle *) p; + + free (info->filename); + /* Should it be relative? best way to do it here? */ + info->filename = strdup(filename); + + return TRUE; +} + +/* Push an enum type onto the type stack. */ + +static bfd_boolean +tg_enum_type (p, tag, names, values) + PTR p; + const char *tag; + const char **names; + bfd_signed_vma *values; +{ + struct pr_handle *info = (struct pr_handle *) p; + unsigned int i; + const char *name; + char ab[20]; + + if (! pr_enum_type (p, tag, names, values)) + return FALSE; + + name = tag ? tag : "unknown"; + /* Generate an entry for the enum */ + if (tag) + { + fprintf(info->f, "%s\t%s\t0;\"\tkind:e\ttype:%s\n", tag, + info->filename, info->stack->type); + } + /* Generate entries for the values */ + if (names != NULL) + { + for (i = 0; names[i] != NULL; i++) + { + print_vma (values[i], ab, FALSE, FALSE); + fprintf (info->f, "%s\t%s\t0;\"\tkind:g\tenum:%s\tvalue:%s\n", + names[i], info->filename, name, ab); + } + } + + return TRUE; +} + +/* Start accumulating a struct type. */ + +static bfd_boolean +tg_start_struct_type (p, tag, id, structp, size) + PTR p; + const char *tag; + unsigned int id; + bfd_boolean structp; + unsigned int size ATTRIBUTE_UNUSED; +{ + struct pr_handle *info = (struct pr_handle *) p; + const char *name; + char idbuf[20]; + + if (tag != NULL) + { + name = tag; + } + else + { + name = idbuf; + sprintf (idbuf, "%%anon%u", id); + } + if (! push_type (info, name)) + return FALSE; + info->stack->flavor = structp ? "struct" : "union"; + + fprintf (info->f, "%s\t%s\t0;\"\tkind:%c\n", name, info->filename, + info->stack->flavor[0]); + + info->stack->visibility = DEBUG_VISIBILITY_PUBLIC; + + return indent_type (info); +} + +/* Output the visibility of a field in a struct. */ + +static bfd_boolean +tg_fix_visibility (info, visibility) + struct pr_handle *info; + enum debug_visibility visibility; +{ + assert (info->stack != NULL); + + if (info->stack->visibility == visibility) + return TRUE; + + assert (info->stack->visibility != DEBUG_VISIBILITY_IGNORE); + + info->stack->visibility = visibility; + + return TRUE; +} + +/* Add a field to a struct type. */ + +static bfd_boolean +tg_struct_field (p, name, bitpos, bitsize, visibility) + PTR p; + const char *name; + bfd_vma bitpos ATTRIBUTE_UNUSED; + bfd_vma bitsize ATTRIBUTE_UNUSED; + enum debug_visibility visibility; +{ + struct pr_handle *info = (struct pr_handle *) p; + char *t; + + t = pop_type (info); + if (t == NULL) + return FALSE; + + if (! tg_fix_visibility (info, visibility)) + return FALSE; + + /* It happends, a bug? */ + if (! name[0]) + return TRUE; + + fprintf (info->f, "%s\t%s\t0;\"\tkind:m\ttype:%s\t%s:%s\taccess:%s\n", + name, info->filename, t, info->stack->flavor, info->stack->type, + visibility_name (visibility)); + + return TRUE; +} + +/* Finish a struct type. */ + +static bfd_boolean +tg_end_struct_type (p) + PTR p ATTRIBUTE_UNUSED; +{ + struct pr_handle *info = (struct pr_handle *) p; + assert (info->stack != NULL); + + return TRUE; +} + +/* Start a class type. */ + +static bfd_boolean +tg_start_class_type (p, tag, id, structp, size, vptr, ownvptr) + PTR p; + const char *tag; + unsigned int id; + bfd_boolean structp; + unsigned int size; + bfd_boolean vptr; + bfd_boolean ownvptr; +{ + struct pr_handle *info = (struct pr_handle *) p; + char *tv = NULL; + const char *name; + + info->indent += 2; + + if (vptr && ! ownvptr) + { + tv = pop_type (info); + if (tv == NULL) + return FALSE; + } + + if (tag != NULL) + { + name=tag; + } + else + { + char idbuf[20]; + + sprintf (idbuf, "%%anon%u", id); + name = idbuf; + } + if (! push_type (info, name)) + return FALSE; + info->stack->flavor = structp ? "class" : "union class"; + info->stack->parents = NULL; + info->stack->num_parents = 0; + + if (size != 0 || vptr || ownvptr || tag != NULL) + { + if (vptr) + { + if (! append_type (info, " vtable ")) + return FALSE; + if (ownvptr) + { + if (! append_type (info, "self ")) + return FALSE; + } + else + { + if (! append_type (info, tv) + || ! append_type (info, " ")) + return FALSE; + } + } + } + + info->stack->visibility = DEBUG_VISIBILITY_PRIVATE; + + return TRUE; +} + +/* Add a static member to a class. */ + +static bfd_boolean +tg_class_static_member (p, name, physname, visibility) + PTR p; + const char *name; + const char *physname ATTRIBUTE_UNUSED; + enum debug_visibility visibility; +{ + struct pr_handle *info = (struct pr_handle *) p; + char *t; + int len_var, len_class; + char *full_name; + + len_var = strlen (name); + len_class = strlen (info->stack->next->type); + full_name = (char *) xmalloc (len_var + len_class + 3); + if (! full_name) + return FALSE; + memcpy (full_name, info->stack->next->type, len_class); + memcpy (full_name + len_class, "::", 2); + memcpy (full_name + len_class + 2, name, len_var + 1); + + if (! substitute_type (info, full_name)) + return FALSE; + + if (! prepend_type (info, "static ")) + return FALSE; + + t = pop_type (info); + if (t == NULL) + return FALSE; + + if (! tg_fix_visibility (info, visibility)) + return FALSE; + + fprintf (info->f, "%s\t%s\t0;\"\tkind:x\ttype:%s\tclass:%s\taccess:%s\n", + name, info->filename, t, info->stack->type, + visibility_name (visibility)); + free (t); + free (full_name); + + return TRUE; +} + +/* Add a base class to a class. */ + +static bfd_boolean +tg_class_baseclass (p, bitpos, virtual, visibility) + PTR p; + bfd_vma bitpos ATTRIBUTE_UNUSED; + bfd_boolean virtual; + enum debug_visibility visibility; +{ + struct pr_handle *info = (struct pr_handle *) p; + char *t; + const char *prefix; + + assert (info->stack != NULL && info->stack->next != NULL); + + t = pop_type (info); + if (t == NULL) + return FALSE; + + if (strncmp (t, "class ", sizeof "class " - 1) == 0) + t += sizeof "class " - 1; + + /* Push it back on to take advantage of the prepend_type and + append_type routines. */ + if (! push_type (info, t)) + return FALSE; + + if (virtual) + { + if (! prepend_type (info, "virtual ")) + return FALSE; + } + + switch (visibility) + { + case DEBUG_VISIBILITY_PUBLIC: + prefix = "public "; + break; + case DEBUG_VISIBILITY_PROTECTED: + prefix = "protected "; + break; + case DEBUG_VISIBILITY_PRIVATE: + prefix = "private "; + break; + default: + prefix = "/* unknown visibility */ "; + break; + } + + if (! prepend_type (info, prefix)) + return FALSE; + + t = pop_type (info); + if (t == NULL) + return FALSE; + + if (info->stack->num_parents && ! append_parent (info, ", ")) + return FALSE; + + if (! append_parent (info, t)) + return FALSE; + info->stack->num_parents++; + + free (t); + + return TRUE; +} + +/* Add a variant to a method. */ + +static bfd_boolean +tg_class_method_variant (p, physname, visibility, constp, volatilep, voffset, + context) + PTR p; + const char *physname ATTRIBUTE_UNUSED; + enum debug_visibility visibility; + bfd_boolean constp; + bfd_boolean volatilep; + bfd_vma voffset ATTRIBUTE_UNUSED; + bfd_boolean context; +{ + struct pr_handle *info = (struct pr_handle *) p; + char *method_type; + char *context_type; + char *method_name; + + assert (info->stack != NULL); + assert (info->stack->next != NULL); + + /* Put the const and volatile qualifiers on the type. */ + if (volatilep) + { + if (! append_type (info, " volatile")) + return FALSE; + } + if (constp) + { + if (! append_type (info, " const")) + return FALSE; + } + + method_name = strdup(context ? info->stack->next->next->method + : info->stack->next->method); + + /* Stick the name of the method into its type. */ + if (! substitute_type (info, method_name)) + return FALSE; + + /* Get the type. */ + method_type = pop_type (info); + if (method_type == NULL) + return FALSE; + + /* Pull off the context type if there is one. */ + if (! context) + context_type = NULL; + else + { + context_type = pop_type (info); + if (context_type == NULL) + return FALSE; + } + + /* Now the top of the stack is the class. */ + + if (! tg_fix_visibility (info, visibility)) + return FALSE; + + fprintf (info->f, "%s\t%s\t0;\"\tkind:p\ttype:%s\tclass:%s\n", + method_name, info->filename, method_type, info->stack->type); + free(method_type); + free(method_name); + free(context_type); + + return TRUE; +} + +/* Add a static variant to a method. */ + +static bfd_boolean +tg_class_static_method_variant (p, physname, visibility, constp, volatilep) + PTR p; + const char *physname ATTRIBUTE_UNUSED; + enum debug_visibility visibility; + bfd_boolean constp; + bfd_boolean volatilep; +{ + struct pr_handle *info = (struct pr_handle *) p; + char *method_type; + char *method_name; + + assert (info->stack != NULL); + assert (info->stack->next != NULL); + assert (info->stack->next->method != NULL); + + /* Put the const and volatile qualifiers on the type. */ + if (volatilep) + { + if (! append_type (info, " volatile")) + return FALSE; + } + if (constp) + { + if (! append_type (info, " const")) + return FALSE; + } + + /* Mark it as static. */ + if (! prepend_type (info, "static ")) + return FALSE; + + method_name = strdup(info->stack->next->method); + /* Stick the name of the method into its type. */ + if (! substitute_type (info, info->stack->next->method)) + return FALSE; + + /* Get the type. */ + method_type = pop_type (info); + if (method_type == NULL) + return FALSE; + + /* Now the top of the stack is the class. */ + + if (! tg_fix_visibility (info, visibility)) + return FALSE; + + fprintf (info->f, "%s\t%s\t0;\"\tkind:p\ttype:%s\tclass:%s\taccess:%s\n", + method_name, info->filename, method_type, info->stack->type, + visibility_name (visibility)); + free(method_type); + free(method_name); + + return TRUE; +} + +/* Finish up a class. */ + +static bfd_boolean +tg_end_class_type (p) + PTR p; +{ + struct pr_handle *info = (struct pr_handle *) p; + + fprintf (info->f, "%s\t%s\t0;\"\tkind:c\ttype:%s", info->stack->type, info->filename, + info->stack->flavor); + if (info->stack->num_parents) + { + fprintf (info->f, "\tinherits:%s", info->stack->parents); + free (info->stack->parents); + } + fputc ('\n', info->f); + + return tg_end_struct_type (p); +} + +/* Push a type on the stack using a tag name. */ + +static bfd_boolean +tg_tag_type (p, name, id, kind) + PTR p; + const char *name; + unsigned int id; + enum debug_type_kind kind; +{ + struct pr_handle *info = (struct pr_handle *) p; + const char *t, *tag; + char idbuf[20]; + + switch (kind) + { + case DEBUG_KIND_STRUCT: + t = "struct "; + break; + case DEBUG_KIND_UNION: + t = "union "; + break; + case DEBUG_KIND_ENUM: + t = "enum "; + break; + case DEBUG_KIND_CLASS: + t = "class "; + break; + case DEBUG_KIND_UNION_CLASS: + t = "union class "; + break; + default: + abort (); + return FALSE; + } + + if (! push_type (info, t)) + return FALSE; + if (name != NULL) + tag = name; + else + { + sprintf (idbuf, "%%anon%u", id); + tag = idbuf; + } + + if (! append_type (info, tag)) + return FALSE; + + return TRUE; +} + +/* Output a typedef. */ + +static bfd_boolean +tg_typdef (p, name) + PTR p; + const char *name; +{ + struct pr_handle *info = (struct pr_handle *) p; + char *s; + + s = pop_type (info); + if (s == NULL) + return FALSE; + + fprintf (info->f, "%s\t%s\t0;\"\tkind:t\ttype:%s\n", name, + info->filename, s); + + free (s); + + return TRUE; +} + +/* Output a tag. The tag should already be in the string on the + stack, so all we have to do here is print it out. */ + +static bfd_boolean +tg_tag (p, name) + PTR p ATTRIBUTE_UNUSED; + const char *name ATTRIBUTE_UNUSED; +{ + struct pr_handle *info = (struct pr_handle *) p; + char *t; + + t = pop_type (info); + if (t == NULL) + return FALSE; + free (t); + + return TRUE; +} + +/* Output an integer constant. */ + +static bfd_boolean +tg_int_constant (p, name, val) + PTR p; + const char *name; + bfd_vma val; +{ + struct pr_handle *info = (struct pr_handle *) p; + char ab[20]; + + indent (info); + print_vma (val, ab, FALSE, FALSE); + fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const int\tvalue:%s\n", + name, info->filename, ab); + return TRUE; +} + +/* Output a floating point constant. */ + +static bfd_boolean +tg_float_constant (p, name, val) + PTR p; + const char *name; + double val; +{ + struct pr_handle *info = (struct pr_handle *) p; + + indent (info); + fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const double\tvalue:%g\n", + name, info->filename, val); + return TRUE; +} + +/* Output a typed constant. */ + +static bfd_boolean +tg_typed_constant (p, name, val) + PTR p; + const char *name; + bfd_vma val; +{ + struct pr_handle *info = (struct pr_handle *) p; + char *t; + char ab[20]; + + t = pop_type (info); + if (t == NULL) + return FALSE; + + indent (info); + print_vma (val, ab, FALSE, FALSE); + fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:const %s\tvalue:%s\n", + name, info->filename, t, ab); + + free (t); + + return TRUE; +} + +/* Output a variable. */ + +static bfd_boolean +tg_variable (p, name, kind, val) + PTR p; + const char *name; + enum debug_var_kind kind; + bfd_vma val ATTRIBUTE_UNUSED; +{ + struct pr_handle *info = (struct pr_handle *) p; + char *t; + const char *dname, *from_class; + + t = pop_type (info); + if (t == NULL) + return FALSE; + + dname = name; + if (info->demangler) + { + dname = info->demangler (info->abfd, name); + if (strcmp (name, dname) == 0) + { + free ((char *)dname); + dname = name; + } + } + + if (dname != name) + { + char *sep; + sep = strstr (dname, "::"); + if (sep) + { + *sep = 0; + name = sep + 2; + from_class = dname; + } + else + { + /* Obscure types as vts and type_info nodes */ + /*fprintf(stderr,"%s => %s\n",name,dname);*/ + name = dname; + from_class = NULL; + } + } + else + from_class = NULL; + + fprintf (info->f, "%s\t%s\t0;\"\tkind:v\ttype:%s", + name, info->filename, t); + + switch (kind) + { + case DEBUG_STATIC: + case DEBUG_LOCAL_STATIC: + fprintf (info->f, "\tfile:"); + break; + case DEBUG_REGISTER: + fprintf (info->f, "\tregister:"); + break; + default: + break; + } + + if (from_class) + { + fprintf (info->f, "\tclass:%s",from_class); + free ((char *)dname); + } + + fprintf (info->f, "\n"); + + free (t); + + return TRUE; +} + +/* Start outputting a function. */ + +static bfd_boolean +tg_start_function (p, name, global) + PTR p; + const char *name; + bfd_boolean global; +{ + struct pr_handle *info = (struct pr_handle *) p; + const char *dname; + + if (! global) + info->stack->flavor = "static"; + else + info->stack->flavor = NULL; + + dname = name; + if (info->demangler) + { + dname = info->demangler (info->abfd, name); + if (strcmp (name, dname) == 0) + { + free ((char *)dname); + dname = name; + } + } + + if (! substitute_type (info, dname)) + return FALSE; + + if (dname != name) + { + char *sep; + sep = strstr (dname, "::"); + if (sep) + { + info->stack->method = dname; + *sep = 0; + name = sep + 2; + } + else + { + info->stack->method = ""; + name = dname; + } + sep = strchr (name, '('); + if (sep) + *sep = 0; + /* Obscure functions as type_info function */ + /* + else + fprintf(stderr,"%s => %s\n",name,dname);*/ + } + else + info->stack->method = NULL; + + info->stack->parents = strdup (name); + //fprintf (info->f, "%s\t%s\t", name, info->filename); + + if (! info->stack->method && ! append_type (info, "(")) + return FALSE; + + info->parameter = 1; + + return TRUE; +} + +/* Output a function parameter. */ + +static bfd_boolean +tg_function_parameter (p, name, kind, val) + PTR p; + const char *name; + enum debug_parm_kind kind; + bfd_vma val ATTRIBUTE_UNUSED; +{ + struct pr_handle *info = (struct pr_handle *) p; + char *t; + + if (kind == DEBUG_PARM_REFERENCE + || kind == DEBUG_PARM_REF_REG) + { + if (! pr_reference_type (p)) + return FALSE; + } + + if (! substitute_type (info, name)) + return FALSE; + + t = pop_type (info); + if (t == NULL) + return FALSE; + + if (! info->stack->method) + { + if (info->parameter != 1 && ! append_type (info, ", ")) + return FALSE; + + if (kind == DEBUG_PARM_REG || kind == DEBUG_PARM_REF_REG) + if (! append_type (info, "register ")) + return FALSE; + + if (! append_type (info, t)) + return FALSE; + } + + free (t); + + ++info->parameter; + + return TRUE; +} + +/* Start writing out a block. */ + +static bfd_boolean +tg_start_block (p, addr) + PTR p; + bfd_vma addr; +{ + struct pr_handle *info = (struct pr_handle *) p; + char ab[20], kind, *partof; + char *t; + bfd_boolean local; + + if (info->parameter > 0) + { + info->parameter = 0; + + /* Delayed name */ + fprintf (info->f, "%s\t%s\t", info->stack->parents, info->filename); + free (info->stack->parents); + + print_vma (addr, ab, TRUE, TRUE); + translate_addresses (info->abfd, ab, info->f, info->syms); + local = info->stack->flavor != NULL; + if (info->stack->method && *info->stack->method) + { + kind = 'm'; + partof = (char *)info->stack->method; + } + else + { + kind='f'; + partof = NULL; + if (! info->stack->method && ! append_type (info, ")")) + return FALSE; + } + t = pop_type (info); + if (t == NULL) + return FALSE; + fprintf(info->f, ";\"\tkind:%c\ttype:%s", kind, t); + if (local) + fputs ("\tfile:", info->f); + if (partof) + { + fprintf (info->f, "\tclass:%s", partof); + free (partof); + } + fputc ('\n', info->f); + } + + return TRUE; +} + +/* Write out line number information. */ + +static bfd_boolean +tg_lineno (p, filename, lineno, addr) + PTR p ATTRIBUTE_UNUSED; + const char *filename ATTRIBUTE_UNUSED; + unsigned long lineno ATTRIBUTE_UNUSED; + bfd_vma addr ATTRIBUTE_UNUSED; +{ + return TRUE; +} + +/* Finish writing out a block. */ + +static bfd_boolean +tg_end_block (p, addr) + PTR p ATTRIBUTE_UNUSED; + bfd_vma addr ATTRIBUTE_UNUSED; +{ + return TRUE; +} + +static +const char *visibility_name (visibility) + enum debug_visibility visibility; +{ + const char *s; + + switch (visibility) + { + case DEBUG_VISIBILITY_PUBLIC: + s = "public"; + break; + case DEBUG_VISIBILITY_PRIVATE: + s = "private"; + break; + case DEBUG_VISIBILITY_PROTECTED: + s = "protected"; + break; + case DEBUG_VISIBILITY_IGNORE: + s = "/* ignore */"; + break; + default: + abort (); + return FALSE; + } + return s; +} +