In include:
* dyn-string.h: Adjust formatting. (dyn_string_insert_char): New macro. New declaration. In libiberty: * 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. From-SVN: r36148
This commit is contained in:
parent
c9672d45dc
commit
31e0ab1f76
6 changed files with 286 additions and 148 deletions
|
@ -1,3 +1,8 @@
|
||||||
|
2000-09-04 Alex Samuel <samuel@codesourcery.com>
|
||||||
|
|
||||||
|
* dyn-string.h: Adjust formatting.
|
||||||
|
(dyn_string_insert_char): New macro. New declaration.
|
||||||
|
|
||||||
2000-08-28 Jason Merrill <jason@redhat.com>
|
2000-08-28 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
* md5.h: New file.
|
* md5.h: New file.
|
||||||
|
|
|
@ -59,6 +59,7 @@ typedef struct dyn_string
|
||||||
#define dyn_string_prepend_cstr __cxa_dyn_string_prepend_cstr
|
#define dyn_string_prepend_cstr __cxa_dyn_string_prepend_cstr
|
||||||
#define dyn_string_insert __cxa_dyn_string_insert
|
#define dyn_string_insert __cxa_dyn_string_insert
|
||||||
#define dyn_string_insert_cstr __cxa_dyn_string_insert_cstr
|
#define dyn_string_insert_cstr __cxa_dyn_string_insert_cstr
|
||||||
|
#define dyn_string_insert_char __cxa_dyn_string_insert_char
|
||||||
#define dyn_string_append __cxa_dyn_string_append
|
#define dyn_string_append __cxa_dyn_string_append
|
||||||
#define dyn_string_append_cstr __cxa_dyn_string_append_cstr
|
#define dyn_string_append_cstr __cxa_dyn_string_append_cstr
|
||||||
#define dyn_string_append_char __cxa_dyn_string_append_char
|
#define dyn_string_append_char __cxa_dyn_string_append_char
|
||||||
|
@ -82,11 +83,10 @@ extern int dyn_string_insert PARAMS ((dyn_string_t, int,
|
||||||
dyn_string_t));
|
dyn_string_t));
|
||||||
extern int dyn_string_insert_cstr PARAMS ((dyn_string_t, int,
|
extern int dyn_string_insert_cstr PARAMS ((dyn_string_t, int,
|
||||||
const char *));
|
const char *));
|
||||||
|
extern int dyn_string_insert_char PARAMS ((dyn_string_t, int, int));
|
||||||
extern int dyn_string_append PARAMS ((dyn_string_t, dyn_string_t));
|
extern int dyn_string_append PARAMS ((dyn_string_t, dyn_string_t));
|
||||||
extern int dyn_string_append_cstr
|
extern int dyn_string_append_cstr PARAMS ((dyn_string_t, const char *));
|
||||||
PARAMS ((dyn_string_t, const char *));
|
extern int dyn_string_append_char PARAMS ((dyn_string_t, int));
|
||||||
extern int dyn_string_append_char
|
|
||||||
PARAMS ((dyn_string_t, int));
|
|
||||||
extern int dyn_string_substring PARAMS ((dyn_string_t,
|
extern int dyn_string_substring PARAMS ((dyn_string_t,
|
||||||
dyn_string_t, int, int));
|
dyn_string_t, int, int));
|
||||||
extern int dyn_string_eq PARAMS ((dyn_string_t, dyn_string_t));
|
extern int dyn_string_eq PARAMS ((dyn_string_t, dyn_string_t));
|
||||||
|
|
|
@ -1,3 +1,35 @@
|
||||||
|
2000-09-03 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-08-31 Hans-Peter Nilsson <hp@axis.com>
|
2000-08-31 Hans-Peter Nilsson <hp@axis.com>
|
||||||
|
|
||||||
* testsuite/demangle-expected: Add nine tests for
|
* testsuite/demangle-expected: Add nine tests for
|
||||||
|
|
|
@ -62,6 +62,10 @@
|
||||||
(((CHAR) >= 'a' && (CHAR) <= 'z') \
|
(((CHAR) >= 'a' && (CHAR) <= 'z') \
|
||||||
|| ((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
|
/* If flag_verbose is zero, some simplifications will be made to the
|
||||||
output to make it easier to read and supress details that are
|
output to make it easier to read and supress details that are
|
||||||
generally not of interest to the average C++ programmer.
|
generally not of interest to the average C++ programmer.
|
||||||
|
@ -92,17 +96,10 @@ struct substitution_def
|
||||||
/* The demangled text of the substitution. */
|
/* The demangled text of the substitution. */
|
||||||
dyn_string_t text;
|
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. */
|
/* Whether this substitution represents a template item. */
|
||||||
int template_p : 1;
|
int template_p : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NOT_TEMPLATE_PARM (-1)
|
|
||||||
|
|
||||||
/* Data structure representing a template argument list. */
|
/* Data structure representing a template argument list. */
|
||||||
|
|
||||||
struct template_arg_list_def
|
struct template_arg_list_def
|
||||||
|
@ -206,7 +203,7 @@ static string_list_t result_pop
|
||||||
static int substitution_start
|
static int substitution_start
|
||||||
PARAMS ((demangling_t));
|
PARAMS ((demangling_t));
|
||||||
static status_t substitution_add
|
static status_t substitution_add
|
||||||
PARAMS ((demangling_t, int, int, int));
|
PARAMS ((demangling_t, int, int));
|
||||||
static dyn_string_t substitution_get
|
static dyn_string_t substitution_get
|
||||||
PARAMS ((demangling_t, int, int *));
|
PARAMS ((demangling_t, int, int *));
|
||||||
#ifdef CP_DEMANGLE_DEBUG
|
#ifdef CP_DEMANGLE_DEBUG
|
||||||
|
@ -288,6 +285,22 @@ static void demangling_delete
|
||||||
(dyn_string_append_char (&(DM)->result->string, (CHAR)) \
|
(dyn_string_append_char (&(DM)->result->string, (CHAR)) \
|
||||||
? STATUS_OK : STATUS_ALLOCATION_FAILED)
|
? 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. */
|
/* The length of the current demangled result. */
|
||||||
#define result_length(DM) \
|
#define result_length(DM) \
|
||||||
dyn_string_length (&(DM)->result->string)
|
dyn_string_length (&(DM)->result->string)
|
||||||
|
@ -458,19 +471,13 @@ substitution_start (dm)
|
||||||
|
|
||||||
/* Adds the suffix of the current demangled result of DM starting at
|
/* Adds the suffix of the current demangled result of DM starting at
|
||||||
START_POSITION as a potential substitution. If TEMPLATE_P is
|
START_POSITION as a potential substitution. If TEMPLATE_P is
|
||||||
non-zero, this potential substitution is a template-id.
|
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. */
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
substitution_add (dm, start_position, template_p, template_parm_number)
|
substitution_add (dm, start_position, template_p)
|
||||||
demangling_t dm;
|
demangling_t dm;
|
||||||
int start_position;
|
int start_position;
|
||||||
int template_p;
|
int template_p;
|
||||||
int template_parm_number;
|
|
||||||
{
|
{
|
||||||
dyn_string_t result = result_string (dm);
|
dyn_string_t result = result_string (dm);
|
||||||
dyn_string_t substitution = dyn_string_new (0);
|
dyn_string_t substitution = dyn_string_new (0);
|
||||||
|
@ -513,7 +520,6 @@ substitution_add (dm, start_position, template_p, template_parm_number)
|
||||||
i = dm->num_substitutions++;
|
i = dm->num_substitutions++;
|
||||||
dm->substitutions[i].text = substitution;
|
dm->substitutions[i].text = substitution;
|
||||||
dm->substitutions[i].template_p = template_p;
|
dm->substitutions[i].template_p = template_p;
|
||||||
dm->substitutions[i].template_parm_number = template_parm_number;
|
|
||||||
|
|
||||||
#ifdef CP_DEMANGLE_DEBUG
|
#ifdef CP_DEMANGLE_DEBUG
|
||||||
substitutions_print (dm, stderr);
|
substitutions_print (dm, stderr);
|
||||||
|
@ -815,7 +821,7 @@ static status_t demangle_special_name
|
||||||
static status_t demangle_ctor_dtor_name
|
static status_t demangle_ctor_dtor_name
|
||||||
PARAMS ((demangling_t));
|
PARAMS ((demangling_t));
|
||||||
static status_t demangle_type_ptr
|
static status_t demangle_type_ptr
|
||||||
PARAMS ((demangling_t));
|
PARAMS ((demangling_t, int *, int));
|
||||||
static status_t demangle_type
|
static status_t demangle_type
|
||||||
PARAMS ((demangling_t));
|
PARAMS ((demangling_t));
|
||||||
static status_t demangle_CV_qualifiers
|
static status_t demangle_CV_qualifiers
|
||||||
|
@ -823,15 +829,15 @@ static status_t demangle_CV_qualifiers
|
||||||
static status_t demangle_builtin_type
|
static status_t demangle_builtin_type
|
||||||
PARAMS ((demangling_t));
|
PARAMS ((demangling_t));
|
||||||
static status_t demangle_function_type
|
static status_t demangle_function_type
|
||||||
PARAMS ((demangling_t, int));
|
PARAMS ((demangling_t, int *));
|
||||||
static status_t demangle_bare_function_type
|
static status_t demangle_bare_function_type
|
||||||
PARAMS ((demangling_t, int));
|
PARAMS ((demangling_t, int *));
|
||||||
static status_t demangle_class_enum_type
|
static status_t demangle_class_enum_type
|
||||||
PARAMS ((demangling_t, int *));
|
PARAMS ((demangling_t, int *));
|
||||||
static status_t demangle_array_type
|
static status_t demangle_array_type
|
||||||
PARAMS ((demangling_t));
|
PARAMS ((demangling_t));
|
||||||
static status_t demangle_template_param
|
static status_t demangle_template_param
|
||||||
PARAMS ((demangling_t, int *));
|
PARAMS ((demangling_t));
|
||||||
static status_t demangle_template_args
|
static status_t demangle_template_args
|
||||||
PARAMS ((demangling_t));
|
PARAMS ((demangling_t));
|
||||||
static status_t demangle_literal
|
static status_t demangle_literal
|
||||||
|
@ -859,7 +865,7 @@ static status_t cp_demangle_type
|
||||||
|
|
||||||
/* When passed to demangle_bare_function_type, indicates that the
|
/* When passed to demangle_bare_function_type, indicates that the
|
||||||
function's return type is not encoded before its parameter types. */
|
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,
|
/* Check that the next character is C. If so, consume it. If not,
|
||||||
return an error. */
|
return an error. */
|
||||||
|
@ -937,7 +943,7 @@ demangle_encoding (dm)
|
||||||
/* Template functions have their return type encoded. The
|
/* Template functions have their return type encoded. The
|
||||||
return type should be inserted at start_position. */
|
return type should be inserted at start_position. */
|
||||||
RETURN_IF_ERROR
|
RETURN_IF_ERROR
|
||||||
(demangle_bare_function_type (dm, start_position));
|
(demangle_bare_function_type (dm, &start_position));
|
||||||
else
|
else
|
||||||
/* Non-template functions don't have their return type
|
/* Non-template functions don't have their return type
|
||||||
encoded. */
|
encoded. */
|
||||||
|
@ -974,6 +980,7 @@ demangle_name (dm, template_p)
|
||||||
{
|
{
|
||||||
int start = substitution_start (dm);
|
int start = substitution_start (dm);
|
||||||
char peek = peek_char (dm);
|
char peek = peek_char (dm);
|
||||||
|
int is_std_substitution = 0;
|
||||||
|
|
||||||
DEMANGLE_TRACE ("name", dm);
|
DEMANGLE_TRACE ("name", dm);
|
||||||
|
|
||||||
|
@ -998,6 +1005,7 @@ demangle_name (dm, template_p)
|
||||||
(void) next_char (dm);
|
(void) next_char (dm);
|
||||||
RETURN_IF_ERROR (result_append (dm, "std::"));
|
RETURN_IF_ERROR (result_append (dm, "std::"));
|
||||||
RETURN_IF_ERROR (demangle_unqualified_name (dm));
|
RETURN_IF_ERROR (demangle_unqualified_name (dm));
|
||||||
|
is_std_substitution = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1007,11 +1015,11 @@ demangle_name (dm, template_p)
|
||||||
If so, then we just demangled an <unqualified-template-name>. */
|
If so, then we just demangled an <unqualified-template-name>. */
|
||||||
if (peek_char (dm) == 'I')
|
if (peek_char (dm) == 'I')
|
||||||
{
|
{
|
||||||
/* The template name is a substitution candidate, unless it
|
/* A template name of the form std::<unqualified-name> is a
|
||||||
was already a back-substitution. */
|
substitution candidate. */
|
||||||
if (peek != 'S')
|
if (is_std_substitution)
|
||||||
RETURN_IF_ERROR (substitution_add (dm, start, 0,
|
RETURN_IF_ERROR (substitution_add (dm, start, 0));
|
||||||
NOT_TEMPLATE_PARM));
|
/* Demangle the <template-args> here. */
|
||||||
RETURN_IF_ERROR (demangle_template_args (dm));
|
RETURN_IF_ERROR (demangle_template_args (dm));
|
||||||
*template_p = 1;
|
*template_p = 1;
|
||||||
}
|
}
|
||||||
|
@ -1029,8 +1037,7 @@ demangle_name (dm, template_p)
|
||||||
if (peek_char (dm) == 'I')
|
if (peek_char (dm) == 'I')
|
||||||
{
|
{
|
||||||
/* Add a substitution for the unqualified template name. */
|
/* Add a substitution for the unqualified template name. */
|
||||||
RETURN_IF_ERROR (substitution_add (dm, start, 0,
|
RETURN_IF_ERROR (substitution_add (dm, start, 0));
|
||||||
NOT_TEMPLATE_PARM));
|
|
||||||
|
|
||||||
RETURN_IF_ERROR (demangle_template_args (dm));
|
RETURN_IF_ERROR (demangle_template_args (dm));
|
||||||
*template_p = 1;
|
*template_p = 1;
|
||||||
|
@ -1185,8 +1192,7 @@ demangle_prefix (dm, template_p)
|
||||||
if (peek != 'S'
|
if (peek != 'S'
|
||||||
&& peek_char (dm) != 'E')
|
&& peek_char (dm) != 'E')
|
||||||
/* Add a new substitution for the prefix thus far. */
|
/* Add a new substitution for the prefix thus far. */
|
||||||
RETURN_IF_ERROR (substitution_add (dm, start, *template_p,
|
RETURN_IF_ERROR (substitution_add (dm, start, *template_p));
|
||||||
NOT_TEMPLATE_PARM));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1353,6 +1359,29 @@ demangle_identifier (dm, length, identifier)
|
||||||
return STATUS_ALLOCATION_FAILED;
|
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;
|
return STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1411,7 +1440,7 @@ demangle_identifier (dm, length, identifier)
|
||||||
::= qu # ?
|
::= qu # ?
|
||||||
::= sz # sizeof
|
::= sz # sizeof
|
||||||
::= cv <type> # cast
|
::= cv <type> # cast
|
||||||
::= vx <source-name> # vendor extended operator */
|
::= v [0-9] <source-name> # vendor extended operator */
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
demangle_operator_name (dm, short_name, num_args)
|
demangle_operator_name (dm, short_name, num_args)
|
||||||
|
@ -1491,10 +1520,10 @@ demangle_operator_name (dm, short_name, num_args)
|
||||||
|
|
||||||
DEMANGLE_TRACE ("operator-name", dm);
|
DEMANGLE_TRACE ("operator-name", dm);
|
||||||
|
|
||||||
/* Is this a vendor extended operator? */
|
/* Is this a vendor-extended operator? */
|
||||||
if (c0 == 'v' && c1 == 'x')
|
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));
|
RETURN_IF_ERROR (demangle_source_name (dm));
|
||||||
*num_args = 0;
|
*num_args = 0;
|
||||||
return STATUS_OK;
|
return STATUS_OK;
|
||||||
|
@ -1832,6 +1861,19 @@ demangle_ctor_dtor_name (dm)
|
||||||
a pointer to data or pointer to function to construct the right
|
a pointer to data or pointer to function to construct the right
|
||||||
output syntax. C++'s pointer syntax is hairy.
|
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>
|
<type> ::= P <type>
|
||||||
::= R <type>
|
::= R <type>
|
||||||
::= <pointer-to-member-type>
|
::= <pointer-to-member-type>
|
||||||
|
@ -1839,104 +1881,131 @@ demangle_ctor_dtor_name (dm)
|
||||||
<pointer-to-member-type> ::= M </class/ type> </member/ type> */
|
<pointer-to-member-type> ::= M </class/ type> </member/ type> */
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
demangle_type_ptr (dm)
|
demangle_type_ptr (dm, insert_pos, substitution_start)
|
||||||
demangling_t dm;
|
demangling_t dm;
|
||||||
|
int *insert_pos;
|
||||||
|
int substitution_start;
|
||||||
{
|
{
|
||||||
char next;
|
char next;
|
||||||
status_t status;
|
status_t status;
|
||||||
|
int is_substitution_candidate = 1;
|
||||||
/* Collect pointer symbols into this string. */
|
|
||||||
dyn_string_t symbols = dyn_string_new (10);
|
|
||||||
|
|
||||||
DEMANGLE_TRACE ("type*", dm);
|
DEMANGLE_TRACE ("type*", dm);
|
||||||
|
|
||||||
if (symbols == NULL)
|
|
||||||
return STATUS_ALLOCATION_FAILED;
|
|
||||||
|
|
||||||
/* Scan forward, collecting pointers and references into symbols,
|
/* Scan forward, collecting pointers and references into symbols,
|
||||||
until we hit something else. Then emit the type. */
|
until we hit something else. Then emit the type. */
|
||||||
while (1)
|
next = peek_char (dm);
|
||||||
|
if (next == 'P')
|
||||||
{
|
{
|
||||||
next = peek_char (dm);
|
/* A pointer. Snarf the `P'. */
|
||||||
if (next == 'P')
|
advance_char (dm);
|
||||||
{
|
/* Demangle the underlying type. */
|
||||||
if (!dyn_string_append_char (symbols, '*'))
|
RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos,
|
||||||
return STATUS_ALLOCATION_FAILED;
|
substitution_start));
|
||||||
advance_char (dm);
|
/* Insert an asterisk where we're told to; it doesn't
|
||||||
}
|
necessarily go at the end. */
|
||||||
else if (next == 'R')
|
RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '*'));
|
||||||
{
|
}
|
||||||
if (!dyn_string_append_char (symbols, '&'))
|
else if (next == 'R')
|
||||||
return STATUS_ALLOCATION_FAILED;
|
{
|
||||||
advance_char (dm);
|
/* A reference. Snarf the `R'. */
|
||||||
}
|
advance_char (dm);
|
||||||
else if (next == 'M')
|
/* Demangle the underlying type. */
|
||||||
{
|
RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos,
|
||||||
/* Pointer-to-member. */
|
substitution_start));
|
||||||
dyn_string_t class_type;
|
/* Insert an ampersand where we're told to; it doesn't
|
||||||
|
necessarily go at the end. */
|
||||||
/* Eat the 'M'. */
|
RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '&'));
|
||||||
advance_char (dm);
|
}
|
||||||
|
else if (next == 'M')
|
||||||
/* Capture the type of which this is a pointer-to-member. */
|
{
|
||||||
RETURN_IF_ERROR (result_push (dm));
|
/* A pointer-to-member. */
|
||||||
RETURN_IF_ERROR (demangle_type (dm));
|
dyn_string_t class_type;
|
||||||
class_type = (dyn_string_t) result_pop (dm);
|
|
||||||
|
/* Eat the 'M'. */
|
||||||
/* Build the pointer-to-member notation. It comes before
|
advance_char (dm);
|
||||||
other pointer and reference qualifiers -- */
|
|
||||||
if (!dyn_string_prepend_cstr (symbols, "::*"))
|
/* Capture the type of which this is a pointer-to-member. */
|
||||||
return STATUS_ALLOCATION_FAILED;
|
RETURN_IF_ERROR (result_push (dm));
|
||||||
if (!dyn_string_prepend (symbols, class_type))
|
RETURN_IF_ERROR (demangle_type (dm));
|
||||||
return STATUS_ALLOCATION_FAILED;
|
class_type = (dyn_string_t) result_pop (dm);
|
||||||
dyn_string_delete (class_type);
|
|
||||||
|
if (peek_char (dm) == 'F')
|
||||||
if (peek_char (dm) == 'F')
|
/* A pointer-to-member function. We want output along the
|
||||||
continue;
|
lines of `void (C::*) (int, int)'. Demangle the function
|
||||||
|
type, which would in this case give `void () (int, int)'
|
||||||
/* Demangle the type of the pointed-to member. */
|
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);
|
status = demangle_type (dm);
|
||||||
/* Make it pretty. */
|
/* Make it pretty. */
|
||||||
if (STATUS_NO_ERROR (status))
|
if (STATUS_NO_ERROR (status))
|
||||||
status = result_append_space (dm);
|
status = result_append_space (dm);
|
||||||
/* Add the pointer-to-member syntax, and other pointer and
|
/* The pointer-to-member notation (e.g. `C::*') follows the
|
||||||
reference symbols. */
|
member's type. */
|
||||||
if (STATUS_NO_ERROR (status))
|
*insert_pos = result_length (dm);
|
||||||
status = result_append_string (dm, symbols);
|
|
||||||
/* Clean up. */
|
|
||||||
dyn_string_delete (symbols);
|
|
||||||
|
|
||||||
RETURN_IF_ERROR (status);
|
|
||||||
return STATUS_OK;
|
|
||||||
}
|
}
|
||||||
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));
|
/* Build the pointer-to-member notation. */
|
||||||
return STATUS_OK;
|
if (STATUS_NO_ERROR (status))
|
||||||
}
|
status = result_insert (dm, *insert_pos, "::*");
|
||||||
else
|
if (STATUS_NO_ERROR (status))
|
||||||
{
|
status = result_insert_string (dm, *insert_pos, class_type);
|
||||||
/* No more pointer or reference tokens. Finish up. */
|
/* There may be additional levels of (pointer or reference)
|
||||||
status = demangle_type (dm);
|
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))
|
/* Clean up. */
|
||||||
status = result_append_string (dm, symbols);
|
dyn_string_delete (class_type);
|
||||||
dyn_string_delete (symbols);
|
|
||||||
|
|
||||||
RETURN_IF_ERROR (status);
|
RETURN_IF_ERROR (status);
|
||||||
return STATUS_OK;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
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>.
|
/* Demangles and emits a <type>.
|
||||||
|
@ -1965,7 +2034,7 @@ demangle_type (dm)
|
||||||
char peek_next;
|
char peek_next;
|
||||||
int template_p = 0;
|
int template_p = 0;
|
||||||
template_arg_list_t old_arg_list = current_template_arg_list (dm);
|
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
|
/* A <type> can be a <substitution>; therefore, this <type> is a
|
||||||
substitution candidate unless a special condition holds (see
|
substitution candidate unless a special condition holds (see
|
||||||
|
@ -2040,7 +2109,7 @@ demangle_type (dm)
|
||||||
/* It's either a <template-param> or a
|
/* It's either a <template-param> or a
|
||||||
<template-template-param>. In either case, demangle the
|
<template-template-param>. In either case, demangle the
|
||||||
`T' token first. */
|
`T' token first. */
|
||||||
RETURN_IF_ERROR (demangle_template_param (dm, &template_parm));
|
RETURN_IF_ERROR (demangle_template_param (dm));
|
||||||
|
|
||||||
/* Check for a template argument list; if one is found, it's a
|
/* Check for a template argument list; if one is found, it's a
|
||||||
<template-template-param> ::= <template-param>
|
<template-template-param> ::= <template-param>
|
||||||
|
@ -2050,8 +2119,7 @@ demangle_type (dm)
|
||||||
/* Add a substitution candidate. The template parameter
|
/* Add a substitution candidate. The template parameter
|
||||||
`T' token is a substitution candidate by itself,
|
`T' token is a substitution candidate by itself,
|
||||||
without the template argument list. */
|
without the template argument list. */
|
||||||
RETURN_IF_ERROR (substitution_add (dm, start, template_p,
|
RETURN_IF_ERROR (substitution_add (dm, start, template_p));
|
||||||
template_parm));
|
|
||||||
|
|
||||||
/* Now demangle the template argument list. */
|
/* Now demangle the template argument list. */
|
||||||
RETURN_IF_ERROR (demangle_template_args (dm));
|
RETURN_IF_ERROR (demangle_template_args (dm));
|
||||||
|
@ -2077,23 +2145,27 @@ demangle_type (dm)
|
||||||
them. */
|
them. */
|
||||||
if (peek_char (dm) == 'I')
|
if (peek_char (dm) == 'I')
|
||||||
RETURN_IF_ERROR (demangle_template_args (dm));
|
RETURN_IF_ERROR (demangle_template_args (dm));
|
||||||
|
else
|
||||||
/* A substitution token is not itself a substitution
|
/* A substitution token is not itself a substitution
|
||||||
candidate. */
|
candidate. (However, if the substituted template is
|
||||||
is_substitution_candidate = 0;
|
instantiated, the resulting type is.) */
|
||||||
|
is_substitution_candidate = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* While the special substitution token itself is not a
|
/* While the special substitution token itself is not a
|
||||||
substitution candidate, the <class-enum-type> is, so
|
substitution candidate, the <class-enum-type> is, so
|
||||||
don't clear is_substitution_candidate. */
|
don't clear is_substitution_candidate. */
|
||||||
demangle_class_enum_type (dm, &template_p);
|
RETURN_IF_ERROR (demangle_class_enum_type (dm, &template_p));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'P':
|
case 'P':
|
||||||
case 'R':
|
case 'R':
|
||||||
case 'M':
|
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;
|
break;
|
||||||
|
|
||||||
case 'C':
|
case 'C':
|
||||||
|
@ -2111,7 +2183,7 @@ demangle_type (dm)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'U':
|
case 'U':
|
||||||
/* Vendor extended type qualifier. */
|
/* Vendor-extended type qualifier. */
|
||||||
advance_char (dm);
|
advance_char (dm);
|
||||||
RETURN_IF_ERROR (demangle_source_name (dm));
|
RETURN_IF_ERROR (demangle_source_name (dm));
|
||||||
RETURN_IF_ERROR (result_append_char (dm, ' '));
|
RETURN_IF_ERROR (result_append_char (dm, ' '));
|
||||||
|
@ -2127,7 +2199,7 @@ demangle_type (dm)
|
||||||
<template-param>, pass its index since from the point of
|
<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. */
|
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, template_p));
|
||||||
|
|
||||||
/* Pop off template argument lists added during mangling of this
|
/* Pop off template argument lists added during mangling of this
|
||||||
type. */
|
type. */
|
||||||
|
@ -2266,16 +2338,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
|
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 */
|
<function-type> ::= F [Y] <bare-function-type> E */
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
demangle_function_type (dm, function_name_pos)
|
demangle_function_type (dm, function_name_pos)
|
||||||
demangling_t dm;
|
demangling_t dm;
|
||||||
int function_name_pos;
|
int *function_name_pos;
|
||||||
{
|
{
|
||||||
DEMANGLE_TRACE ("function-type", dm);
|
DEMANGLE_TRACE ("function-type", dm);
|
||||||
RETURN_IF_ERROR (demangle_char (dm, 'F'));
|
RETURN_IF_ERROR (demangle_char (dm, 'F'));
|
||||||
|
@ -2301,7 +2375,7 @@ demangle_function_type (dm, function_name_pos)
|
||||||
static status_t
|
static status_t
|
||||||
demangle_bare_function_type (dm, return_type_pos)
|
demangle_bare_function_type (dm, return_type_pos)
|
||||||
demangling_t dm;
|
demangling_t dm;
|
||||||
int return_type_pos;
|
int *return_type_pos;
|
||||||
{
|
{
|
||||||
/* Sequence is the index of the current function parameter, counting
|
/* Sequence is the index of the current function parameter, counting
|
||||||
from zero. The value -1 denotes the return type. */
|
from zero. The value -1 denotes the return type. */
|
||||||
|
@ -2326,10 +2400,16 @@ demangle_bare_function_type (dm, return_type_pos)
|
||||||
|
|
||||||
/* Add a space to the end of the type. Insert the return
|
/* Add a space to the end of the type. Insert the return
|
||||||
type where we've been asked to. */
|
type where we've been asked to. */
|
||||||
if (!dyn_string_append_space (return_type)
|
if (!dyn_string_append_space (return_type))
|
||||||
|| !dyn_string_insert (result_string (dm), return_type_pos,
|
|
||||||
return_type))
|
|
||||||
status = STATUS_ALLOCATION_FAILED;
|
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);
|
dyn_string_delete (return_type);
|
||||||
RETURN_IF_ERROR (status);
|
RETURN_IF_ERROR (status);
|
||||||
|
@ -2436,16 +2516,14 @@ demangle_array_type (dm)
|
||||||
return STATUS_OK;
|
return STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Demangles and emits a <template-param>. The zero-indexed position
|
/* Demangles and emits a <template-param>.
|
||||||
in the parameter list is placed in *TEMPLATE_PARM_NUMBER.
|
|
||||||
|
|
||||||
<template-param> ::= T_ # first template parameter
|
<template-param> ::= T_ # first template parameter
|
||||||
::= T <parameter-2 number> _ */
|
::= T <parameter-2 number> _ */
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
demangle_template_param (dm, template_parm_number)
|
demangle_template_param (dm)
|
||||||
demangling_t dm;
|
demangling_t dm;
|
||||||
int *template_parm_number;
|
|
||||||
{
|
{
|
||||||
int parm_number;
|
int parm_number;
|
||||||
template_arg_list_t current_arg_list = current_template_arg_list (dm);
|
template_arg_list_t current_arg_list = current_template_arg_list (dm);
|
||||||
|
@ -2475,7 +2553,6 @@ demangle_template_param (dm, template_parm_number)
|
||||||
return "Template parameter number out of bounds.";
|
return "Template parameter number out of bounds.";
|
||||||
RETURN_IF_ERROR (result_append_string (dm, (dyn_string_t) arg));
|
RETURN_IF_ERROR (result_append_string (dm, (dyn_string_t) arg));
|
||||||
|
|
||||||
*template_parm_number = parm_number;
|
|
||||||
return STATUS_OK;
|
return STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2784,12 +2861,11 @@ demangle_expr_primary (dm)
|
||||||
demangling_t dm;
|
demangling_t dm;
|
||||||
{
|
{
|
||||||
char peek = peek_char (dm);
|
char peek = peek_char (dm);
|
||||||
int unused;
|
|
||||||
|
|
||||||
DEMANGLE_TRACE ("expr-primary", dm);
|
DEMANGLE_TRACE ("expr-primary", dm);
|
||||||
|
|
||||||
if (peek == 'T')
|
if (peek == 'T')
|
||||||
RETURN_IF_ERROR (demangle_template_param (dm, &unused));
|
RETURN_IF_ERROR (demangle_template_param (dm));
|
||||||
else if (peek == 'L')
|
else if (peek == 'L')
|
||||||
{
|
{
|
||||||
/* Consume the `L'. */
|
/* Consume the `L'. */
|
||||||
|
@ -2826,7 +2902,7 @@ demangle_expr_primary (dm)
|
||||||
::= So # ::std::basic_ostream<char,
|
::= So # ::std::basic_ostream<char,
|
||||||
std::char_traits<char> >
|
std::char_traits<char> >
|
||||||
::= Sd # ::std::basic_iostream<char,
|
::= Sd # ::std::basic_iostream<char,
|
||||||
std::char_traits<char> >
|
std::char_traits<char> >
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
|
@ -3297,7 +3373,8 @@ static void print_usage
|
||||||
|
|
||||||
/* Non-zero if CHAR is a character than can occur in a mangled name. */
|
/* Non-zero if CHAR is a character than can occur in a mangled name. */
|
||||||
#define is_mangled_char(CHAR) \
|
#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. */
|
/* The name of this program, as invoked. */
|
||||||
const char* program_name;
|
const char* program_name;
|
||||||
|
|
|
@ -4853,7 +4853,7 @@ hp_symbol_characters ()
|
||||||
static const char *
|
static const char *
|
||||||
gnu_new_abi_symbol_characters ()
|
gnu_new_abi_symbol_characters ()
|
||||||
{
|
{
|
||||||
return "_";
|
return "_$.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -305,6 +305,30 @@ dyn_string_insert_cstr (dest, pos, src)
|
||||||
return 1;
|
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.
|
/* Append S to DS, resizing DS if necessary. Returns 1 on success.
|
||||||
On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and
|
On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and
|
||||||
returns 0. */
|
returns 0. */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue