All,
for the last couple of releases, gdb had the ability to print data types in a 
prettier way than by just dumping them element-by-element [1]. For example, by 
default, this is how a cell iterator looks like:
------------------------------------------------------------------
$2 = {<dealii::TriaIterator<dealii::DoFCellAccessor<dealii::DoFHandler<2, 3> > 
>> = {<dealii::TriaRawIterator<dealii::DoFCellAccessor<dealii::DoFHandler<2, 
3> > >> = {<std::iterator<std::bidirectional_iterator_tag, 
dealii::DoFCellAccessor<dealii::DoFHandler<2, 3> >, long, 
dealii::DoFCellAccessor<dealii::DoFHandler<2, 3> >*, 
dealii::DoFCellAccessor<dealii::DoFHandler<2, 3> >&>> = {<No data fields>}, 
      accessor = {<dealii::DoFAccessor<2, dealii::DoFHandler<2, 3> >> = 
{<dealii::CellAccessor<2, 3>> = {<dealii::TriaAccessor<2, 2, 3>> = 
{<dealii::TriaAccessorBase<2, 2, 3>> = {
                static space_dimension = <optimized out>, static dimension = 
<optimized out>, 
                static structure_dimension = <optimized out>, present_level = 
-9856, 
                present_index = 32767, tria = 0x4a1556}, <No data fields>}, 
<No data fields>}, 
          static dimension = 2, static space_dimension = 3, dof_handler = 
0x7fffffffdac8}, 
        static dim = <optimized out>, 
        static spacedim = <optimized out>}}, <No data fields>}, <No data 
fields>}
------------------------------------------------------------------

By doing
  set print pretty on
in gdb, we can improve this to the slightly more structured
------------------------------------------------------------------
$1 = {
  <dealii::TriaIterator<dealii::DoFCellAccessor<dealii::DoFHandler<2, 3> > >> 
= {
    <dealii::TriaRawIterator<dealii::DoFCellAccessor<dealii::DoFHandler<2, 3> 
> >> = {
      <std::iterator<std::bidirectional_iterator_tag, 
dealii::DoFCellAccessor<dealii::DoFHandler<2, 3> >, long, 
dealii::DoFCellAccessor<dealii::DoFHandler<2, 3> >*, 
dealii::DoFCellAccessor<dealii::DoFHandler<2, 3> >&>> = {<No data fields>}, 
      members of 
dealii::TriaRawIterator<dealii::DoFCellAccessor<dealii::DoFHandler<2, 3> > >: 
      accessor = {
        <dealii::DoFAccessor<2, dealii::DoFHandler<2, 3> >> = {
          <dealii::CellAccessor<2, 3>> = {
            <dealii::TriaAccessor<2, 2, 3>> = {
              <dealii::TriaAccessorBase<2, 2, 3>> = {
                static space_dimension = <optimized out>, 
                static dimension = <optimized out>, 
                static structure_dimension = <optimized out>, 
                present_level = -9856, 
                present_index = 32767, 
                tria = 0x4a1556
              }, <No data fields>}, <No data fields>}, 
          members of dealii::DoFAccessor<2, dealii::DoFHandler<2, 3> >: 
          static dimension = 2, 
          static space_dimension = 3, 
          dof_handler = 0x7fffffffdac8
        }, 
        members of dealii::DoFCellAccessor<dealii::DoFHandler<2, 3> >: 
        static dim = <optimized out>, 
        static spacedim = <optimized out>
      }
    }, <No data fields>}, <No data fields>}
------------------------------------------------------------------

What we'd like to have is this:
------------------------------------------------------------------
$3 = {
  triangulation = 0x4a1556,
  dof_handler = 0x7fffffffdac8,
  level = -9856,
  index = 32767
}
------------------------------------------------------------------

This turns out to be not too difficult in recent gdb versions. I've 
implemented such pretty printers currently for the following data types:
  Point<dim>
  Tensor<rank,dim>
  Vector<T>
  the various iterator classes
Are there any other classes people would like to see?

As for how to do it: gdb reads initialization procedures from $HOME/.gdbinit 
-- attached is the one I use for now.

Let me know if someone has ideas for extensions! Best
 W.

[1] Most graphical frontends for gdb, such as ddd and kdevelop just print the 
variable values they get from gdb. In other words, all of the above pretty 
printers also work for these graphical front ends :-)

-------------------------------------------------------------------------
Wolfgang Bangerth                email:            [email protected]
                                 www: http://www.math.tamu.edu/~bangerth/
set print pretty 1


python

import gdb
import itertools
import re

# Try to use the new-style pretty-printing if available.
_use_gdb_pp = True
try:
    import gdb.printing
except ImportError:
    _use_gdb_pp = False

class PointPrinter:
    "Print dealii::Point"

    def __init__ (self, typename, val):
        self.typename = typename
        self.val = val

    def to_string (self):
        return '%s' % self.val['values']


class TensorPrinter:
    "Print dealii::Tensor"

    def __init__ (self, typename, val):
        self.typename = typename
        self.val = val

    def to_string (self):
        # we could distinguish between Tensor<1,dim> and Tensor<2,dim>
        # by asking self.val.type.template_argument(0) but unfortunately
        # template_argument does not handle value arguments...
        try:
          return self.val['values']
        except:
          return self.val['subtensor']


class TriaIteratorPrinter:
    "Print dealii::TriaIterator"

    def __init__ (self, typename, val):
        self.typename = typename
        self.val = val

    def to_string (self):
        if re.compile('.*DoF.*').match('%s' % 
self.val.type.template_argument(0)):
          return ('{\n  triangulation = %s,\n  dof_handler = %s,\n  level = 
%d,\n  index = %d\n}' %
                  (self.val['accessor']['tria'],
                   self.val['accessor']['dof_handler'],
                   self.val['accessor']['present_level'],
                   self.val['accessor']['present_index']))
        else:
          return ('{\n  triangulation = %s,\n  level = %d,\n  index = %d\n}' %
                  (self.val['accessor']['tria'],
                   self.val['accessor']['present_level'],
                   self.val['accessor']['present_index']))



class VectorPrinter:
    "Print dealii::Vector"

    class _iterator:
        def __init__ (self, start, size):
            self.start = start
            self.size = size
            self.count = 0

        def __iter__(self):
            return self

        def next(self):
            count = self.count
            self.count = self.count + 1
            self.start = self.start + 1
            if self.count == self.size:
                raise StopIteration
            elt = self.start.dereference()
            return ('[%d]' % count, elt)

    def __init__ (self, typename, val):
        self.typename = typename
        self.val = val

    def children(self):
        return self._iterator(self.val['val'],
                              self.val['vec_size'])

    def to_string_x (self):
        return ('%s[%d] = {%s}' % (self.val.type.template_argument(0),
                                   self.val['vec_size'],
                                   self.val['val'].dereference()))

    def to_string (self):
        return ('%s[%d]' % (self.val.type.template_argument(0),
                            self.val['vec_size']))

    def display_hint(self):
        return 'array'



# A "regular expression" printer which conforms to the
# "SubPrettyPrinter" protocol from gdb.printing.
class RxPrinter(object):
    def __init__(self, name, function):
        super(RxPrinter, self).__init__()
        self.name = name
        self.function = function
        self.enabled = True

    def invoke(self, value):
        if not self.enabled:
            return None
        return self.function(self.name, value)


# A pretty-printer that conforms to the "PrettyPrinter" protocol from
# gdb.printing.  It can also be used directly as an old-style printer.
class Printer(object):
    def __init__(self, name):
        super(Printer, self).__init__()
        self.name = name
        self.subprinters = []
        self.lookup = {}
        self.enabled = True
        self.compiled_rx = re.compile('^([a-zA-Z0-9_:]+)<.*>$')

    def add(self, name, function):
        # A small sanity check.
        # FIXME
        if not self.compiled_rx.match(name + '<>'):
            raise ValueError, 'libstdc++ programming error: "%s" does not 
match' % name
        printer = RxPrinter(name, function)
        self.subprinters.append(printer)
        self.lookup[name] = printer

    @staticmethod
    def get_basic_type(type):
        # If it points to a reference, get the reference.
        if type.code == gdb.TYPE_CODE_REF:
            type = type.target ()

        # Get the unqualified type, stripped of typedefs.
        type = type.unqualified ().strip_typedefs ()

        return type.tag

    def __call__(self, val):
        typename = self.get_basic_type(val.type)
        if not typename:
            return None

        # All the types we match are template types, so we can use a
        # dictionary.
        match = self.compiled_rx.match(typename)
        if not match:
            return None

        basename = match.group(1)
        if basename in self.lookup:
            return self.lookup[basename].invoke(val)

        # Cannot find a pretty printer.  Return None.
        return None

dealii_printer = None

def build_dealii_dictionary ():
    global dealii_printer

    dealii_printer = Printer("deal.II")
    dealii_printer.add ('dealii::Point', PointPrinter)
    dealii_printer.add ('dealii::Tensor', TensorPrinter)
    dealii_printer.add ('dealii::TriaRawIterator', TriaIteratorPrinter)
    dealii_printer.add ('dealii::TriaIterator', TriaIteratorPrinter)
    dealii_printer.add ('dealii::TriaActiveIterator', TriaIteratorPrinter)
    dealii_printer.add ('dealii::Vector', VectorPrinter)

def register_dealii_printers (obj):
    "Register deal.II pretty-printers with objfile Obj."

    global _use_gdb_pp
    global dealii_printer

    build_dealii_dictionary ()
    if _use_gdb_pp:
        gdb.printing.register_pretty_printer(obj, dealii_printer)
    else:
        if obj is None:
            obj = gdb
        obj.pretty_printers.append(dealii_printer)


register_dealii_printers (None)

end

_______________________________________________
dealii mailing list http://poisson.dealii.org/mailman/listinfo/dealii

Reply via email to