# Type printer commands.
# Copyright (C) 2010-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/>.

import copy
import gdb

"""GDB commands for working with type-printers."""

class InfoTypePrinter(gdb.Command):
    """GDB command to list all registered type-printers.

    Usage: info type-printers
    """

    def __init__ (self):
        super(InfoTypePrinter, self).__init__("info type-printers",
                                              gdb.COMMAND_DATA)

    def list_type_printers(self, type_printers):
        """Print a list of type printers."""
        # A potential enhancement is to provide an option to list printers in
        # "lookup order" (i.e. unsorted).
        sorted_type_printers = copy.copy(type_printers)
        sorted_type_printers.sort(lambda x, y: cmp(x.name, y.name))
        for printer in sorted_type_printers:
            if printer.enabled:
                enabled = ''
            else:
                enabled = " [disabled]"
            print "  %s%s" % (printer.name, enabled)

    def invoke(self, arg, from_tty):
        """GDB calls this to perform the command."""
        sep = ''
        for objfile in gdb.objfiles():
            if objfile.type_printers:
                print "%sType printers for %s:" % (sep, objfile.name)
                self.list_type_printers(objfile.type_printers)
                sep = '\n'
        if gdb.current_progspace().type_printers:
            print "%sType printers for program space:" % sep
            self.list_type_printers(gdb.current_progspace().type_printers)
            sep = '\n'
        if gdb.type_printers:
            print "%sGlobal type printers:" % sep
            self.list_type_printers(gdb.type_printers)

class _EnableOrDisableCommand(gdb.Command):
    def __init__(self, setting, name):
        super(_EnableOrDisableCommand, self).__init__(name, gdb.COMMAND_DATA)
        self.setting = setting

    def set_some(self, name, printers):
        result = False
        for p in printers:
            if name == p.name:
                p.enabled = self.setting
                result = True
        return result

    def invoke(self, arg, from_tty):
        """GDB calls this to perform the command."""
        for name in arg.split():
            ok = False
            for objfile in gdb.objfiles():
                if self.set_some(name, objfile.type_printers):
                    ok = True
            if self.set_some(name, gdb.current_progspace().type_printers):
                ok = True
            if self.set_some(name, gdb.type_printers):
                ok = True
            if not ok:
                print "No type printer named '%s'" % name

    def add_some(self, result, word, printers):
        for p in printers:
            if p.name.startswith(word):
                result.append(p.name)

    def complete(self, text, word):
        result = []
        for objfile in gdb.objfiles():
            self.add_some(result, word, objfile.type_printers)
        self.add_some(result, word, gdb.current_progspace().type_printers)
        self.add_some(result, word, gdb.type_printers)
        return result

class EnableTypePrinter(_EnableOrDisableCommand):
    """GDB command to enable the specified type printer.

    Usage: enable type-printer NAME

    NAME is the name of the type-printer.
    """

    def __init__(self):
        super(EnableTypePrinter, self).__init__(True, "enable type-printer")

class DisableTypePrinter(_EnableOrDisableCommand):
    """GDB command to disable the specified type-printer.

    Usage: disable type-printer NAME

    NAME is the name of the type-printer.
    """

    def __init__(self):
        super(DisableTypePrinter, self).__init__(False, "disable type-printer")

InfoTypePrinter()
EnableTypePrinter()
DisableTypePrinter()
