aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/ChangeLog4
-rw-r--r--include/splay-tree.h8
-rw-r--r--libiberty/ChangeLog184
-rw-r--r--libiberty/Makefile.in4
-rw-r--r--libiberty/cp-demangle.c977
-rw-r--r--libiberty/cplus-dem.c27
-rw-r--r--libiberty/dyn-string.c24
-rw-r--r--libiberty/pexecute.c25
-rw-r--r--libiberty/setenv.c2
-rw-r--r--libiberty/sigsetmask.c2
-rw-r--r--libiberty/splay-tree.c72
-rw-r--r--libiberty/vasprintf.c54
-rw-r--r--libiberty/vfork.c4
-rw-r--r--libiberty/xexit.c8
14 files changed, 1001 insertions, 394 deletions
diff --git a/include/ChangeLog b/include/ChangeLog
index b6ea943..c6ad3b4 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,7 @@
+2000-10-11 Mark Mitchell <mark@codesourcery.com>
+
+ * splay-tree.h (splay_tree_predecessor): Declare.
+
2000-09-29 Hans-Peter Nilsson <hp@axis.com>
* dis-asm.h: Declare cris_get_disassembler, not print_insn_cris.
diff --git a/include/splay-tree.h b/include/splay-tree.h
index 39882a4..f53f855 100644
--- a/include/splay-tree.h
+++ b/include/splay-tree.h
@@ -1,5 +1,5 @@
/* A splay-tree datatype.
- Copyright (C) 1998 Free Software Foundation, Inc.
+ Copyright (C) 1998, 2000 Free Software Foundation, Inc.
Contributed by Mark Mitchell (mark@markmitchell.com).
This file is part of GNU CC.
@@ -104,6 +104,12 @@ extern void splay_tree_remove PARAMS((splay_tree,
extern splay_tree_node splay_tree_lookup
PARAMS((splay_tree,
splay_tree_key));
+extern splay_tree_node splay_tree_predecessor
+ PARAMS((splay_tree,
+ splay_tree_key));
+extern splay_tree_node splay_tree_successor
+ PARAMS((splay_tree,
+ splay_tree_key));
extern int splay_tree_foreach PARAMS((splay_tree,
splay_tree_foreach_fn,
void*));
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index f4745f0..b78b80b 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,187 @@
+2000-10-11 DJ Delorie <dj@redhat.com>
+
+ Merge from gcc, all 2000-10-11 entries below
+
+2000-10-11 Mark Mitchell <mark@codesourcery.com>
+
+ * splay-tree.c (splay_tree_insert): Fix formatting.
+
+2000-10-11 Mark Mitchell <mark@codesourcery.com>
+
+ * splay-tree.c (splay_tree_predecessor): Fix typo in comment.
+
+2000-10-11 Mark Mitchell <mark@codesourcery.com>
+
+ * splay-tree.c (splay_tree_predecessor): New function.
+ (splay_tree_successor): Likewise.
+
+2000-10-11 Alex Samuel <samuel@codesourcery.com>
+
+ * cp-demangle.c: Fix copyright banner.
+
+2000-10-11 Alex Samuel <samuel@codesourcery.com>
+
+ * cp-demangle.c (status_allocation_failed): Rearrange whitespace.
+ (demangle_type): Handle substitution candidates correctly in the
+ face of special substitutions.
+
+2000-10-11 Alex Samuel <samuel@codesourcery.com>
+
+ * cp-demangle.c (demangle_encoding): Rename variable.
+ (demangle_name): Rename parameter. Handle return type
+ suppression.
+ (demangle_nested_name): Rename parameter.
+ (demangle_prefix): Likewise. Change return type suppression.
+ (demangle_unqualified_name): Add parameter. Flag constructors and
+ conversion operators.
+ (demangle_special_name): Fix comment.
+ (demangle_type): Rename variable.
+ (demangle_bare_function_type): Check for missing return type and
+ parameter.
+ (demangle_class_enum_type): Rename parameter.
+ (demangle_discriminator): Fix misspelling in comment.
+
+2000-10-11 Alex Samuel <samuel@codesourcery.com>
+
+ * cp-demangle.c (demangle_template_arg): Eat an `E' after an
+ <expression>.
+
+2000-10-11 Alex Samuel <samuel@codesourcery.com>
+
+ * cp-demangle.c (demangle_type_ptr): Increment position past
+ pointer and reference characters.
+
+2000-10-11 Alex Samuel <samuel@codesourcery.com>
+
+ * cp-demangle.c (demangle_nv_offset): New function.
+ (demangle_v_offset): Likewise.
+ (demangle_call_offset): Likewise.
+ (demangle_special_name): Update thunk demangling to comply with
+ ABI changes.
+
+2000-10-11 Alex Samuel <samuel@codesourcery.com>
+
+ * cp-demangle.c (ANONYMOUS_NAMESPACE_PREFIX): New macro.
+ (substitution_def): Remove template_parm_number.
+ (NOT_TEMPLATE_PARM): Remove.
+ (result_insert_string): New macro.
+ (result_insert): Likewise.
+ (result_insert_char): Likewise.
+ (substitution_add): Remove last parameter. Don't store template
+ parm number.
+ (BFT_NO_RETURN_TYPE): Define as NULL.
+ (demangle_encoding): Adjust call to demangle_bare_function_type.
+ (demangle_name): Adjust substitution. Adjust call to
+ substitution_add.
+ (demangle_prefix): Adjust call to substitution_add.
+ (demangle_identifier): Handle anonymous namespaces.
+ (demangle_operator_name): Change demangling of vendor-extended
+ operator to match ABI changes.
+ (demangle_type_ptr): Change parameters. Make recursive. Handle
+ substitutions here.
+ (demangle_type): Adjust calls to demangle_template_param,
+ substitution_add, and demangle_type_ptr. Fix substitution of
+ templated types.
+ (demangle_function_type): Change parameter to a pointer.
+ (demangle_bare_function_type): Likewise. Adjust insertion point.
+ (demangle_template_param): Remove last parameter.
+ (demangle_expr_primary): Remove unused variable. Adjust call to
+ demangle_template_param.
+ (is_mangled_char): Accept `$' and `.'.
+ * cplus-dem.c (gnu_new_abi_symbol_characters): Add '$' and '.'.
+ * dyn-string.c (dyn_string_insert_char): New function.
+
+2000-10-11 Richard Henderson <rth@cygnus.com>
+
+ * Makefile.in (md5.o): Depend on config.h.
+
+2000-10-11 Alex Samuel <samuel@codesourcery.com>
+
+ * cp-demangle.c (demangle_name): Initialize template_p in local
+ name case. Don't re-add substitutions as candidates.
+ (demangle_nested_name): Use <unqualified-name>.
+ (demangle_prefix): Likewise. Don't add template names as
+ substitution candidates twice, or re-add a substitution or the
+ last prefix component.
+ (demangle_local_name): Adjust output format.
+
+2000-10-11 Alex Samuel <samuel@codesourcery.com>
+
+ * cp-demangle.c (result_add_separated_char): Change parameter to
+ int.
+ (substitution_add): Don't check for duplicates. Check if
+ previously allocated size is zero.
+ (demangle_name): Remove duplicate check for std substitution.
+ Clear template flag appropriately.
+ (demangle_prefix): Remove argument to demangle_substitution.
+ Don't check that template flag is already set.
+ (demangle_operator_name): Add pt operator.
+ (demangle_type): Don't treat r as built-in type. Remove argument
+ to demangle_substitution. Fix substitution candidate mechanics.
+ Handle <template-template-parm>s. Improve comments.
+ (demangle_template_param): Don't handle template arg lists here.
+ (demangle_substitution): Remove parameter.
+ (print_usage): Remove extra fprintf option.
+
+2000-10-11 Greg McGary <greg@mcgary.org>
+
+ * libiberty/random.c (end_ptr): Revert previous change.
+
+2000-10-11 Greg McGary <greg@mcgary.org>
+
+ * libiberty/cplus-dem.c (cplus_demangle_opname, cplus_mangle_opname,
+ demangle_expression, demangle_function_name): Use ARRAY_SIZE.
+ * libiberty/random.c (end_ptr): Likewise.
+
+2000-10-11 Alex Samuel <samuel@codesourcery.com>
+
+ * cp-demangle.c (result_close_template_list): Remove function.
+ (result_add_separated_char): New function.
+ (result_open_template_list): New macro.
+ (result_close_template_list): Likewise.
+ (demangle_prefix): Don't set template_p if the
+ prefix ends with a ctor name.
+ (demangle_type_ptr): Remove duplicate RETURN_IF_ERROR.
+ (demangle_type): Check for template args after substitution.
+ (demangle_template_args): Use result_open_template_list.
+
+2000-10-11 Zack Weinberg <zack@wolery.cumb.org>
+
+ * pexecute.c: Don't use vfork. Initialize 'pid' before retry loop.
+
+2000-10-11 RodneyBrown <RodneyBrown@pmsc.com>
+
+ Jeff Law <law@cygnus.com>
+ * getcwd.c: Include string.h, stdlib.h for prototypes
+ * Makefile.in (rename.o, waitpid.o): Depend on config.h
+ * rename.c: Include config.h, unistd.h
+ * waitpid.c: Include config.h, sys/wait.h
+
+2000-10-11 Alex Samuel <samuel@codesourcery.com>
+
+ * cp-demangle.c (demangle_ctor_dtor_name): Remove not-in-charge
+ allocating ctor mangling.
+ (demangle_array_type): Handle empty and non-constant array length.
+
+2000-10-11 Mike Stump <mrs@wrs.com>
+
+ * Makefile.in (xexit.o): Add dependency for config.h in xexit.c.
+ * (vasprintf.o): Add dependency for config.h in vasprintf.c.
+
+2000-10-11 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * cp-demangle.c (cp_demangle_type): Wrap in IN_LIBGCC2.
+ * setenv.c (setenv): Initialize variable `ep'.
+ * sigsetmask.c (abort): Prototype.
+ * vasprintf.c: Include config.h. Check ANSI_PROTOTYPES, not
+ __STDC__ for stdarg.h include.
+ (int_vasprintf): Prototype.
+ (checkit): Prototype. Use VPARAMS/ANSI_PROTOTYPES/VA_START in
+ definition. Cast `global_total_width' in comparison.
+ (main): Prototype. Return a value.
+ * vfork.c (fork): Prototype.
+ * xexit.c: Include config.h.
+
2000-09-25 Michael Sokolov <msokolov@ivan.Harhan.ORG>
* md5.c: #include "ansidecl.h".
diff --git a/libiberty/Makefile.in b/libiberty/Makefile.in
index 58c07c4..62a97dc 100644
--- a/libiberty/Makefile.in
+++ b/libiberty/Makefile.in
@@ -276,6 +276,7 @@ getruntime.o: config.h $(INCDIR)/libiberty.h
hex.o: $(INCDIR)/libiberty.h
floatformat.o: $(INCDIR)/floatformat.h
mkstemps.o: config.h
+md5.o: config.h
objalloc.o: config.h $(INCDIR)/objalloc.h
obstack.o: config.h $(INCDIR)/obstack.h
partition.o: config.h $(INCDIR)/partition.h
@@ -289,8 +290,9 @@ strerror.o: config.h $(INCDIR)/libiberty.h
strsignal.o: config.h $(INCDIR)/libiberty.h
strtol.o: config.h
strtoul.o: config.h
+vasprintf.o: config.h
xatexit.o: $(INCDIR)/libiberty.h
-xexit.o: $(INCDIR)/libiberty.h
+xexit.o: config.h $(INCDIR)/libiberty.h
xmalloc.o: config.h $(INCDIR)/libiberty.h
xmemdup.o: config.h $(INCDIR)/libiberty.h
xstrdup.o: config.h $(INCDIR)/libiberty.h
diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index 1eb2402..e543edf 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -1,7 +1,9 @@
/* Demangler for IA64 / g++ standard C++ ABI.
- Copyright (C) 2000 CodeSourcery LLC.
+ Copyright (C) 2000 Free Software Foundation, Inc.
Written by Alex Samuel <samuel@codesourcery.com>.
+ This file is part of GNU CC.
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
@@ -21,7 +23,8 @@
the IA64 / g++ standard C++ ABI. Use the cp_demangle function to
demangle a mangled name, or compile with the preprocessor macro
STANDALONE_DEMANGLER defined to create a demangling filter
- executable. */
+ executable (functionally similar to c++filt, but includes this
+ demangler only). */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -61,6 +64,10 @@
(((CHAR) >= 'a' && (CHAR) <= 'z') \
|| ((CHAR) >= 'A' && (CHAR) <= 'Z'))
+/* The prefix prepended by GCC to an identifier represnting the
+ anonymous namespace. */
+#define ANONYMOUS_NAMESPACE_PREFIX "_GLOBAL_"
+
/* If flag_verbose is zero, some simplifications will be made to the
output to make it easier to read and supress details that are
generally not of interest to the average C++ programmer.
@@ -91,17 +98,10 @@ struct substitution_def
/* The demangled text of the substitution. */
dyn_string_t text;
- /* The template parameter that this represents, indexed from zero.
- If this is not a template paramter number, the value is
- NOT_TEMPLATE_PARM. */
- int template_parm_number;
-
/* Whether this substitution represents a template item. */
int template_p : 1;
};
-#define NOT_TEMPLATE_PARM (-1)
-
/* Data structure representing a template argument list. */
struct template_arg_list_def
@@ -172,7 +172,7 @@ typedef const char *status_t;
#define STATUS_INTERNAL_ERROR "Internal error."
/* This status code indicates a failure in malloc or realloc. */
-static const char* const status_allocation_failed = "Allocation failed.";
+static const char *const status_allocation_failed = "Allocation failed.";
#define STATUS_ALLOCATION_FAILED status_allocation_failed
/* Non-zero if STATUS indicates that no error has occurred. */
@@ -196,8 +196,8 @@ static string_list_t string_list_new
PARAMS ((int));
static void string_list_delete
PARAMS ((string_list_t));
-static status_t result_close_template_list
- PARAMS ((demangling_t));
+static status_t result_add_separated_char
+ PARAMS ((demangling_t, int));
static status_t result_push
PARAMS ((demangling_t));
static string_list_t result_pop
@@ -205,7 +205,7 @@ static string_list_t result_pop
static int substitution_start
PARAMS ((demangling_t));
static status_t substitution_add
- PARAMS ((demangling_t, int, int, int));
+ PARAMS ((demangling_t, int, int));
static dyn_string_t substitution_get
PARAMS ((demangling_t, int, int *));
#ifdef CP_DEMANGLE_DEBUG
@@ -287,6 +287,22 @@ static void demangling_delete
(dyn_string_append_char (&(DM)->result->string, (CHAR)) \
? STATUS_OK : STATUS_ALLOCATION_FAILED)
+/* Inserts a dyn_string_t to the demangled result at position POS. */
+#define result_insert_string(DM, POS, STRING) \
+ (dyn_string_insert (&(DM)->result->string, (POS), (STRING)) \
+ ? STATUS_OK : STATUS_ALLOCATION_FAILED)
+
+/* Inserts NUL-terminated string CSTR to the demangled result at
+ position POS. */
+#define result_insert(DM, POS, CSTR) \
+ (dyn_string_insert_cstr (&(DM)->result->string, (POS), (CSTR)) \
+ ? STATUS_OK : STATUS_ALLOCATION_FAILED)
+
+/* Inserts character CHAR to the demangled result at position POS. */
+#define result_insert_char(DM, POS, CHAR) \
+ (dyn_string_insert_char (&(DM)->result->string, (POS), (CHAR)) \
+ ? STATUS_OK : STATUS_ALLOCATION_FAILED)
+
/* The length of the current demangled result. */
#define result_length(DM) \
dyn_string_length (&(DM)->result->string)
@@ -297,6 +313,13 @@ static void demangling_delete
(dyn_string_append_space (&(DM)->result->string) \
? STATUS_OK : STATUS_ALLOCATION_FAILED)
+/* Appends a (less-than, greater-than) character to the result in DM
+ to (open, close) a template argument or parameter list. Appends a
+ space first if necessary to prevent spurious elision of angle
+ brackets with the previous character. */
+#define result_open_template_list(DM) result_add_separated_char(DM, '<')
+#define result_close_template_list(DM) result_add_separated_char(DM, '>')
+
/* Appends a base 10 representation of VALUE to DS. STATUS_OK on
success. On failure, deletes DS and returns an error code. */
@@ -378,28 +401,27 @@ string_list_delete (node)
}
}
-/* Appends a greater-than character to the demangled result. If the
- last character is a greater-than character, a space is inserted
- first, so that the two greater-than characters don't look like a
- right shift token. */
+/* Appends CHARACTER to the demangled result. If the current trailing
+ character of the result is CHARACTER, a space is inserted first. */
static status_t
-result_close_template_list (dm)
+result_add_separated_char (dm, character)
demangling_t dm;
+ int character;
{
dyn_string_t s = &dm->result->string;
/* Add a space if the last character is already a closing angle
bracket, so that a nested template arg list doesn't look like
it's closed with a right-shift operator. */
- if (dyn_string_last_char (s) == '>')
+ if (dyn_string_last_char (s) == character)
{
if (!dyn_string_append_char (s, ' '))
return STATUS_ALLOCATION_FAILED;
}
/* Add closing angle brackets. */
- if (!dyn_string_append_char (s, '>'))
+ if (!dyn_string_append_char (s, character))
return STATUS_ALLOCATION_FAILED;
return STATUS_OK;
@@ -451,19 +473,13 @@ substitution_start (dm)
/* Adds the suffix of the current demangled result of DM starting at
START_POSITION as a potential substitution. If TEMPLATE_P is
- non-zero, this potential substitution is a template-id.
-
- If TEMPLATE_PARM_NUMBER is not NOT_TEMPLATE_PARM, the substitution
- is for that particular <template-param>, and is distinct from other
- otherwise-identical types and other <template-param>s with
- different indices. */
+ non-zero, this potential substitution is a template-id. */
static status_t
-substitution_add (dm, start_position, template_p, template_parm_number)
+substitution_add (dm, start_position, template_p)
demangling_t dm;
int start_position;
int template_p;
- int template_parm_number;
{
dyn_string_t result = result_string (dm);
dyn_string_t substitution = dyn_string_new (0);
@@ -481,23 +497,14 @@ substitution_add (dm, start_position, template_p, template_parm_number)
return STATUS_ALLOCATION_FAILED;
}
- /* Check whether SUBSTITUTION already occurs. */
- for (i = 0; i < dm->num_substitutions; ++i)
- if (dyn_string_eq (dm->substitutions[i].text, substitution)
- && dm->substitutions[i].template_parm_number == template_parm_number)
- /* Found SUBSTITUTION already present. */
- {
- /* Callers expect this function to take ownership of
- SUBSTITUTION, so delete it. */
- dyn_string_delete (substitution);
- return STATUS_OK;
- }
-
/* If there's no room for the new entry, grow the array. */
if (dm->substitutions_allocated == dm->num_substitutions)
{
size_t new_array_size;
- dm->substitutions_allocated *= 2;
+ if (dm->substitutions_allocated > 0)
+ dm->substitutions_allocated *= 2;
+ else
+ dm->substitutions_allocated = 2;
new_array_size =
sizeof (struct substitution_def) * dm->substitutions_allocated;
@@ -512,10 +519,9 @@ substitution_add (dm, start_position, template_p, template_parm_number)
}
/* Add the substitution to the array. */
+ i = dm->num_substitutions++;
dm->substitutions[i].text = substitution;
dm->substitutions[i].template_p = template_p;
- dm->substitutions[i].template_parm_number = template_parm_number;
- ++dm->num_substitutions;
#ifdef CP_DEMANGLE_DEBUG
substitutions_print (dm, stderr);
@@ -801,7 +807,7 @@ static status_t demangle_nested_name
static status_t demangle_prefix
PARAMS ((demangling_t, int *));
static status_t demangle_unqualified_name
- PARAMS ((demangling_t));
+ PARAMS ((demangling_t, int *));
static status_t demangle_source_name
PARAMS ((demangling_t));
static status_t demangle_number
@@ -812,12 +818,18 @@ static status_t demangle_identifier
PARAMS ((demangling_t, int, dyn_string_t));
static status_t demangle_operator_name
PARAMS ((demangling_t, int, int *));
+static status_t demangle_nv_offset
+ PARAMS ((demangling_t));
+static status_t demangle_v_offset
+ PARAMS ((demangling_t));
+static status_t demangle_call_offset
+ PARAMS ((demangling_t));
static status_t demangle_special_name
PARAMS ((demangling_t));
static status_t demangle_ctor_dtor_name
PARAMS ((demangling_t));
static status_t demangle_type_ptr
- PARAMS ((demangling_t));
+ PARAMS ((demangling_t, int *, int));
static status_t demangle_type
PARAMS ((demangling_t));
static status_t demangle_CV_qualifiers
@@ -825,15 +837,15 @@ static status_t demangle_CV_qualifiers
static status_t demangle_builtin_type
PARAMS ((demangling_t));
static status_t demangle_function_type
- PARAMS ((demangling_t, int));
+ PARAMS ((demangling_t, int *));
static status_t demangle_bare_function_type
- PARAMS ((demangling_t, int));
+ PARAMS ((demangling_t, int *));
static status_t demangle_class_enum_type
PARAMS ((demangling_t, int *));
static status_t demangle_array_type
PARAMS ((demangling_t));
static status_t demangle_template_param
- PARAMS ((demangling_t, int *));
+ PARAMS ((demangling_t));
static status_t demangle_template_args
PARAMS ((demangling_t));
static status_t demangle_literal
@@ -847,19 +859,21 @@ static status_t demangle_scope_expression
static status_t demangle_expr_primary
PARAMS ((demangling_t));
static status_t demangle_substitution
- PARAMS ((demangling_t, int *, int *));
+ PARAMS ((demangling_t, int *));
static status_t demangle_local_name
PARAMS ((demangling_t));
static status_t demangle_discriminator
PARAMS ((demangling_t, int));
static status_t cp_demangle
PARAMS ((const char *, dyn_string_t));
+#ifdef IN_LIBGCC2
static status_t cp_demangle_type
PARAMS ((const char*, dyn_string_t));
+#endif
/* When passed to demangle_bare_function_type, indicates that the
function's return type is not encoded before its parameter types. */
-#define BFT_NO_RETURN_TYPE -1
+#define BFT_NO_RETURN_TYPE NULL
/* Check that the next character is C. If so, consume it. If not,
return an error. */
@@ -910,7 +924,7 @@ static status_t
demangle_encoding (dm)
demangling_t dm;
{
- int template_p;
+ int encode_return_type;
int start_position;
template_arg_list_t old_arg_list = current_template_arg_list (dm);
char peek = peek_char (dm);
@@ -926,18 +940,18 @@ demangle_encoding (dm)
else
{
/* Now demangle the name. */
- RETURN_IF_ERROR (demangle_name (dm, &template_p));
+ RETURN_IF_ERROR (demangle_name (dm, &encode_return_type));
/* If there's anything left, the name was a function name, with
maybe its return type, and its parameters types, following. */
if (!end_of_name_p (dm)
&& peek_char (dm) != 'E')
{
- if (template_p)
+ if (encode_return_type)
/* Template functions have their return type encoded. The
return type should be inserted at start_position. */
RETURN_IF_ERROR
- (demangle_bare_function_type (dm, start_position));
+ (demangle_bare_function_type (dm, &start_position));
else
/* Non-template functions don't have their return type
encoded. */
@@ -968,24 +982,32 @@ demangle_encoding (dm)
::= <substitution> */
static status_t
-demangle_name (dm, template_p)
+demangle_name (dm, encode_return_type)
demangling_t dm;
- int *template_p;
+ int *encode_return_type;
{
- int special_std_substitution;
int start = substitution_start (dm);
+ char peek = peek_char (dm);
+ int is_std_substitution = 0;
+
+ /* Generally, the return type is encoded if the function is a
+ template-id, and suppressed otherwise. There are a few cases,
+ though, in which the return type is not encoded even for a
+ templated function. In these cases, this flag is set. */
+ int suppress_return_type = 0;
DEMANGLE_TRACE ("name", dm);
- switch (peek_char (dm))
+ switch (peek)
{
case 'N':
/* This is a <nested-name>. */
- RETURN_IF_ERROR (demangle_nested_name (dm, template_p));
+ RETURN_IF_ERROR (demangle_nested_name (dm, encode_return_type));
break;
case 'Z':
RETURN_IF_ERROR (demangle_local_name (dm));
+ *encode_return_type = 0;
break;
case 'S':
@@ -996,48 +1018,45 @@ demangle_name (dm, template_p)
(void) next_char (dm);
(void) next_char (dm);
RETURN_IF_ERROR (result_append (dm, "std::"));
- RETURN_IF_ERROR (demangle_unqualified_name (dm));
+ RETURN_IF_ERROR
+ (demangle_unqualified_name (dm, &suppress_return_type));
+ is_std_substitution = 1;
}
else
- {
- RETURN_IF_ERROR (demangle_substitution (dm, template_p,
- &special_std_substitution));
- if (special_std_substitution)
- {
- /* This was the magic `std::' substitution. We can have
- a <nested-name> or one of the unscoped names
- following. */
- RETURN_IF_ERROR (result_append (dm, "::"));
- RETURN_IF_ERROR (demangle_name (dm, template_p));
- }
- }
+ RETURN_IF_ERROR (demangle_substitution (dm, encode_return_type));
/* Check if a template argument list immediately follows.
If so, then we just demangled an <unqualified-template-name>. */
if (peek_char (dm) == 'I')
{
- RETURN_IF_ERROR (substitution_add (dm, start, 0,
- NOT_TEMPLATE_PARM));
+ /* A template name of the form std::<unqualified-name> is a
+ substitution candidate. */
+ if (is_std_substitution)
+ RETURN_IF_ERROR (substitution_add (dm, start, 0));
+ /* Demangle the <template-args> here. */
RETURN_IF_ERROR (demangle_template_args (dm));
+ *encode_return_type = !suppress_return_type;
}
+ else
+ *encode_return_type = 0;
+
break;
default:
/* This is an <unscoped-name> or <unscoped-template-name>. */
- RETURN_IF_ERROR (demangle_unqualified_name (dm));
+ RETURN_IF_ERROR (demangle_unqualified_name (dm, &suppress_return_type));
/* If the <unqualified-name> is followed by template args, this
is an <unscoped-template-name>. */
if (peek_char (dm) == 'I')
{
/* Add a substitution for the unqualified template name. */
- RETURN_IF_ERROR (substitution_add (dm, start, 0,
- NOT_TEMPLATE_PARM));
+ RETURN_IF_ERROR (substitution_add (dm, start, 0));
RETURN_IF_ERROR (demangle_template_args (dm));
- *template_p = 1;
+ *encode_return_type = !suppress_return_type;
}
else
- *template_p = 0;
+ *encode_return_type = 0;
break;
}
@@ -1047,12 +1066,12 @@ demangle_name (dm, template_p)
/* Demangles and emits a <nested-name>.
- <nested-name> ::= N [<CV-qualifiers>] <prefix> <component> E */
+ <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqulified-name> E */
static status_t
-demangle_nested_name (dm, template_p)
+demangle_nested_name (dm, encode_return_type)
demangling_t dm;
- int *template_p;
+ int *encode_return_type;
{
char peek;
@@ -1077,9 +1096,9 @@ demangle_nested_name (dm, template_p)
RETURN_IF_ERROR (result_append_space (dm));
}
- RETURN_IF_ERROR (demangle_prefix (dm, template_p));
- /* No need to demangle the final <component>; demangle_prefix will
- handle it. */
+ RETURN_IF_ERROR (demangle_prefix (dm, encode_return_type));
+ /* No need to demangle the final <unqualified-name>; demangle_prefix
+ will handle it. */
RETURN_IF_ERROR (demangle_char (dm, 'E'));
return STATUS_OK;
@@ -1087,41 +1106,52 @@ demangle_nested_name (dm, template_p)
/* Demangles and emits a <prefix>.
- <prefix> ::= <prefix> <component>
+ <prefix> ::= <prefix> <unqualified-name>
::= <template-prefix> <template-args>
::= # empty
::= <substitution>
<template-prefix> ::= <prefix>
- ::= <substitution>
-
- <component> ::= <unqualified-name>
- ::= <local-name> */
+ ::= <substitution> */
static status_t
-demangle_prefix (dm, template_p)
+demangle_prefix (dm, encode_return_type)
demangling_t dm;
- int *template_p;
+ int *encode_return_type;
{
int start = substitution_start (dm);
int nested = 0;
- /* TEMPLATE_P is updated as we decend the nesting chain. After
- <template-args>, it is set to non-zero; after everything else it
- is set to zero. */
+ /* ENCODE_RETURN_TYPE is updated as we decend the nesting chain.
+ After <template-args>, it is set to non-zero; after everything
+ else it is set to zero. */
+
+ /* Generally, the return type is encoded if the function is a
+ template-id, and suppressed otherwise. There are a few cases,
+ though, in which the return type is not encoded even for a
+ templated function. In these cases, this flag is set. */
+ int suppress_return_type = 0;
DEMANGLE_TRACE ("prefix", dm);
while (1)
{
char peek;
- int unused;
if (end_of_name_p (dm))
return "Unexpected end of name in <compound-name>.";
peek = peek_char (dm);
+ /* We'll initialize suppress_return_type to false, and set it to true
+ if we end up demangling a constructor name. However, make
+ sure we're not actually about to demangle template arguments
+ -- if so, this is the <template-args> following a
+ <template-prefix>, so we'll want the previous flag value
+ around. */
+ if (peek != 'I')
+ suppress_return_type = 0;
+
if (IS_DIGIT ((unsigned char) peek)
|| (peek >= 'a' && peek <= 'z')
|| peek == 'C' || peek == 'D'
@@ -1135,25 +1165,30 @@ demangle_prefix (dm, template_p)
if (peek == 'S')
/* The substitution determines whether this is a
- template-id. */
- RETURN_IF_ERROR (demangle_substitution (dm, template_p,
- &unused));
+ template-id. */
+ RETURN_IF_ERROR (demangle_substitution (dm, encode_return_type));
else
{
- RETURN_IF_ERROR (demangle_unqualified_name (dm));
- *template_p = 0;
+ /* It's just a name. */
+ RETURN_IF_ERROR
+ (demangle_unqualified_name (dm, &suppress_return_type));
+ *encode_return_type = 0;
}
}
else if (peek == 'Z')
RETURN_IF_ERROR (demangle_local_name (dm));
else if (peek == 'I')
{
- if (*template_p)
- return STATUS_INTERNAL_ERROR;
- /* The template name is a substitution candidate. */
- RETURN_IF_ERROR (substitution_add (dm, start, 0, NOT_TEMPLATE_PARM));
RETURN_IF_ERROR (demangle_template_args (dm));
- *template_p = 1;
+
+ /* Now we want to indicate to the caller that we've
+ demangled template arguments, thus the prefix was a
+ <template-prefix>. That's so that the caller knows to
+ demangle the function's return type, if this turns out to
+ be a function name. But, if it's a member template
+ constructor or a templated conversion operator, report it
+ as untemplated. Those never get encoded return types. */
+ *encode_return_type = !suppress_return_type;
}
else if (peek == 'E')
/* All done. */
@@ -1161,38 +1196,56 @@ demangle_prefix (dm, template_p)
else
return "Unexpected character in <compound-name>.";
- /* Add a new substitution for the prefix thus far. */
- RETURN_IF_ERROR (substitution_add (dm, start, *template_p,
- NOT_TEMPLATE_PARM));
+ if (peek != 'S'
+ && peek_char (dm) != 'E')
+ /* Add a new substitution for the prefix thus far. */
+ RETURN_IF_ERROR (substitution_add (dm, start, *encode_return_type));
}
}
-/* Demangles and emits an <unqualified-name>. If the
- <unqualified-name> is a function and the first element in the
- argument list should be taken to be its return type,
- ENCODE_RETURN_TYPE is non-zero.
+/* Demangles and emits an <unqualified-name>. If this
+ <unqualified-name> is for a special function type that should never
+ have its return type encoded (particularly, a constructor or
+ conversion operator), *SUPPRESS_RETURN_TYPE is set to 1; otherwise,
+ it is set to zero.
<unqualified-name> ::= <operator-name>
::= <special-name>
::= <source-name> */
static status_t
-demangle_unqualified_name (dm)
+demangle_unqualified_name (dm, suppress_return_type)
demangling_t dm;
+ int *suppress_return_type;
{
char peek = peek_char (dm);
DEMANGLE_TRACE ("unqualified-name", dm);
+ /* By default, don't force suppression of the return type (though
+ non-template functions still don't get a return type encoded). */
+ *suppress_return_type = 0;
+
if (IS_DIGIT ((unsigned char) peek))
RETURN_IF_ERROR (demangle_source_name (dm));
else if (peek >= 'a' && peek <= 'z')
{
int num_args;
+
+ /* Conversion operators never have a return type encoded. */
+ if (peek == 'c' && peek_char_next (dm) == 'v')
+ *suppress_return_type = 1;
+
RETURN_IF_ERROR (demangle_operator_name (dm, 0, &num_args));
}
else if (peek == 'C' || peek == 'D')
- RETURN_IF_ERROR (demangle_ctor_dtor_name (dm));
+ {
+ /* Constructors never have a return type encoded. */
+ if (peek == 'C')
+ *suppress_return_type = 1;
+
+ RETURN_IF_ERROR (demangle_ctor_dtor_name (dm));
+ }
else
return "Unexpected character in <unqualified-name>.";
@@ -1330,6 +1383,29 @@ demangle_identifier (dm, length, identifier)
return STATUS_ALLOCATION_FAILED;
}
+ /* GCC encodes anonymous namespaces using a `_GLOBAL_[_.$]N.'
+ followed by the source file name and some random characters.
+ Unless we're in strict mode, decipher these names appropriately. */
+ if (!flag_strict)
+ {
+ char *name = dyn_string_buf (identifier);
+ int prefix_length = strlen (ANONYMOUS_NAMESPACE_PREFIX);
+
+ /* Compare the first, fixed part. */
+ if (strncmp (name, ANONYMOUS_NAMESPACE_PREFIX, prefix_length) == 0)
+ {
+ name += prefix_length;
+ /* The next character might be a period, an underscore, or
+ dollar sign, depending on the target architecture's
+ assembler's capabilities. After that comes an `N'. */
+ if ((*name == '.' || *name == '_' || *name == '$')
+ && *(name + 1) == 'N')
+ /* This looks like the anonymous namespace identifier.
+ Replace it with something comprehensible. */
+ dyn_string_copy_cstr (identifier, "(anonymous namespace)");
+ }
+ }
+
return STATUS_OK;
}
@@ -1388,7 +1464,7 @@ demangle_identifier (dm, length, identifier)
::= qu # ?
::= sz # sizeof
::= cv <type> # cast
- ::= vx <source-name> # vendor extended operator */
+ ::= v [0-9] <source-name> # vendor extended operator */
static status_t
demangle_operator_name (dm, short_name, num_args)
@@ -1449,6 +1525,7 @@ demangle_operator_name (dm, short_name, num_args)
{ "pm", "->*" , 2 },
{ "pp", "++" , 1 },
{ "ps", "+" , 1 },
+ { "pt", "->" , 2 },
{ "qu", "?" , 3 },
{ "rM", "%=" , 2 },
{ "rS", ">>=" , 2 },
@@ -1467,10 +1544,10 @@ demangle_operator_name (dm, short_name, num_args)
DEMANGLE_TRACE ("operator-name", dm);
- /* Is this a vendor extended operator? */
- if (c0 == 'v' && c1 == 'x')
+ /* Is this a vendor-extended operator? */
+ if (c0 == 'v' && IS_DIGIT (c1))
{
- RETURN_IF_ERROR (result_append (dm, "operator"));
+ RETURN_IF_ERROR (result_append (dm, "operator "));
RETURN_IF_ERROR (demangle_source_name (dm));
*num_args = 0;
return STATUS_OK;
@@ -1516,22 +1593,157 @@ demangle_operator_name (dm, short_name, num_args)
}
}
+/* Demangles and omits an <nv-offset>.
+
+ <nv-offset> ::= <offset number> # non-virtual base override */
+
+static status_t
+demangle_nv_offset (dm)
+ demangling_t dm;
+{
+ dyn_string_t number;
+ status_t status = STATUS_OK;
+
+ DEMANGLE_TRACE ("h-offset", dm);
+
+ /* Demangle the offset. */
+ number = dyn_string_new (4);
+ if (number == NULL)
+ return STATUS_ALLOCATION_FAILED;
+ demangle_number_literally (dm, number, 10, 1);
+
+ /* Don't display the offset unless in verbose mode. */
+ if (flag_verbose)
+ {
+ status = result_append (dm, " [nv:");
+ if (STATUS_NO_ERROR (status))
+ status = result_append_string (dm, number);
+ if (STATUS_NO_ERROR (status))
+ status = result_append_char (dm, ']');
+ }
+
+ /* Clean up. */
+ dyn_string_delete (number);
+ RETURN_IF_ERROR (status);
+ return STATUS_OK;
+}
+
+/* Demangles and emits a <v-offset>.
+
+ <v-offset> ::= <offset number> _ <virtual offset number>
+ # virtual base override, with vcall offset */
+
+static status_t
+demangle_v_offset (dm)
+ demangling_t dm;
+{
+ dyn_string_t number;
+ status_t status = STATUS_OK;
+
+ DEMANGLE_TRACE ("v-offset", dm);
+
+ /* Demangle the offset. */
+ number = dyn_string_new (4);
+ if (number == NULL)
+ return STATUS_ALLOCATION_FAILED;
+ demangle_number_literally (dm, number, 10, 1);
+
+ /* Don't display the offset unless in verbose mode. */
+ if (flag_verbose)
+ {
+ status = result_append (dm, " [v:");
+ if (STATUS_NO_ERROR (status))
+ status = result_append_string (dm, number);
+ if (STATUS_NO_ERROR (status))
+ result_append_char (dm, ',');
+ }
+ dyn_string_delete (number);
+ RETURN_IF_ERROR (status);
+
+ /* Demangle the separator. */
+ RETURN_IF_ERROR (demangle_char (dm, '_'));
+
+ /* Demangle the vcall offset. */
+ number = dyn_string_new (4);
+ if (number == NULL)
+ return STATUS_ALLOCATION_FAILED;
+ demangle_number_literally (dm, number, 10, 1);
+
+ /* Don't display the vcall offset unless in verbose mode. */
+ if (flag_verbose)
+ {
+ status = result_append_string (dm, number);
+ if (STATUS_NO_ERROR (status))
+ status = result_append_char (dm, ']');
+ }
+ dyn_string_delete (number);
+ RETURN_IF_ERROR (status);
+
+ return STATUS_OK;
+}
+
+/* Demangles and emits a <call-offset>.
+
+ <call-offset> ::= h <nv-offset> _
+ ::= v <v-offset> _ */
+
+static status_t
+demangle_call_offset (dm)
+ demangling_t dm;
+{
+ DEMANGLE_TRACE ("call-offset", dm);
+
+ switch (peek_char (dm))
+ {
+ case 'h':
+ advance_char (dm);
+ /* Demangle the offset. */
+ RETURN_IF_ERROR (demangle_nv_offset (dm));
+ /* Demangle the separator. */
+ RETURN_IF_ERROR (demangle_char (dm, '_'));
+ break;
+
+ case 'v':
+ advance_char (dm);
+ /* Demangle the offset. */
+ RETURN_IF_ERROR (demangle_v_offset (dm));
+ /* Demangle the separator. */
+ RETURN_IF_ERROR (demangle_char (dm, '_'));
+ break;
+
+ default:
+ return "Unrecognized <call-offset>.";
+ }
+
+ return STATUS_OK;
+}
+
/* Demangles and emits a <special-name>.
<special-name> ::= GV <object name> # Guard variable
- ::= Th[n] <offset number> _ <base name> <base encoding>
- # non-virtual base override thunk
- ::= Tv[n] <offset number> _ <vcall offset number>
- _ <base encoding>
- # virtual base override thunk
::= TV <type> # virtual table
::= TT <type> # VTT
::= TI <type> # typeinfo structure
::= TS <type> # typeinfo name
+ Other relevant productions include thunks:
+
+ <special-name> ::= T <call-offset> <base encoding>
+ # base is the nominal target function of thunk
+
+ <special-name> ::= Tc <call-offset> <call-offset> <base encoding>
+ # base is the nominal target function of thunk
+ # first call-offset is 'this' adjustment
+ # second call-offset is result adjustment
+
+ where
+
+ <call-offset> ::= h <nv-offset> _
+ ::= v <v-offset> _
+
Also demangles the special g++ manglings,
- <special-name> ::= CT <type> <offset number> _ <base type>
+ <special-name> ::= TC <type> <offset number> _ <base type>
# construction vtable
::= TF <type> # typeinfo function (old ABI only)
::= TJ <type> # java Class structure */
@@ -1609,20 +1821,7 @@ demangle_special_name (dm)
/* Non-virtual thunk. */
advance_char (dm);
RETURN_IF_ERROR (result_append (dm, "non-virtual thunk"));
- /* Demangle and emit the offset. */
- number = dyn_string_new (4);
- if (number == NULL)
- return STATUS_ALLOCATION_FAILED;
- demangle_number_literally (dm, number, 10, 1);
- /* Don't display the offset unless in verbose mode. */
- if (flag_verbose)
- {
- status = result_append_char (dm, ' ');
- if (STATUS_NO_ERROR (status))
- status = result_append_string (dm, number);
- }
- dyn_string_delete (number);
- RETURN_IF_ERROR (status);
+ RETURN_IF_ERROR (demangle_nv_offset (dm));
/* Demangle the separator. */
RETURN_IF_ERROR (demangle_char (dm, '_'));
/* Demangle and emit the target name and function type. */
@@ -1633,41 +1832,23 @@ demangle_special_name (dm)
case 'v':
/* Virtual thunk. */
advance_char (dm);
- RETURN_IF_ERROR (result_append (dm, "virtual thunk "));
- /* Demangle and emit the offset. */
- number = dyn_string_new (4);
- if (number == NULL)
- return STATUS_ALLOCATION_FAILED;
- demangle_number_literally (dm, number, 10, 1);
- /* Don't display the offset unless in verbose mode. */
- if (flag_verbose)
- {
- status = result_append_string (dm, number);
- if (STATUS_NO_ERROR (status))
- result_append_char (dm, ' ');
- }
- dyn_string_delete (number);
- RETURN_IF_ERROR (status);
- /* Demangle the separator. */
- RETURN_IF_ERROR (demangle_char (dm, '_'));
- /* Demangle and emit the vcall offset. */
- number = dyn_string_new (4);
- if (number == NULL)
- return STATUS_ALLOCATION_FAILED;
- demangle_number_literally (dm, number, 10, 1);
- /* Don't display the vcall offset unless in verbose mode. */
- if (flag_verbose)
- {
- status = result_append_string (dm, number);
- if (STATUS_NO_ERROR (status))
- status = result_append_char (dm, ' ');
- }
- dyn_string_delete (number);
- RETURN_IF_ERROR (status);
+ RETURN_IF_ERROR (result_append (dm, "virtual thunk"));
+ RETURN_IF_ERROR (demangle_v_offset (dm));
/* Demangle the separator. */
RETURN_IF_ERROR (demangle_char (dm, '_'));
/* Demangle and emit the target function. */
- RETURN_IF_ERROR (result_append (dm, "to "));
+ RETURN_IF_ERROR (result_append (dm, " to "));
+ RETURN_IF_ERROR (demangle_encoding (dm));
+ break;
+
+ case 'c':
+ /* Covariant return thunk. */
+ advance_char (dm);
+ RETURN_IF_ERROR (result_append (dm, "covariant return thunk"));
+ RETURN_IF_ERROR (demangle_call_offset (dm));
+ RETURN_IF_ERROR (demangle_call_offset (dm));
+ /* Demangle and emit the target function. */
+ RETURN_IF_ERROR (result_append (dm, " to "));
RETURN_IF_ERROR (demangle_encoding (dm));
break;
@@ -1736,7 +1917,6 @@ demangle_special_name (dm)
::= C1 # complete object (in-charge) ctor
::= C2 # base object (not-in-charge) ctor
::= C3 # complete object (in-charge) allocating ctor
- ::= C4 # base object (not-in-charge) allocating ctor
::= D0 # deleting (in-charge) dtor
::= D1 # complete object (in-charge) dtor
::= D2 # base object (not-in-charge) dtor */
@@ -1749,8 +1929,7 @@ demangle_ctor_dtor_name (dm)
{
"in-charge",
"not-in-charge",
- "in-charge allocating",
- "not-in-charge allocating"
+ "allocating"
};
static const char *const dtor_flavors[] =
{
@@ -1768,7 +1947,7 @@ demangle_ctor_dtor_name (dm)
{
/* A constructor name. Consume the C. */
advance_char (dm);
- if (peek_char (dm) < '1' || peek_char (dm) > '4')
+ if (peek_char (dm) < '1' || peek_char (dm) > '3')
return "Unrecognized constructor.";
RETURN_IF_ERROR (result_append_string (dm, dm->last_source_name));
/* Print the flavor of the constructor if in verbose mode. */
@@ -1810,6 +1989,19 @@ demangle_ctor_dtor_name (dm)
a pointer to data or pointer to function to construct the right
output syntax. C++'s pointer syntax is hairy.
+ This function adds substitution candidates for every nested
+ pointer/reference type it processes, including the outermost, final
+ type, assuming the substitution starts at SUBSTITUTION_START in the
+ demangling result. For example, if this function demangles
+ `PP3Foo', it will add a substitution for `Foo', `Foo*', and
+ `Foo**', in that order.
+
+ *INSERT_POS is a quantity used internally, when this function calls
+ itself recursively, to figure out where to insert pointer
+ punctuation on the way up. On entry to this function, INSERT_POS
+ should point to a temporary value, but that value need not be
+ initialized.
+
<type> ::= P <type>
::= R <type>
::= <pointer-to-member-type>
@@ -1817,105 +2009,137 @@ demangle_ctor_dtor_name (dm)
<pointer-to-member-type> ::= M </class/ type> </member/ type> */
static status_t
-demangle_type_ptr (dm)
+demangle_type_ptr (dm, insert_pos, substitution_start)
demangling_t dm;
+ int *insert_pos;
+ int substitution_start;
{
char next;
status_t status;
-
- /* Collect pointer symbols into this string. */
- dyn_string_t symbols = dyn_string_new (10);
+ int is_substitution_candidate = 1;
DEMANGLE_TRACE ("type*", dm);
- if (symbols == NULL)
- return STATUS_ALLOCATION_FAILED;
-
/* Scan forward, collecting pointers and references into symbols,
until we hit something else. Then emit the type. */
- while (1)
+ next = peek_char (dm);
+ if (next == 'P')
{
- next = peek_char (dm);
- if (next == 'P')
- {
- if (!dyn_string_append_char (symbols, '*'))
- return STATUS_ALLOCATION_FAILED;
- advance_char (dm);
- }
- else if (next == 'R')
- {
- if (!dyn_string_append_char (symbols, '&'))
- return STATUS_ALLOCATION_FAILED;
- advance_char (dm);
- }
- else if (next == 'M')
- {
- /* Pointer-to-member. */
- dyn_string_t class_type;
-
- /* Eat the 'M'. */
- advance_char (dm);
-
- /* Capture the type of which this is a pointer-to-member. */
- RETURN_IF_ERROR (result_push (dm));
- RETURN_IF_ERROR (demangle_type (dm));
- class_type = (dyn_string_t) result_pop (dm);
-
- /* Build the pointer-to-member notation. It comes before
- other pointer and reference qualifiers -- */
- if (!dyn_string_prepend_cstr (symbols, "::*"))
- return STATUS_ALLOCATION_FAILED;
- if (!dyn_string_prepend (symbols, class_type))
- return STATUS_ALLOCATION_FAILED;
- dyn_string_delete (class_type);
-
- if (peek_char (dm) == 'F')
- continue;
-
- /* Demangle the type of the pointed-to member. */
+ /* A pointer. Snarf the `P'. */
+ advance_char (dm);
+ /* Demangle the underlying type. */
+ RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos,
+ substitution_start));
+ /* Insert an asterisk where we're told to; it doesn't
+ necessarily go at the end. */
+ RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '*'));
+ /* The next (outermost) pointer or reference character should go
+ after this one. */
+ ++(*insert_pos);
+ }
+ else if (next == 'R')
+ {
+ /* A reference. Snarf the `R'. */
+ advance_char (dm);
+ /* Demangle the underlying type. */
+ RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos,
+ substitution_start));
+ /* Insert an ampersand where we're told to; it doesn't
+ necessarily go at the end. */
+ RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '&'));
+ /* The next (outermost) pointer or reference character should go
+ after this one. */
+ ++(*insert_pos);
+ }
+ else if (next == 'M')
+ {
+ /* A pointer-to-member. */
+ dyn_string_t class_type;
+
+ /* Eat the 'M'. */
+ advance_char (dm);
+
+ /* Capture the type of which this is a pointer-to-member. */
+ RETURN_IF_ERROR (result_push (dm));
+ RETURN_IF_ERROR (demangle_type (dm));
+ class_type = (dyn_string_t) result_pop (dm);
+
+ if (peek_char (dm) == 'F')
+ /* A pointer-to-member function. We want output along the
+ lines of `void (C::*) (int, int)'. Demangle the function
+ type, which would in this case give `void () (int, int)'
+ and set *insert_pos to the spot between the first
+ parentheses. */
+ status = demangle_type_ptr (dm, insert_pos, substitution_start);
+ else
+ {
+ /* A pointer-to-member variable. Demangle the type of the
+ pointed-to member. */
status = demangle_type (dm);
/* Make it pretty. */
if (STATUS_NO_ERROR (status))
status = result_append_space (dm);
- /* Add the pointer-to-member syntax, and other pointer and
- reference symbols. */
- if (STATUS_NO_ERROR (status))
- status = result_append_string (dm, symbols);
- /* Clean up. */
- dyn_string_delete (symbols);
-
- RETURN_IF_ERROR (status);
- return STATUS_OK;
+ /* The pointer-to-member notation (e.g. `C::*') follows the
+ member's type. */
+ *insert_pos = result_length (dm);
}
- else if (next == 'F')
- {
- /* Ooh, tricky, a pointer-to-function. */
- int position = result_length (dm);
- status = result_append_char (dm, '(');
- if (STATUS_NO_ERROR (status))
- status = result_append_string (dm, symbols);
- if (STATUS_NO_ERROR (status))
- status = result_append_char (dm, ')');
- dyn_string_delete (symbols);
- RETURN_IF_ERROR (status);
- RETURN_IF_ERROR (demangle_function_type (dm, position));
- return STATUS_OK;
- }
- else
- {
- /* No more pointe or reference tokens. Finish up. */
- status = demangle_type (dm);
+ /* Build the pointer-to-member notation. */
+ if (STATUS_NO_ERROR (status))
+ status = result_insert (dm, *insert_pos, "::*");
+ if (STATUS_NO_ERROR (status))
+ status = result_insert_string (dm, *insert_pos, class_type);
+ /* There may be additional levels of (pointer or reference)
+ indirection in this type. If so, the `*' and `&' should be
+ added after the pointer-to-member notation (e.g. `C::*&' for
+ a reference to a pointer-to-member of class C). */
+ *insert_pos += dyn_string_length (class_type) + 3;
- if (STATUS_NO_ERROR (status))
- status = result_append_string (dm, symbols);
- dyn_string_delete (symbols);
- RETURN_IF_ERROR (status);
+ /* Clean up. */
+ dyn_string_delete (class_type);
- RETURN_IF_ERROR (status);
- return STATUS_OK;
- }
+ RETURN_IF_ERROR (status);
+ }
+ else if (next == 'F')
+ {
+ /* Ooh, tricky, a pointer-to-function. When we demangle the
+ function type, the return type should go at the very
+ beginning. */
+ *insert_pos = result_length (dm);
+ /* The parentheses indicate this is a function pointer or
+ reference type. */
+ RETURN_IF_ERROR (result_append (dm, "()"));
+ /* Now demangle the function type. The return type will be
+ inserted before the `()', and the argument list will go after
+ it. */
+ RETURN_IF_ERROR (demangle_function_type (dm, insert_pos));
+ /* We should now have something along the lines of
+ `void () (int, int)'. The pointer or reference characters
+ have to inside the first set of parentheses. *insert_pos has
+ already been updated to point past the end of the return
+ type. Move it one character over so it points inside the
+ `()'. */
+ ++(*insert_pos);
+ }
+ else
+ {
+ /* No more pointer or reference tokens; this is therefore a
+ pointer to data. Finish up by demangling the underlying
+ type. */
+ RETURN_IF_ERROR (demangle_type (dm));
+ /* The pointer or reference characters follow the underlying
+ type, as in `int*&'. */
+ *insert_pos = result_length (dm);
+ /* Because of the production <type> ::= <substitution>,
+ demangle_type will already have added the underlying type as
+ a substitution candidate. Don't do it again. */
+ is_substitution_candidate = 0;
}
+
+ if (is_substitution_candidate)
+ RETURN_IF_ERROR (substitution_add (dm, substitution_start, 0));
+
+ return STATUS_OK;
}
/* Demangles and emits a <type>.
@@ -1926,6 +2150,7 @@ demangle_type_ptr (dm)
::= <array-type>
::= <pointer-to-member-type>
::= <template-param>
+ ::= <template-template-param> <template-args>
::= <CV-qualifiers> <type>
::= P <type> # pointer-to
::= R <type> # reference-to
@@ -1941,22 +2166,28 @@ demangle_type (dm)
int start = substitution_start (dm);
char peek = peek_char (dm);
char peek_next;
- int template_p = 0;
- int special_std_substitution;
- int is_builtin_type = 0;
+ int encode_return_type = 0;
template_arg_list_t old_arg_list = current_template_arg_list (dm);
- int template_parm = NOT_TEMPLATE_PARM;
+ int insert_pos;
+
+ /* A <type> can be a <substitution>; therefore, this <type> is a
+ substitution candidate unless a special condition holds (see
+ below). */
+ int is_substitution_candidate = 1;
DEMANGLE_TRACE ("type", dm);
/* A <class-enum-type> can start with a digit (a <source-name>), an
N (a <nested-name>), or a Z (a <local-name>). */
if (IS_DIGIT ((unsigned char) peek) || peek == 'N' || peek == 'Z')
- RETURN_IF_ERROR (demangle_class_enum_type (dm, &template_p));
- else if (peek >= 'a' && peek <= 'z')
+ RETURN_IF_ERROR (demangle_class_enum_type (dm, &encode_return_type));
+ /* Lower-case letters begin <builtin-type>s, except for `r', which
+ denotes restrict. */
+ else if (peek >= 'a' && peek <= 'z' && peek != 'r')
{
RETURN_IF_ERROR (demangle_builtin_type (dm));
- is_builtin_type = 1;
+ /* Built-in types are not substitution candidates. */
+ is_substitution_candidate = 0;
}
else
switch (peek)
@@ -1964,6 +2195,9 @@ demangle_type (dm)
case 'r':
case 'V':
case 'K':
+ /* CV-qualifiers (including restrict). We have to demangle
+ them off to the side, since C++ syntax puts them in a funny
+ place for qualified pointer and reference types. */
{
status_t status;
dyn_string_t cv_qualifiers = dyn_string_new (24);
@@ -2006,7 +2240,28 @@ demangle_type (dm)
break;
case 'T':
- RETURN_IF_ERROR (demangle_template_param (dm, &template_parm));
+ /* It's either a <template-param> or a
+ <template-template-param>. In either case, demangle the
+ `T' token first. */
+ RETURN_IF_ERROR (demangle_template_param (dm));
+
+ /* Check for a template argument list; if one is found, it's a
+ <template-template-param> ::= <template-param>
+ ::= <substitution> */
+ if (peek_char (dm) == 'I')
+ {
+ /* Add a substitution candidate. The template parameter
+ `T' token is a substitution candidate by itself,
+ without the template argument list. */
+ RETURN_IF_ERROR (substitution_add (dm, start, encode_return_type));
+
+ /* Now demangle the template argument list. */
+ RETURN_IF_ERROR (demangle_template_args (dm));
+ /* The entire type, including the template template
+ parameter and its argument list, will be added as a
+ substitution candidate below. */
+ }
+
break;
case 'S':
@@ -2016,16 +2271,56 @@ demangle_type (dm)
or underscore. */
peek_next = peek_char_next (dm);
if (IS_DIGIT (peek_next) || peek_next == '_')
- RETURN_IF_ERROR (demangle_substitution (dm, &template_p,
- &special_std_substitution));
+ {
+ RETURN_IF_ERROR (demangle_substitution (dm, &encode_return_type));
+
+ /* The substituted name may have been a template name.
+ Check if template arguments follow, and if so, demangle
+ them. */
+ if (peek_char (dm) == 'I')
+ RETURN_IF_ERROR (demangle_template_args (dm));
+ else
+ /* A substitution token is not itself a substitution
+ candidate. (However, if the substituted template is
+ instantiated, the resulting type is.) */
+ is_substitution_candidate = 0;
+ }
else
- demangle_class_enum_type (dm, &template_p);
+ {
+ /* Now some trickiness. We have a special substitution
+ here. Often, the special substitution provides the
+ name of a template that's subsequently instantiated,
+ for instance `SaIcE' => std::allocator<char>. In these
+ cases we need to add a substitution candidate for the
+ entire <class-enum-type> and thus don't want to clear
+ the is_substitution_candidate flag.
+
+ However, it's possible that what we have here is a
+ substitution token representing an entire type, such as
+ `Ss' => std::string. In this case, we mustn't add a
+ new substitution candidate for this substitution token.
+ To detect this case, remember where the start of the
+ substitution token is. */
+ const char *next = dm->next;
+ /* Now demangle the <class-enum-type>. */
+ RETURN_IF_ERROR
+ (demangle_class_enum_type (dm, &encode_return_type));
+ /* If all that was just demangled is the two-character
+ special substitution token, supress the addition of a
+ new candidate for it. */
+ if (dm->next == next + 2)
+ is_substitution_candidate = 0;
+ }
+
break;
case 'P':
case 'R':
case 'M':
- RETURN_IF_ERROR (demangle_type_ptr (dm));
+ RETURN_IF_ERROR (demangle_type_ptr (dm, &insert_pos, start));
+ /* demangle_type_ptr adds all applicable substitution
+ candidates. */
+ is_substitution_candidate = 0;
break;
case 'C':
@@ -2043,7 +2338,7 @@ demangle_type (dm)
break;
case 'U':
- /* Vendor extended type qualifier. */
+ /* Vendor-extended type qualifier. */
advance_char (dm);
RETURN_IF_ERROR (demangle_source_name (dm));
RETURN_IF_ERROR (result_append_char (dm, ' '));
@@ -2054,13 +2349,12 @@ demangle_type (dm)
return "Unexpected character in <type>.";
}
- /* Unqualified builin types are not substitution candidates. */
- if (!is_builtin_type)
+ if (is_substitution_candidate)
/* Add a new substitution for the type. If this type was a
<template-param>, pass its index since from the point of
- substitutions, a <template-param> token is a substitution
+ substitutions; a <template-param> token is a substitution
candidate distinct from the type that is substituted for it. */
- RETURN_IF_ERROR (substitution_add (dm, start, template_p, template_parm));
+ RETURN_IF_ERROR (substitution_add (dm, start, encode_return_type));
/* Pop off template argument lists added during mangling of this
type. */
@@ -2199,16 +2493,18 @@ demangle_CV_qualifiers (dm, qualifiers)
}
}
-/* Demangles and emits a <function-type> FUNCTION_NAME_POS is the
+/* Demangles and emits a <function-type>. *FUNCTION_NAME_POS is the
position in the result string of the start of the function
- identifier, at which the function's return type will be inserted.
+ identifier, at which the function's return type will be inserted;
+ *FUNCTION_NAME_POS is updated to position past the end of the
+ function's return type.
<function-type> ::= F [Y] <bare-function-type> E */
static status_t
demangle_function_type (dm, function_name_pos)
demangling_t dm;
- int function_name_pos;
+ int *function_name_pos;
{
DEMANGLE_TRACE ("function-type", dm);
RETURN_IF_ERROR (demangle_char (dm, 'F'));
@@ -2234,7 +2530,7 @@ demangle_function_type (dm, function_name_pos)
static status_t
demangle_bare_function_type (dm, return_type_pos)
demangling_t dm;
- int return_type_pos;
+ int *return_type_pos;
{
/* Sequence is the index of the current function parameter, counting
from zero. The value -1 denotes the return type. */
@@ -2259,10 +2555,16 @@ demangle_bare_function_type (dm, return_type_pos)
/* Add a space to the end of the type. Insert the return
type where we've been asked to. */
- if (!dyn_string_append_space (return_type)
- || !dyn_string_insert (result_string (dm), return_type_pos,
- return_type))
+ if (!dyn_string_append_space (return_type))
status = STATUS_ALLOCATION_FAILED;
+ if (STATUS_NO_ERROR (status))
+ {
+ if (!dyn_string_insert (result_string (dm), *return_type_pos,
+ return_type))
+ status = STATUS_ALLOCATION_FAILED;
+ else
+ *return_type_pos += dyn_string_length (return_type);
+ }
dyn_string_delete (return_type);
RETURN_IF_ERROR (status);
@@ -2273,60 +2575,88 @@ demangle_bare_function_type (dm, return_type_pos)
the only type in a parameter list; in that case, we want
to print `foo ()' instead of `foo (void)'. */
if (peek_char (dm) == 'v')
+ /* Consume the v. */
+ advance_char (dm);
+ else
{
- /* Consume the v. */
- advance_char (dm);
- continue;
+ /* Separate parameter types by commas. */
+ if (sequence > 0)
+ RETURN_IF_ERROR (result_append (dm, ", "));
+ /* Demangle the type. */
+ RETURN_IF_ERROR (demangle_type (dm));
}
- /* Separate parameter types by commas. */
- if (sequence > 0)
- RETURN_IF_ERROR (result_append (dm, ", "));
- /* Demangle the type. */
- RETURN_IF_ERROR (demangle_type (dm));
}
++sequence;
}
RETURN_IF_ERROR (result_append_char (dm, ')'));
+ /* We should have demangled at least one parameter type (which would
+ be void, for a function that takes no parameters), plus the
+ return type, if we were supposed to demangle that. */
+ if (sequence == -1)
+ return "Missing function return type.";
+ else if (sequence == 0)
+ return "Missing function parameter.";
+
return STATUS_OK;
}
-/* Demangles and emits a <class-enum-type>. *TEMPLATE_P is set to
+/* Demangles and emits a <class-enum-type>. *ENCODE_RETURN_TYPE is set to
non-zero if the type is a template-id, zero otherwise.
<class-enum-type> ::= <name> */
static status_t
-demangle_class_enum_type (dm, template_p)
+demangle_class_enum_type (dm, encode_return_type)
demangling_t dm;
- int *template_p;
+ int *encode_return_type;
{
DEMANGLE_TRACE ("class-enum-type", dm);
- RETURN_IF_ERROR (demangle_name (dm, template_p));
+ RETURN_IF_ERROR (demangle_name (dm, encode_return_type));
return STATUS_OK;
}
/* Demangles and emits an <array-type>.
- <array-type> ::= A [<dimension number>] _ <element type> */
+ <array-type> ::= A [<dimension number>] _ <element type>
+ ::= A <dimension expression> _ <element type> */
static status_t
demangle_array_type (dm)
demangling_t dm;
{
- status_t status;
- dyn_string_t array_size = dyn_string_new (10);
-
- if (array_size == NULL)
- return STATUS_ALLOCATION_FAILED;
+ status_t status = STATUS_OK;
+ dyn_string_t array_size = NULL;
+ char peek;
- status = demangle_char (dm, 'A');
+ RETURN_IF_ERROR (demangle_char (dm, 'A'));
/* Demangle the array size into array_size. */
- if (STATUS_NO_ERROR (status))
- status = demangle_number_literally (dm, array_size, 10, 0);
+ peek = peek_char (dm);
+ if (peek == '_')
+ /* Array bound is omitted. This is a C99-style VLA. */
+ ;
+ else if (IS_DIGIT (peek_char (dm)))
+ {
+ /* It looks like a constant array bound. */
+ array_size = dyn_string_new (10);
+ if (array_size == NULL)
+ return STATUS_ALLOCATION_FAILED;
+ status = demangle_number_literally (dm, array_size, 10, 0);
+ }
+ else
+ {
+ /* Anything is must be an expression for a nont-constant array
+ bound. This happens if the array type occurs in a template
+ and the array bound references a template parameter. */
+ RETURN_IF_ERROR (result_push (dm));
+ RETURN_IF_ERROR (demangle_expression (dm));
+ array_size = (dyn_string_t) result_pop (dm);
+ }
+ /* array_size may have been allocated by now, so we can't use
+ RETURN_IF_ERROR until it's been deallocated. */
/* Demangle the base type of the array. */
if (STATUS_NO_ERROR (status))
@@ -2337,27 +2667,26 @@ demangle_array_type (dm)
/* Emit the array dimension syntax. */
if (STATUS_NO_ERROR (status))
status = result_append_char (dm, '[');
- if (STATUS_NO_ERROR (status))
+ if (STATUS_NO_ERROR (status) && array_size != NULL)
status = result_append_string (dm, array_size);
if (STATUS_NO_ERROR (status))
status = result_append_char (dm, ']');
- dyn_string_delete (array_size);
+ if (array_size != NULL)
+ dyn_string_delete (array_size);
RETURN_IF_ERROR (status);
return STATUS_OK;
}
-/* Demangles and emits a <template-param>. The zero-indexed position
- in the parameter list is placed in *TEMPLATE_PARM_NUMBER.
+/* Demangles and emits a <template-param>.
<template-param> ::= T_ # first template parameter
::= T <parameter-2 number> _ */
static status_t
-demangle_template_param (dm, template_parm_number)
+demangle_template_param (dm)
demangling_t dm;
- int *template_parm_number;
{
int parm_number;
template_arg_list_t current_arg_list = current_template_arg_list (dm);
@@ -2387,10 +2716,6 @@ demangle_template_param (dm, template_parm_number)
return "Template parameter number out of bounds.";
RETURN_IF_ERROR (result_append_string (dm, (dyn_string_t) arg));
- if (peek_char (dm) == 'I')
- RETURN_IF_ERROR (demangle_template_args (dm));
-
- *template_parm_number = parm_number;
return STATUS_OK;
}
@@ -2419,7 +2744,7 @@ demangle_template_args (dm)
return STATUS_ALLOCATION_FAILED;
RETURN_IF_ERROR (demangle_char (dm, 'I'));
- RETURN_IF_ERROR (result_append_char (dm, '<'));
+ RETURN_IF_ERROR (result_open_template_list (dm));
do
{
string_list_t arg;
@@ -2595,6 +2920,7 @@ demangle_template_arg (dm)
/* Expression. */
advance_char (dm);
RETURN_IF_ERROR (demangle_expression (dm));
+ RETURN_IF_ERROR (demangle_char (dm, 'E'));
break;
default:
@@ -2699,12 +3025,11 @@ demangle_expr_primary (dm)
demangling_t dm;
{
char peek = peek_char (dm);
- int unused;
DEMANGLE_TRACE ("expr-primary", dm);
if (peek == 'T')
- RETURN_IF_ERROR (demangle_template_param (dm, &unused));
+ RETURN_IF_ERROR (demangle_template_param (dm));
else if (peek == 'L')
{
/* Consume the `L'. */
@@ -2725,10 +3050,7 @@ demangle_expr_primary (dm)
}
/* Demangles and emits a <substitution>. Sets *TEMPLATE_P to non-zero
- if the substitution is the name of a template, zero otherwise. If
- the substitution token is St, which corresponds to the `::std::'
- namespace and can appear in a non-nested name, sets
- *SPECIAL_STD_SUBSTITUTION to non-zero; zero otherwise.
+ if the substitution is the name of a template, zero otherwise.
<substitution> ::= S <seq-id> _
::= S_
@@ -2744,14 +3066,13 @@ demangle_expr_primary (dm)
::= So # ::std::basic_ostream<char,
std::char_traits<char> >
::= Sd # ::std::basic_iostream<char,
- std::char_traits<char> >
+ std::char_traits<char> >
*/
static status_t
-demangle_substitution (dm, template_p, special_std_substitution)
+demangle_substitution (dm, template_p)
demangling_t dm;
int *template_p;
- int *special_std_substitution;
{
int seq_id;
int peek;
@@ -2760,7 +3081,6 @@ demangle_substitution (dm, template_p, special_std_substitution)
DEMANGLE_TRACE ("substitution", dm);
RETURN_IF_ERROR (demangle_char (dm, 'S'));
- *special_std_substitution = 0;
/* Scan the substitution sequence index. A missing number denotes
the first index. */
@@ -2781,7 +3101,6 @@ demangle_substitution (dm, template_p, special_std_substitution)
{
case 't':
RETURN_IF_ERROR (result_append (dm, "std"));
- *special_std_substitution = 1;
break;
case 'a':
@@ -2897,7 +3216,7 @@ demangle_local_name (dm)
RETURN_IF_ERROR (demangle_char (dm, 'Z'));
RETURN_IF_ERROR (demangle_encoding (dm));
RETURN_IF_ERROR (demangle_char (dm, 'E'));
- RETURN_IF_ERROR (result_append (dm, "'s "));
+ RETURN_IF_ERROR (result_append (dm, "::"));
if (peek_char (dm) == 's')
{
@@ -2910,7 +3229,6 @@ demangle_local_name (dm)
else
{
int unused;
- RETURN_IF_ERROR (result_append (dm, "local "));
/* Local name for some other entity. Demangle its name. */
RETURN_IF_ERROR (demangle_name (dm, &unused));
RETURN_IF_ERROR (demangle_discriminator (dm, 1));
@@ -2933,7 +3251,7 @@ demangle_discriminator (dm, suppress_first)
int suppress_first;
{
/* Output for <discriminator>s to the demangled name is completely
- supressed if not in verbose mode. */
+ suppressed if not in verbose mode. */
if (peek_char (dm) == '_')
{
@@ -3025,6 +3343,7 @@ cp_demangle (name, result)
dyn_string_t. On success, returns STATUS_OK. On failiure, returns
an error message, and the contents of RESULT are unchanged. */
+#ifdef IN_LIBGCC2
static status_t
cp_demangle_type (type_name, result)
const char* type_name;
@@ -3062,9 +3381,6 @@ cp_demangle_type (type_name, result)
return status;
}
-
-#ifdef IN_LIBGCC2
-
extern char *__cxa_demangle PARAMS ((const char *, char *, size_t *, int *));
/* ABI-mandated entry point in the C++ runtime library for performing
@@ -3221,7 +3537,8 @@ static void print_usage
/* Non-zero if CHAR is a character than can occur in a mangled name. */
#define is_mangled_char(CHAR) \
- (IS_ALPHA (CHAR) || IS_DIGIT (CHAR) || (CHAR) == '_')
+ (IS_ALPHA (CHAR) || IS_DIGIT (CHAR) \
+ || (CHAR) == '_' || (CHAR) == '.' || (CHAR) == '$')
/* The name of this program, as invoked. */
const char* program_name;
@@ -3234,7 +3551,7 @@ print_usage (fp, exit_value)
int exit_value;
{
fprintf (fp, "Usage: %s [options] [names ...]\n", program_name);
- fprintf (fp, "Options:\n", program_name);
+ fprintf (fp, "Options:\n");
fprintf (fp, " -h,--help Display this message.\n");
fprintf (fp, " -s,--strict Demangle standard names only.\n");
fprintf (fp, " -v,--verbose Produce verbose demanglings.\n");
diff --git a/libiberty/cplus-dem.c b/libiberty/cplus-dem.c
index 8a672c6..3fe70b4 100644
--- a/libiberty/cplus-dem.c
+++ b/libiberty/cplus-dem.c
@@ -1,5 +1,6 @@
/* Demangler for GNU C++
- Copyright 1989, 91, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc.
+ Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.uucp)
Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
Modified by Satish Pai (pai@apollo.hp.com) for HP demangling
@@ -705,7 +706,7 @@ cplus_demangle_opname (opname, result, options)
{
/* Operator. */
size_t i;
- for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ for (i = 0; i < ARRAY_SIZE (optable); i++)
{
if (strlen (optable[i].in) == 2
&& memcmp (optable[i].in, opname + 2, 2) == 0)
@@ -723,7 +724,7 @@ cplus_demangle_opname (opname, result, options)
{
/* Assignment. */
size_t i;
- for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ for (i = 0; i < ARRAY_SIZE (optable); i++)
{
if (strlen (optable[i].in) == 3
&& memcmp (optable[i].in, opname + 2, 3) == 0)
@@ -747,7 +748,7 @@ cplus_demangle_opname (opname, result, options)
&& memcmp (opname + 3, "assign_", 7) == 0)
{
size_t i;
- for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ for (i = 0; i < ARRAY_SIZE (optable); i++)
{
len1 = len - 10;
if ((int) strlen (optable[i].in) == len1
@@ -764,7 +765,7 @@ cplus_demangle_opname (opname, result, options)
else
{
size_t i;
- for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ for (i = 0; i < ARRAY_SIZE (optable); i++)
{
len1 = len - 3;
if ((int) strlen (optable[i].in) == len1
@@ -811,7 +812,7 @@ cplus_mangle_opname (opname, options)
int len;
len = strlen (opname);
- for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ for (i = 0; i < ARRAY_SIZE (optable); i++)
{
if ((int) strlen (optable[i].out) == len
&& (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
@@ -1573,9 +1574,7 @@ demangle_expression (work, mangled, s, tk)
len = strlen (*mangled);
- for (i = 0;
- i < sizeof (optable) / sizeof (optable [0]);
- ++i)
+ for (i = 0; i < ARRAY_SIZE (optable); ++i)
{
size_t l = strlen (optable[i].in);
@@ -4449,7 +4448,7 @@ demangle_function_name (work, mangled, declp, scan)
if (declp->p - declp->b >= 10 /* op$assign_ */
&& memcmp (declp->b + 3, "assign_", 7) == 0)
{
- for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ for (i = 0; i < ARRAY_SIZE (optable); i++)
{
int len = declp->p - declp->b - 10;
if ((int) strlen (optable[i].in) == len
@@ -4465,7 +4464,7 @@ demangle_function_name (work, mangled, declp, scan)
}
else
{
- for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ for (i = 0; i < ARRAY_SIZE (optable); i++)
{
int len = declp->p - declp->b - 3;
if ((int) strlen (optable[i].in) == len
@@ -4513,7 +4512,7 @@ demangle_function_name (work, mangled, declp, scan)
if (declp->b[4] == '\0')
{
/* Operator. */
- for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ for (i = 0; i < ARRAY_SIZE (optable); i++)
{
if (strlen (optable[i].in) == 2
&& memcmp (optable[i].in, declp->b + 2, 2) == 0)
@@ -4530,7 +4529,7 @@ demangle_function_name (work, mangled, declp, scan)
if (declp->b[2] == 'a' && declp->b[5] == '\0')
{
/* Assignment. */
- for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ for (i = 0; i < ARRAY_SIZE (optable); i++)
{
if (strlen (optable[i].in) == 3
&& memcmp (optable[i].in, declp->b + 2, 3) == 0)
@@ -4873,7 +4872,7 @@ hp_symbol_characters ()
static const char *
gnu_new_abi_symbol_characters ()
{
- return "_";
+ return "_$.";
}
diff --git a/libiberty/dyn-string.c b/libiberty/dyn-string.c
index 69897f8..34f88ad 100644
--- a/libiberty/dyn-string.c
+++ b/libiberty/dyn-string.c
@@ -305,6 +305,30 @@ dyn_string_insert_cstr (dest, pos, src)
return 1;
}
+/* Inserts character C into DEST starting at position POS. DEST is
+ expanded as necessary. Returns 1 on success. On failure,
+ RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0. */
+
+int
+dyn_string_insert_char (dest, pos, c)
+ dyn_string_t dest;
+ int pos;
+ int c;
+{
+ int i;
+
+ if (dyn_string_resize (dest, dest->length + 1) == NULL)
+ return 0;
+ /* Make room for the insertion. Be sure to copy the NUL. */
+ for (i = dest->length; i >= pos; --i)
+ dest->s[i + 1] = dest->s[i];
+ /* Add the new character. */
+ dest->s[pos] = c;
+ /* Compute the new length. */
+ ++dest->length;
+ return 1;
+}
+
/* Append S to DS, resizing DS if necessary. Returns 1 on success.
On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and
returns 0. */
diff --git a/libiberty/pexecute.c b/libiberty/pexecute.c
index 9c62b57..34d2deb 100644
--- a/libiberty/pexecute.c
+++ b/libiberty/pexecute.c
@@ -46,19 +46,6 @@ extern int errno;
#include <sys/wait.h>
#endif
-#ifdef vfork /* Autoconf may define this to fork for us. */
-# define VFORK_STRING "fork"
-#else
-# define VFORK_STRING "vfork"
-#endif
-#ifdef HAVE_VFORK_H
-#include <vfork.h>
-#endif
-#ifdef VMS
-#define vfork() (decc$$alloc_vfork_blocks() >= 0 ? \
- lib$get_current_invo_context(decc$$get_vfork_jmpbuf()) : -1)
-#endif /* VMS */
-
#include "libiberty.h"
/* stdin file number. */
@@ -714,9 +701,10 @@ pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
/* Fork a subprocess; wait and retry if it fails. */
sleep_interval = 1;
+ pid = -1;
for (retries = 0; retries < 4; retries++)
{
- pid = vfork ();
+ pid = fork ();
if (pid >= 0)
break;
sleep (sleep_interval);
@@ -726,11 +714,9 @@ pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
switch (pid)
{
case -1:
- {
- *errmsg_fmt = VFORK_STRING;
- *errmsg_arg = NULL;
- return -1;
- }
+ *errmsg_fmt = "fork";
+ *errmsg_arg = NULL;
+ return -1;
case 0: /* child */
/* Move the input and output pipes into place, if necessary. */
@@ -754,7 +740,6 @@ pexecute (program, argv, this_pname, temp_base, errmsg_fmt, errmsg_arg, flags)
/* Exec the program. */
(*func) (program, argv);
- /* Note: Calling fprintf and exit here doesn't seem right for vfork. */
fprintf (stderr, "%s: ", this_pname);
fprintf (stderr, install_error_msg, program);
fprintf (stderr, ": %s\n", xstrerror (errno));
diff --git a/libiberty/setenv.c b/libiberty/setenv.c
index a90c83a..f025716 100644
--- a/libiberty/setenv.c
+++ b/libiberty/setenv.c
@@ -63,7 +63,7 @@ setenv (name, value, replace)
const char *value;
int replace;
{
- register char **ep;
+ register char **ep = 0;
register size_t size;
const size_t namelen = strlen (name);
const size_t vallen = strlen (value) + 1;
diff --git a/libiberty/sigsetmask.c b/libiberty/sigsetmask.c
index 2a09e6a..db6408d 100644
--- a/libiberty/sigsetmask.c
+++ b/libiberty/sigsetmask.c
@@ -12,6 +12,8 @@
#include <sys/types.h>
#include <signal.h>
+extern void abort PARAMS ((void)) ATTRIBUTE_NORETURN;
+
#ifdef SIG_SETMASK
int
DEFUN(sigsetmask,(set),
diff --git a/libiberty/splay-tree.c b/libiberty/splay-tree.c
index 609cd68..52b57c0 100644
--- a/libiberty/splay-tree.c
+++ b/libiberty/splay-tree.c
@@ -1,5 +1,5 @@
/* A splay-tree datatype.
- Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
Contributed by Mark Mitchell (mark@markmitchell.com).
This file is part of GNU CC.
@@ -305,8 +305,8 @@ splay_tree_insert (sp, key, value)
node->right->left = 0;
}
- sp->root = node;
- }
+ sp->root = node;
+ }
return sp->root;
}
@@ -368,6 +368,72 @@ splay_tree_lookup (sp, key)
return 0;
}
+/* Return the immediate predecessor KEY, or NULL if there is no
+ predecessor. KEY need not be present in the tree. */
+
+splay_tree_node
+splay_tree_predecessor (sp, key)
+ splay_tree sp;
+ splay_tree_key key;
+{
+ int comparison;
+ splay_tree_node node;
+
+ /* If the tree is empty, there is certainly no predecessor. */
+ if (!sp->root)
+ return NULL;
+
+ /* Splay the tree around KEY. That will leave either the KEY
+ itself, its predecessor, or its successor at the root. */
+ splay_tree_splay (sp, key);
+ comparison = (*sp->comp)(sp->root->key, key);
+
+ /* If the predecessor is at the root, just return it. */
+ if (comparison < 0)
+ return sp->root;
+
+ /* Otherwise, find the leftmost element of the right subtree. */
+ node = sp->root->left;
+ if (node)
+ while (node->right)
+ node = node->right;
+
+ return node;
+}
+
+/* Return the immediate successor KEY, or NULL if there is no
+ predecessor. KEY need not be present in the tree. */
+
+splay_tree_node
+splay_tree_successor (sp, key)
+ splay_tree sp;
+ splay_tree_key key;
+{
+ int comparison;
+ splay_tree_node node;
+
+ /* If the tree is empty, there is certainly no predecessor. */
+ if (!sp->root)
+ return NULL;
+
+ /* Splay the tree around KEY. That will leave either the KEY
+ itself, its predecessor, or its successor at the root. */
+ splay_tree_splay (sp, key);
+ comparison = (*sp->comp)(sp->root->key, key);
+
+ /* If the successor is at the root, just return it. */
+ if (comparison > 0)
+ return sp->root;
+
+ /* Otherwise, find the rightmost element of the left subtree. */
+ node = sp->root->right;
+ if (node)
+ while (node->left)
+ node = node->left;
+
+ return node;
+}
+
/* Call FN, passing it the DATA, for every node in SP, following an
in-order traversal. If FN every returns a non-zero value, the
iteration ceases immediately, and the value is returned.
diff --git a/libiberty/vasprintf.c b/libiberty/vasprintf.c
index b959f5f..c34585d 100644
--- a/libiberty/vasprintf.c
+++ b/libiberty/vasprintf.c
@@ -18,21 +18,31 @@ License along with libiberty; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#ifdef __STDC__
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <ansidecl.h>
+#ifdef ANSI_PROTOTYPES
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#include <stdio.h>
#include <string.h>
-#include <ansidecl.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#else
+extern unsigned long strtoul ();
+extern PTR malloc ();
+#endif
+#include "libiberty.h"
#ifdef TEST
int global_total_width;
#endif
-unsigned long strtoul ();
-char *malloc ();
+
+static int int_vasprintf PARAMS ((char **, const char *, va_list *));
static int
int_vasprintf (result, format, args)
@@ -60,7 +70,7 @@ int_vasprintf (result, format, args)
total_width += abs (va_arg (ap, int));
}
else
- total_width += strtoul (p, &p, 10);
+ total_width += strtoul (p, (char **) &p, 10);
if (*p == '.')
{
++p;
@@ -70,7 +80,7 @@ int_vasprintf (result, format, args)
total_width += abs (va_arg (ap, int));
}
else
- total_width += strtoul (p, &p, 10);
+ total_width += strtoul (p, (char **) &p, 10);
}
while (strchr ("hlL", *p))
++p;
@@ -132,33 +142,33 @@ vasprintf (result, format, args)
}
#ifdef TEST
-void
-checkit
-#ifdef __STDC__
- (const char* format, ...)
-#else
- (va_alist)
- va_dcl
-#endif
+static void checkit PARAMS ((const char *, ...));
+
+static void
+checkit VPARAMS ((const char* format, ...))
{
va_list args;
char *result;
+#ifndef ANSI_PROTOTYPES
+ const char *format;
+#endif
-#ifdef __STDC__
- va_start (args, format);
-#else
- char *format;
- va_start (args);
- format = va_arg (args, char *);
+ VA_START (args, format);
+
+#ifndef ANSI_PROTOTYPES
+ format = va_arg (args, const char *);
#endif
+
vasprintf (&result, format, args);
- if (strlen (result) < global_total_width)
+ if (strlen (result) < (size_t) global_total_width)
printf ("PASS: ");
else
printf ("FAIL: ");
printf ("%d %s\n", global_total_width, result);
}
+extern int main PARAMS ((void));
+
int
main ()
{
@@ -169,5 +179,7 @@ main ()
checkit ("%s", "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
777777777777777777333333333333366666666666622222222222777777777777733333");
checkit ("%f%s%d%s", 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx");
+
+ return 0;
}
#endif /* TEST */
diff --git a/libiberty/vfork.c b/libiberty/vfork.c
index 86c4591..5e87721 100644
--- a/libiberty/vfork.c
+++ b/libiberty/vfork.c
@@ -1,6 +1,10 @@
/* Emulate vfork using just plain fork, for systems without a real vfork.
This function is in the public domain. */
+#include "ansidecl.h"
+
+extern int fork PARAMS ((void));
+
int
vfork ()
{
diff --git a/libiberty/xexit.c b/libiberty/xexit.c
index 7aa52ac..e8b1ed1 100644
--- a/libiberty/xexit.c
+++ b/libiberty/xexit.c
@@ -17,13 +17,15 @@ License along with libiberty; see the file COPYING.LIB. If not, write
to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include "ansidecl.h"
-#include "libiberty.h"
-
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
+#include "libiberty.h"
+
/* This variable is set by xatexit if it is called. This way, xmalloc
doesn't drag xatexit into the link. */