From 763914f14ca1b05fe07c4160232bee3917f8d506 Mon Sep 17 00:00:00 2001 From: David Carlton Date: Fri, 11 Oct 2002 21:56:48 +0000 Subject: [PATCH] 2002-10-11 David Carlton * jv-lang.c (get_java_class_symtab): Initialize BLOCK_USING (bl) to NULL. * cp-support.c: Change all uses of 'struct using_data' and 'struct using_data_node' to 'struct using_direct' and 'struct using_direct_node'. (cp_free_usings): Fix loop. * symtab.c: Ditto. * symtab.h: Ditto * cp-support.h: Delete declarations for commented-out functions. Rename 'struct using_data' and 'struct using_data_node' to 'struct using_direct' and 'struct using_direct_node'. * cp-support.c: Delete commented-out functions. 2002-10-10 David Carlton * symtab.c (lookup_symbol_aux_using_loop): New function. (lookup_symbol_aux_nonlocal): New function. (lookup_symbol_aux): Call lookup_symbol_aux_nonlocal instead of lookup_symbol_aux_symtabs and lookup_symbol_aux_psymtabs. * Makefile.in (symtab.o): Depend on $(cp_support_h). * symtab.c: #include "cp-support.h" * cp-support.h: Declare cp_copy_usings, cp_free_usings. * cp-support.c (cp_free_usings): New function. (cp_copy_usings): New function. * symtab.c (lookup_symbol_aux): Call lookup_symbol_aux_using to apply using directives. (lookup_symbol_aux_using): New function. 2002-10-11 David Carlton * gdb.c++/namespace.exp: Add tests from within C::D::marker2. * gdb.c++/namespace.cc: Add namespace C and its contents. --- gdb/ChangeLog | 35 +++++ gdb/Makefile.in | 2 +- gdb/cp-support.c | 157 ++++++--------------- gdb/cp-support.h | 45 +++--- gdb/jv-lang.c | 1 + gdb/symtab.c | 206 ++++++++++++++++++++++++++-- gdb/symtab.h | 6 +- gdb/testsuite/ChangeLog | 5 + gdb/testsuite/gdb.c++/namespace.cc | 49 ++++++- gdb/testsuite/gdb.c++/namespace.exp | 19 +++ 10 files changed, 368 insertions(+), 157 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 1054705a551..709fa89a82b 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,38 @@ +2002-10-11 David Carlton + + * jv-lang.c (get_java_class_symtab): Initialize BLOCK_USING (bl) + to NULL. + * cp-support.c: Change all uses of 'struct using_data' and 'struct + using_data_node' to 'struct using_direct' and 'struct + using_direct_node'. + (cp_free_usings): Fix loop. + * symtab.c: Ditto. + * symtab.h: Ditto + * cp-support.h: Delete declarations for commented-out functions. + Rename 'struct using_data' and 'struct using_data_node' to 'struct + using_direct' and 'struct using_direct_node'. + * cp-support.c: Delete commented-out functions. + +2002-10-10 David Carlton + + * symtab.c (lookup_symbol_aux_using_loop): New function. + (lookup_symbol_aux_nonlocal): New function. + (lookup_symbol_aux): Call lookup_symbol_aux_nonlocal instead of + lookup_symbol_aux_symtabs and lookup_symbol_aux_psymtabs. + + * Makefile.in (symtab.o): Depend on $(cp_support_h). + + * symtab.c: #include "cp-support.h" + + * cp-support.h: Declare cp_copy_usings, cp_free_usings. + + * cp-support.c (cp_free_usings): New function. + (cp_copy_usings): New function. + + * symtab.c (lookup_symbol_aux): Call lookup_symbol_aux_using to + apply using directives. + (lookup_symbol_aux_using): New function. + 2002-10-09 David Carlton * cp-support.c: Comment out cp_find_last_component and diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 96d0298e97f..30b931f73e5 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -2206,7 +2206,7 @@ symtab.o: symtab.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(gdbcore_h) \ $(gdbcmd_h) $(call_cmds_h) $(gdb_regex_h) $(expression_h) \ $(language_h) $(demangle_h) $(inferior_h) $(linespec_h) \ $(filenames_h) $(dictionary_h) $(gdb_obstack_h) \ - $(gdb_string_h) $(gdb_stat_h) $(cp_abi_h) $(source_h) + $(gdb_string_h) $(gdb_stat_h) $(cp_abi_h) $(source_h) $(cp_support_h) target.o: target.c $(defs_h) $(gdb_string_h) $(target_h) $(gdbcmd_h) \ $(symtab_h) $(inferior_h) $(bfd_h) $(symfile_h) $(objfiles_h) \ $(gdb_wait_h) $(dcache_h) $(regcache_h) diff --git a/gdb/cp-support.c b/gdb/cp-support.c index 1c7fcf1828d..09c5d542475 100644 --- a/gdb/cp-support.c +++ b/gdb/cp-support.c @@ -170,134 +170,65 @@ method_name_from_physname (const char *physname) return ret; } -#if 0 - -/* FIXME: carlton/2002-10-09: cp_locate_arguments and - cp_find_last_component are broken: they don't deal with operator<< - and the like. Oops. I decided to fix this by starting from the - front, leading to cp_find_first_component (which may or may not be - correct...); if I don't find other uses for cp_locate_arguments and - cp_find_last_component soon, I'll delete them. */ - -/* Given a name that may or may not be the demangled name of a - function or method, this returns a pointer to the last character - that isn't part of the arguments, if there are any. I.e. given a - pointer to "foo", it returns a pointer to the trailing '\0'; given - a pointer to "C::foo() const", it returns a pointer to the '('. */ +/* This allocates a new using_direct structure initialized to contain + OUTER and INNER, and puts it at the beginning of the linked list + given by NEXT. It returns the resulting struct using_direct_node. + All memory is allocated using OBSTACK. */ -const char * -cp_locate_arguments (const char *name) +struct using_direct_node * +cp_add_using (const char *outer, const char *inner, + struct using_direct_node *next, + struct obstack *obstack) { -/* NOTE: carlton/2002-10-08: we search from the front rather than from - the back to avoid getting screwed up by the 'const' on the end. - ARGSOK says when a parenthesis should be the start of the arguments - to a function: otherwise, we get screwed up by 'A::(anonymous - namespace)::foo' and its ilk. */ - - const char *current = name; - const char *end = name + strlen(name); - /* The nesting depth. */ - int depth = 0; - /* Might a parenthesis be the start of arguments? */ - int argsok = 0; + struct using_direct *current + = obstack_alloc (obstack, sizeof (struct using_direct)); + struct using_direct_node *retval + = obstack_alloc (obstack, sizeof (struct using_direct_node)); - while (current < end) - { - switch (*current) - { - case '(': - if (depth == 0 && argsok) - return current; - ++depth; - argsok = 0; - break; - case '<': - ++depth; - argsok = 0; - break; - case ')': - case '>': - --depth; - argsok = 1; - break; - case ':': - argsok = 0; - break; - default: - argsok = 1; - break; - } - ++current; - } + current->outer = outer; + current->inner = inner; + retval->current = current; + retval->next = next; - return current; + return retval; } -/* Given pointers FIRST and LAST such that [FIRST,LAST) is a substring - of a demangled name, not including the arguments (i.e. call - cp_locate_arguments first!), this returns a pointer to the - beginning of the end of the last component. For example, given - either "A::B::C::foo" or "foo", it returns a pointer to 'f'. */ - -/* FIXME: carlton/2002-10-08: This overlaps dreadfully with - find_last_component. Sigh. */ - -const char * -cp_find_last_component (const char *first, const char *last) +/* This copies the using_direct_nodes in TOCOPY, using xmalloc, and + sticks them onto a list ending in TAIL. */ +struct using_direct_node * +cp_copy_usings (struct using_direct_node *tocopy, + struct using_direct_node *tail) { - const char *current; - int depth; + struct using_direct_node *new_node; + + if (tocopy == NULL) + return tail; - for (current = last - 1, depth = 0; - current >= first; - --current) - { - switch (*current) - { - case '(': - case '<': - --depth; - break; - case ')': - case '>': - ++depth; - break; - case ':': - if (depth == 0) - return current + 1; - break; - default: - break; - } - } + new_node = xmalloc (sizeof (struct using_direct_node)); + new_node->current = tocopy->current; + new_node->next = cp_copy_usings (tocopy->next, tail); - return first; + return new_node; } -#endif /* 0 */ - -/* This allocates a new using_data structure initialized to contain - OUTER and INNER, and puts it at the beginning of the linked list - given by NEXT. It returns the resulting struct using_data_node. - All memory is allocated using OBSTACK. */ -struct using_data_node * -cp_add_using (const char *outer, const char *inner, - struct using_data_node *next, - struct obstack *obstack) +/* This xfree's all the using_direct_nodes in USING (but not their + using_directs!) */ +void +cp_free_usings (struct using_direct_node *using) { - struct using_data *current - = obstack_alloc (obstack, sizeof (struct using_data)); - struct using_data_node *retval - = obstack_alloc (obstack, sizeof (struct using_data_node)); + struct using_direct_node *next; - current->outer = outer; - current->inner = inner; - retval->current = current; - retval->next = next; - - return retval; + if (using != NULL) + { + for (next = using->next; next; + using = next, next = next->next) + xfree (using); + + xfree (using); + } } + /* This returns the first component of NAME, which should be the demangled name of a C++ variable/function/method/etc. Specifically, it returns a pointer to the first colon forming the diff --git a/gdb/cp-support.h b/gdb/cp-support.h index c9ea966fed3..500521c2d8b 100644 --- a/gdb/cp-support.h +++ b/gdb/cp-support.h @@ -28,23 +28,18 @@ extern char *class_name_from_physname (const char *physname); extern char *method_name_from_physname (const char *physname); -extern const char *cp_locate_arguments (const char *name); - -extern const char *cp_find_last_component (const char *first, - const char *last); - extern const char *cp_find_first_component (const char *name); /* This is a struct to store data from "using directives" and similar language constructs. It contains two strings, OUTER and INNER; - both should be fully-qualified namespace names, OUTER should be an - initial substring of INNER, and it says that names in the namespace - INNER should be imported into namespace OUTER. For example, if it - is used to represent the directive "using namespace std;" then - INNER should be "std" and new should be "". For a more complicated - example, if there is an anonymous namespace with a named namespace - A, then INNER should be "A::(anonymous namespace)" and new should - be "A". */ + both should be fully-qualified namespace names, OUTER should be a + strict initial substring of INNER, and it says that names in the + namespace INNER should be imported into namespace OUTER. For + example, if it is used to represent the directive "using namespace + std;" then INNER should be "std" and new should be "". For a more + complicated example, if there is an anonymous namespace with a + named namespace A, then INNER should be "A::(anonymous namespace)" + and new should be "A". */ /* FIXME: carlton/2002-10-07: That anonymous namespace example isn't that great, since it really depends not only on what the @@ -53,21 +48,27 @@ extern const char *cp_find_first_component (const char *name); alas, it doesn't, but should, leaving us with no way to distinguish between anonymous namespaces in different files. Sigh... */ -struct using_data +struct using_direct { const char *outer; const char *inner; }; -/* This is a struct for a linked list of using_data's. */ +/* This is a struct for a linked list of using_direct's. */ -struct using_data_node +struct using_direct_node { - struct using_data *current; - struct using_data_node *next; + struct using_direct *current; + struct using_direct_node *next; }; -extern struct using_data_node *cp_add_using (const char *outer, - const char *inner, - struct using_data_node *next, - struct obstack *obstack); +extern struct using_direct_node *cp_add_using (const char *outer, + const char *inner, + struct using_direct_node *next, + struct obstack *obstack); + +extern +struct using_direct_node *cp_copy_usings (struct using_direct_node *tocopy, + struct using_direct_node *tail); + +extern void cp_free_usings (struct using_direct_node *using); diff --git a/gdb/jv-lang.c b/gdb/jv-lang.c index 2035f1a60e2..b5d2df995b1 100644 --- a/gdb/jv-lang.c +++ b/gdb/jv-lang.c @@ -116,6 +116,7 @@ get_java_class_symtab (void) BLOCK_SUPERBLOCK (bl) = NULL; BLOCK_DICT (bl) = dict_create_linear (&objfile->symbol_obstack, NULL); + BLOCK_USING (bl) = NULL; BLOCK_GCC_COMPILED (bl) = 0; BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = bl; diff --git a/gdb/symtab.c b/gdb/symtab.c index c3485b56001..341f95f26c5 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -50,6 +50,7 @@ #include "gdb_stat.h" #include #include "cp-abi.h" +#include "cp-support.h" /* Prototype for one function in parser-defs.h, instead of including that entire file. */ @@ -95,6 +96,13 @@ static struct symbol *lookup_symbol_aux_local (const char *name, const namespace_enum namespace, struct symtab **symtab); +static +struct symbol *lookup_symbol_aux_nonlocal (int block_index, + const char *name, + const char *mangled_name, + const namespace_enum namespace, + struct symtab **symtab); + static struct symbol *lookup_symbol_aux_symtabs (int block_index, const char *name, @@ -108,6 +116,22 @@ struct symbol *lookup_symbol_aux_psymtabs (int block_index, const char *mangled_name, const namespace_enum namespace, struct symtab **symtab); + +static +struct symbol *lookup_symbol_aux_using (const char *name, + const char *mangled_name, + const struct block *block, + const namespace_enum namespace, + struct symtab **symtab); + +static +struct symbol *lookup_symbol_aux_using_loop (const char *prefix, + const char *rest, + struct using_direct_node *using, + const char *mangled_name, + namespace_enum namespace, + struct symtab **symtab); + static struct symbol *lookup_symbol_aux_minsyms (const char *name, const char *mangled_name, @@ -782,16 +806,27 @@ lookup_symbol_aux (const char *name, const char *mangled_name, of the desired name as a global, then do psymtab-to-symtab conversion on the fly and return the found symbol. */ - sym = lookup_symbol_aux_symtabs (GLOBAL_BLOCK, name, mangled_name, - namespace, symtab); - if (sym != NULL) - return sym; - - sym = lookup_symbol_aux_psymtabs (GLOBAL_BLOCK, name, mangled_name, + sym = lookup_symbol_aux_nonlocal (GLOBAL_BLOCK, name, mangled_name, namespace, symtab); if (sym != NULL) return sym; + /* If we're in the C++ case, check to see if the symbol is defined + in a namespace accessible via a "using" declaration. */ + + /* FIXME: carlton/2002-10-10: is "is_a_field_of_this" always + non-NULL if we're in the C++ case? Maybe we should always do + this, and delete the two previous searches: this will always + search the global namespace, after all. */ + + if (is_a_field_of_this) + { + sym = lookup_symbol_aux_using (name, mangled_name, block, namespace, + symtab); + if (sym != NULL) + return sym; + } + #ifndef HPUXHPPA /* Check for the possibility of the symbol being a function or a @@ -813,17 +848,11 @@ lookup_symbol_aux (const char *name, const char *mangled_name, desired name as a file-level static, then do psymtab-to-symtab conversion on the fly and return the found symbol. */ - sym = lookup_symbol_aux_symtabs (STATIC_BLOCK, name, mangled_name, - namespace, symtab); - if (sym != NULL) - return sym; - - sym = lookup_symbol_aux_psymtabs (STATIC_BLOCK, name, mangled_name, + sym = lookup_symbol_aux_nonlocal (STATIC_BLOCK, name, mangled_name, namespace, symtab); if (sym != NULL) return sym; - #ifdef HPUXHPPA /* Check for the possibility of the symbol being a function or a @@ -900,6 +929,32 @@ lookup_symbol_aux_local (const char *name, const char *mangled_name, return NULL; } +/* Check to see if the symbol is defined in one of the symtabs or + psymtabs. BLOCK_INDEX should be either GLOBAL_BLOCK or + STATIC_BLOCK, depending on whether or not we want to search global + symbols or static symbols. */ + +/* FIXME: carlton/2002-10-11: Should this also do some minsym + lookup? */ + +static struct symbol * +lookup_symbol_aux_nonlocal (int block_index, + const char *name, + const char *mangled_name, + const namespace_enum namespace, + struct symtab **symtab) +{ + struct symbol *sym; + + sym = lookup_symbol_aux_symtabs (block_index, name, mangled_name, + namespace, symtab); + if (sym != NULL) + return sym; + + return lookup_symbol_aux_psymtabs (block_index, name, mangled_name, + namespace, symtab); +} + /* Check to see if the symbol is defined in one of the symtabs. BLOCK_INDEX should be either GLOBAL_BLOCK or STATIC_BLOCK, depending on whether or not we want to search global symbols or @@ -993,6 +1048,131 @@ lookup_symbol_aux_psymtabs (int block_index, const char *name, return NULL; } +/* This function gathers using directives from BLOCK and its + superblocks, and then searches for symbols in the global namespace + by trying to apply those various using directives. */ +static struct symbol *lookup_symbol_aux_using (const char *name, + const char *mangled_name, + const struct block *block, + const namespace_enum namespace, + struct symtab **symtab) +{ + struct using_direct_node *using = NULL; + struct symbol *sym; + + while (block != NULL) + { + using = cp_copy_usings (BLOCK_USING (block), using); + block = BLOCK_SUPERBLOCK (block); + } + + sym = lookup_symbol_aux_using_loop ("", name, using, mangled_name, + namespace, symtab); + cp_free_usings (using); + + return sym; +} + +/* This tries to look up a symbol whose name is the concatenation of + PREFIX, "::", and REST, where "::" is ommitted if PREFIX is the + empty string, applying the various using directives given in USING. + When applying the using directives, however, it assumes that the + part of the name given by PREFIX is immutable, so it only adds + symbols to namespaces whose names contain PREFIX. + + Basically, assume that we have using directives adding A to the + global namespace, adding A::inner to namespace A, and adding B to + the global namespace. Then, when looking up a symbol "foo", we + want to recurse by looking up stuff in A::foo and seeing which + using directives still apply. The only one that still applies + converts that to A::inner::foo: we _don't_ want to then look at + B::A::foo (let alone A::A::foo!). So we end up just looking at + A::foo, A::inner::foo, and B::foo. (Though if the original caller + to lookup_symbol had specified A::foo, we would want to look up + stuff in A::A::foo, A::inner::A::foo, A::inner::foo, and + B::A::foo). + + The reason why this treates the case of PREFIX = "" specially is to + avoid having to create temporary strings with "::" stuck on the end + of them. */ + +/* FIXME: carlton/2002-10-11: There are still some places where this + will return false positives. For example, if you have namespaces + C, C::D, C::E, and C::D::E, then, from a function defined in C::D, + all references to variables E::var _should_ be treated as + C::D::E::var, but this function will also see variables in + C::E::var. I don't think this can be fixed without making + namespaces first-class objects. (Which is certainly a good idea + for other reasons, but it will take a little while.) */ + +static struct symbol * +lookup_symbol_aux_using_loop (const char *prefix, const char *rest, + struct using_direct_node *using, + const char *mangled_name, + namespace_enum namespace, + struct symtab **symtab) +{ + struct using_direct_node *current; + struct symbol *sym; + int prefix_len = strlen (prefix); + + for (current = using; current; current = current->next) + { + /* First, see if the prefix matches the start of this using + directive. */ + if (strncmp (prefix, current->current->outer, prefix_len) == 0) + { + /* Great, it matches: now does the rest of the using + directive match the rest of the name? */ + + const char *rest_of_outer = current->current->outer + prefix_len; + /* Should we skip some colons? */ + if (*rest_of_outer == ':') + rest_of_outer += 2; + int rest_of_outer_len = strlen (rest_of_outer); + if (strncmp (rest_of_outer, rest, rest_of_outer_len) == 0) + { + /* Everything matches! Yippee! So apply the using + directive and recurse. */ + const char *new_rest = rest + rest_of_outer_len; + if (*new_rest == ':') + new_rest += 2; + + sym = lookup_symbol_aux_using_loop (current->current->inner, + new_rest, + using, + mangled_name, + namespace, + symtab); + if (sym != NULL) + return sym; + } + } + } + + /* We didn't find anything by applying any of the using directives + that are still applicable; so let's see if we've got a match + using the current name. */ + if (prefix_len == 0) + { + return lookup_symbol_aux_nonlocal (GLOBAL_BLOCK, rest, mangled_name, + namespace, symtab); + } + else + { + char *concatenated_name + = xmalloc (prefix_len + 2 + strlen (rest) + 1); + strcpy (concatenated_name, prefix); + strcpy (concatenated_name + prefix_len, "::"); + strcpy (concatenated_name + prefix_len + 2, rest); + sym = lookup_symbol_aux_nonlocal (GLOBAL_BLOCK, concatenated_name, + mangled_name, namespace, symtab); + + xfree (concatenated_name); + return sym; + } +} + /* Check for the possibility of the symbol being a function or a mangled variable that is stored in one of the minimal symbol tables. Eventually, all global symbols might be resolved in this diff --git a/gdb/symtab.h b/gdb/symtab.h index 2d747f0703c..fcfca15820f 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -26,7 +26,7 @@ /* Opaque declarations. */ struct obstack; struct dictionary; -struct using_data_node; +struct using_direct_node; /* Don't do this; it means that if some .o's are compiled with GNU C and some are not (easy to do accidentally the way we configure @@ -400,6 +400,7 @@ struct block struct dictionary *dict; /* Used for language-specific info. */ + union { struct @@ -408,7 +409,8 @@ struct block similar features are added by this block. This should always be NULL for global blocks: if there are using directives that affect an entire file, put it in the static block. */ - struct using_data_node *using; + + struct using_direct_node *using; } cplus_specific; } diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index e530e61a281..5736277965f 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2002-10-11 David Carlton + + * gdb.c++/namespace.exp: Add tests from within C::D::marker2. + * gdb.c++/namespace.cc: Add namespace C and its contents. + 2002-09-26 Keith Seitz * lib/insight-support.exp (gdbtk_start): Figure out where diff --git a/gdb/testsuite/gdb.c++/namespace.cc b/gdb/testsuite/gdb.c++/namespace.cc index 7667266c278..76b8a36b12b 100644 --- a/gdb/testsuite/gdb.c++/namespace.cc +++ b/gdb/testsuite/gdb.c++/namespace.cc @@ -68,6 +68,47 @@ void marker1(void) return; } +namespace C +{ + int c = 1; + + namespace C + { + int cc = 2; + } + + namespace E + { + int ce = 4; + } + + namespace D + { + int cd = 3; + + namespace E + { + int cde = 5; + } + + void marker2 (void) + { + // NOTE: carlton/2002-10-11: I'm listing the expressions that I + // plan to have GDB try to print out, just to make sure that the + // compiler and I agree which ones should be legal! It's easy + // to screw up when testing the boundaries of namespace stuff. + c; + //cc; + C::cc; + cd; + E::cde; + //E::ce; + return; + } + + } +} + int main () { @@ -94,10 +135,6 @@ int main () c1 = cl.xyzq('e'); marker1(); - -} - - - - + C::D::marker2 (); +} diff --git a/gdb/testsuite/gdb.c++/namespace.exp b/gdb/testsuite/gdb.c++/namespace.exp index 3e502c4b50a..e87425b26d1 100644 --- a/gdb/testsuite/gdb.c++/namespace.exp +++ b/gdb/testsuite/gdb.c++/namespace.exp @@ -186,3 +186,22 @@ gdb_expect { timeout { fail "(timeout) break BBB::Class::xyzq" } } +# Now, test to see if the appropriate namespaces are in scope when +# trying to print out stuff from within a function defined within a +# namespace. + +if ![runto "'C::D::marker2'"] then { + perror "couldn't run to marker2" + continue +} + +gdb_test "print c" "\\$\[0-9\].* = 1" "print c" +gdb_test "print cc" "No symbol \"cc\" in current context." "print cc" +gdb_test "print 'C::cc'" "\\$\[0-9\].* = 2" "print C::cc" +gdb_test "print cd" "\\$\[0-9\].* = 3" "print cd" +gdb_test "print 'C::D::cd'" "\\$\[0-9\].* = 3" "print C::D::cd" +gdb_test "print 'E::cde'" "\\$\[0-9\].* = 5" "print E::cde" + +# FIXME: carlton/2002-10-11: It would be nice to test printing +# "E::ce", but unfortunately GDB will print it out even though it +# shouldn't. Oops. -- 2.47.2