# Frame-filter commands.
# Copyright (C) 2013-2021 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/>.

"""Internal functions for working with frame-filters."""

import gdb
from gdb.FrameIterator import FrameIterator
from gdb.FrameDecorator import FrameDecorator
import itertools
import collections


def get_priority(filter_item):
    """Internal worker function to return the frame-filter's priority
    from a frame filter object.  This is a fail free function as it is
    used in sorting and filtering.  If a badly implemented frame
    filter does not implement the priority attribute, return zero
    (otherwise sorting/filtering will fail and prevent other frame
    filters from executing).

    Arguments:
        filter_item: An object conforming to the frame filter
                     interface.

    Returns:
        The priority of the frame filter from the "priority"
        attribute, or zero.
    """
    # Do not fail here, as the sort will fail.  If a filter has not
    # (incorrectly) set a priority, set it to zero.
    return getattr(filter_item, "priority", 0)


def set_priority(filter_item, priority):
    """Internal worker function to set the frame-filter's priority.

    Arguments:
        filter_item: An object conforming to the frame filter
                     interface.
        priority: The priority to assign as an integer.
    """

    filter_item.priority = priority


def get_enabled(filter_item):
    """Internal worker function to return a filter's enabled state
    from a frame filter object.  This is a fail free function as it is
    used in sorting and filtering.  If a badly implemented frame
    filter does not implement the enabled attribute, return False
    (otherwise sorting/filtering will fail and prevent other frame
    filters from executing).

    Arguments:
        filter_item: An object conforming to the frame filter
                     interface.

    Returns:
        The enabled state of the frame filter from the "enabled"
        attribute, or False.
    """

    # If the filter class is badly implemented when called from the
    # Python filter command, do not cease filter operations, just set
    # enabled to False.
    return getattr(filter_item, "enabled", False)


def set_enabled(filter_item, state):
    """Internal Worker function to set the frame-filter's enabled
    state.

    Arguments:
        filter_item: An object conforming to the frame filter
                     interface.
        state: True or False, depending on desired state.
    """

    filter_item.enabled = state


def return_list(name):
    """Internal Worker function to return the frame filter
    dictionary, depending on the name supplied as an argument.  If the
    name is not "all", "global" or "progspace", it is assumed to name
    an object-file.

    Arguments:
        name: The name of the list, as specified by GDB user commands.

    Returns:
        A dictionary object for a single specified dictionary, or a
        list containing all the items for "all"

    Raises:
        gdb.GdbError:  A dictionary of that name cannot be found.
    """

    # If all dictionaries are wanted in the case of "all" we
    # cannot return a combined dictionary as keys() may clash in
    # between different dictionaries.  As we just want all the frame
    # filters to enable/disable them all, just return the combined
    # items() as a chained iterator of dictionary values.
    if name == "all":
        glob = gdb.frame_filters.values()
        prog = gdb.current_progspace().frame_filters.values()
        return_iter = itertools.chain(glob, prog)
        for objfile in gdb.objfiles():
            return_iter = itertools.chain(return_iter, objfile.frame_filters.values())

        return return_iter

    if name == "global":
        return gdb.frame_filters
    else:
        if name == "progspace":
            cp = gdb.current_progspace()
            return cp.frame_filters
        else:
            for objfile in gdb.objfiles():
                if name == objfile.filename:
                    return objfile.frame_filters

    msg = "Cannot find frame-filter dictionary for '" + name + "'"
    raise gdb.GdbError(msg)


def _sort_list():
    """Internal Worker function to merge all known frame-filter
    lists, prune any filters with the state set to "disabled", and
    sort the list on the frame-filter's "priority" attribute.

    Returns:
        sorted_list: A sorted, pruned list of frame filters to
                     execute.
    """

    all_filters = return_list("all")
    sorted_frame_filters = sorted(all_filters, key=get_priority, reverse=True)

    sorted_frame_filters = filter(get_enabled, sorted_frame_filters)

    return sorted_frame_filters


def execute_frame_filters(frame, frame_low, frame_high):
    """Internal function called from GDB that will execute the chain
    of frame filters.  Each filter is executed in priority order.
    After the execution completes, slice the iterator to frame_low -
    frame_high range.

    Arguments:
        frame: The initial frame.

        frame_low: The low range of the slice.  If this is a negative
        integer then it indicates a backward slice (ie bt -4) which
        counts backward from the last frame in the backtrace.

        frame_high: The high range of the slice.  If this is -1 then
        it indicates all frames until the end of the stack from
        frame_low.

    Returns:
        frame_iterator: The sliced iterator after all frame
        filters have had a change to execute, or None if no frame
        filters are registered.
    """

    # Get a sorted list of frame filters.
    sorted_list = list(_sort_list())

    # Check to see if there are any frame-filters.  If not, just
    # return None and let default backtrace printing occur.
    if len(sorted_list) == 0:
        return None

    frame_iterator = FrameIterator(frame)

    # Apply a basic frame decorator to all gdb.Frames.  This unifies
    # the interface.  Python 3.x moved the itertools.imap
    # functionality to map(), so check if it is available.
    if hasattr(itertools, "imap"):
        frame_iterator = itertools.imap(FrameDecorator, frame_iterator)
    else:
        frame_iterator = map(FrameDecorator, frame_iterator)

    for ff in sorted_list:
        frame_iterator = ff.filter(frame_iterator)

    # Slicing

    # Is this a slice from the end of the backtrace, ie bt -2?
    if frame_low < 0:
        count = 0
        slice_length = abs(frame_low)
        # We cannot use MAXLEN argument for deque as it is 2.6 onwards
        # and some GDB versions might be < 2.6.
        sliced = collections.deque()

        for frame_item in frame_iterator:
            if count >= slice_length:
                sliced.popleft()
            count = count + 1
            sliced.append(frame_item)

        return iter(sliced)

    # -1 for frame_high means until the end of the backtrace.  Set to
    # None if that is the case, to indicate to itertools.islice to
    # slice to the end of the iterator.
    if frame_high == -1:
        frame_high = None
    else:
        # As frames start from 0, add one to frame_high so islice
        # correctly finds the end
        frame_high = frame_high + 1

    sliced = itertools.islice(frame_iterator, frame_low, frame_high)

    return sliced
