Commit 0870bfd6 by Alex Samuel Committed by Alex Samuel

cp-demangle.c (string_list_def): Add caret_position and comments.

	* cp-demangle.c (string_list_def): Add caret_position and comments.
	(result_caret_pos): New macro.
	(result_append_string): Rename to...
	(result_add_string): ... this, and insert at caret position.
	Rename throughout.
	(result_append): Rename to...
	(result_add): ... this, and insert at caret position.  Rename
	throughout.
	(result_append_char): Rename to...
	(result_add_char): ... this, and insert at caret position.  Rename
	throughout.
	(result_append_space): Remove.
	(string_list_new): Initialize caret position.
	(result_add_separated_char): Use caret position.
	(result_get_caret): New funtion.
	(result_set_caret): Likewise.
	(result_shift_caret): Likewise.
	(result_previous_char_is_space): Likewise.
	(substitution_start): Use caret position.
	(substitution_add): Likewise.
	(demangling_new): Initialize caret position.
	(demangle_encoding): Use caret position.
	(demanglin_nested_name): Put CV qualifiers after name.
	(demangle_type_ptr): Use switch statement.  Handle pointers to
	arrays.  Don't use result_append_space.  Use caret position.
	(demangle_type): Emit CV qualifiers after underlying type.  Adjust
	call to demangle_array_type.
	(demangle_array_type): Add parameter to handle pointers to arrays.

