# Unwinder commands.
# Copyright 2015 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/>.

import gdb
import re


def validate_regexp(exp, idstring):
    try:
        return re.compile(exp)
    except SyntaxError:
        raise SyntaxError("Invalid %s regexp: %s." % (idstring, exp))


def parse_unwinder_command_args(arg):
    """Internal utility to parse unwinder command argv.

    Arguments:
        arg: The arguments to the command. The format is:
             [locus-regexp [name-regexp]]

    Returns:
        A 2-tuple of compiled regular expressions.

    Raises:
        SyntaxError: an error processing ARG
    """

    argv = gdb.string_to_argv(arg)
    argc = len(argv)
    if argc > 2:
        raise SyntaxError("Too many arguments.")
    locus_regexp = ""
    name_regexp = ""
    if argc >= 1:
        locus_regexp = argv[0]
        if argc >= 2:
            name_regexp = argv[1]
    return (validate_regexp(locus_regexp, "locus"),
            validate_regexp(name_regexp, "unwinder"))


class InfoUnwinder(gdb.Command):
    """GDB command to list unwinders.

    Usage: info unwinder [locus-regexp [name-regexp]]

    LOCUS-REGEXP is a regular expression matching the location of the
    unwinder.  If it is omitted, all registered unwinders from all
    loci are listed.  A locus can be 'global', 'progspace' to list
    the unwinders from the current progspace, or a regular expression
    matching filenames of objfiles.

    NAME-REGEXP is a regular expression to filter unwinder names.  If
    this omitted for a specified locus, then all registered unwinders
    in the locus are listed.
    """

    def __init__(self):
        super(InfoUnwinder, self).__init__("info unwinder",
                                            gdb.COMMAND_STACK)

    def list_unwinders(self, title, unwinders, name_re):
        """Lists the unwinders whose name matches regexp.

        Arguments:
            title: The line to print before the list.
            unwinders: The list of the unwinders.
            name_re: unwinder name filter.
        """
        if not unwinders:
            return
        print(title)
        for unwinder in unwinders:
            if name_re.match(unwinder.name):
                print("  %s%s" % (unwinder.name,
                                  "" if unwinder.enabled else " [disabled]"))

    def invoke(self, arg, from_tty):
        locus_re, name_re = parse_unwinder_command_args(arg)
        if locus_re.match("global"):
            self.list_unwinders("Global:", gdb.frame_unwinders,
                                name_re)
        if locus_re.match("progspace"):
            cp = gdb.current_progspace()
            self.list_unwinders("Progspace %s:" % cp.filename,
                                cp.frame_unwinders, name_re)
        for objfile in gdb.objfiles():
            if locus_re.match(objfile.filename):
                self.list_unwinders("Objfile %s:" % objfile.filename,
                                    objfile.frame_unwinders, name_re)


def do_enable_unwinder1(unwinders, name_re, flag):
    """Enable/disable unwinders whose names match given regex.

    Arguments:
        unwinders: The list of unwinders.
        name_re: Unwinder name filter.
        flag: Enable/disable.

    Returns:
        The number of unwinders affected.
    """
    total = 0
    for unwinder in unwinders:
        if name_re.match(unwinder.name):
            unwinder.enabled = flag
            total += 1
    return total


def do_enable_unwinder(arg, flag):
    """Enable/disable unwinder(s)."""
    (locus_re, name_re) = parse_unwinder_command_args(arg)
    total = 0
    if locus_re.match("global"):
        total += do_enable_unwinder1(gdb.frame_unwinders, name_re, flag)
    if locus_re.match("progspace"):
        total += do_enable_unwinder1(gdb.current_progspace().frame_unwinders,
                                     name_re, flag)
    for objfile in gdb.objfiles():
        if locus_re.match(objfile.filename):
            total += do_enable_unwinder1(objfile.frame_unwinders, name_re,
                                         flag)
    print("%d unwinder%s %s" % (total, "" if total == 1 else "s",
                                "enabled" if flag else "disabled"))


class EnableUnwinder(gdb.Command):
    """GDB command to enable unwinders.

    Usage: enable unwinder [locus-regexp [name-regexp]]

    LOCUS-REGEXP is a regular expression specifying the unwinders to
    enable.  It can 'global', 'progspace', or the name of an objfile
    within that progspace.

    NAME_REGEXP is a regular expression to filter unwinder names.  If
    this omitted for a specified locus, then all registered unwinders
    in the locus are affected.

    """

    def __init__(self):
        super(EnableUnwinder, self).__init__("enable unwinder",
                                             gdb.COMMAND_STACK)

    def invoke(self, arg, from_tty):
        """GDB calls this to perform the command."""
        do_enable_unwinder(arg, True)


class DisableUnwinder(gdb.Command):
    """GDB command to disable the specified unwinder.

    Usage: disable unwinder [locus-regexp [name-regexp]]

    LOCUS-REGEXP is a regular expression specifying the unwinders to
    disable.  It can 'global', 'progspace', or the name of an objfile
    within that progspace.

    NAME_REGEXP is a regular expression to filter unwinder names.  If
    this omitted for a specified locus, then all registered unwinders
    in the locus are affected.

    """

    def __init__(self):
        super(DisableUnwinder, self).__init__("disable unwinder",
                                              gdb.COMMAND_STACK)

    def invoke(self, arg, from_tty):
        """GDB calls this to perform the command."""
        do_enable_unwinder(arg, False)


def register_unwinder_commands():
    """Installs the unwinder commands."""
    InfoUnwinder()
    EnableUnwinder()
    DisableUnwinder()


register_unwinder_commands()
