+
+ processing_current_prefix = old_prefix;
+ do_cleanups (back_to);
+}
+
+/* Return the name of the namespace/class that DIE is defined within,
+ or "" if we can't tell. The caller should xfree the result. */
+
+/* NOTE: carlton/2004-01-23: See read_func_scope (and the comment
+ therein) for an example of how to use this function to deal with
+ DW_AT_specification. */
+
+static char *
+determine_prefix (struct die_info *die, struct dwarf2_cu *cu)
+{
+ char *prefix = determine_prefix_aux (die, cu);
+
+ return prefix ? prefix : xstrdup ("");
+}
+
+/* Return the name of the namespace/class that DIE is defined
+ within, or NULL if we can't tell. The caller should xfree the
+ result. */
+
+static char *
+determine_prefix_aux (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct die_info *parent;
+
+ if (cu->language != language_cplus)
+ return NULL;
+
+ parent = die->parent;
+
+ if (parent == NULL)
+ {
+ return (processing_has_namespace_info ? xstrdup ("") : NULL);
+ }
+ else
+ {
+ char *parent_prefix = determine_prefix_aux (parent, cu);
+ char *retval;
+
+ switch (parent->tag) {
+ case DW_TAG_namespace:
+ {
+ int dummy;
+
+ retval = typename_concat (parent_prefix,
+ namespace_name (parent, &dummy, cu));
+ }
+ break;
+ case DW_TAG_class_type:
+ case DW_TAG_structure_type:
+ {
+ if (parent_prefix != NULL)
+ {
+ const char *parent_name = dwarf2_name (parent, cu);
+
+ if (parent_name != NULL)
+ retval = typename_concat (parent_prefix, dwarf2_name (parent, cu));
+ else
+ /* FIXME: carlton/2003-11-10: I'm not sure what the
+ best thing to do here is. */
+ retval = typename_concat (parent_prefix,
+ "<<anonymous class>>");
+ }
+ else
+ retval = class_name (parent, cu);
+ }
+ break;
+ default:
+ retval = parent_prefix;
+ break;
+ }
+
+ if (retval != parent_prefix)
+ xfree (parent_prefix);
+ return retval;
+ }
+}
+
+/* Return a newly-allocated string formed by concatenating PREFIX,
+ "::", and SUFFIX, except that if PREFIX is NULL or the empty
+ string, just return a copy of SUFFIX. */
+
+static char *
+typename_concat (const char *prefix, const char *suffix)
+{
+ if (prefix == NULL || prefix[0] == '\0')
+ return xstrdup (suffix);
+ else
+ {
+ char *retval = xmalloc (strlen (prefix) + 2 + strlen (suffix) + 1);
+
+ strcpy (retval, prefix);
+ strcat (retval, "::");
+ strcat (retval, suffix);
+
+ return retval;
+ }
+}
+
+/* Return a newly-allocated string giving the name of the class given
+ by DIE. */
+
+static char *
+class_name (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct die_info *child;
+ const char *name;
+
+ for (child = die->child; child != NULL; child = sibling_die (child))
+ {
+ if (child->tag == DW_TAG_subprogram)
+ return class_name_from_physname (dwarf2_linkage_name (child, cu));
+ }
+
+ name = dwarf2_name (die, cu);
+ if (name != NULL)
+ return xstrdup (name);
+ else
+ return xstrdup ("");