From-SVN: r37011
parent ae4bd622
2000-10-20 Alex Samuel <samuel@codesourcery.com>
* cp-demangle.c (string_list_def): Add caret_position and comments.
(result_caret_pos): New macro.
(result_append_string): Rename to...
(result_add_string): ... this, and insert at caret position.
Rename throughout.
(result_append): Rename to...
(result_add): ... this, and insert at caret position. Rename
throughout.
(result_append_char): Rename to...
(result_add_char): ... this, and insert at caret position. Rename
throughout.
(result_append_space): Remove.
(string_list_new): Initialize caret position.
(result_add_separated_char): Use caret position.
(result_get_caret): New funtion.
(result_set_caret): Likewise.
(result_shift_caret): Likewise.
(result_previous_char_is_space): Likewise.
(substitution_start): Use caret position.
(substitution_add): Likewise.
(demangling_new): Initialize caret position.
(demangle_encoding): Use caret position.
(demanglin_nested_name): Put CV qualifiers after name.
(demangle_type_ptr): Use switch statement. Handle pointers to
arrays. Don't use result_append_space. Use caret position.
(demangle_type): Emit CV qualifiers after underlying type. Adjust
call to demangle_array_type.
(demangle_array_type): Add parameter to handle pointers to arrays.
2000-10-01 Mark Mitchell <mark@codesourcery.com>
* splay-tree.c (splay_tree_insert): Fix formatting.
......
......@@ -79,13 +79,22 @@ static int flag_verbose;
specification -- don't demangle special g++ manglings. */
static int flag_strict;
/* String_list_t is an extended form of dyn_string_t which provides a link
field. A string_list_t may safely be cast to and used as a
dyn_string_t. */
/* String_list_t is an extended form of dyn_string_t which provides a
link field and a caret position for additions to the string. A
string_list_t may safely be cast to and used as a dyn_string_t. */
struct string_list_def
{
/* The dyn_string; must be first. */
struct dyn_string string;
/* The position at which additional text is added to this string
(using the result_add* macros). This value is an offset from the
end of the string, not the beginning (and should be
non-positive). */
int caret_position;
/* The next string in the list. */
struct string_list_def *next;
};
......@@ -272,19 +281,28 @@ static void demangling_delete
/* Returns the string containing the current demangled result. */
#define result_string(DM) (&(DM)->result->string)
/* Appends a dyn_string_t to the demangled result. */
#define result_append_string(DM, STRING) \
(dyn_string_append (&(DM)->result->string, (STRING)) \
/* Returns the position at which new text is inserted into the
demangled result. */
#define result_caret_pos(DM) \
(result_length (DM) + \
((string_list_t) result_string (DM))->caret_position)
/* Adds a dyn_string_t to the demangled result. */
#define result_add_string(DM, STRING) \
(dyn_string_insert (&(DM)->result->string, \
result_caret_pos (DM), (STRING)) \
? STATUS_OK : STATUS_ALLOCATION_FAILED)
/* Appends NUL-terminated string CSTR to the demangled result. */
#define result_append(DM, CSTR) \
(dyn_string_append_cstr (&(DM)->result->string, (CSTR)) \
/* Adds NUL-terminated string CSTR to the demangled result. */
#define result_add(DM, CSTR) \
(dyn_string_insert_cstr (&(DM)->result->string, \
result_caret_pos (DM), (CSTR)) \
? STATUS_OK : STATUS_ALLOCATION_FAILED)
/* Appends character CHAR to the demangled result. */
#define result_append_char(DM, CHAR) \
(dyn_string_append_char (&(DM)->result->string, (CHAR)) \
/* Adds character CHAR to the demangled result. */
#define result_add_char(DM, CHAR) \
(dyn_string_insert_char (&(DM)->result->string, \
result_caret_pos (DM), (CHAR)) \
? STATUS_OK : STATUS_ALLOCATION_FAILED)
/* Inserts a dyn_string_t to the demangled result at position POS. */
......@@ -307,12 +325,6 @@ static void demangling_delete
#define result_length(DM) \
dyn_string_length (&(DM)->result->string)
/* Appends a space to the demangled result if the last character is
not a space. */
#define result_append_space(DM) \
(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
......@@ -380,6 +392,7 @@ string_list_new (length)
int length;
{
string_list_t s = (string_list_t) malloc (sizeof (struct string_list_def));
s->caret_position = 0;
if (s == NULL)
return NULL;
if (!dyn_string_init ((dyn_string_t) s, length))
......@@ -409,20 +422,15 @@ result_add_separated_char (dm, character)
demangling_t dm;
int character;
{
dyn_string_t s = &dm->result->string;
char *result = dyn_string_buf (result_string (dm));
int caret_pos = result_caret_pos (dm);
/* 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) == character)
{
if (!dyn_string_append_char (s, ' '))
return STATUS_ALLOCATION_FAILED;
}
/* Add closing angle brackets. */
if (!dyn_string_append_char (s, character))
return STATUS_ALLOCATION_FAILED;
/* Add a space if the last character is already the character we
want to add. */
if (caret_pos > 0 && result[caret_pos - 1] == character)
RETURN_IF_ERROR (result_add_char (dm, ' '));
/* Add the character. */
RETURN_IF_ERROR (result_add_char (dm, character));
return STATUS_OK;
}
......@@ -460,6 +468,51 @@ result_pop (dm)
return top;
}
/* Returns the current value of the caret for the result string. The
value is an offet from the end of the result string. */
static int
result_get_caret (dm)
demangling_t dm;
{
return ((string_list_t) result_string (dm))->caret_position;
}
/* Sets the value of the caret for the result string, counted as an
offet from the end of the result string. */
static void
result_set_caret (dm, position)
demangling_t dm;
int position;
{
((string_list_t) result_string (dm))->caret_position = position;
}
/* Shifts the position of the next addition to the result by
POSITION_OFFSET. A negative value shifts the caret to the left. */
static void
result_shift_caret (dm, position_offset)
demangling_t dm;
int position_offset;
{
((string_list_t) result_string (dm))->caret_position += position_offset;
}
/* Returns non-zero if the character that comes right before the place
where text will be added to the result is a space. In this case,
the caller should supress adding another space. */
static int
result_previous_char_is_space (dm)
demangling_t dm;
{
char *result = dyn_string_buf (result_string (dm));
int pos = result_caret_pos (dm);
return pos > 0 && result[pos - 1] == ' ';
}
/* Returns the start position of a fragment of the demangled result
that will be a substitution candidate. Should be called at the
start of productions that can add substitutions. */
......@@ -468,7 +521,7 @@ static int
substitution_start (dm)
demangling_t dm;
{
return result_length (dm);
return result_caret_pos (dm);
}
/* Adds the suffix of the current demangled result of DM starting at
......@@ -491,7 +544,7 @@ substitution_add (dm, start_position, template_p)
/* Extract the substring of the current demangling result that
represents the subsitution candidate. */
if (!dyn_string_substring (substitution,
result, start_position, result_length (dm)))
result, start_position, result_caret_pos (dm)))
{
dyn_string_delete (substitution);
return STATUS_ALLOCATION_FAILED;
......@@ -843,7 +896,7 @@ static status_t demangle_bare_function_type
static status_t demangle_class_enum_type
PARAMS ((demangling_t, int *));
static status_t demangle_array_type
PARAMS ((demangling_t));
PARAMS ((demangling_t, int *));
static status_t demangle_template_param
PARAMS ((demangling_t));
static status_t demangle_template_args
......@@ -933,7 +986,7 @@ demangle_encoding (dm)
/* Remember where the name starts. If it turns out to be a template
function, we'll have to insert the return type here. */
start_position = result_length (dm);
start_position = result_caret_pos (dm);
if (peek == 'G' || peek == 'T')
RETURN_IF_ERROR (demangle_special_name (dm));
......@@ -943,7 +996,7 @@ demangle_encoding (dm)
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. */
maybe its return type, and its parameter types, following. */
if (!end_of_name_p (dm)
&& peek_char (dm) != 'E')
{
......@@ -1017,7 +1070,7 @@ demangle_name (dm, encode_return_type)
{
(void) next_char (dm);
(void) next_char (dm);
RETURN_IF_ERROR (result_append (dm, "std::"));
RETURN_IF_ERROR (result_add (dm, "std::"));
RETURN_IF_ERROR
(demangle_unqualified_name (dm, &suppress_return_type));
is_std_substitution = 1;
......@@ -1082,20 +1135,30 @@ demangle_nested_name (dm, encode_return_type)
peek = peek_char (dm);
if (peek == 'r' || peek == 'V' || peek == 'K')
{
dyn_string_t cv_qualifiers;
status_t status;
/* Snarf up and emit CV qualifiers. */
dyn_string_t cv_qualifiers = dyn_string_new (24);
/* Snarf up CV qualifiers. */
cv_qualifiers = dyn_string_new (24);
if (cv_qualifiers == NULL)
return STATUS_ALLOCATION_FAILED;
demangle_CV_qualifiers (dm, cv_qualifiers);
status = result_append_string (dm, cv_qualifiers);
/* Emit them, preceded by a space. */
status = result_add_char (dm, ' ');
if (STATUS_NO_ERROR (status))
status = result_add_string (dm, cv_qualifiers);
/* The CV qualifiers that occur in a <nested-name> will be
qualifiers for member functions. These are placed at the end
of the function. Therefore, shift the caret to the left by
the length of the qualifiers, so other text is inserted
before them and they stay at the end. */
result_shift_caret (dm, -dyn_string_length (cv_qualifiers) - 1);
/* Clean up. */
dyn_string_delete (cv_qualifiers);
RETURN_IF_ERROR (status);
RETURN_IF_ERROR (result_append_space (dm));
}
RETURN_IF_ERROR (demangle_prefix (dm, encode_return_type));
/* No need to demangle the final <unqualified-name>; demangle_prefix
will handle it. */
......@@ -1159,7 +1222,7 @@ demangle_prefix (dm, encode_return_type)
{
/* We have another level of scope qualification. */
if (nested)
RETURN_IF_ERROR (result_append (dm, "::"));
RETURN_IF_ERROR (result_add (dm, "::"));
else
nested = 1;
......@@ -1275,7 +1338,7 @@ demangle_source_name (dm)
dm->last_source_name));
/* Emit it. */
RETURN_IF_ERROR (result_append_string (dm, dm->last_source_name));
RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
return STATUS_OK;
}
......@@ -1547,7 +1610,7 @@ demangle_operator_name (dm, short_name, num_args)
/* Is this a vendor-extended operator? */
if (c0 == 'v' && IS_DIGIT (c1))
{
RETURN_IF_ERROR (result_append (dm, "operator "));
RETURN_IF_ERROR (result_add (dm, "operator "));
RETURN_IF_ERROR (demangle_source_name (dm));
*num_args = 0;
return STATUS_OK;
......@@ -1556,7 +1619,7 @@ demangle_operator_name (dm, short_name, num_args)
/* Is this a conversion operator? */
if (c0 == 'c' && c1 == 'v')
{
RETURN_IF_ERROR (result_append (dm, "operator "));
RETURN_IF_ERROR (result_add (dm, "operator "));
/* Demangle the converted-to type. */
RETURN_IF_ERROR (demangle_type (dm));
*num_args = 0;
......@@ -1574,8 +1637,8 @@ demangle_operator_name (dm, short_name, num_args)
/* Found it. */
{
if (!short_name)
RETURN_IF_ERROR (result_append (dm, "operator"));
RETURN_IF_ERROR (result_append (dm, p->name));
RETURN_IF_ERROR (result_add (dm, "operator"));
RETURN_IF_ERROR (result_add (dm, p->name));
*num_args = p->num_args;
return STATUS_OK;
......@@ -1615,11 +1678,11 @@ demangle_nv_offset (dm)
/* Don't display the offset unless in verbose mode. */
if (flag_verbose)
{
status = result_append (dm, " [nv:");
status = result_add (dm, " [nv:");
if (STATUS_NO_ERROR (status))
status = result_append_string (dm, number);
status = result_add_string (dm, number);
if (STATUS_NO_ERROR (status))
status = result_append_char (dm, ']');
status = result_add_char (dm, ']');
}
/* Clean up. */
......@@ -1651,11 +1714,11 @@ demangle_v_offset (dm)
/* Don't display the offset unless in verbose mode. */
if (flag_verbose)
{
status = result_append (dm, " [v:");
status = result_add (dm, " [v:");
if (STATUS_NO_ERROR (status))
status = result_append_string (dm, number);
status = result_add_string (dm, number);
if (STATUS_NO_ERROR (status))
result_append_char (dm, ',');
result_add_char (dm, ',');
}
dyn_string_delete (number);
RETURN_IF_ERROR (status);
......@@ -1672,9 +1735,9 @@ demangle_v_offset (dm)
/* Don't display the vcall offset unless in verbose mode. */
if (flag_verbose)
{
status = result_append_string (dm, number);
status = result_add_string (dm, number);
if (STATUS_NO_ERROR (status))
status = result_append_char (dm, ']');
status = result_add_char (dm, ']');
}
dyn_string_delete (number);
RETURN_IF_ERROR (status);
......@@ -1763,7 +1826,7 @@ demangle_special_name (dm)
/* A guard variable name. Consume the G. */
advance_char (dm);
RETURN_IF_ERROR (demangle_char (dm, 'V'));
RETURN_IF_ERROR (result_append (dm, "guard variable for "));
RETURN_IF_ERROR (result_add (dm, "guard variable for "));
RETURN_IF_ERROR (demangle_name (dm, &unused));
}
else if (peek == 'T')
......@@ -1778,77 +1841,77 @@ demangle_special_name (dm)
case 'V':
/* Virtual table. */
advance_char (dm);
RETURN_IF_ERROR (result_append (dm, "vtable for "));
RETURN_IF_ERROR (result_add (dm, "vtable for "));
RETURN_IF_ERROR (demangle_type (dm));
break;
case 'T':
/* VTT structure. */
advance_char (dm);
RETURN_IF_ERROR (result_append (dm, "VTT for "));
RETURN_IF_ERROR (result_add (dm, "VTT for "));
RETURN_IF_ERROR (demangle_type (dm));
break;
case 'I':
/* Typeinfo structure. */
advance_char (dm);
RETURN_IF_ERROR (result_append (dm, "typeinfo for "));
RETURN_IF_ERROR (result_add (dm, "typeinfo for "));
RETURN_IF_ERROR (demangle_type (dm));
break;
case 'F':
/* Typeinfo function. Used only in old ABI with new mangling. */
advance_char (dm);
RETURN_IF_ERROR (result_append (dm, "typeinfo fn for "));
RETURN_IF_ERROR (result_add (dm, "typeinfo fn for "));
RETURN_IF_ERROR (demangle_type (dm));
break;
case 'S':
/* Character string containing type name, used in typeinfo. */
advance_char (dm);
RETURN_IF_ERROR (result_append (dm, "typeinfo name for "));
RETURN_IF_ERROR (result_add (dm, "typeinfo name for "));
RETURN_IF_ERROR (demangle_type (dm));
break;
case 'J':
/* The java Class variable corresponding to a C++ class. */
advance_char (dm);
RETURN_IF_ERROR (result_append (dm, "java Class for "));
RETURN_IF_ERROR (result_add (dm, "java Class for "));
RETURN_IF_ERROR (demangle_type (dm));
break;
case 'h':
/* Non-virtual thunk. */
advance_char (dm);
RETURN_IF_ERROR (result_append (dm, "non-virtual thunk"));
RETURN_IF_ERROR (result_add (dm, "non-virtual thunk"));
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. */
RETURN_IF_ERROR (result_append (dm, " to "));
RETURN_IF_ERROR (result_add (dm, " to "));
RETURN_IF_ERROR (demangle_encoding (dm));
break;
case 'v':
/* Virtual thunk. */
advance_char (dm);
RETURN_IF_ERROR (result_append (dm, "virtual thunk"));
RETURN_IF_ERROR (result_add (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_add (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 (result_add (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 (result_add (dm, " to "));
RETURN_IF_ERROR (demangle_encoding (dm));
break;
......@@ -1859,7 +1922,7 @@ demangle_special_name (dm)
dyn_string_t derived_type;
advance_char (dm);
RETURN_IF_ERROR (result_append (dm, "construction vtable for "));
RETURN_IF_ERROR (result_add (dm, "construction vtable for "));
/* Demangle the derived type off to the side. */
RETURN_IF_ERROR (result_push (dm));
......@@ -1883,17 +1946,17 @@ demangle_special_name (dm)
/* Emit the derived type. */
if (STATUS_NO_ERROR (status))
status = result_append (dm, "-in-");
status = result_add (dm, "-in-");
if (STATUS_NO_ERROR (status))
status = result_append_string (dm, derived_type);
status = result_add_string (dm, derived_type);
dyn_string_delete (derived_type);
/* Don't display the offset unless in verbose mode. */
if (flag_verbose)
{
status = result_append_char (dm, ' ');
status = result_add_char (dm, ' ');
if (STATUS_NO_ERROR (status))
result_append_string (dm, number);
result_add_string (dm, number);
}
dyn_string_delete (number);
RETURN_IF_ERROR (status);
......@@ -1949,14 +2012,14 @@ demangle_ctor_dtor_name (dm)
advance_char (dm);
if (peek_char (dm) < '1' || peek_char (dm) > '3')
return "Unrecognized constructor.";
RETURN_IF_ERROR (result_append_string (dm, dm->last_source_name));
RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
/* Print the flavor of the constructor if in verbose mode. */
flavor = next_char (dm) - '1';
if (flag_verbose)
{
RETURN_IF_ERROR (result_append (dm, "["));
RETURN_IF_ERROR (result_append (dm, ctor_flavors[flavor]));
RETURN_IF_ERROR (result_append_char (dm, ']'));
RETURN_IF_ERROR (result_add (dm, "["));
RETURN_IF_ERROR (result_add (dm, ctor_flavors[flavor]));
RETURN_IF_ERROR (result_add_char (dm, ']'));
}
}
else if (peek == 'D')
......@@ -1965,15 +2028,15 @@ demangle_ctor_dtor_name (dm)
advance_char (dm);
if (peek_char (dm) < '0' || peek_char (dm) > '2')
return "Unrecognized destructor.";
RETURN_IF_ERROR (result_append_char (dm, '~'));
RETURN_IF_ERROR (result_append_string (dm, dm->last_source_name));
RETURN_IF_ERROR (result_add_char (dm, '~'));
RETURN_IF_ERROR (result_add_string (dm, dm->last_source_name));
/* Print the flavor of the destructor if in verbose mode. */
flavor = next_char (dm) - '0';
if (flag_verbose)
{
RETURN_IF_ERROR (result_append (dm, " ["));
RETURN_IF_ERROR (result_append (dm, dtor_flavors[flavor]));
RETURN_IF_ERROR (result_append_char (dm, ']'));
RETURN_IF_ERROR (result_add (dm, " ["));
RETURN_IF_ERROR (result_add (dm, dtor_flavors[flavor]));
RETURN_IF_ERROR (result_add_char (dm, ']'));
}
}
else
......@@ -2014,7 +2077,6 @@ demangle_type_ptr (dm, insert_pos, substitution_start)
int *insert_pos;
int substitution_start;
{
char next;
status_t status;
int is_substitution_candidate = 1;
......@@ -2022,9 +2084,9 @@ demangle_type_ptr (dm, insert_pos, substitution_start)
/* Scan forward, collecting pointers and references into symbols,
until we hit something else. Then emit the type. */
next = peek_char (dm);
if (next == 'P')
switch (peek_char (dm))
{
case 'P':
/* A pointer. Snarf the `P'. */
advance_char (dm);
/* Demangle the underlying type. */
......@@ -2036,9 +2098,9 @@ demangle_type_ptr (dm, insert_pos, substitution_start)
/* The next (outermost) pointer or reference character should go
after this one. */
++(*insert_pos);
}
else if (next == 'R')
{
break;
case 'R':
/* A reference. Snarf the `R'. */
advance_char (dm);
/* Demangle the underlying type. */
......@@ -2050,8 +2112,9 @@ demangle_type_ptr (dm, insert_pos, substitution_start)
/* The next (outermost) pointer or reference character should go
after this one. */
++(*insert_pos);
}
else if (next == 'M')
break;
case 'M':
{
/* A pointer-to-member. */
dyn_string_t class_type;
......@@ -2071,17 +2134,24 @@ demangle_type_ptr (dm, insert_pos, substitution_start)
and set *insert_pos to the spot between the first
parentheses. */
status = demangle_type_ptr (dm, insert_pos, substitution_start);
else if (peek_char (dm) == 'A')
/* A pointer-to-member array variable. We want output that
looks like `int (Klass::*) [10]'. Demangle the array type
as `int () [10]', and set *insert_pos to the spot between
the parentheses. */
status = demangle_array_type (dm, insert_pos);
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);
if (STATUS_NO_ERROR (status)
&& !result_previous_char_is_space (dm))
status = result_add_char (dm, ' ');
/* The pointer-to-member notation (e.g. `C::*') follows the
member's type. */
*insert_pos = result_length (dm);
*insert_pos = result_caret_pos (dm);
}
/* Build the pointer-to-member notation. */
......@@ -2100,15 +2170,16 @@ demangle_type_ptr (dm, insert_pos, substitution_start)
RETURN_IF_ERROR (status);
}
else if (next == 'F')
{
break;
case '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);
*insert_pos = result_caret_pos (dm);
/* The parentheses indicate this is a function pointer or
reference type. */
RETURN_IF_ERROR (result_append (dm, "()"));
RETURN_IF_ERROR (result_add (dm, "()"));
/* Now demangle the function type. The return type will be
inserted before the `()', and the argument list will go after
it. */
......@@ -2120,20 +2191,27 @@ demangle_type_ptr (dm, insert_pos, substitution_start)
type. Move it one character over so it points inside the
`()'. */
++(*insert_pos);
}
else
{
break;
case 'A':
/* An array pointer or reference. demangle_array_type will figure
out where the asterisks and ampersands go. */
RETURN_IF_ERROR (demangle_array_type (dm, insert_pos));
break;
default:
/* 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);
*insert_pos = result_caret_pos (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;
break;
}
if (is_substitution_candidate)
......@@ -2201,34 +2279,30 @@ demangle_type (dm)
{
status_t status;
dyn_string_t cv_qualifiers = dyn_string_new (24);
int old_caret_position = result_get_caret (dm);
if (cv_qualifiers == NULL)
return STATUS_ALLOCATION_FAILED;
/* Decode all adjacent CV qualifiers. */
demangle_CV_qualifiers (dm, cv_qualifiers);
/* If the qualifiers apply to a pointer or reference, they
need to come after the whole qualified type. */
if (peek_char (dm) == 'P' || peek_char (dm) == 'R')
{
status = demangle_type (dm);
if (STATUS_NO_ERROR (status))
status = result_append_space (dm);
if (STATUS_NO_ERROR (status))
status = result_append_string (dm, cv_qualifiers);
}
/* Otherwise, the qualifiers come first. */
else
{
status = result_append_string (dm, cv_qualifiers);
if (STATUS_NO_ERROR (status))
status = result_append_space (dm);
if (STATUS_NO_ERROR (status))
status = demangle_type (dm);
}
/* Emit them, and shift the caret left so that the
underlying type will be emitted before the qualifiers. */
status = result_add_string (dm, cv_qualifiers);
result_shift_caret (dm, -dyn_string_length (cv_qualifiers));
/* Clean up. */
dyn_string_delete (cv_qualifiers);
RETURN_IF_ERROR (status);
/* Also prepend a blank, if needed. */
RETURN_IF_ERROR (result_add_char (dm, ' '));
result_shift_caret (dm, -1);
/* Demangle the underlying type. It will be emitted before
the CV qualifiers, since we moved the caret. */
RETURN_IF_ERROR (demangle_type (dm));
/* Put the caret back where it was previously. */
result_set_caret (dm, old_caret_position);
}
break;
......@@ -2236,7 +2310,7 @@ demangle_type (dm)
return "Non-pointer or -reference function type.";
case 'A':
RETURN_IF_ERROR (demangle_array_type (dm));
RETURN_IF_ERROR (demangle_array_type (dm, NULL));
break;
case 'T':
......@@ -2325,14 +2399,14 @@ demangle_type (dm)
case 'C':
/* A C99 complex type. */
RETURN_IF_ERROR (result_append (dm, "complex "));
RETURN_IF_ERROR (result_add (dm, "complex "));
advance_char (dm);
RETURN_IF_ERROR (demangle_type (dm));
break;
case 'G':
/* A C99 imaginary type. */
RETURN_IF_ERROR (result_append (dm, "imaginary "));
RETURN_IF_ERROR (result_add (dm, "imaginary "));
advance_char (dm);
RETURN_IF_ERROR (demangle_type (dm));
break;
......@@ -2341,7 +2415,7 @@ demangle_type (dm)
/* Vendor-extended type qualifier. */
advance_char (dm);
RETURN_IF_ERROR (demangle_source_name (dm));
RETURN_IF_ERROR (result_append_char (dm, ' '));
RETURN_IF_ERROR (result_add_char (dm, ' '));
RETURN_IF_ERROR (demangle_type (dm));
break;
......@@ -2441,7 +2515,7 @@ demangle_builtin_type (dm)
if (type_name == NULL)
return "Unrecognized <builtin-type> code.";
RETURN_IF_ERROR (result_append (dm, type_name));
RETURN_IF_ERROR (result_add (dm, type_name));
advance_char (dm);
return STATUS_OK;
}
......@@ -2512,7 +2586,7 @@ demangle_function_type (dm, function_name_pos)
{
/* Indicate this function has C linkage if in verbose mode. */
if (flag_verbose)
RETURN_IF_ERROR (result_append (dm, " [extern \"C\"] "));
RETURN_IF_ERROR (result_add (dm, " [extern \"C\"] "));
advance_char (dm);
}
RETURN_IF_ERROR (demangle_bare_function_type (dm, function_name_pos));
......@@ -2539,7 +2613,7 @@ demangle_bare_function_type (dm, return_type_pos)
DEMANGLE_TRACE ("bare-function-type", dm);
RETURN_IF_ERROR (result_append_char (dm, '('));
RETURN_IF_ERROR (result_add_char (dm, '('));
while (!end_of_name_p (dm) && peek_char (dm) != 'E')
{
if (sequence == -1)
......@@ -2581,7 +2655,7 @@ demangle_bare_function_type (dm, return_type_pos)
{
/* Separate parameter types by commas. */
if (sequence > 0)
RETURN_IF_ERROR (result_append (dm, ", "));
RETURN_IF_ERROR (result_add (dm, ", "));
/* Demangle the type. */
RETURN_IF_ERROR (demangle_type (dm));
}
......@@ -2589,7 +2663,7 @@ demangle_bare_function_type (dm, return_type_pos)
++sequence;
}
RETURN_IF_ERROR (result_append_char (dm, ')'));
RETURN_IF_ERROR (result_add_char (dm, ')'));
/* We should have demangled at least one parameter type (which would
be void, for a function that takes no parameters), plus the
......@@ -2620,17 +2694,32 @@ demangle_class_enum_type (dm, encode_return_type)
/* Demangles and emits an <array-type>.
If PTR_INSERT_POS is not NULL, the array type is formatted as a
pointer or reference to an array, except that asterisk and
ampersand punctuation is omitted (since it's not know at this
point). *PTR_INSERT_POS is set to the position in the demangled
name at which this punctuation should be inserted. For example,
`A10_i' is demangled to `int () [10]' and *PTR_INSERT_POS points
between the parentheses.
If PTR_INSERT_POS is NULL, the array type is assumed not to be
pointer- or reference-qualified. Then, for example, `A10_i' is
demangled simply as `int[10]'.
<array-type> ::= A [<dimension number>] _ <element type>
::= A <dimension expression> _ <element type> */
static status_t
demangle_array_type (dm)
demangle_array_type (dm, ptr_insert_pos)
demangling_t dm;
int *ptr_insert_pos;
{
status_t status = STATUS_OK;
dyn_string_t array_size = NULL;
char peek;
DEMANGLE_TRACE ("array-type", dm);
RETURN_IF_ERROR (demangle_char (dm, 'A'));
/* Demangle the array size into array_size. */
......@@ -2664,13 +2753,24 @@ demangle_array_type (dm)
if (STATUS_NO_ERROR (status))
status = demangle_type (dm);
if (ptr_insert_pos != NULL)
{
/* This array is actually part of an pointer- or
reference-to-array type. Format appropriately, except we
don't know which and how much punctuation to use. */
if (STATUS_NO_ERROR (status))
status = result_add (dm, " () ");
/* Let the caller know where to insert the punctuation. */
*ptr_insert_pos = result_caret_pos (dm) - 2;
}
/* Emit the array dimension syntax. */
if (STATUS_NO_ERROR (status))
status = result_append_char (dm, '[');
status = result_add_char (dm, '[');
if (STATUS_NO_ERROR (status) && array_size != NULL)
status = result_append_string (dm, array_size);
status = result_add_string (dm, array_size);
if (STATUS_NO_ERROR (status))
status = result_append_char (dm, ']');
status = result_add_char (dm, ']');
if (array_size != NULL)
dyn_string_delete (array_size);
......@@ -2714,7 +2814,7 @@ demangle_template_param (dm)
/* parm_number exceeded the number of arguments in the current
template argument list. */
return "Template parameter number out of bounds.";
RETURN_IF_ERROR (result_append_string (dm, (dyn_string_t) arg));
RETURN_IF_ERROR (result_add_string (dm, (dyn_string_t) arg));
return STATUS_OK;
}
......@@ -2752,7 +2852,7 @@ demangle_template_args (dm)
if (first)
first = 0;
else
RETURN_IF_ERROR (result_append (dm, ", "));
RETURN_IF_ERROR (result_add (dm, ", "));
/* Capture the template arg. */
RETURN_IF_ERROR (result_push (dm));
......@@ -2760,7 +2860,7 @@ demangle_template_args (dm)
arg = result_pop (dm);
/* Emit it in the demangled name. */
RETURN_IF_ERROR (result_append_string (dm, (dyn_string_t) arg));
RETURN_IF_ERROR (result_add_string (dm, (dyn_string_t) arg));
/* Save it for use in expanding <template-param>s. */
template_arg_list_add_arg (arg_list, arg);
......@@ -2836,9 +2936,9 @@ demangle_literal (dm)
corresponding to false or true, respectively. */
value = peek_char (dm);
if (value == '0')
RETURN_IF_ERROR (result_append (dm, "false"));
RETURN_IF_ERROR (result_add (dm, "false"));
else if (value == '1')
RETURN_IF_ERROR (result_append (dm, "true"));
RETURN_IF_ERROR (result_add (dm, "true"));
else
return "Unrecognized bool constant.";
/* Consume the 0 or 1. */
......@@ -2856,10 +2956,10 @@ demangle_literal (dm)
value_string = dyn_string_new (0);
status = demangle_number_literally (dm, value_string, 10, 1);
if (STATUS_NO_ERROR (status))
status = result_append_string (dm, value_string);
status = result_add_string (dm, value_string);
/* For long integers, append an l. */
if (code == 'l' && STATUS_NO_ERROR (status))
status = result_append_char (dm, code);
status = result_add_char (dm, code);
dyn_string_delete (value_string);
RETURN_IF_ERROR (status);
......@@ -2869,9 +2969,9 @@ demangle_literal (dm)
literal's type explicitly using cast syntax. */
}
RETURN_IF_ERROR (result_append_char (dm, '('));
RETURN_IF_ERROR (result_add_char (dm, '('));
RETURN_IF_ERROR (demangle_type (dm));
RETURN_IF_ERROR (result_append_char (dm, ')'));
RETURN_IF_ERROR (result_add_char (dm, ')'));
value_string = dyn_string_new (0);
if (value_string == NULL)
......@@ -2879,7 +2979,7 @@ demangle_literal (dm)
status = demangle_number_literally (dm, value_string, 10, 1);
if (STATUS_NO_ERROR (status))
status = result_append_string (dm, value_string);
status = result_add_string (dm, value_string);
dyn_string_delete (value_string);
RETURN_IF_ERROR (status);
......@@ -2967,30 +3067,30 @@ demangle_expression (dm)
/* If it's binary, do an operand first. */
if (num_args > 1)
{
status = result_append_char (dm, '(');
status = result_add_char (dm, '(');
if (STATUS_NO_ERROR (status))
status = demangle_expression (dm);
if (STATUS_NO_ERROR (status))
status = result_append_char (dm, ')');
status = result_add_char (dm, ')');
}
/* Emit the operator. */
if (STATUS_NO_ERROR (status))
status = result_append_string (dm, operator_name);
status = result_add_string (dm, operator_name);
dyn_string_delete (operator_name);
RETURN_IF_ERROR (status);
/* Emit its second (if binary) or only (if unary) operand. */
RETURN_IF_ERROR (result_append_char (dm, '('));
RETURN_IF_ERROR (result_add_char (dm, '('));
RETURN_IF_ERROR (demangle_expression (dm));
RETURN_IF_ERROR (result_append_char (dm, ')'));
RETURN_IF_ERROR (result_add_char (dm, ')'));
/* The ternary operator takes a third operand. */
if (num_args == 3)
{
RETURN_IF_ERROR (result_append (dm, ":("));
RETURN_IF_ERROR (result_add (dm, ":("));
RETURN_IF_ERROR (demangle_expression (dm));
RETURN_IF_ERROR (result_append_char (dm, ')'));
RETURN_IF_ERROR (result_add_char (dm, ')'));
}
}
......@@ -3009,7 +3109,7 @@ demangle_scope_expression (dm)
RETURN_IF_ERROR (demangle_char (dm, 's'));
RETURN_IF_ERROR (demangle_char (dm, 'r'));
RETURN_IF_ERROR (demangle_type (dm));
RETURN_IF_ERROR (result_append (dm, "::"));
RETURN_IF_ERROR (result_add (dm, "::"));
RETURN_IF_ERROR (demangle_encoding (dm));
return STATUS_OK;
}
......@@ -3100,17 +3200,17 @@ demangle_substitution (dm, template_p)
switch (peek)
{
case 't':
RETURN_IF_ERROR (result_append (dm, "std"));
RETURN_IF_ERROR (result_add (dm, "std"));
break;
case 'a':
RETURN_IF_ERROR (result_append (dm, "std::allocator"));
RETURN_IF_ERROR (result_add (dm, "std::allocator"));
new_last_source_name = "allocator";
*template_p = 1;
break;
case 'b':
RETURN_IF_ERROR (result_append (dm, "std::basic_string"));
RETURN_IF_ERROR (result_add (dm, "std::basic_string"));
new_last_source_name = "basic_string";
*template_p = 1;
break;
......@@ -3118,12 +3218,12 @@ demangle_substitution (dm, template_p)
case 's':
if (!flag_verbose)
{
RETURN_IF_ERROR (result_append (dm, "std::string"));
RETURN_IF_ERROR (result_add (dm, "std::string"));
new_last_source_name = "string";
}
else
{
RETURN_IF_ERROR (result_append (dm, "std::basic_string<char, std::char_traits<char>, std::allocator<char> >"));
RETURN_IF_ERROR (result_add (dm, "std::basic_string<char, std::char_traits<char>, std::allocator<char> >"));
new_last_source_name = "basic_string";
}
*template_p = 0;
......@@ -3132,12 +3232,12 @@ demangle_substitution (dm, template_p)
case 'i':
if (!flag_verbose)
{
RETURN_IF_ERROR (result_append (dm, "std::istream"));
RETURN_IF_ERROR (result_add (dm, "std::istream"));
new_last_source_name = "istream";
}
else
{
RETURN_IF_ERROR (result_append (dm, "std::basic_istream<char, std::char_traints<char> >"));
RETURN_IF_ERROR (result_add (dm, "std::basic_istream<char, std::char_traints<char> >"));
new_last_source_name = "basic_istream";
}
*template_p = 0;
......@@ -3146,12 +3246,12 @@ demangle_substitution (dm, template_p)
case 'o':
if (!flag_verbose)
{
RETURN_IF_ERROR (result_append (dm, "std::ostream"));
RETURN_IF_ERROR (result_add (dm, "std::ostream"));
new_last_source_name = "ostream";
}
else
{
RETURN_IF_ERROR (result_append (dm, "std::basic_ostream<char, std::char_traits<char> >"));
RETURN_IF_ERROR (result_add (dm, "std::basic_ostream<char, std::char_traits<char> >"));
new_last_source_name = "basic_ostream";
}
*template_p = 0;
......@@ -3160,12 +3260,12 @@ demangle_substitution (dm, template_p)
case 'd':
if (!flag_verbose)
{
RETURN_IF_ERROR (result_append (dm, "std::iostream"));
RETURN_IF_ERROR (result_add (dm, "std::iostream"));
new_last_source_name = "iostream";
}
else
{
RETURN_IF_ERROR (result_append (dm, "std::basic_iostream<char, std::char_traits<char> >"));
RETURN_IF_ERROR (result_add (dm, "std::basic_iostream<char, std::char_traits<char> >"));
new_last_source_name = "basic_iostream";
}
*template_p = 0;
......@@ -3196,7 +3296,7 @@ demangle_substitution (dm, template_p)
return "Substitution number out of range.";
/* Emit the substitution text. */
RETURN_IF_ERROR (result_append_string (dm, text));
RETURN_IF_ERROR (result_add_string (dm, text));
RETURN_IF_ERROR (demangle_char (dm, '_'));
return STATUS_OK;
......@@ -3216,12 +3316,12 @@ 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, "::"));
RETURN_IF_ERROR (result_add (dm, "::"));
if (peek_char (dm) == 's')
{
/* Local character string literal. */
RETURN_IF_ERROR (result_append (dm, "string literal"));
RETURN_IF_ERROR (result_add (dm, "string literal"));
/* Consume the s. */
advance_char (dm);
RETURN_IF_ERROR (demangle_discriminator (dm, 0));
......@@ -3258,7 +3358,7 @@ demangle_discriminator (dm, suppress_first)
/* Consume the underscore. */
advance_char (dm);
if (flag_verbose)
RETURN_IF_ERROR (result_append (dm, " [#"));
RETURN_IF_ERROR (result_add (dm, " [#"));
/* Check if there's a number following the underscore. */
if (IS_DIGIT ((unsigned char) peek_char (dm)))
{
......@@ -3276,15 +3376,15 @@ demangle_discriminator (dm, suppress_first)
{
if (flag_verbose)
/* A missing digit correspond to one. */
RETURN_IF_ERROR (result_append_char (dm, '1'));
RETURN_IF_ERROR (result_add_char (dm, '1'));
}
if (flag_verbose)
RETURN_IF_ERROR (result_append_char (dm, ']'));
RETURN_IF_ERROR (result_add_char (dm, ']'));
}
else if (!suppress_first)
{
if (flag_verbose)
RETURN_IF_ERROR (result_append (dm, " [#0]"));
RETURN_IF_ERROR (result_add (dm, " [#0]"));
}
return STATUS_OK;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment