From 74bcd5294fa6894905a705d18c229cbe5ea42b59 Mon Sep 17 00:00:00 2001 From: DJ Delorie Date: Thu, 12 Oct 2000 02:16:48 +0000 Subject: merge from gcc repository --- include/ChangeLog | 4 + include/splay-tree.h | 8 +- libiberty/ChangeLog | 184 +++++++++ libiberty/Makefile.in | 4 +- libiberty/cp-demangle.c | 977 ++++++++++++++++++++++++++++++++---------------- libiberty/cplus-dem.c | 27 +- libiberty/dyn-string.c | 24 ++ libiberty/pexecute.c | 25 +- libiberty/setenv.c | 2 +- libiberty/sigsetmask.c | 2 + libiberty/splay-tree.c | 72 +++- libiberty/vasprintf.c | 54 +-- libiberty/vfork.c | 4 + libiberty/xexit.c | 8 +- 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 + + * splay-tree.h (splay_tree_predecessor): Declare. + 2000-09-29 Hans-Peter Nilsson * 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 + + Merge from gcc, all 2000-10-11 entries below + +2000-10-11 Mark Mitchell + + * splay-tree.c (splay_tree_insert): Fix formatting. + +2000-10-11 Mark Mitchell + + * splay-tree.c (splay_tree_predecessor): Fix typo in comment. + +2000-10-11 Mark Mitchell + + * splay-tree.c (splay_tree_predecessor): New function. + (splay_tree_successor): Likewise. + +2000-10-11 Alex Samuel + + * cp-demangle.c: Fix copyright banner. + +2000-10-11 Alex Samuel + + * 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 + + * 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 + + * cp-demangle.c (demangle_template_arg): Eat an `E' after an + . + +2000-10-11 Alex Samuel + + * cp-demangle.c (demangle_type_ptr): Increment position past + pointer and reference characters. + +2000-10-11 Alex Samuel + + * 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 + + * 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 + + * Makefile.in (md5.o): Depend on config.h. + +2000-10-11 Alex Samuel + + * cp-demangle.c (demangle_name): Initialize template_p in local + name case. Don't re-add substitutions as candidates. + (demangle_nested_name): Use . + (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 + + * 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 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 + + * libiberty/random.c (end_ptr): Revert previous change. + +2000-10-11 Greg McGary + + * 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 + + * 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 + + * pexecute.c: Don't use vfork. Initialize 'pid' before retry loop. + +2000-10-11 RodneyBrown + + Jeff Law + * 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 + + * 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 + + * 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 + + * 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 * 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 . + 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 , and is distinct from other - otherwise-identical types and other 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) ::= */ 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 . */ - 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 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 . */ if (peek_char (dm) == 'I') { - RETURN_IF_ERROR (substitution_add (dm, start, 0, - NOT_TEMPLATE_PARM)); + /* A template name of the form std:: is a + substitution candidate. */ + if (is_std_substitution) + RETURN_IF_ERROR (substitution_add (dm, start, 0)); + /* Demangle the here. */ RETURN_IF_ERROR (demangle_template_args (dm)); + *encode_return_type = !suppress_return_type; } + else + *encode_return_type = 0; + break; default: /* This is an or . */ - RETURN_IF_ERROR (demangle_unqualified_name (dm)); + RETURN_IF_ERROR (demangle_unqualified_name (dm, &suppress_return_type)); /* If the is followed by template args, this is an . */ 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 . - ::= N [] E */ + ::= N [] 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 ; demangle_prefix will - handle it. */ + RETURN_IF_ERROR (demangle_prefix (dm, encode_return_type)); + /* No need to demangle the final ; 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 . - ::= + ::= ::= ::= # empty ::= ::= - ::= - - ::= - ::= */ + ::= */ 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 - , 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 , 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 ."; 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 following a + , 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 + . 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 ."; - /* 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 . If the - 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 . If this + 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. ::= ::= ::= */ 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 ."; @@ -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 # cast - ::= vx # vendor extended operator */ + ::= v [0-9] # 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 . + + ::= # 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 . + + ::= _ + # 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 . + + ::= h _ + ::= v _ */ + +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 ."; + } + + return STATUS_OK; +} + /* Demangles and emits a . ::= GV # Guard variable - ::= Th[n] _ - # non-virtual base override thunk - ::= Tv[n] _ - _ - # virtual base override thunk ::= TV # virtual table ::= TT # VTT ::= TI # typeinfo structure ::= TS # typeinfo name + Other relevant productions include thunks: + + ::= T + # base is the nominal target function of thunk + + ::= Tc + # base is the nominal target function of thunk + # first call-offset is 'this' adjustment + # second call-offset is result adjustment + + where + + ::= h _ + ::= v _ + Also demangles the special g++ manglings, - ::= CT _ + ::= TC _ # construction vtable ::= TF # typeinfo function (old ABI only) ::= TJ # 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. + ::= P ::= R ::= @@ -1817,105 +2009,137 @@ demangle_ctor_dtor_name (dm) ::= M */ 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 ::= , + 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 . @@ -1926,6 +2150,7 @@ demangle_type_ptr (dm) ::= ::= ::= + ::= ::= ::= P # pointer-to ::= R # 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 can be a ; therefore, this is a + substitution candidate unless a special condition holds (see + below). */ + int is_substitution_candidate = 1; DEMANGLE_TRACE ("type", dm); /* A can start with a digit (a ), an N (a ), or a Z (a ). */ 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 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 or a + . 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 + ::= + ::= */ + 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. In these + cases we need to add a substitution candidate for the + entire 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 . */ + 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 ."; } - /* 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 , pass its index since from the point of - substitutions, a token is a substitution + substitutions; a 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_NAME_POS is the +/* Demangles and emits a . *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. ::= F [Y] 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 . *TEMPLATE_P is set to +/* Demangles and emits a . *ENCODE_RETURN_TYPE is set to non-zero if the type is a template-id, zero otherwise. ::= */ 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 . - ::= A [] _ */ + ::= A [] _ + ::= A _ */ 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 . The zero-indexed position - in the parameter list is placed in *TEMPLATE_PARM_NUMBER. +/* Demangles and emits a . ::= T_ # first template parameter ::= T _ */ 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 . 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. ::= S _ ::= S_ @@ -2744,14 +3066,13 @@ demangle_expr_primary (dm) ::= So # ::std::basic_ostream > ::= Sd # ::std::basic_iostream > + std::char_traits > */ 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 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 #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 -#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 #include +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 +#ifdef ANSI_PROTOTYPES #include #else #include #endif #include #include -#include +#ifdef HAVE_STDLIB_H +#include +#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 #ifdef HAVE_STDLIB_H #include #endif +#include "libiberty.h" + /* This variable is set by xatexit if it is called. This way, xmalloc doesn't drag xatexit into the link. */ -- cgit v1.1