# Copyright (C) 2009-2021 Free Software Foundation, Inc.
#
# This file is part of GDB.
#
# 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/>.

import gdb
import os.path


class TypeFlag:
    """A class that allows us to store a flag name, its short name,
    and its value.

    In the GDB sources, struct type has a component called instance_flags
    in which the value is the addition of various flags.  These flags are
    defined by the enumerates type_instance_flag_value.  This class helps us
    recreate a list with all these flags that is easy to manipulate and sort.
    Because all flag names start with TYPE_INSTANCE_FLAG_, a short_name
    attribute is provided that strips this prefix.

    ATTRIBUTES
      name:  The enumeration name (eg: "TYPE_INSTANCE_FLAG_CONST").
      value: The associated value.
      short_name: The enumeration name, with the suffix stripped.
    """

    def __init__(self, name, value):
        self.name = name
        self.value = value
        self.short_name = name.replace("TYPE_INSTANCE_FLAG_", "")

    def __lt__(self, other):
        """Sort by value order."""
        return self.value < other.value


# A list of all existing TYPE_INSTANCE_FLAGS_* enumerations,
# stored as TypeFlags objects.  Lazy-initialized.
TYPE_FLAGS = None


class TypeFlagsPrinter:
    """A class that prints a decoded form of an instance_flags value.

    This class uses a global named TYPE_FLAGS, which is a list of
    all defined TypeFlag values.  Using a global allows us to compute
    this list only once.

    This class relies on a couple of enumeration types being defined.
    If not, then printing of the instance_flag is going to be degraded,
    but it's not a fatal error.
    """

    def __init__(self, val):
        self.val = val

    def __str__(self):
        global TYPE_FLAGS
        if TYPE_FLAGS is None:
            self.init_TYPE_FLAGS()
        if not self.val:
            return "0"
        if TYPE_FLAGS:
            flag_list = [
                flag.short_name for flag in TYPE_FLAGS if self.val & flag.value
            ]
        else:
            flag_list = ["???"]
        return "0x%x [%s]" % (self.val, "|".join(flag_list))

    def init_TYPE_FLAGS(self):
        """Initialize the TYPE_FLAGS global as a list of TypeFlag objects.
        This operation requires the search of a couple of enumeration types.
        If not found, a warning is printed on stdout, and TYPE_FLAGS is
        set to the empty list.

        The resulting list is sorted by increasing value, to facilitate
        printing of the list of flags used in an instance_flags value.
        """
        global TYPE_FLAGS
        TYPE_FLAGS = []
        try:
            iflags = gdb.lookup_type("enum type_instance_flag_value")
        except:
            print("Warning: Cannot find enum type_instance_flag_value type.")
            print("         `struct type' pretty-printer will be degraded")
            return
        TYPE_FLAGS = [TypeFlag(field.name, field.enumval) for field in iflags.fields()]
        TYPE_FLAGS.sort()


class StructTypePrettyPrinter:
    """Pretty-print an object of type struct type"""

    def __init__(self, val):
        self.val = val

    def to_string(self):
        fields = []
        fields.append("pointer_type = %s" % self.val["pointer_type"])
        fields.append("reference_type = %s" % self.val["reference_type"])
        fields.append("chain = %s" % self.val["reference_type"])
        fields.append(
            "instance_flags = %s" % TypeFlagsPrinter(self.val["m_instance_flags"])
        )
        fields.append("length = %d" % self.val["length"])
        fields.append("main_type = %s" % self.val["main_type"])
        return "\n{" + ",\n ".join(fields) + "}"


