# GDB 'explore' command.
# Copyright (C) 2012 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 <http://www.gnu.org/licenses/>.

"""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 guard_expr(expr):
        length = len(expr)
        guard = False

        if expr[0] == '(' and expr[length-1] == ')':
            pass
        else:
            i = 0
            while i < length:
                c = expr[i]
                if (c == '_' or ('a' <= c and c <= 'z') or
                    ('A' <= c and c <= 'Z') or ('0' <= c and c <= '9')):
                    pass
                else:
                    guard = True
                    break
                i += 1

        if guard:
            return "(" + expr + ")"
        else:
            return expr

    @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:
            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_REF : ReferenceExplorer,
            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 return_to_parent_value():
        """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: ")
        
    @staticmethod
    def return_to_enclosing_type():
        """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: ")


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'." %
               (expr, value.type))
        print "%s = %s" % (expr, str(value))

        if is_child:
            Explorer.return_to_parent_value_prompt()
            Explorer.return_to_parent_value()

        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 scalar type '%s'." %
                       (name, str(datatype)))
            else:
                print "'%s' is a scalar type." % name

        if is_child:
            Explorer.return_to_enclosing_type_prompt()
            Explorer.return_to_enclosing_type()

        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.
        """
        print ("'%s' is a pointer to a value of type '%s'" %
               (expr, str(value.type.target())))
        option  = raw_input("Continue exploring it as a pointer to a single "
                            "value [y/n]: ")
        if option == "y":
            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" % Explorer.guard_expr(expr),
                                  deref_value, is_child)
            return False
        
        option  = raw_input("Continue exploring it as a pointer to an "
                            "array [y/n]: ")
        if option == "y":
            while True:
                index = 0
                try:
                    index = int(raw_input("Enter the index of the element you "
                                          "want to explore in '%s': " % expr))
                except ValueError:
                    break
                element_expr = "%s[%d]" % (Explorer.guard_expr(expr), index)
                element = value[index]
                try:
                    str(element)
                except gdb.MemoryError:
                    print "Cannot read value at index %d." % index
                    continue
                Explorer.explore_expr(element_expr, element, True)
            return False

        if is_child:
            Explorer.return_to_parent_value()
        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 a pointer to a value of type '%s'." %
               (name, str(target_type)))

        Explorer.explore_type("the pointee type of %s" % name,
                              target_type,
                              is_child)
        return False


class ReferenceExplorer(object):
    """Internal class used to explore reference (TYPE_CODE_REF) values."""

    @staticmethod
    def explore_expr(expr, value, is_child):
        """Function to explore array values.
        See Explorer.explore_expr for more information.
        """
        referenced_value = value.referenced_value()
        Explorer.explore_expr(expr, referenced_value, is_child)
        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()
        Explorer.explore_type(name, target_type, is_child)
        return False


class ArrayExplorer(object):
    """Internal class used to explore arrays."""

    @staticmethod
    def explore_expr(expr, value, is_child):
        """Function to explore array values.
        See Explorer.explore_expr for more information.
        """
        target_type = value.type.target()
        print ("'%s' is an array of '%s'." % (expr, str(target_type)))
        index = 0
        try:
            index = int(raw_input("Enter the index of the element you want to "
                                  "explore in '%s': " % expr))
        except ValueError:
            if is_child:
                Explorer.return_to_parent_value()
            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[%d]" % (Explorer.guard_expr(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()
        print "%s is an array of '%s'." % (name, str(target_type))

        Explorer.explore_type("the array element of %s" % name, target_type,
                              is_child)
        return False


