diff -rupN src/gdb/data-directory/Makefile.in src_local/gdb/data-directory/Makefile.in --- src/gdb/data-directory/Makefile.in 2011-08-17 16:11:20.000000000 +0530 +++ src_local/gdb/data-directory/Makefile.in 2011-11-12 12:07:34.802506703 +0530 @@ -58,7 +58,8 @@ PYTHON_FILES = \ gdb/prompt.py \ gdb/command/__init__.py \ gdb/command/pretty_printers.py \ - gdb/command/prompt.py + gdb/command/prompt.py \ + gdb/command/explore.py FLAGS_TO_PASS = \ "prefix=$(prefix)" \ diff -rupN src/gdb/python/lib/gdb/command/explore.py src_local/gdb/python/lib/gdb/command/explore.py --- src/gdb/python/lib/gdb/command/explore.py 1970-01-01 05:30:00.000000000 +0530 +++ src_local/gdb/python/lib/gdb/command/explore.py 2011-12-27 10:45:00.090174863 +0530 @@ -0,0 +1,693 @@ +# GDB 'explore' command. +# Copyright (C) 2011 Free Software Foundation, Inc. + +# 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 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# 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, see . + +"""Implementation of the GDB 'explore' command using the GDB Python API.""" + +import gdb + +class Explorer(object): + """Internal class which invokes other explorers.""" + + # This map is filled by the Explorer.init_env() function + type_code_to_explorer_map = { } + + _SCALAR_TYPE_LIST = ( + gdb.TYPE_CODE_CHAR, + gdb.TYPE_CODE_INT, + gdb.TYPE_CODE_BOOL, + gdb.TYPE_CODE_FLT, + gdb.TYPE_CODE_VOID, + gdb.TYPE_CODE_ENUM, + ) + + @staticmethod + def explore_expr(expr, value, is_child): + """Main function to explore an expression value. + + Arguments: + expr: The expression string that is being explored. + value: The gdb.Value value of the expression. + is_child: Boolean value to indicate if the expression is a child. + An expression is a child if it is derived from the main + expression entered by the user. For example, if the user + entered an expression which evaluates to a struct, then + when exploring the fields of the struct, is_child is set + to True internally. + + Returns: + No return value. + """ + type_code = value.type.code + if type_code in Explorer.type_code_to_explorer_map: + if expr[0] == '*': + expr = "(%s)" % expr + explorer_class = Explorer.type_code_to_explorer_map[type_code] + while explorer_class.explore_expr(expr, value, is_child): + pass + else: + print ("Explorer for type '%s' not yet available.\n" % + str(value.type)) + + @staticmethod + def explore_type(name, datatype, is_child): + """Main function to explore a data type. + + Arguments: + name: The string representing the path to the data type being + explored. + datatype: The gdb.Type value of the data type being explored. + is_child: Boolean value to indicate if the name is a child. + A name is a child if it is derived from the main name + entered by the user. For example, if the user entered the + name of struct type, then when exploring the fields of the + struct, is_child is set to True internally. + + Returns: + No return value. + """ + type_code = datatype.code + if type_code in Explorer.type_code_to_explorer_map: + explorer_class = Explorer.type_code_to_explorer_map[type_code] + while explorer_class.explore_type(name, datatype, is_child): + pass + else: + print ("Explorer for type '%s' not yet available.\n" % + str(datatype)) + + @staticmethod + def init_env(): + """Initializes the Explorer environment. + This function should be invoked before starting any exploration. If + invoked before an exploration, it need not be invoked for subsequent + explorations. + """ + Explorer.type_code_to_explorer_map = { + gdb.TYPE_CODE_CHAR : ScalarExplorer, + gdb.TYPE_CODE_INT : ScalarExplorer, + gdb.TYPE_CODE_BOOL : ScalarExplorer, + gdb.TYPE_CODE_FLT : ScalarExplorer, + gdb.TYPE_CODE_VOID : ScalarExplorer, + gdb.TYPE_CODE_ENUM : ScalarExplorer, + gdb.TYPE_CODE_STRUCT : CompoundExplorer, + gdb.TYPE_CODE_UNION : CompoundExplorer, + gdb.TYPE_CODE_PTR : PointerExplorer, + gdb.TYPE_CODE_TYPEDEF : TypedefExplorer, + gdb.TYPE_CODE_ARRAY : ArrayExplorer + } + + @staticmethod + def is_scalar_type(type): + """Checks whether a type is a scalar type. + A type is a scalar type of its type is + gdb.TYPE_CODE_CHAR or + gdb.TYPE_CODE_INT or + gdb.TYPE_CODE_BOOL or + gdb.TYPE_CODE_FLT or + gdb.TYPE_CODE_VOID or + gdb.TYPE_CODE_ENUM. + + Arguments: + type: The type to be checked. + + Returns: + 'True' if 'type' is a scalar type. 'False' otherwise. + """ + return type.code in Explorer._SCALAR_TYPE_LIST + + @staticmethod + def returning_to_parent_value_message(): + """A utility function which prints that the current exploration session + is returning to the parent value. Useful when exploring values. + """ + print "\nReturning to parent value...\n" + + @staticmethod + def return_to_parent_value_prompt(): + """A utility function which prompts the user to press the 'enter' key so + that the exploration session can shift back to the parent value. Useful + when exploring values. + """ + raw_input("\nPress enter to return to parent value...") + Explorer.returning_to_parent_value_message() + + @staticmethod + def returning_to_enclosing_type_message(): + """A utility function which prints that the current exploration session + is returning to the enclosing type. Useful when exploring types. + """ + print "\nReturning to enclosing type...\n" + + @staticmethod + def return_to_enclosing_type_prompt(): + """A utility function which prompts the user to press the 'enter' key so + that the exploration session can shift back to the enclosing type. + Useful when exploring types. + """ + raw_input("\nPress enter to return to enclosing type...") + Explorer.returning_to_enclosing_type_message() + + +class ScalarExplorer(object): + """Internal class used to explore scalar values.""" + + @staticmethod + def explore_expr(expr, value, is_child): + """Function to explore scalar values. + See Explorer.explore_expr and Explorer.is_scalar_type for more + information. + """ + print ("'%s' is a scalar value of type '%s'.\n" % + (expr, value.type)) + print " %s = %s" % (expr, str(value)) + + if is_child: + Explorer.return_to_parent_value_prompt() + + return False + + @staticmethod + def explore_type(name, datatype, is_child): + """Function to explore scalar types. + See Explorer.explore_type and Explorer.is_scalar_type for more + information. + """ + if datatype.code == gdb.TYPE_CODE_ENUM: + if is_child: + print ("%s is of an enumerated type '%s'." % + (name, str(datatype))) + else: + print "%s is an enumerated type." % name + else: + if is_child: + print ("%s is of a primitive scalar type '%s'." % + (name, str(datatype))) + else: + print "%s is a primitive scalar type." % name + + if is_child: + Explorer.return_to_enclosing_type_prompt() + + return False + + +class PointerExplorer(object): + """Internal class used to explore pointer values.""" + + @staticmethod + def explore_expr(expr, value, is_child): + """Function to explore pointer values. + See Explorer.explore_expr for more information. + """ + if str(value) == "0x0": + print "\n %s = NULL" % expr + if is_child: + Explorer.return_to_parent_value_prompt() + return False + + print ("\n'%s' is a pointer to a value of type '%s'" % + (expr, str(value.type.target()))) + option = raw_input("\nEnter 's' to continue exploring as a pointer " + "to a single value, 'a' to explore as an array: ") + if option == "s": + deref_value = None + try: + deref_value = value.dereference() + str(deref_value) + except gdb.MemoryError: + print ("'%s' a pointer pointing to an invalid memory " + "location." % expr) + if is_child: + Explorer.return_to_parent_value_prompt() + return False + Explorer.explore_expr("*(%s)" % expr, deref_value, is_child) + if option == "a": + while True: + index = 0 + try: + index = int(raw_input("Enter the index to explore: ")) + except ValueError: + break + element_expr = "%s[%d]" % (expr, index) + element = gdb.parse_and_eval(element_expr) + try: + str(element) + except gdb.MemoryError: + print "Cannot read value at index %d." % index + continue + Explorer.explore_expr(element_expr, element, True) + if option != "s" and option != "a": + if is_child: + Explorer.returning_to_parent_value_message() + + return False + + @staticmethod + def explore_type(name, datatype, is_child): + """Function to explore pointer types. + See Explorer.explore_type for more information. + """ + target_type = datatype.target() + print ("\n'%s' is of a pointer type with target type '%s'." % + (name, str(target_type))) + + Explorer.explore_type("the value pointed to by %s" % name, + target_type, + is_child) + return False + + +class ArrayExplorer(object): + """Internal class used to explore arrays.""" + + @staticmethod + def _print_array_info(name, target_type): + """Internal function which prints the information about the array type. + """ + print ("\n%s is an array of elements of type '%s'." % + (name, target_type)) + + @staticmethod + def explore_expr(expr, value, is_child): + """Function to explore array values. + See Explorer.explore_expr for more information. + """ + ArrayExplorer._print_array_info("'%s'" % expr, value.type.target()) + index = 0 + try: + index = int(raw_input("Enter the index to explore: ")) + except ValueError: + if is_child: + Explorer.returning_to_parent_value_message() + return False + + element = None + try: + element = value[index] + str(element) + except gdb.MemoryError: + print "Cannot read value at index %d." % index + raw_input("Press enter to continue... ") + return True + + Explorer.explore_expr("%s[%s]" % (expr, index), element, True) + return True + + @staticmethod + def explore_type(name, datatype, is_child): + """Function to explore array types. + See Explorer.explore_type for more information. + """ + target_type = datatype.target() + ArrayExplorer._print_array_info(name, target_type) + + entry = raw_input("Enter 's' to step in to exploring the " + "type of the elements: ") + if entry == "s": + Explorer.explore_type("an array element of %s" % name, + target_type, + True) + else: + if is_child: + Explorer.returning_to_enclosing_type_message() + return False + + return True + + +class CompoundExplorer(object): + """Internal class used to explore struct, classes and unions.""" + + _VALUES = 0 + _TYPES = 1 + + @staticmethod + def _print_fields(print_list, print_type): + """Internal function which prints the fields of a struct/class/union.""" + max_type_name_length = 0 + max_field_name_length = 0 + for triple in print_list: + if max_type_name_length < len(triple[0]): + max_type_name_length = len(triple[0]) + if max_field_name_length < len(triple[1]): + max_field_name_length = len(triple[1]) + + format_str = "" + if print_type == CompoundExplorer._VALUES: + format_str = (" {0:>%d} {1:<%d} = {2}" % + (max_type_name_length, max_field_name_length)) + if print_type == CompoundExplorer._TYPES: + format_str = (" {0:>%d} {1:<%d} // {2}" % + (max_type_name_length, max_field_name_length)) + + for triple in print_list: + print format_str.format(triple[0], triple[1], triple[2]) + + @staticmethod + def explore_expr(expr, value, is_child): + """Function to explore structs/classes and union values. + See Explorer.explore_expr for more information. + """ + type_code = value.type.code + if type_code == gdb.TYPE_CODE_STRUCT: + print ("\n'%s' is a struct/class of type '%s' " + "with the following fields:\n" % + (expr, str(value.type))) + else: + print ("\n'%s' is a union of type '%s' with the following " + "fields:\n" % + (expr, str(value.type))) + + fields = value.type.fields() + has_explorable_fields = False + current_choice = 0 + choice_to_compound_field_map = { } + print_list = [ ] + for field in fields: + field_full_name = expr + "." + field.name + field_value = value[field.name] + literal_value = "" + is_compound_field = False + if type_code == gdb.TYPE_CODE_UNION: + literal_value = ("" % + str(current_choice)) + is_compound_field = True + else: + if Explorer.is_scalar_type(field.type): + literal_value = str(field_value) + else: + literal_value = ("" % + str(current_choice)) + is_compound_field = True + + if is_compound_field: + choice_to_compound_field_map[str(current_choice)] = ( + field_full_name, field_value) + current_choice = current_choice + 1 + + print_list.append((str(field.type), field.name, literal_value)) + + CompoundExplorer._print_fields(print_list, CompoundExplorer._VALUES) + print "" + + if len(choice_to_compound_field_map) > 0: + choice = raw_input("Enter the number of the field you " + "want to explore in '%s': " % expr) + if choice in choice_to_compound_field_map: + Explorer.explore_expr(choice_to_compound_field_map[choice][0], + choice_to_compound_field_map[choice][1], + True) + return True + else: + if is_child: + Explorer.returning_to_parent_value_message() + else: + if is_child: + Explorer.return_to_parent_value_prompt() + + return False + + @staticmethod + def explore_type(name, datatype, is_child): + """Function to explore struct/class and union types. + See Explorer.explore_type for more information. + """ + type_code = datatype.code + if type_code == gdb.TYPE_CODE_STRUCT: + if is_child: + print ("\n%s is a struct/class of type '%s' " + "with the following fields:\n" % + (name, str(datatype))) + else: + print ("\n%s is a struct/class with the following " + "fields:\n" % + name) + else: + if is_child: + print ("\n%s is a union of type '%s' " + "with the following fields:\n" % + (name, str(datatype))) + else: + print ("\n%s is a union with the following fields:\n" % + name) + + fields = datatype.fields() + has_explorable_fields = False + current_choice = 0 + choice_to_compound_field_map = { } + print_list = [ ] + for field in fields: + if Explorer.is_scalar_type(field.type): + print_list.append((str(field.type), field.name, "Scalar Value")) + else: + print_list.append( + (str(field.type), + field.name, + "" % current_choice)) + choice_to_compound_field_map[str(current_choice)] = ( + field.name, field.type) + current_choice = current_choice + 1 + + CompoundExplorer._print_fields(print_list, CompoundExplorer._TYPES) + print "" + + if len(choice_to_compound_field_map) > 0: + choice = raw_input("Enter the number of the field you want to " + "explore : ") + if choice in choice_to_compound_field_map: + Explorer.explore_type( + ("field '%s' of '%s'" % + (choice_to_compound_field_map[choice][0], name)), + choice_to_compound_field_map[choice][1], + True) + return True + else: + if is_child: + Explorer.returning_to_enclosing_type_message() + else: + if is_child: + Explorer.return_to_enclosing_type_prompt() + + return False + + +class TypedefExplorer(object): + """Internal class used to explore values whose type is a typedef.""" + + @staticmethod + def explore_expr(expr, value, is_child): + """Function to explore typedef values. + See Explorer.explore_expr for more information. + """ + actual_type = value.type.strip_typedefs() + print ("\n'%s' is a value of type '%s' " + "which is a typedef of type '%s'" % + (expr, str(value.type), str(actual_type))) + + Explorer.explore_expr(expr, value.cast(actual_type), is_child) + return False + + @staticmethod + def explore_type(name, datatype, is_child): + """Function to explore typedef types. + See Explorer.explore_type for more information. + """ + actual_type = datatype.strip_typedefs() + print("\n%s is of a type which is a typedef of type '%s'." % + (name, str(actual_type))) + Explorer.explore_type(name, actual_type, is_child) + return False + + +class ExploreUtils(object): + """Internal class which provides utilities for the main command classes.""" + + @staticmethod + def check_args(name, arg_str): + """Utility to check if adequate number of arguments are passed to an + explore command. + + Arguments: + name: The name of the explore command. + arg_str: The argument string passed to the explore command. + + Returns: + True if adequate arguments are passed, false otherwise. + + Raises: + gdb.GdbError if adequate arguments are not passed. + """ + if len(arg_str) < 1: + raise gdb.GdbError("ERROR: '%s' command requires an argument." + % name) + return False + else: + return True + + @staticmethod + def get_type_from_str(type_str): + """A utility function to deduce the gdb.Type value from a string + representing the type. + + Arguments: + type_str: The type string from which the gdb.Type value should be + deduced. + + Returns: + The deduced gdb.Type value if possible, None otherwise. + """ + try: + # Assume the current language to be C/C++ and make a try. + return gdb.parse_and_eval("(%s *)0" % type_str).type.target() + except RuntimeError: + # If assumption of current language to be C/C++ was wrong, then + # lookup the type using the API. + try: + return gdb.lookup_type(type_str) + except RuntimeError: + return None + + @staticmethod + def get_value_from_str(value_str): + """A utility function to deduce the gdb.Value value from a string + representing the value. + + Arguments: + value_str: The value string from which the gdb.Value value should be + deduced. + + Returns: + The deduced gdb.Value value if possible, None otherwise. + """ + try: + return gdb.parse_and_eval(value_str) + except RuntimeError: + return None + + +class ExploreCommand(gdb.Command): + """GDB command to explore expression values and types top down. + + Usage: explore ARG + + ARG is either an expression or a type visible in the current scope. + + If ARG is an expression which evaluates to a scalar value or struct/class + with only scalar fields, then the value is printed. If it evaluates to a + union, or if it is a class/struct with class/struct fields, or if is as + array, the user can interactively explore the value. Exploration here means + to observe, starting from the fields/elements of the VALUE, right down to + the leaf scalar values embedded in these fields. + + If ARG is a type visible in the current scope, then the user can explore + the type top down. + """ + + def __init__(self): + super(ExploreCommand, self).__init__(name = "explore", + command_class = gdb.COMMAND_DATA, + prefix = True) + + def invoke(self, arg_str, from_tty): + if ExploreUtils.check_args("explore", arg_str) == False: + return + + # Check if it is a value + value = ExploreUtils.get_value_from_str(arg_str) + if value is not None: + Explorer.explore_expr(arg_str, value, False) + return + + # If it is not a value, check if it is a type + datatype = ExploreUtils.get_type_from_str(arg_str) + if datatype is not None: + Explorer.explore_type(arg_str, datatype, False) + return + + # If it is neither a value nor a type, raise an error. + raise gdb.GdbError( + ("'%s' neither evaluates to a value nor is a type " + "in the current context." % + arg_str)) + + +class ExploreValueCommand(gdb.Command): + """GDB command to explore expression values top down. + + Usage: explore value ARG + + ARG is an expression visible in the current scope. + + If ARG is an expression which evaluates to a scalar value or struct/class + with only scalar fields, then the value is printed. If it evaluates to a + union, or if it is a class/struct with class/struct fields, or if is as + array, the user can interactively explore the value. Exploration here means + to observe, starting from the fields/elements of the VALUE, right down to + the leaf scalar values embedded in these fields. + """ + + def __init__(self): + super(ExploreValueCommand, self).__init__( + name = "explore value", command_class = gdb.COMMAND_DATA) + + def invoke(self, arg_str, from_tty): + if ExploreUtils.check_args("explore value", arg_str) == False: + return + + value = ExploreUtils.get_value_from_str(arg_str) + if value is None: + raise gdb.GdbError( + (" '%s' does not evaluate to a value in the current " + "context." % + arg_str)) + return + + Explorer.explore_expr(arg_str, value, False) + + +class ExploreTypeCommand(gdb.Command): + """GDB command to explore types top down. + + Usage: explore type ARG + + ARG is a type visible in the current scope. + + If ARG is a type visible in the current scope, then the user can explore + the type top down. + """ + + def __init__(self): + super(ExploreTypeCommand, self).__init__( + name = "explore type", command_class = gdb.COMMAND_DATA) + + def invoke(self, arg_str, from_tty): + if ExploreUtils.check_args("explore type", arg_str) == False: + return + + datatype = ExploreUtils.get_type_from_str(arg_str) + if datatype is None: + raise gdb.GdbError( + ("'%s' is not a type in the current context." % + arg_str)) + return + + Explorer.explore_type(arg_str, datatype, False) + + +Explorer.init_env() + +ExploreCommand() +ExploreValueCommand() +ExploreTypeCommand() diff -rupN src/gdb/testsuite/gdb.python/Makefile.in src_local/gdb/testsuite/gdb.python/Makefile.in --- src/gdb/testsuite/gdb.python/Makefile.in 2011-05-16 19:26:40.000000000 +0530 +++ src_local/gdb/testsuite/gdb.python/Makefile.in 2011-11-12 11:48:44.872558912 +0530 @@ -4,7 +4,8 @@ srcdir = @srcdir@ EXECUTABLES = py-type py-value py-prettyprint py-template py-block \ py-symbol py-mi py-breakpoint py-inferior py-infthread \ py-shared python lib-types py-events py-evthreads py-frame \ - py-mi py-pp-maint py-progspace py-section-script py-objfile + py-mi py-pp-maint py-progspace py-section-script py-objfile \ + py-explore MISCELLANEOUS = py-shared-sl.sl diff -rupN src/gdb/testsuite/gdb.python/py-explore.c src_local/gdb/testsuite/gdb.python/py-explore.c --- src/gdb/testsuite/gdb.python/py-explore.c 1970-01-01 05:30:00.000000000 +0530 +++ src_local/gdb/testsuite/gdb.python/py-explore.c 2011-12-25 23:46:14.641927363 +0530 @@ -0,0 +1,83 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2011 Free Software Foundation, Inc. + + 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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, see . +*/ + +#define ARRAY_SIZE 10 + +struct SimpleStruct +{ + int a; + double d; +}; + +union SimpleUnion +{ + int i; + char c; + float f; + double d; +}; + +typedef struct SimpleStruct SS; + +struct ComplexStruct +{ + struct SimpleStruct s; + union SimpleUnion u; + SS sa[ARRAY_SIZE]; +}; + +union ComplexUnion +{ + SS s; + struct SimpleStruct sa[ARRAY_SIZE]; +}; + +int +main (void) +{ + int* invalid_ptr = (int *)10; + struct SimpleStruct ss; + struct SimpleStruct* ss_ptr = &ss; + SS ss_t; + + union SimpleUnion su; + struct ComplexStruct cs; + struct ComplexStruct* cs_ptr = &cs; + union ComplexUnion cu; + int i; + double darray[5] = {0.1, 0.2, 0.3, 0.4, 0.5}; + double *darray_ref = darray; + + ss.a = 10; + ss.d = 100.01; + ss_t = ss; + + su.d = 100.1; + + cs.s = ss; + cs.u = su; + for (i = 0; i < ARRAY_SIZE; i++) + { + cs.sa[i].a = i; + cs.sa[i].d = 10.10 + i; + cu.sa[i].a = i; + cu.sa[i].d = 100.10 + i; + } + + return 0; /* Break here. */ +} diff -rupN src/gdb/testsuite/gdb.python/py-explore.exp src_local/gdb/testsuite/gdb.python/py-explore.exp --- src/gdb/testsuite/gdb.python/py-explore.exp 1970-01-01 05:30:00.000000000 +0530 +++ src_local/gdb/testsuite/gdb.python/py-explore.exp 2011-12-27 01:21:50.302487431 +0530 @@ -0,0 +1,358 @@ +# Copyright (C) 2011 Free Software Foundation, Inc. + +# 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 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# 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, see . + +# This file is part of the GDB testsuite. It tests the command 'explore' +# which is implemented using the GDB-Python API. + +load_lib gdb-python.exp + +set testfile "py-explore" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } { + return -1 +} + +# Skip all tests if Python scripting is not enabled. +if { [skip_python_tests] } { continue } + +set SS "struct SimpleStruct" +set SU "union SimpleUnion" +set CS "struct ComplexStruct" +set CU "union ComplexUnion" +set return_to_parent_prompt {Press enter to return to parent value...} +set array_index_prompt {Enter the index to explore: } + +proc enter_field_number_prompt { value_name } { + return "Enter the number of the field you want to explore in '$value_name': " +} + +proc compound_description { value_name type_kind type_name } { + return "'$value_name' is a $type_kind of type '$type_name' with the following fields:\[\r\n\]+" +} + +proc typedef_description { value_name typedef_name type_name } { + return "'$value_name' is a value of type '$typedef_name' which is a typedef of type '$type_name'\[\r\n\]+" +} + +proc scalar_description { value_name type } { + return "'$value_name' is a scalar value of type '$type'\.\[\r\n\]+" +} + +proc array_description { value_name type } { + return "'$value_name' is an array of elements of type '$type'.\[\r\n\]+" +} + +proc pointer_description { value_name type_name } { + set type_description "'$value_name' is a pointer to a value of type '$type_name'\[\r\n\]+" + set prompt "Enter 's' to continue exploring as a pointer to a single value, 'a' to explore as an array: " + return "$type_description$prompt" +} + +proc field_values { args } { + set result "" + foreach field $args { + set result "$result\[ \]*$field\[\r\n\]+" + } + return $result +} + +proc field_choices { args } { + set result "" + set field_num 0 + foreach field $args { + set result "$result$field\[ \]+=\[ \]+} {union SimpleUnion u // } {SS \[10\] sa // }] +set CU_fields_types [field_values {SS s // } {struct SimpleStruct \[10\] sa // }] + +gdb_test "explore int" ".*[scalar_primitive_type_decsription {int}].*" +gdb_test "explore struct SimpleStruct" ".*[compound_type_description $SS {struct/class}].*$SS_fields_types.*" +gdb_test "explore union SimpleUnion" ".*[compound_type_description $SU {union}].*$SU_fields_types" +gdb_test "explore SS" ".*[typedef_type_description {SS} $SS].*[compound_type_description {SS} {struct/class}].*$SS_fields_types.*" + +gdb_test_multiple "explore type struct ComplexStruct" "" { + -re ".*[compound_type_description $CS {struct/class}].*$CS_fields_types.*" { + pass "explore type struct ComplexStruct" + gdb_test_multiple "0" "explore type struct ComplexStruct field 0" { + -re ".*[compound_field_type_description $CS_field_0 {struct/class} $SS].*$SS_fields_types.*" { + pass "explore type struct ComplexStruct field 0" + gdb_test_multiple " " "return to ComplexStruct from field 0" { + -re ".*[compound_type_description $CS {struct/class}].*$CS_fields_types.*" { + pass "return to ComplexStruct from field 0" + } + } + } + } + gdb_test_multiple "1" "explore type struct ComplexStruct field 1" { + -re ".*[compound_field_type_description $CS_field_1 {union} $SU].*$SU_fields_types.*" { + pass "explore type struct ComplexStruct field 1" + gdb_test_multiple " " "return to ComplexStruct from field 1" { + -re ".*[compound_type_description $CS {struct/class}].*$CS_fields_types.*" { + pass "return to ComplexStruct from field 1" + } + } + } + } + gdb_test_multiple "2" "explore type struct ComplexStruct field 2" { + -re ".*[array_type_description $CS_field_2 {SS}].*" { + pass "explore type struct ComplexStruct field 2" + gdb_test_multiple "s" "array element of field 2 of ComplexStruct" { + -re ".*[compound_field_type_description $CS_field_2_array_element {struct/class} $SS].*$SS_fields_types.*" { + pass "array element of field 2 of ComplexStruct" + gdb_test_multiple " " "return to ComplexStruct array" { + -re ".*[array_type_description $CS_field_2 {SS}].*" { + pass "return to ComplexStruct array" + gdb_test_multiple " " "return to ComplexStruct from field 2" { + -re ".*[compound_type_description $CS {struct/class}].*$CS_fields_types.*" { + pass "return to ComplexStruct from field 2" + } + } + } + } + } + } + } + } + gdb_test_multiple " " "return to GDB prompt from ComplexStruct type exploration" { + -re "$gdb_prompt" { + pass "return to GDB prompt from ComplexStruct type exploration" + } + } + } +} + +gdb_test_multiple "explore type union ComplexUnion" "" { + -re ".*[compound_type_description $CU {union}].*$CU_fields_types.*" { + pass "explore type union ComplexUnion" + gdb_test_multiple "0" "explore type union ComplexStruct field 0" { + -re ".*[compound_field_type_description $CU_field_0 {struct/class} $SS].*$SS_fields_types.*" { + pass "explore type union ComplexUnion field 0" + gdb_test_multiple " " "return to ComplexUnion from field 0" { + -re ".*[compound_type_description $CU {union}].*$CU_fields_types.*" { + pass "return to ComplexUnion from field 0" + } + } + } + } + gdb_test_multiple "1" "explore type union ComplexUnion field 1" { + -re ".*[array_type_description $CU_field_1 $SS].*" { + pass "explore type union ComplexUnion field 1" + gdb_test_multiple "s" "array element of field 1 of ComplexUnion" { + -re ".*[compound_field_type_description $CU_field_1_array_element {struct/class} $SS].*$SS_fields_types.*" { + pass "array element of field 1 of ComplexUnion" + gdb_test_multiple " " "return to ComplexUnion array" { + -re ".*[array_type_description $CU_field_1 $SS].*" { + pass "return to ComplexUnion array" + gdb_test_multiple " " "return to ComplexUnion from field 1" { + -re ".*[compound_type_description $CU {union}].*$CU_fields_types.*" { + pass "return to ComplexUnion from field 1" + } + } + } + } + } + } + } + } + gdb_test_multiple " " "return to GDB prompt from ComplexUnion type exploration" { + -re "$gdb_prompt" { + pass "return to GDB prompt from ComplexUnion type exploration" + } + } + } +}