X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fcp-support.c;h=684943bcc25bd08b1bf90440b9a7ec90e683ea44;hb=1290797801825ff96506c8197d301b60154c3250;hp=d9cdc46832da478b204c25a7c35801c05fcfa9f9;hpb=a3f171870f6bcdf091a0647c37e4e25c0020e4f4;p=deliverable%2Fbinutils-gdb.git
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index d9cdc46832..684943bcc2 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -1,5 +1,6 @@
/* Helper routines for C++ support in GDB.
- Copyright 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009
+ Free Software Foundation, Inc.
Contributed by MontaVista Software.
@@ -7,7 +8,7 @@
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
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
@@ -16,12 +17,9 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ along with this program. If not, see . */
#include "defs.h"
-#include
#include "cp-support.h"
#include "gdb_string.h"
#include "demangle.h"
@@ -34,10 +32,16 @@
#include "block.h"
#include "complaints.h"
#include "gdbtypes.h"
+#include "exceptions.h"
+#include "expression.h"
+#include "value.h"
-/* Functions related to demangled name parsing. */
+#include "safe-ctype.h"
+
+#define d_left(dc) (dc)->u.s_binary.left
+#define d_right(dc) (dc)->u.s_binary.right
-static const char *find_last_component (const char *name);
+/* Functions related to demangled name parsing. */
static unsigned int cp_find_first_component_aux (const char *name,
int permissive);
@@ -50,8 +54,6 @@ static int sym_return_val_size;
static int sym_return_val_index;
static struct symbol **sym_return_val;
-static char *remove_params (const char *demangled_name);
-
static void overload_list_add_symbol (struct symbol *sym,
const char *oload_name);
@@ -71,78 +73,121 @@ struct cmd_list_element *maint_cplus_cmd_list = NULL;
static void maint_cplus_command (char *arg, int from_tty);
static void first_component_command (char *arg, int from_tty);
-/* Here are some random pieces of trivia to keep in mind while trying
- to take apart demangled names:
+/* Operator validation.
+ NOTE: Multi-byte operators (usually the assignment variety operator)
+ must appear before the single byte version, i.e., "+=" before "+". */
+static const char *operator_tokens[] =
+ {
+ "++", "+=", "+", "->*", "->", "--", "-=", "-", "*=", "*", "/=", "/",
+ "%=", "%", "!=", "==", "!", "&&", "<<=", "<<", ">>=", ">>",
+ "<=", "<", ">=", ">", "~", "&=", "&", "|=", "||", "|", "^=", "^",
+ "=", "()", "[]", ",", "new", "delete"
+ /* new[] and delete[] require special whitespace handling */
+ };
+
+/* Return 1 if STRING is clearly already in canonical form. This
+ function is conservative; things which it does not recognize are
+ assumed to be non-canonical, and the parser will sort them out
+ afterwards. This speeds up the critical path for alphanumeric
+ identifiers. */
+
+static int
+cp_already_canonical (const char *string)
+{
+ /* Identifier start character [a-zA-Z_]. */
+ if (!ISIDST (string[0]))
+ return 0;
+
+ /* These are the only two identifiers which canonicalize to other
+ than themselves or an error: unsigned -> unsigned int and
+ signed -> int. */
+ if (string[0] == 'u' && strcmp (&string[1], "nsigned") == 0)
+ return 0;
+ else if (string[0] == 's' && strcmp (&string[1], "igned") == 0)
+ return 0;
+
+ /* Identifier character [a-zA-Z0-9_]. */
+ while (ISIDNUM (string[1]))
+ string++;
+
+ if (string[1] == '\0')
+ return 1;
+ else
+ return 0;
+}
- - Names can contain function arguments or templates, so the process
- has to be, to some extent recursive: maybe keep track of your
- depth based on encountering <> and ().
+/* Parse STRING and convert it to canonical form. If parsing fails,
+ or if STRING is already canonical, return NULL. Otherwise return
+ the canonical form. The return value is allocated via xmalloc. */
- - Parentheses don't just have to happen at the end of a name: they
- can occur even if the name in question isn't a function, because
- a template argument might be a type that's a function.
+char *
+cp_canonicalize_string (const char *string)
+{
+ struct demangle_component *ret_comp;
+ unsigned int estimated_len;
+ char *ret;
- - Conversely, even if you're trying to deal with a function, its
- demangled name might not end with ')': it could be a const or
- volatile class method, in which case it ends with "const" or
- "volatile".
+ if (cp_already_canonical (string))
+ return NULL;
- - Parentheses are also used in anonymous namespaces: a variable
- 'foo' in an anonymous namespace gets demangled as "(anonymous
- namespace)::foo".
+ ret_comp = cp_demangled_name_to_comp (string, NULL);
+ if (ret_comp == NULL)
+ return NULL;
- - And operator names can contain parentheses or angle brackets. */
+ estimated_len = strlen (string) * 2;
+ ret = cp_comp_to_string (ret_comp, estimated_len);
-/* FIXME: carlton/2003-03-13: We have several functions here with
- overlapping functionality; can we combine them? Also, do they
- handle all the above considerations correctly? */
+ if (strcmp (string, ret) == 0)
+ {
+ xfree (ret);
+ return NULL;
+ }
-/* Find the last component of the demangled C++ name NAME. NAME
- must be a method name including arguments, in order to correctly
- locate the last component.
+ return ret;
+}
- This function return a pointer to the first colon before the
- last component, or NULL if the name had only one component. */
+/* Convert a mangled name to a demangle_component tree. *MEMORY is set to the
+ block of used memory that should be freed when finished with the tree.
+ DEMANGLED_P is set to the char * that should be freed when finished with
+ the tree, or NULL if none was needed. OPTIONS will be passed to the
+ demangler. */
-static const char *
-find_last_component (const char *name)
+static struct demangle_component *
+mangled_name_to_comp (const char *mangled_name, int options,
+ void **memory, char **demangled_p)
{
- const char *p;
- int depth;
-
- /* Functions can have local classes, so we need to find the
- beginning of the last argument list, not the end of the first
- one. */
- p = name + strlen (name) - 1;
- while (p > name && *p != ')')
- p--;
-
- if (p == name)
- return NULL;
+ struct demangle_component *ret;
+ char *demangled_name;
+ int len;
- /* P now points at the `)' at the end of the argument list. Walk
- back to the beginning. */
- p--;
- depth = 1;
- while (p > name && depth > 0)
+ /* If it looks like a v3 mangled name, then try to go directly
+ to trees. */
+ if (mangled_name[0] == '_' && mangled_name[1] == 'Z')
{
- if (*p == '<' || *p == '(')
- depth--;
- else if (*p == '>' || *p == ')')
- depth++;
- p--;
+ ret = cplus_demangle_v3_components (mangled_name, options, memory);
+ if (ret)
+ {
+ *demangled_p = NULL;
+ return ret;
+ }
}
- if (p == name)
- return NULL;
-
- while (p > name && *p != ':')
- p--;
+ /* If it doesn't, or if that failed, then try to demangle the name. */
+ demangled_name = cplus_demangle (mangled_name, options);
+ if (demangled_name == NULL)
+ return NULL;
+
+ /* If we could demangle the name, parse it to build the component tree. */
+ ret = cp_demangled_name_to_comp (demangled_name, NULL);
- if (p == name || p == name + 1 || p[-1] != ':')
- return NULL;
+ if (ret == NULL)
+ {
+ xfree (demangled_name);
+ return NULL;
+ }
- return p - 1;
+ *demangled_p = demangled_name;
+ return ret;
}
/* Return the name of the class containing method PHYSNAME. */
@@ -150,68 +195,269 @@ find_last_component (const char *name)
char *
cp_class_name_from_physname (const char *physname)
{
- char *ret = NULL;
- const char *end;
- int depth = 0;
- char *demangled_name = cplus_demangle (physname, DMGL_ANSI | DMGL_PARAMS);
-
- if (demangled_name == NULL)
+ void *storage = NULL;
+ char *demangled_name = NULL, *ret;
+ struct demangle_component *ret_comp, *prev_comp, *cur_comp;
+ int done;
+
+ ret_comp = mangled_name_to_comp (physname, DMGL_ANSI, &storage,
+ &demangled_name);
+ if (ret_comp == NULL)
return NULL;
- end = find_last_component (demangled_name);
- if (end != NULL)
+ done = 0;
+
+ /* First strip off any qualifiers, if we have a function or method. */
+ while (!done)
+ switch (ret_comp->type)
+ {
+ case DEMANGLE_COMPONENT_CONST:
+ case DEMANGLE_COMPONENT_RESTRICT:
+ case DEMANGLE_COMPONENT_VOLATILE:
+ case DEMANGLE_COMPONENT_CONST_THIS:
+ case DEMANGLE_COMPONENT_RESTRICT_THIS:
+ case DEMANGLE_COMPONENT_VOLATILE_THIS:
+ case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
+ ret_comp = d_left (ret_comp);
+ break;
+ default:
+ done = 1;
+ break;
+ }
+
+ /* If what we have now is a function, discard the argument list. */
+ if (ret_comp->type == DEMANGLE_COMPONENT_TYPED_NAME)
+ ret_comp = d_left (ret_comp);
+
+ /* If what we have now is a template, strip off the template
+ arguments. The left subtree may be a qualified name. */
+ if (ret_comp->type == DEMANGLE_COMPONENT_TEMPLATE)
+ ret_comp = d_left (ret_comp);
+
+ /* What we have now should be a name, possibly qualified. Additional
+ qualifiers could live in the left subtree or the right subtree. Find
+ the last piece. */
+ done = 0;
+ prev_comp = NULL;
+ cur_comp = ret_comp;
+ while (!done)
+ switch (cur_comp->type)
+ {
+ case DEMANGLE_COMPONENT_QUAL_NAME:
+ case DEMANGLE_COMPONENT_LOCAL_NAME:
+ prev_comp = cur_comp;
+ cur_comp = d_right (cur_comp);
+ break;
+ case DEMANGLE_COMPONENT_TEMPLATE:
+ case DEMANGLE_COMPONENT_NAME:
+ case DEMANGLE_COMPONENT_CTOR:
+ case DEMANGLE_COMPONENT_DTOR:
+ case DEMANGLE_COMPONENT_OPERATOR:
+ case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
+ done = 1;
+ break;
+ default:
+ done = 1;
+ cur_comp = NULL;
+ break;
+ }
+
+ ret = NULL;
+ if (cur_comp != NULL && prev_comp != NULL)
{
- ret = xmalloc (end - demangled_name + 1);
- memcpy (ret, demangled_name, end - demangled_name);
- ret[end - demangled_name] = '\0';
+ /* We want to discard the rightmost child of PREV_COMP. */
+ *prev_comp = *d_left (prev_comp);
+ /* The ten is completely arbitrary; we don't have a good estimate. */
+ ret = cp_comp_to_string (ret_comp, 10);
}
- xfree (demangled_name);
+ xfree (storage);
+ if (demangled_name)
+ xfree (demangled_name);
return ret;
}
+/* Return the child of COMP which is the basename of a method, variable,
+ et cetera. All scope qualifiers are discarded, but template arguments
+ will be included. The component tree may be modified. */
+
+static struct demangle_component *
+unqualified_name_from_comp (struct demangle_component *comp)
+{
+ struct demangle_component *ret_comp = comp, *last_template;
+ int done;
+
+ done = 0;
+ last_template = NULL;
+ while (!done)
+ switch (ret_comp->type)
+ {
+ case DEMANGLE_COMPONENT_QUAL_NAME:
+ case DEMANGLE_COMPONENT_LOCAL_NAME:
+ ret_comp = d_right (ret_comp);
+ break;
+ case DEMANGLE_COMPONENT_TYPED_NAME:
+ ret_comp = d_left (ret_comp);
+ break;
+ case DEMANGLE_COMPONENT_TEMPLATE:
+ gdb_assert (last_template == NULL);
+ last_template = ret_comp;
+ ret_comp = d_left (ret_comp);
+ break;
+ case DEMANGLE_COMPONENT_CONST:
+ case DEMANGLE_COMPONENT_RESTRICT:
+ case DEMANGLE_COMPONENT_VOLATILE:
+ case DEMANGLE_COMPONENT_CONST_THIS:
+ case DEMANGLE_COMPONENT_RESTRICT_THIS:
+ case DEMANGLE_COMPONENT_VOLATILE_THIS:
+ case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
+ ret_comp = d_left (ret_comp);
+ break;
+ case DEMANGLE_COMPONENT_NAME:
+ case DEMANGLE_COMPONENT_CTOR:
+ case DEMANGLE_COMPONENT_DTOR:
+ case DEMANGLE_COMPONENT_OPERATOR:
+ case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
+ done = 1;
+ break;
+ default:
+ return NULL;
+ break;
+ }
+
+ if (last_template)
+ {
+ d_left (last_template) = ret_comp;
+ return last_template;
+ }
+
+ return ret_comp;
+}
+
/* Return the name of the method whose linkage name is PHYSNAME. */
char *
method_name_from_physname (const char *physname)
{
+ void *storage = NULL;
+ char *demangled_name = NULL, *ret;
+ struct demangle_component *ret_comp;
+ int done;
+
+ ret_comp = mangled_name_to_comp (physname, DMGL_ANSI, &storage,
+ &demangled_name);
+ if (ret_comp == NULL)
+ return NULL;
+
+ ret_comp = unqualified_name_from_comp (ret_comp);
+
+ ret = NULL;
+ if (ret_comp != NULL)
+ /* The ten is completely arbitrary; we don't have a good estimate. */
+ ret = cp_comp_to_string (ret_comp, 10);
+
+ xfree (storage);
+ if (demangled_name)
+ xfree (demangled_name);
+ return ret;
+}
+
+/* If FULL_NAME is the demangled name of a C++ function (including an
+ arg list, possibly including namespace/class qualifications),
+ return a new string containing only the function name (without the
+ arg list/class qualifications). Otherwise, return NULL. The
+ caller is responsible for freeing the memory in question. */
+
+char *
+cp_func_name (const char *full_name)
+{
+ char *ret;
+ struct demangle_component *ret_comp;
+ int done;
+
+ ret_comp = cp_demangled_name_to_comp (full_name, NULL);
+ if (!ret_comp)
+ return NULL;
+
+ ret_comp = unqualified_name_from_comp (ret_comp);
+
+ ret = NULL;
+ if (ret_comp != NULL)
+ ret = cp_comp_to_string (ret_comp, 10);
+
+ return ret;
+}
+
+/* DEMANGLED_NAME is the name of a function, including parameters and
+ (optionally) a return type. Return the name of the function without
+ parameters or return type, or NULL if we can not parse the name. */
+
+char *
+cp_remove_params (const char *demangled_name)
+{
+ int done = 0;
+ struct demangle_component *ret_comp;
char *ret = NULL;
- const char *end;
- int depth = 0;
- char *demangled_name = cplus_demangle (physname, DMGL_ANSI | DMGL_PARAMS);
if (demangled_name == NULL)
return NULL;
- end = find_last_component (demangled_name);
- if (end != NULL)
- {
- char *args;
- int len;
-
- /* Skip "::". */
- end = end + 2;
+ ret_comp = cp_demangled_name_to_comp (demangled_name, NULL);
+ if (ret_comp == NULL)
+ return NULL;
- /* Find the argument list, if any. */
- args = strchr (end, '(');
- if (args == NULL)
- len = strlen (end + 2);
- else
- {
- args --;
- while (*args == ' ')
- args --;
- len = args - end + 1;
- }
- ret = xmalloc (len + 1);
- memcpy (ret, end, len);
- ret[len] = 0;
- }
+ /* First strip off any qualifiers, if we have a function or method. */
+ while (!done)
+ switch (ret_comp->type)
+ {
+ case DEMANGLE_COMPONENT_CONST:
+ case DEMANGLE_COMPONENT_RESTRICT:
+ case DEMANGLE_COMPONENT_VOLATILE:
+ case DEMANGLE_COMPONENT_CONST_THIS:
+ case DEMANGLE_COMPONENT_RESTRICT_THIS:
+ case DEMANGLE_COMPONENT_VOLATILE_THIS:
+ case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
+ ret_comp = d_left (ret_comp);
+ break;
+ default:
+ done = 1;
+ break;
+ }
+
+ /* What we have now should be a function. Return its name. */
+ if (ret_comp->type == DEMANGLE_COMPONENT_TYPED_NAME)
+ ret = cp_comp_to_string (d_left (ret_comp), 10);
- xfree (demangled_name);
return ret;
}
+/* Here are some random pieces of trivia to keep in mind while trying
+ to take apart demangled names:
+
+ - Names can contain function arguments or templates, so the process
+ has to be, to some extent recursive: maybe keep track of your
+ depth based on encountering <> and ().
+
+ - Parentheses don't just have to happen at the end of a name: they
+ can occur even if the name in question isn't a function, because
+ a template argument might be a type that's a function.
+
+ - Conversely, even if you're trying to deal with a function, its
+ demangled name might not end with ')': it could be a const or
+ volatile class method, in which case it ends with "const" or
+ "volatile".
+
+ - Parentheses are also used in anonymous namespaces: a variable
+ 'foo' in an anonymous namespace gets demangled as "(anonymous
+ namespace)::foo".
+
+ - And operator names can contain parentheses or angle brackets. */
+
+/* FIXME: carlton/2003-03-13: We have several functions here with
+ overlapping functionality; can we combine them? Also, do they
+ handle all the above considerations correctly? */
+
+
/* This returns the length of first component of NAME, which should be
the demangled name of a C++ variable/function/method/etc.
Specifically, it returns the index of the first colon forming the
@@ -311,7 +557,7 @@ cp_find_first_component_aux (const char *name, int permissive)
&& strncmp (name + index, "operator", LENGTH_OF_OPERATOR) == 0)
{
index += LENGTH_OF_OPERATOR;
- while (isspace(name[index]))
+ while (ISSPACE(name[index]))
++index;
switch (name[index])
{
@@ -394,78 +640,8 @@ cp_entire_prefix_len (const char *name)
return previous_len;
}
-/* If FULL_NAME is the demangled name of a C++ function (including an
- arg list, possibly including namespace/class qualifications),
- return a new string containing only the function name (without the
- arg list/class qualifications). Otherwise, return NULL. The
- caller is responsible for freeing the memory in question. */
-
-char *
-cp_func_name (const char *full_name)
-{
- const char *previous_component = full_name;
- const char *next_component;
-
- if (!full_name)
- return NULL;
-
- for (next_component = (previous_component
- + cp_find_first_component (previous_component));
- *next_component == ':';
- next_component = (previous_component
- + cp_find_first_component (previous_component)))
- {
- /* Skip '::'. */
- previous_component = next_component + 2;
- }
-
- return remove_params (previous_component);
-}
-
/* Overload resolution functions. */
-static char *
-remove_params (const char *demangled_name)
-{
- const char *argp;
- char *new_name;
- int depth;
-
- if (demangled_name == NULL)
- return NULL;
-
- /* First find the end of the arg list. */
- argp = strrchr (demangled_name, ')');
- if (argp == NULL)
- return NULL;
-
- /* Back up to the beginning. */
- depth = 1;
-
- while (argp-- > demangled_name)
- {
- if (*argp == ')')
- depth ++;
- else if (*argp == '(')
- {
- depth --;
-
- if (depth == 0)
- break;
- }
- }
- if (depth != 0)
- internal_error (__FILE__, __LINE__,
- _("bad demangled name %s\n"), demangled_name);
- while (argp[-1] == ' ' && argp > demangled_name)
- argp --;
-
- new_name = xmalloc (argp - demangled_name + 1);
- memcpy (new_name, demangled_name, argp - demangled_name);
- new_name[argp - demangled_name] = '\0';
- return new_name;
-}
-
/* Test to see if SYM is a symbol that we haven't seen corresponding
to a function named OLOAD_NAME. If so, add it to the current
completion list. */
@@ -488,7 +664,7 @@ overload_list_add_symbol (struct symbol *sym, const char *oload_name)
return;
/* Get the demangled name without parameters */
- sym_name = remove_params (SYMBOL_NATURAL_NAME (sym));
+ sym_name = cp_remove_params (SYMBOL_NATURAL_NAME (sym));
if (!sym_name)
return;
@@ -555,10 +731,10 @@ make_symbol_overload_list_using (const char *func_name,
current != NULL;
current = current->next)
{
- if (strcmp (namespace, current->outer) == 0)
+ if (strcmp (namespace, current->import_dest) == 0)
{
make_symbol_overload_list_using (func_name,
- current->inner);
+ current->import_src);
}
}
@@ -618,7 +794,7 @@ make_symbol_overload_list_qualified (const char *func_name)
/* Go through the symtabs and check the externs and statics for
symbols which match. */
- ALL_SYMTABS (objfile, s)
+ ALL_PRIMARY_SYMTABS (objfile, s)
{
QUIT;
b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
@@ -632,7 +808,7 @@ make_symbol_overload_list_qualified (const char *func_name)
}
}
- ALL_SYMTABS (objfile, s)
+ ALL_PRIMARY_SYMTABS (objfile, s)
{
QUIT;
b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
@@ -680,7 +856,7 @@ cp_lookup_rtti_type (const char *name, struct block *block)
struct symbol * rtti_sym;
struct type * rtti_type;
- rtti_sym = lookup_symbol (name, block, STRUCT_DOMAIN, NULL, NULL);
+ rtti_sym = lookup_symbol (name, block, STRUCT_DOMAIN, NULL);
if (rtti_sym == NULL)
{
@@ -731,8 +907,14 @@ maint_cplus_command (char *arg, int from_tty)
static void
first_component_command (char *arg, int from_tty)
{
- int len = cp_find_first_component (arg);
- char *prefix = alloca (len + 1);
+ int len;
+ char *prefix;
+
+ if (!arg)
+ return;
+
+ len = cp_find_first_component (arg);
+ prefix = alloca (len + 1);
memcpy (prefix, arg, len);
prefix[len] = '\0';
@@ -742,16 +924,116 @@ first_component_command (char *arg, int from_tty)
extern initialize_file_ftype _initialize_cp_support; /* -Wmissing-prototypes */
+#define SKIP_SPACE(P) \
+ do \
+ { \
+ while (*(P) == ' ' || *(P) == '\t') \
+ ++(P); \
+ } \
+ while (0)
+
+/* Returns the length of the operator name or 0 if INPUT does not
+ point to a valid C++ operator. INPUT should start with "operator". */
+int
+cp_validate_operator (const char *input)
+{
+ int i;
+ char *copy;
+ const char *p;
+ struct expression *expr;
+ struct value *val;
+ struct gdb_exception except;
+ struct cleanup *old_chain;
+
+ p = input;
+
+ if (strncmp (p, "operator", 8) == 0)
+ {
+ int valid = 0;
+ p += 8;
+
+ SKIP_SPACE (p);
+ for (i = 0; i < sizeof (operator_tokens) / sizeof (operator_tokens[0]);
+ ++i)
+ {
+ int length = strlen (operator_tokens[i]);
+ /* By using strncmp here, we MUST have operator_tokens ordered!
+ See additional notes where operator_tokens is defined above. */
+ if (strncmp (p, operator_tokens[i], length) == 0)
+ {
+ const char *op = p;
+ valid = 1;
+ p += length;
+
+ if (strncmp (op, "new", 3) == 0
+ || strncmp (op, "delete", 6) == 0)
+ {
+
+ /* Special case: new[] and delete[]. We must be careful
+ to swallow whitespace before/in "[]". */
+ SKIP_SPACE (p);
+
+ if (*p == '[')
+ {
+ ++p;
+ SKIP_SPACE (p);
+ if (*p == ']')
+ ++p;
+ else
+ valid = 0;
+ }
+ }
+
+ if (valid)
+ return (p - input);
+ }
+ }
+
+ /* Check input for a conversion operator. */
+
+ /* Skip past base typename */
+ while (*p != '*' && *p != '&' && *p != 0 && *p != ' ')
+ ++p;
+ SKIP_SPACE (p);
+
+ /* Add modifiers '*'/'&' */
+ while (*p == '*' || *p == '&')
+ {
+ ++p;
+ SKIP_SPACE (p);
+ }
+
+ /* Check for valid type. [Remember: input starts with
+ "operator".] */
+ copy = savestring (input + 8, p - input - 8);
+ expr = NULL;
+ val = NULL;
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ expr = parse_expression (copy);
+ val = evaluate_type (expr);
+ }
+
+ xfree (copy);
+ if (expr)
+ xfree (expr);
+
+ if (val != NULL && value_type (val) != NULL)
+ return (p - input);
+ }
+
+ return 0;
+}
+
void
_initialize_cp_support (void)
{
add_prefix_cmd ("cplus", class_maintenance, maint_cplus_command,
- "C++ maintenance commands.", &maint_cplus_cmd_list,
+ _("C++ maintenance commands."), &maint_cplus_cmd_list,
"maintenance cplus ", 0, &maintenancelist);
add_alias_cmd ("cp", "cplus", class_maintenance, 1, &maintenancelist);
add_cmd ("first_component", class_maintenance, first_component_command,
- "Print the first class/namespace component of NAME.",
+ _("Print the first class/namespace component of NAME."),
&maint_cplus_cmd_list);
-
}