class CompoundExplorer(object):
    """Internal class used to explore struct, classes and unions."""

    @staticmethod
    def _print_fields(print_list):
        """Internal function which prints the fields of a struct/class/union.
        """
        max_field_name_length = 0
        for pair in print_list:
            if max_field_name_length < len(pair[0]):
                max_field_name_length = len(pair[0])

        format_str = "  {0:>%d} = {1}" % max_field_name_length
        for pair in print_list:
            print format_str.format(pair[0], pair[1])

    @staticmethod
    def _get_real_field_count(fields):
        real_field_count = 0;
        for field in fields:
            if not field.artificial:
                real_field_count = real_field_count + 1

        return real_field_count

    @staticmethod
    def explore_expr(expr, value, is_child):
        """Function to explore structs/classes and union values.
        See Explorer.explore_expr for more information.
        """
        datatype = value.type
        type_code = datatype.code
        fields = datatype.fields()

        if type_code == gdb.TYPE_CODE_STRUCT:
            type_desc = "struct/class"
        else:
            type_desc = "union"

        if CompoundExplorer._get_real_field_count(fields) == 0:
            print ("The value of '%s' is a %s of type '%s' with no fields." %
                   (expr, type_desc, str(value.type)))
            if is_child:
                Explorer.return_to_parent_value_prompt()
            return False

        print ("The value of '%s' is a %s of type '%s' with the following "
              "fields:\n" % (expr, type_desc, str(value.type)))

        has_explorable_fields = False
        choice_to_compound_field_map = { }
        current_choice = 0
        print_list = [ ]
        for field in fields:
            if field.artificial:
                continue
            field_full_name = Explorer.guard_expr(expr) + "." + field.name
            if field.is_base_class:
                field_value = value.cast(field.type)
            else:
                field_value = value[field.name]
            literal_value = ""
            if type_code == gdb.TYPE_CODE_UNION:
                literal_value = ("<Enter %d to explore this field of type "
                                 "'%s'>" % (current_choice, str(field.type)))
                has_explorable_fields = True
            else:
                if Explorer.is_scalar_type(field.type):
                    literal_value = ("%s .. (Value of type '%s')" %
                                     (str(field_value), str(field.type)))
                else:
                    if field.is_base_class:
                        field_desc = "base class"
                    else:
                        field_desc = "field"
                    literal_value = ("<Enter %d to explore this %s of type "
                                     "'%s'>" %
                                     (current_choice, field_desc,
                                      str(field.type)))
                    has_explorable_fields = True

            choice_to_compound_field_map[str(current_choice)] = (
                field_full_name, field_value)
            current_choice = current_choice + 1

            print_list.append((field.name, literal_value))

        CompoundExplorer._print_fields(print_list)
        print ""

        if has_explorable_fields:
            choice = raw_input("Enter the field number of choice: ")
            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
        type_desc = ""
        if type_code == gdb.TYPE_CODE_STRUCT:
            type_desc = "struct/class"
        else:
            type_desc = "union"

        fields = datatype.fields()
        if CompoundExplorer._get_real_field_count(fields) == 0:
            if is_child:
                print ("%s is a %s of type '%s' with no fields." %
                       (name, type_desc, str(datatype)))
                Explorer.return_to_enclosing_type_prompt()
            else:
                print "'%s' is a %s with no fields." % (name, type_desc)
            return False

        if is_child:
            print ("%s is a %s of type '%s' "
                   "with the following fields:\n" %
                   (name, type_desc, str(datatype)))
        else:
            print ("'%s' is a %s with the following "
                   "fields:\n" %
                   (name, type_desc))

        has_explorable_fields = False
        current_choice = 0
        choice_to_compound_field_map = { }
        print_list = [ ]
        for field in fields:
            if field.artificial:
                continue
            if field.is_base_class:
                field_desc = "base class"
            else:
                field_desc = "field"
            rhs = ("<Enter %d to explore this %s of type '%s'>" %
                   (current_choice, field_desc, str(field.type)))
            print_list.append((field.name, rhs))
            choice_to_compound_field_map[str(current_choice)] = (
                field.name, field.type, field_desc)
            current_choice = current_choice + 1

        CompoundExplorer._print_fields(print_list)
        print ""

        if len(choice_to_compound_field_map) > 0:
            choice = raw_input("Enter the field number of choice: ")
            if choice in choice_to_compound_field_map:
                if is_child:
                    new_name = ("%s '%s' of %s" % 
                                (choice_to_compound_field_map[choice][2],
                                 choice_to_compound_field_map[choice][0],
                                 name))
                else:
                    new_name = ("%s '%s' of '%s'" % 
                                (choice_to_compound_field_map[choice][2],
                                 choice_to_compound_field_map[choice][0],
                                 name))
                Explorer.explore_type(new_name,
                    choice_to_compound_field_map[choice][1], True)
                return True
            else:
                if is_child:
                    Explorer.return_to_enclosing_type()
        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 ("The value of '%s' is 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()
        if is_child:
            print ("The type of %s is a typedef of type '%s'." %
                   (name, str(actual_type)))
        else:
            print ("The type '%s' 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' 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):
    """Explore a value or a type valid in the current context.

       Usage:

         explore ARG

         - ARG is either a valid expression or a type name.
         - At any stage of exploration, hit the return key (instead of a
           choice, if any) to return to the enclosing type or value.
    """

    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):
    """Explore value of an expression valid in the current context.

       Usage:

         explore value ARG

         - ARG is a valid expression.
         - At any stage of exploration, hit the return key (instead of a
           choice, if any) to return to the enclosing value.
    """
 
    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):            
    """Explore a type or the type of an expression valid in the current
       context.

       Usage:

         explore type ARG

         - ARG is a valid expression or a type name.
         - At any stage of exploration, hit the return key (instead of a
           choice, if any) to return to the enclosing type.
    """

    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 not None:
            Explorer.explore_type(arg_str, datatype, False)
            return

        value = ExploreUtils.get_value_from_str(arg_str)
        if value is not None:
            print "'%s' is of type '%s'." % (arg_str, str(value.type))
            Explorer.explore_type(str(value.type), value.type, False)

        raise gdb.GdbError(("'%s' is not a type or value in the current "
                            "context." % arg_str))


Explorer.init_env()

ExploreCommand()
ExploreValueCommand()
ExploreTypeCommand()
