* NEWS: Update.
* data-directory/Makefile.in (PYTHON_FILES): Add type_printers.py. * python/lib/gdb/command/type_printers.py: New file. * python/lib/gdb/command/types.py (TypePrinter): New class. (_get_some_type_recognizers, get_type_recognizers, apply_type_recognizers, register_type_printer): New functions. * python/py-objfile.c (objfile_object) <type_printers>: New field. (objfpy_dealloc): Decref new field. (objfpy_new): Set new field. (objfpy_get_type_printers, objfpy_set_type_printers): New functions. (objfile_to_objfile_object): Set new field. (objfile_getset): Add "type_printers". * python/py-progspace.c (pspace_object) <type_printers>: New field. (pspy_dealloc): Decref new field. (pspy_new): Set new field. (pspy_get_type_printers, pspy_set_type_printers): New functions. (pspace_to_pspace_object): Set new field. (pspace_getset): Add "type_printers". * python/python.c (start_type_printers, apply_type_printers, free_type_printers): New functions. (_initialize_python): Set gdb.type_printers. * python/python.h (start_type_printers, apply_type_printers, free_type_printers): Declare. * typeprint.c (type_print_raw_options, default_ptype_flags): Update for new fields. (do_free_global_table, create_global_typedef_table, find_global_typedef): New functions. (find_typedef_in_hash): Use find_global_typedef. (whatis_exp): Use create_global_typedef_table. Change cleanup handling. * typeprint.h (struct type_print_options) <global_typedefs, global_printers>: New fields. doc * gdb.texinfo (Symbols): Document "info type-printers", "enable type-printer" and "disable type-printer". (Python API): Add new node to menu. (Type Printing API): New node. (Progspaces In Python): Document type_printers field. (Objfiles In Python): Likewise. (gdb.types) <get_type_recognizers, apply_type_recognizers, register_type_printer, TypePrinter>: Document. testsuite * gdb.base/completion.exp: Update for "info type-printers". * gdb.python/py-typeprint.cc: New file. * gdb.python/py-typeprint.exp: New file. * gdb.python/py-typeprint.py: New file.
This commit is contained in:
parent
bd69fc683f
commit
18a9fc1261
19 changed files with 874 additions and 17 deletions
|
@ -70,6 +70,9 @@ sys.argv = ['']
|
|||
# Initial pretty printers.
|
||||
pretty_printers = []
|
||||
|
||||
# Initial type printers.
|
||||
type_printers = []
|
||||
|
||||
# Convenience variable to GDB's python directory
|
||||
PYTHONDIR = os.path.dirname(os.path.dirname(__file__))
|
||||
|
||||
|
|
125
gdb/python/lib/gdb/command/type_printers.py
Normal file
125
gdb/python/lib/gdb/command/type_printers.py
Normal file
|
@ -0,0 +1,125 @@
|
|||
# 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()
|
|
@ -109,3 +109,68 @@ def deep_items (type_):
|
|||
else:
|
||||
for i in deep_items (v.type):
|
||||
yield i
|
||||
|
||||
class TypePrinter(object):
|
||||
"""The base class for type printers.
|
||||
|
||||
Instances of this type can be used to substitute type names during
|
||||
'ptype'.
|
||||
|
||||
A type printer must have at least 'name' and 'enabled' attributes,
|
||||
and supply an 'instantiate' method.
|
||||
|
||||
The 'instantiate' method must either return None, or return an
|
||||
object which has a 'recognize' method. This method must accept a
|
||||
gdb.Type argument and either return None, meaning that the type
|
||||
was not recognized, or a string naming the type.
|
||||
"""
|
||||
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.enabled = True
|
||||
|
||||
def instantiate(self):
|
||||
return None
|
||||
|
||||
# Helper function for computing the list of type recognizers.
|
||||
def _get_some_type_recognizers(result, plist):
|
||||
for printer in plist:
|
||||
if printer.enabled:
|
||||
inst = printer.instantiate()
|
||||
if inst is not None:
|
||||
result.append(inst)
|
||||
return None
|
||||
|
||||
def get_type_recognizers():
|
||||
"Return a list of the enabled type recognizers for the current context."
|
||||
result = []
|
||||
|
||||
# First try the objfiles.
|
||||
for objfile in gdb.objfiles():
|
||||
_get_some_type_recognizers(result, objfile.type_printers)
|
||||
# Now try the program space.
|
||||
_get_some_type_recognizers(result, gdb.current_progspace().type_printers)
|
||||
# Finally, globals.
|
||||
_get_some_type_recognizers(result, gdb.type_printers)
|
||||
|
||||
return result
|
||||
|
||||
def apply_type_recognizers(recognizers, type_obj):
|
||||
"""Apply the given list of type recognizers to the type TYPE_OBJ.
|
||||
If any recognizer in the list recognizes TYPE_OBJ, returns the name
|
||||
given by the recognizer. Otherwise, this returns None."""
|
||||
for r in recognizers:
|
||||
result = r.recognize(type_obj)
|
||||
if result is not None:
|
||||
return result
|
||||
return None
|
||||
|
||||
def register_type_printer(locus, printer):
|
||||
"""Register a type printer.
|
||||
PRINTER is the type printer instance.
|
||||
LOCUS is either an objfile, a program space, or None, indicating
|
||||
global registration."""
|
||||
|
||||
if locus is None:
|
||||
locus = gdb
|
||||
locus.type_printers.insert(0, printer)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue