Re: Adding support for pretty printing of 2D arrays
Jan Kratochvil <[email protected]>
| Newsgroups | gmane.comp.gdb.devel |
|---|---|
| Message-ID | <[email protected]> |
On Thu, 17 Apr 2014 14:06:54 +0200, Morten Olsen Lysgaard wrote:
> I would like to know if it makes sense to add 2D, and possibly a
> n-dimensional, array pretty printing hint and logic?
FYI there was for some time support for 2D printing in Fedora GDB but it was
later removed and it is probably no longer relevant for current GDB.
Also from what I heard the way it was implement was not right.
Jan
Author: Chris Moller (Red Hat that time)
Originally added by Fedora commit:
http://pkgs.fedoraproject.org/cgit/gdb.git/commit/?id=6068e6305ed7d05b4a919c28aa5bcb737e1f163b
Removed by Fedora commit:
http://pkgs.fedoraproject.org/cgit/gdb.git/commit/?id=f8eee055504d803578fc226027045ef37277c9f6
gdb_test "p test2" "= $nl {$nl {.*"
# Complete result is:
#
# (gdb) p test2
# $2 =
# {
# {0 1 }
# {2 3 }
# {4 5 }
# }
gdb_test "p test3" "= $nl {$nl {$nl {.*"
# Complete result is:
#
# (gdb) p test3
# $3 =
# {
# {
# {0 1 }
# {10 11 }
# {20 21 }
# }
# {
# {100 101 }
# {110 111 }
# {120 121 }
# }
# {
# {200 201 }
# {210 211 }
# {220 221 }
# }
# {
# {300 301 }
# {310 311 }
# {320 321 }
# }
# }
gdb-bz562763-pretty-print-2d-vectors.patch
(text/plain, 12.2 KB)
2010-05-31 Chris Moller <[email protected]> * python/py-prettyprint.c (print_children): Add formatting for matrices. (apply_val_pretty_printer): Detect and deal with matrix hints. 2010-05-31 Chris Moller <[email protected]> * gdb.python/Makefile.in (EXECUTABLES): Added pr10659. * gdb.python/pr10659.cc: New file. * gdb.python/pr10659.exp. New file. * gdb.python/pr10659.py: New file. Index: gdb-7.2.50.20110218/gdb/valprint.h =================================================================== --- gdb-7.2.50.20110218.orig/gdb/valprint.h 2011-02-14 12:35:45.000000000 +0100 +++ gdb-7.2.50.20110218/gdb/valprint.h 2011-02-18 10:44:32.000000000 +0100 @@ -90,6 +90,9 @@ struct value_print_options /* If nonzero, print the value in "summary" form. */ int summary; + + /* Affects pretty printing of matrices. */ + int prettyprint_matrix; }; /* The global print options set by the user. In general this should Index: gdb-7.2.50.20110218/gdb/python/py-prettyprint.c =================================================================== --- gdb-7.2.50.20110218.orig/gdb/python/py-prettyprint.c 2011-02-14 12:10:53.000000000 +0100 +++ gdb-7.2.50.20110218/gdb/python/py-prettyprint.c 2011-02-18 10:45:02.000000000 +0100 @@ -501,7 +501,7 @@ print_children (PyObject *printer, const /* Use the prettyprint_arrays option if we are printing an array, and the pretty option otherwise. */ - if (is_array) + if (is_array || options->prettyprint_matrix) pretty = options->prettyprint_arrays; else { @@ -521,6 +521,9 @@ print_children (PyObject *printer, const goto done; } make_cleanup_py_decref (frame); + + if (options->prettyprint_matrix && recurse == 0) + fputs_filtered ("\n", stream); done_flag = 0; for (i = 0; i < options->print_max; ++i) @@ -555,12 +558,23 @@ print_children (PyObject *printer, const 3. Other. Always print a ",". */ if (i == 0) { - if (is_py_none) - fputs_filtered ("{", stream); - else - fputs_filtered (" = {", stream); + if (options->prettyprint_matrix && recurse == 0) + print_spaces_filtered (2 + 2 * recurse, stream); + if (is_py_none) + { + if (options->prettyprint_matrix && strcmp (hint, "array")) + { + fputs_filtered ("{\n", stream); + print_spaces_filtered (4 + 2 * recurse, stream); + } + else + fputs_filtered ("{", stream); + } + else + fputs_filtered (" = {", stream); } - + else if (options->prettyprint_matrix) + print_spaces_filtered (4 + 2 * recurse, stream); else if (! is_map || i % 2 == 0) fputs_filtered (pretty ? "," : ", ", stream); @@ -589,6 +603,10 @@ print_children (PyObject *printer, const if (is_map && i % 2 == 0) fputs_filtered ("[", stream); + else if (options->prettyprint_matrix) + { + /* Force a do-nothing. */ + } else if (is_array) { /* We print the index, not whatever the child method @@ -667,7 +685,12 @@ print_children (PyObject *printer, const fputs_filtered ("\n", stream); print_spaces_filtered (2 * recurse, stream); } - fputs_filtered ("}", stream); + if (options->prettyprint_matrix) + { + print_spaces_filtered (4 * recurse, stream); + fputs_filtered ("}\n", stream); + } + else fputs_filtered ("}", stream); } done: @@ -689,6 +712,7 @@ apply_val_pretty_printer (struct type *t char *hint = NULL; struct cleanup *cleanups; int result = 0; + struct value_print_options *options_copy; enum string_repr_result print_result; /* No pretty-printer support for unavailable values. */ @@ -726,9 +750,21 @@ apply_val_pretty_printer (struct type *t /* If we are printing a map, we want some special formatting. */ hint = gdbpy_get_display_hint (printer); + + if (recurse == 0) + { + options_copy = alloca (sizeof (struct value_print_options)); + memcpy (options_copy, options, sizeof (struct value_print_options)); + options_copy->prettyprint_matrix = hint && !strcmp (hint, "matrix"); + } + else options_copy = (struct value_print_options *)options; + make_cleanup (free_current_contents, &hint); /* Print the section */ + if (options_copy->prettyprint_matrix) + print_result = string_repr_none; +else /* Red Hat 2D matrix patch */ print_result = print_string_repr (printer, hint, stream, recurse, options, language, gdbarch); if (print_result != string_repr_error) Index: gdb-7.2.50.20110218/gdb/testsuite/gdb.python/pr10659.cc =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gdb-7.2.50.20110218/gdb/testsuite/gdb.python/pr10659.cc 2011-02-18 10:44:32.000000000 +0100 @@ -0,0 +1,43 @@ +#include <list> +#include <vector> // /usr/include/c++/4.4.1/bits/vector.tcc +#include <iostream> + +using namespace std; + +int use_windows = 9999; + +int +main(){ + vector<int> test1(2,0); + test1[0]=8; + test1[1]=9; + + vector< vector<int> > test2(3, vector<int>(2,0)); + test2[0][0]=0; + test2[0][1]=1; + test2[1][0]=2; + test2[1][1]=3; + test2[2][0]=4; + test2[2][1]=5; + +#define NR_ROWS 2 +#define NR_COLS 3 +#define NR_PLANES 4 + vector<int> rows(NR_ROWS, 0); + vector< vector<int> > columns(NR_COLS, rows); + vector< vector < vector<int> > > test3(NR_PLANES, columns); + + cout << "rows.size() = " << rows.size() + << ", columns.size() = " << columns.size() + << ", test3.size() = " << test3.size() << "\n"; + + for (int i = 0; i < rows.size(); i++) { + for (int j = 0; j < columns.size(); j++) { + for (int k = 0; k < test3.size(); k++) { + test3[k][j][i] = k * 100 + j * 10 + i; + } + } + } + + return 0; // break +} Index: gdb-7.2.50.20110218/gdb/testsuite/gdb.python/pr10659.exp =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gdb-7.2.50.20110218/gdb/testsuite/gdb.python/pr10659.exp 2011-02-18 10:44:32.000000000 +0100 @@ -0,0 +1,82 @@ +#Copyright 2010 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/>. + +set nl "\[\r\n\]+" + +set testfile pr10659 +set srcfile ${testfile}.cc +if [prepare_for_testing $testfile.exp $testfile $srcfile {debug c++}] { + return -1 +} + +#if { [skip_python_tests] } { continue } + +gdb_test "python execfile(\"$srcdir/$subdir/pr10659.py\")" "" +gdb_test "python gdb.pretty_printers = \[lookup_function\]" "" + +if ![runto_main] then { + fail "Can't run to main" + return +} + +gdb_breakpoint [gdb_get_line_number "break"] +gdb_continue_to_breakpoint "break" + +gdb_test "p test1" "vector of length 2, capacity 2 =.*" + +gdb_test "p test2" "= $nl {$nl {.*" + +# Complete result is: +# +# (gdb) p test2 +# $2 = +# { +# {0 1 } +# {2 3 } +# {4 5 } +# } + + +gdb_test "p test3" "= $nl {$nl {$nl {.*" + +# Complete result is: +# +# (gdb) p test3 +# $3 = +# { +# { +# {0 1 } +# {10 11 } +# {20 21 } +# } +# { +# {100 101 } +# {110 111 } +# {120 121 } +# } +# { +# {200 201 } +# {210 211 } +# {220 221 } +# } +# { +# {300 301 } +# {310 311 } +# {320 321 } +# } +# } +# + + Index: gdb-7.2.50.20110218/gdb/testsuite/gdb.python/pr10659.py =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gdb-7.2.50.20110218/gdb/testsuite/gdb.python/pr10659.py 2011-02-18 10:44:32.000000000 +0100 @@ -0,0 +1,109 @@ +# Copyright (C) 2008, 2009 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 gdb +import itertools +import re + +vector_sig = 'std::vector' +vector_regex = re.compile('^' + vector_sig + '<.*>$') + +class FakeVectorPrinter: + "Print a std::vector" + + class _iterator: + def __init__ (self, start, finish): + self.item = start + self.finish = finish + self.count = 0 + + def __iter__(self): + return self + + def next(self): + if self.item == self.finish: + raise StopIteration + count = self.count + self.count = self.count + 1 + elt = self.item.dereference() + self.item = self.item + 1 + return ('[%d]' % count, elt) + + def __init__(self, typename, val): + self.typename = typename + self.val = val + + def children(self): + return self._iterator(self.val['_M_impl']['_M_start'], + self.val['_M_impl']['_M_finish']) + + def to_string(self): + start = self.val['_M_impl']['_M_start'] + finish = self.val['_M_impl']['_M_finish'] + end = self.val['_M_impl']['_M_end_of_storage'] + return ('std::vector of length %d, capacity %d' + % (int (finish - start), int (end - start))) + + def display_hint(self): + itype0 = self.val.type.template_argument(0) + itag = itype0.tag + if itag and re.match(vector_regex, itag): + rc = 'matrix' + else: + rc = 'array' + return rc + +def register_libstdcxx_printers (obj): + "Register libstdc++ pretty-printers with objfile Obj." + + if obj == None: + obj = gdb + + obj.pretty_printers.append (lookup_function) + +def lookup_function (val): + "Look-up and return a pretty-printer that can print val." + + # Get the type. + type = val.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 () + + # Get the type name. + typename = type.tag + if typename == None: + return None + + # Iterate over local dictionary of types to determine + # if a printer is registered for that type. Return an + # instantiation of the printer if found. + for function in fake_pretty_printers_dict: + if function.search (typename): + return fake_pretty_printers_dict[function] (val) + + # Cannot find a pretty printer. Return None. + return None + +def build_libfakecxx_dictionary (): + fake_pretty_printers_dict[vector_regex] = lambda val: FakeVectorPrinter(vector_sig, val) + +fake_pretty_printers_dict = {} + +build_libfakecxx_dictionary () Index: gdb-7.2.50.20110218/gdb/valprint.c =================================================================== --- gdb-7.2.50.20110218.orig/gdb/valprint.c 2011-02-18 10:44:16.000000000 +0100 +++ gdb-7.2.50.20110218/gdb/valprint.c 2011-02-18 10:44:32.000000000 +0100 @@ -85,7 +85,8 @@ struct value_print_options user_print_op 1, /* static_field_print */ 1, /* pascal_static_field_print */ 0, /* raw */ - 0 /* summary */ + 0, /* summary */ + 0 /* prettyprint_matrix */ }; /* Initialize *OPTS to be a copy of the user print options. */
gdb-bz562763-pretty-print-2d-vectors-libstdcxx.patch
(text/plain, 1.6 KB)
2010-06-01 Chris Moller <[email protected]> * python/libstdcxx/v6/printers.py (StdVectorPrinter): Add detection for matrices as nested vectors. Index: libstdc++-v3/python/libstdcxx/v6/printers.py =================================================================== --- ./libstdc++-v3-python-r155978/libstdcxx/v6/printers.py (revision 159937) +++ ./libstdc++-v3-python-r155978/libstdcxx/v6/printers.py (working copy) @@ -19,6 +19,9 @@ import itertools import re +vector_sig = 'std::vector' +vector_regex = re.compile('^' + vector_sig + '<.*>$') + class StdPointerPrinter: "Print a smart pointer of some kind" @@ -186,7 +189,13 @@ % (self.typename, int (finish - start), int (end - start))) def display_hint(self): - return 'array' + itype0 = self.val.type.template_argument(0) + itag = itype0.tag + if itag and re.match(vector_regex, itag): + rc = 'matrix' + else: + rc = 'array' + return rc class StdVectorIteratorPrinter: "Print std::vector::iterator" @@ -692,7 +701,7 @@ pretty_printers_dict[re.compile('^std::set<.*>$')] = lambda val: StdSetPrinter("std::set", val) pretty_printers_dict[re.compile('^std::stack<.*>$')] = lambda val: StdStackOrQueuePrinter("std::stack", val) pretty_printers_dict[re.compile('^std::unique_ptr<.*>$')] = UniquePointerPrinter - pretty_printers_dict[re.compile('^std::vector<.*>$')] = lambda val: StdVectorPrinter("std::vector", val) + pretty_printers_dict[vector_regex] = lambda val: StdVectorPrinter(vector_sig, val) # vector<bool> # Printer registrations for classes compiled with -D_GLIBCXX_DEBUG.