6

I use boost::mpl::string<...> types extensively... enough that it would really help with debugging to have the types pretty-printed in gdb.

So... instead of gdb showing the individual (multicharacter literal) components like it currently does ...

boost::mpl::string<1668248165, 778856802, 778858343, ..., ..., 0, 0, 0, 0, 0, 0>

It would display the equivalent string value instead ...

boost::mpl::string<"The way out is through">

I've seen gdb macros and python scripts for pretty-printing STL containers in gdb, but I couldn't find one for pretty-printing boost::mpl strings. Can anyone help with this?


UPDATE: I've added a +100 bounty... I'm looking for a solution that utilizes the latest GDB support for pretty-printing via python (as described here for STL containers).

manlio
  • 18,345
  • 14
  • 76
  • 126
etherice
  • 1,761
  • 15
  • 25

1 Answers1

7

Here is my solution utilizing Boost-Pretty-Printer (https://github.com/ruediger/Boost-Pretty-Printer/wiki):

File mpl_printers.py:

import printers
import re
import string
import struct

@printers.register_pretty_printer
class BoostMplString:
    "Pretty Printer for boost::mpl::string"
    regex = re.compile('^boost::mpl::string<(.*)>$')

    @printers.static
    def supports(typename):
        return BoostMplString.regex.search(typename)

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

    def to_string(self):
            s = ''
            try:
                m = BoostMplString.regex.match(self.typename)
                args = string.split(m.group(1), ', ')
                for packed in args: 
                    i = int(packed)
                    if i == 0: 
                        break
                    r = ''
                    while i != 0:
                        i, c = divmod(i, 0x100)
                        r += chr(c)
                    s += r[::-1]
            except RuntimeError:
                s = '[Exception]'
            return '(boost::mpl::string) %s' % (s)

def register_boost_mpl_printers(obj):
    "Register Boost Pretty Printers."
    pass

File register_printers.gdb:

python

# Add the following line in your .gdbinit:
# source /usr/local/share/gdb/register_printers.gdb

import sys
sys.path.insert(0, '/usr/local/share/gdb/python')
# You might have these, too
# from libstdcxx.v6.printers import register_libstdcxx_printers
from boost.printers import register_boost_printers
from boost.mpl_printers import register_boost_mpl_printers

# register_libstdcxx_printers(None)
register_boost_printers(None)
register_boost_mpl_printers(None)

end
  • Install printers.py and the above mpl_printers.py in the directory /usr/local/share/gdb/python/boost.
  • Ensure you have an __init__.py in /usr/local/share/gdb/python/boost (An empty file will do it)
  • Install the above 'register_printers.gdb' in /usr/local/share/gdb.
  • Add 'source /usr/local/share/gdb/register_printers.gdb' in your .gdbinit

(You might choose different directories)

Test:

#include <boost/mpl/string.hpp>
int main() {
    boost::mpl::string<'hell','o wo','rld'> s;
    return 0;
}

gdb Test -ex 'b main' -ex 'r' -ex 'p s' -ex 'c' -ex 'q'

$1 = (boost::mpl::string) hello world

  • **Works like a charm!** And now I can easily beautify other typenames with python using this same method. Thank you. – etherice Sep 10 '13 at 12:50
  • @etherice Please publish your printers, some day. –  Sep 10 '13 at 13:10
  • 1
    To clarify a couple parts in the instructions: `printers.py` and `mpl_printers.py` should go in a `boost` subdirectory (i.e., `/usr/local/share/gdb/python/boost`) so the module names in `register_printers.gdb` are valid. Also, the `boost` subdirectory must contain an `__init__.py` file (which can be empty) so python recognizes it as a directory containing modules (otherwise, you will get a `ImportError: No module named boost.printers` error). – etherice Sep 10 '13 at 13:24
  • Dieter- NP. Thanks again for providing an elegant solution that does **exactly** what was asked for. – etherice Sep 10 '13 at 13:30