From 31ad644ff7e565070398adaabb2f615858d87ce8 Mon Sep 17 00:00:00 2001 From: David Wells Date: Thu, 10 Sep 2015 14:29:12 -0400 Subject: [PATCH] Added a small set of pretty printers for GDB. --- contrib/utilities/dotgdbinit.py | 206 ++++++++++++++++++++++++++++++++ doc/news/changes.h | 7 ++ 2 files changed, 213 insertions(+) create mode 100644 contrib/utilities/dotgdbinit.py diff --git a/contrib/utilities/dotgdbinit.py b/contrib/utilities/dotgdbinit.py new file mode 100644 index 0000000000..56786a78aa --- /dev/null +++ b/contrib/utilities/dotgdbinit.py @@ -0,0 +1,206 @@ +# --------------------------------------------------------------------- +# +# Copyright (C) 2015 by the deal.II authors +# +# This file is part of the deal.II library. +# +# The deal.II library is free software; you can use it, redistribute +# it, and/or modify it under the terms of the GNU Lesser General +# Public License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# The full text of the license can be found in the file LICENSE at +# the top level of the deal.II distribution. +# +# --------------------------------------------------------------------- + +# +# Instructions: Place a copy of this file, renamed as ".gdbinit", in your home +# directory to enable pretty-printing of various deal.II objects. +# +# This has only been tested with GDB 7.7.1 and newer, but it should work with +# slightly older versions of GDB (the Python interface was added in 7.0, +# released in 2009). +# +# Authors: Wolfgang Bangerth, 2015, David Wells, 2015 +# +set print pretty 1 + +python + +import gdb +import re + + +def build_output_string(keys, accessor): + """Build an output string of the form + { + a = foo, + b = bar + } + where a and b are elements of keys and foo and bar are values of + accessor (e.g., accessor['a'] = foo). + + Note that accessor need not be a dictionary (i.e., gdb.Values + redefines __getitem__).""" + return ("{\n" + + ",\n".join([" {} = {}".format(key, accessor[key]) + for key in keys]) + + "\n}") + + +class PointPrinter(object): + """Print a deal.II Point instance.""" + def __init__(self, typename, val): + self.typename = typename + self.val = val + + def to_string(self): + return self.val['values'] + + +class TensorPrinter(object): + """Print a deal.II Tensor instance.""" + def __init__(self, typename, val): + self.typename = typename + self.val = val + + def to_string(self): + if int(self.val.type.template_argument(0)) == 0: + return self.val['value'] + else: + return self.val['values'] + + +class TriaIteratorPrinter(object): + """Print a deal.II TriaIterator instance.""" + def __init__(self, typename, val): + self.typename = typename + self.val = val + + def to_string(self): + keys = ['tria', 'present_level', 'present_index'] + if 'DoFHandler' in str(self.val.type.template_argument(0)): + keys.insert(1, 'dof_handler') + + return build_output_string(keys, self.val['accessor']) + + +class VectorPrinter(object): + """Print a deal.II Vector instance.""" + def __init__(self, typename, val): + self.typename = typename + self.val = val + + def children(self): + # The first entry (see the "Pretty Printing API" documentation of GDB) + # in the tuple should be a name for the child, which should be nothing + # (an empty string) here. + return (("", (self.val['val'] + count).dereference()) + for count in range(int(self.val['vec_size']))) + + def to_string(self): + return "{}[{}]".format(self.val.type.template_argument(0), + self.val['vec_size']) + + @staticmethod + def display_hint(): + """Provide a hint to GDB that this is an array-like container + (so print values in sequence).""" + return "array" + + +class QuadraturePrinter(object): + """Print a deal.II Quadrature instance.""" + def __init__(self, typename, val): + self.typename = typename + self.val = val + + def to_string(self): + return build_output_string(['quadrature_points', 'weights'], self.val) + + +class RxPrinter(object): + """A "regular expression" printer which conforms to the + "SubPrettyPrinter" protocol from gdb.printing.""" + def __init__(self, name, function): + self.name = name + self.function = function + self.enabled = True + + def __call__(self, value): + if self.enabled: + return self.function(self.name, value) + else: + return None + + +class Printer(object): + """A pretty-printer that conforms to the "PrettyPrinter" protocol + from gdb.printing. It can also be used directly as an old-style + printer.""" + def __init__(self, name): + self.name = name + self.subprinters = list() + self.lookup = dict() + self.enabled = True + self.compiled_rx = re.compile('^([a-zA-Z0-9_:]+)<.*>$') + + def add(self, name, function): + printer = RxPrinter(name, function) + self.subprinters.append(printer) + self.lookup[name] = printer + + @staticmethod + def get_basic_type(object_type): + # If it points to a reference, then get the reference. + if object_type.code == gdb.TYPE_CODE_REF: + object_type = object_type.target() + + object_type = object_type.unqualified().strip_typedefs() + + return object_type.tag + + def __call__(self, val): + typename = self.get_basic_type(val.type) + if typename: + # All the types we match are template types, so we can use a + # dictionary. + match = self.compiled_rx.match(typename) + if match: + basename = match.group(1) + if basename in self.lookup: + return self.lookup[basename](val) + + return None + + +dealii_printer = Printer("deal.II") + + +def register_dealii_printers(): + """Register deal.II pretty-printers with gdb.""" + printers = { + PointPrinter: ['Point'], + TensorPrinter: ['Tensor'], + VectorPrinter: ['Vector'], + TriaIteratorPrinter: + ['TriaRawIterator', 'TriaIterator', 'TriaActiveIterator'], + QuadraturePrinter: + ['Quadrature', 'QGauss', 'QGaussLobatto', 'QMidpoint', 'QSimpson', + 'QTrapez', 'QMilne', 'QWeddle', 'QGaussLog', 'QGaussLogR', + 'QGaussOneOverR', 'QSorted', 'QTelles', 'QGaussChebyshev', + 'QGaussRadauChebyshev', 'QIterated', 'QAnisotropic'] + } + for printer, class_names in printers.items(): + for class_name in class_names: + dealii_printer.add('dealii::' + class_name, printer) + try: + from gdb import printing + printing.register_pretty_printer(gdb, dealii_printer) + except ImportError: + gdb.pretty_printers.append(dealii_printer) + + +register_dealii_printers() + +end diff --git a/doc/news/changes.h b/doc/news/changes.h index 64c86b4ec8..a153bdb7d0 100644 --- a/doc/news/changes.h +++ b/doc/news/changes.h @@ -122,6 +122,13 @@ inconvenience this causes.
    +
  1. New: A python script (including instructions) for enabling pretty + printing with GDB is now available in + /contrib/utilities/dotgdbinit.py. +
    + (Wolfgang Bangerth, David Wells, 2015/09/11) +
  2. +
  3. Improved: When available, deal.II now uses the "gold" linker, a reimplementation of the traditional Unix "ld" linker that is substantially faster. This reduces build and, in particular, test turnaround times. -- 2.39.5