class StructMainTypePrettyPrinter:
    """Pretty-print an objet of type main_type"""

    def __init__(self, val):
        self.val = val

    def flags_to_string(self):
        """struct main_type contains a series of components that
        are one-bit ints whose name start with "flag_".  For instance:
        flag_unsigned, flag_stub, etc.  In essence, these components are
        really boolean flags, and this method prints a short synthetic
        version of the value of all these flags.  For instance, if
        flag_unsigned and flag_static are the only components set to 1,
        this function will return "unsigned|static".
        """
        fields = [
            field.name.replace("flag_", "")
            for field in self.val.type.fields()
            if field.name.startswith("flag_") and self.val[field.name]
        ]
        return "|".join(fields)

    def owner_to_string(self):
        """Return an image of component "owner"."""
        if self.val["m_flag_objfile_owned"] != 0:
            return "%s (objfile)" % self.val["m_owner"]["objfile"]
        else:
            return "%s (gdbarch)" % self.val["m_owner"]["gdbarch"]

    def struct_field_location_img(self, field_val):
        """Return an image of the loc component inside the given field
        gdb.Value.
        """
        loc_val = field_val["loc"]
        loc_kind = str(field_val["loc_kind"])
        if loc_kind == "FIELD_LOC_KIND_BITPOS":
            return "bitpos = %d" % loc_val["bitpos"]
        elif loc_kind == "FIELD_LOC_KIND_ENUMVAL":
            return "enumval = %d" % loc_val["enumval"]
        elif loc_kind == "FIELD_LOC_KIND_PHYSADDR":
            return "physaddr = 0x%x" % loc_val["physaddr"]
        elif loc_kind == "FIELD_LOC_KIND_PHYSNAME":
            return "physname = %s" % loc_val["physname"]
        elif loc_kind == "FIELD_LOC_KIND_DWARF_BLOCK":
            return "dwarf_block = %s" % loc_val["dwarf_block"]
        else:
            return "loc = ??? (unsupported loc_kind value)"

    def struct_field_img(self, fieldno):
        """Return an image of the main_type field number FIELDNO."""
        f = self.val["flds_bnds"]["fields"][fieldno]
        label = "flds_bnds.fields[%d]:" % fieldno
        if f["artificial"]:
            label += " (artificial)"
        fields = []
        fields.append("name = %s" % f["name"])
        fields.append("type = %s" % f["m_type"])
        fields.append("loc_kind = %s" % f["loc_kind"])
        fields.append("bitsize = %d" % f["bitsize"])
        fields.append(self.struct_field_location_img(f))
        return label + "\n" + "  {" + ",\n   ".join(fields) + "}"

    def bound_img(self, bound_name):
        """Return an image of the given main_type's bound."""
        bounds = self.val["flds_bnds"]["bounds"].dereference()
        b = bounds[bound_name]
        bnd_kind = str(b["m_kind"])
        if bnd_kind == "PROP_CONST":
            return str(b["m_data"]["const_val"])
        elif bnd_kind == "PROP_UNDEFINED":
            return "(undefined)"
        else:
            info = [bnd_kind]
            if bound_name == "high" and bounds["flag_upper_bound_is_count"]:
                info.append("upper_bound_is_count")
            return "{} ({})".format(str(b["m_data"]["baton"]), ",".join(info))

    def bounds_img(self):
        """Return an image of the main_type bounds."""
        b = self.val["flds_bnds"]["bounds"].dereference()
        low = self.bound_img("low")
        high = self.bound_img("high")

        img = "flds_bnds.bounds = {%s, %s}" % (low, high)
        if b["flag_bound_evaluated"]:
            img += " [evaluated]"
        return img

    def type_specific_img(self):
        """Return a string image of the main_type type_specific union.
        Only the relevant component of that union is printed (based on
        the value of the type_specific_kind field.
        """
        type_specific_kind = str(self.val["type_specific_field"])
        type_specific = self.val["type_specific"]
        if type_specific_kind == "TYPE_SPECIFIC_NONE":
            img = "type_specific_field = %s" % type_specific_kind
        elif type_specific_kind == "TYPE_SPECIFIC_CPLUS_STUFF":
            img = "cplus_stuff = %s" % type_specific["cplus_stuff"]
        elif type_specific_kind == "TYPE_SPECIFIC_GNAT_STUFF":
            img = (
                "gnat_stuff = {descriptive_type = %s}"
                % type_specific["gnat_stuff"]["descriptive_type"]
            )
        elif type_specific_kind == "TYPE_SPECIFIC_FLOATFORMAT":
            img = "floatformat[0..1] = %s" % type_specific["floatformat"]
        elif type_specific_kind == "TYPE_SPECIFIC_FUNC":
            img = (
                "calling_convention = %d"
                % type_specific["func_stuff"]["calling_convention"]
            )
            # tail_call_list is not printed.
        elif type_specific_kind == "TYPE_SPECIFIC_SELF_TYPE":
            img = "self_type = %s" % type_specific["self_type"]
        elif type_specific_kind == "TYPE_SPECIFIC_FIXED_POINT":
            # The scaling factor is an opaque structure, so we cannot
            # decode its value from Python (not without insider knowledge).
            img = (
                "scaling_factor: <opaque> (call __gmpz_dump with "
                " _mp_num and _mp_den fields if needed)"
            )
        else:
            img = (
                "type_specific = ??? (unknown type_secific_kind: %s)"
                % type_specific_kind
            )
        return img

    def to_string(self):
        """Return a pretty-printed image of our main_type."""
        fields = []
        fields.append("name = %s" % self.val["name"])
        fields.append("code = %s" % self.val["code"])
        fields.append("flags = [%s]" % self.flags_to_string())
        fields.append("owner = %s" % self.owner_to_string())
        fields.append("target_type = %s" % self.val["target_type"])
        if self.val["nfields"] > 0:
            for fieldno in range(self.val["nfields"]):
                fields.append(self.struct_field_img(fieldno))
        if self.val["code"] == gdb.TYPE_CODE_RANGE:
            fields.append(self.bounds_img())
        fields.append(self.type_specific_img())

        return "\n{" + ",\n ".join(fields) + "}"


class CoreAddrPrettyPrinter:
    """Print CORE_ADDR values as hex."""

    def __init__(self, val):
        self._val = val

    def to_string(self):
        return hex(int(self._val))


class IntrusiveListPrinter:
    """Print a struct intrusive_list."""

    def __init__(self, val):
        self._val = val

        # Type of linked items.
        self._item_type = self._val.type.template_argument(0)
        self._node_ptr_type = gdb.lookup_type(
            "intrusive_list_node<{}>".format(self._item_type.tag)
        ).pointer()

        # Type of value -> node converter.
        self._conv_type = self._val.type.template_argument(1)

        if self._uses_member_node():
            # The second template argument of intrusive_member_node is a member
            # pointer value.  Its value is the offset of the node member in the
            # enclosing type.
            member_node_ptr = self._conv_type.template_argument(1)
            member_node_ptr = member_node_ptr.cast(gdb.lookup_type("int"))
            self._member_node_offset = int(member_node_ptr)

            # This is only needed in _as_node_ptr if using a member node.  Look it
            # up here so we only do it once.
            self._char_ptr_type = gdb.lookup_type("char").pointer()

    def display_hint(self):
        return "array"

    def _uses_member_node(self):
        """Return True if the list items use a node as a member, False if
        they use a node as a base class.
        """

        if self._conv_type.name.startswith("intrusive_member_node<"):
            return True
        elif self._conv_type.name.startswith("intrusive_base_node<"):
            return False
        else:
            raise RuntimeError(
                "Unexpected intrusive_list value -> node converter type: {}".format(
                    self._conv_type.name
                )
            )

    def to_string(self):
        s = "intrusive list of {}".format(self._item_type)

        if self._uses_member_node():
            node_member = self._conv_type.template_argument(1)
            s += ", linked through {}".format(node_member)

        return s

    def _as_node_ptr(self, elem_ptr):
        """Given ELEM_PTR, a pointer to a list element, return a pointer to the
        corresponding intrusive_list_node.
        """

        assert elem_ptr.type.code == gdb.TYPE_CODE_PTR

        if self._uses_member_node():
            # Node as a member: add the member node offset from to the element's
            # address to get the member node's address.
            elem_char_ptr = elem_ptr.cast(self._char_ptr_type)
            node_char_ptr = elem_char_ptr + self._member_node_offset
            return node_char_ptr.cast(self._node_ptr_type)
        else:
            # Node as a base: just casting from node pointer to item pointer
            # will adjust the pointer value.
            return elem_ptr.cast(self._node_ptr_type)

    def _children_generator(self):
        """Generator that yields one tuple per list item."""

        elem_ptr = self._val["m_front"]
        idx = 0
        while elem_ptr != 0:
            yield (str(idx), elem_ptr.dereference())
            node_ptr = self._as_node_ptr(elem_ptr)
            elem_ptr = node_ptr["next"]
            idx += 1

    def children(self):
        return self._children_generator()


def type_lookup_function(val):
    """A routine that returns the correct pretty printer for VAL
    if appropriate.  Returns None otherwise.
    """
    tag = val.type.tag
    name = val.type.name
    if tag == "type":
        return StructTypePrettyPrinter(val)
    elif tag == "main_type":
        return StructMainTypePrettyPrinter(val)
    elif name == "CORE_ADDR":
        return CoreAddrPrettyPrinter(val)
    elif tag is not None and tag.startswith("intrusive_list<"):
        return IntrusiveListPrinter(val)
    return None


def register_pretty_printer(objfile):
    """A routine to register a pretty-printer against the given OBJFILE."""
    objfile.pretty_printers.append(type_lookup_function)


if __name__ == "__main__":
    if gdb.current_objfile() is not None:
        # This is the case where this script is being "auto-loaded"
        # for a given objfile.  Register the pretty-printer for that
        # objfile.
        register_pretty_printer(gdb.current_objfile())
    else:
        # We need to locate the objfile corresponding to the GDB
        # executable, and register the pretty-printer for that objfile.
        # FIXME: The condition used to match the objfile is too simplistic
        # and will not work on Windows.
        for objfile in gdb.objfiles():
            if os.path.basename(objfile.filename) == "gdb":
                objfile.pretty_printers.append(type_lookup_function)
