From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 6162 invoked by alias); 13 Apr 2010 15:05:29 -0000 Received: (qmail 5877 invoked by uid 22791); 13 Apr 2010 15:05:26 -0000 X-SWARE-Spam-Status: No, hits=-6.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 13 Apr 2010 15:05:19 +0000 Received: from int-mx03.intmail.prod.int.phx2.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.16]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o3DF5I4A029444 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 13 Apr 2010 11:05:18 -0400 Received: from localhost.localdomain (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx03.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o3DF5GZO012658; Tue, 13 Apr 2010 11:05:17 -0400 Message-ID: <4BC4882C.8060601@redhat.com> Date: Tue, 13 Apr 2010 15:05:00 -0000 From: Phil Muldoon User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.8) Gecko/20100301 Fedora/3.0.3-1.fc12 Lightning/1.0b2pre Thunderbird/3.0.3 MIME-Version: 1.0 To: tromey@redhat.com CC: gdb-patches ml Subject: Re: [python][patch] PR pyton/11381 References: <4BBE1073.40703@redhat.com> In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2010-04/txt/msg00403.txt.bz2 On 04/09/2010 04:48 PM, Tom Tromey wrote: >>>>>> "Phil" == Phil Muldoon writes: > Phil> children should be printed in a pretty-printer. This patch allows the > Phil> printer's 'to_string' method to return the Python "None". If this is > Phil> the case, the GDB pretty-printers will print nothing in place of > Phil> to_string and also alter the preceding text slightly, stripping off > Phil> leading spaces and the '=" text. > > What should happen if to_string returns None but there is no children > method? > > I think we should not worry about corner cases like this, but even so we > should explicitly decide that. With this patch if the 'to_string' method returns 'None', and there is no 'children' method, nothing will be output following the standard "$x = " prefix. (gdb) p nstype $2 = If there is a 'children' method but the 'to_string' returns 'None' you will just get the children: (gdb) p nstype $2 = { [0] = 7, [1] = 42 } I'm not sure what to do in the 'to_string' returns 'None' and the missing 'children' method above. It's obviously a bogus pretty printers that outputs nothing at all, and the '$x = ' gets appended to the stream before the Python pretty-printers assume control. I'm open to ideas. > Does the varobj code do something sensible when to_string returns None? > I think there should be a test for this. Yes, added. > Phil> + is_py_none = print_string_repr (printer, hint, stream, recurse, options, language, > Phil> + gdbarch); > Phil> + print_children (printer, hint, stream, recurse, options, language, is_py_none); > > These lines look like they wrap now. OK. Cheers, Phil -- diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 887547b..104a1ec 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -20435,6 +20435,9 @@ the resulting value. Again, this may result in a call to another pretty-printer. Python scalars (integers, floats, and booleans) and strings are convertible to @code{gdb.Value}; other types are not. +Finally, if this method returns @code{None} then no further operations +are peformed in this method and nothing is printed. + If the result is not one of these types, an exception is raised. @end defop diff --git a/gdb/python/py-prettyprint.c b/gdb/python/py-prettyprint.c index 454aa5a..5c3757c 100644 --- a/gdb/python/py-prettyprint.c +++ b/gdb/python/py-prettyprint.c @@ -125,9 +125,12 @@ find_pretty_printer (PyObject *value) /* Pretty-print a single value, via the printer object PRINTER. If the function returns a string, a PyObject containing the string - is returned. Otherwise, if the function returns a value, - *OUT_VALUE is set to the value, and NULL is returned. On error, - *OUT_VALUE is set to NULL, and NULL is returned. */ + is returned. If the function returns Py_NONE that means the pretty + printer returned the Python None as a value. Otherwise, if the + function returns a value, *OUT_VALUE is set to the value, and NULL + is returned. On error, *OUT_VALUE is set to NULL, and NULL is + returned. */ + static PyObject * pretty_print_one_value (PyObject *printer, struct value **out_value) { @@ -140,7 +143,8 @@ pretty_print_one_value (PyObject *printer, struct value **out_value) result = PyObject_CallMethodObjArgs (printer, gdbpy_to_string_cst, NULL); if (result) { - if (! gdbpy_is_string (result) && ! gdbpy_is_lazy_string (result)) + if (! gdbpy_is_string (result) && ! gdbpy_is_lazy_string (result) + && result != Py_None) { *out_value = convert_value_from_python (result); if (PyErr_Occurred ()) @@ -179,8 +183,11 @@ gdbpy_get_display_hint (PyObject *printer) } /* Helper for apply_val_pretty_printer which calls to_string and - formats the result. */ -static void + formats the result. If the value returnd is Py_None, nothing is + printed and the function returns a 1; in all other cases data is + printed as given by the pretty printer and the function returns 0. +*/ +static int print_string_repr (PyObject *printer, const char *hint, struct ui_file *stream, int recurse, const struct value_print_options *options, @@ -189,52 +196,58 @@ print_string_repr (PyObject *printer, const char *hint, { struct value *replacement = NULL; PyObject *py_str = NULL; + int is_py_none = 0; py_str = pretty_print_one_value (printer, &replacement); if (py_str) { - gdb_byte *output = NULL; - long length; - struct type *type; - char *encoding = NULL; - PyObject *string = NULL; - int is_lazy; - - is_lazy = gdbpy_is_lazy_string (py_str); - if (is_lazy) - output = gdbpy_extract_lazy_string (py_str, &type, &length, &encoding); + if (py_str == Py_None) + is_py_none = 1; else { - string = python_string_to_target_python_string (py_str); - if (string) + gdb_byte *output = NULL; + long length; + struct type *type; + char *encoding = NULL; + PyObject *string = NULL; + int is_lazy; + + is_lazy = gdbpy_is_lazy_string (py_str); + if (is_lazy) + output = gdbpy_extract_lazy_string (py_str, &type, &length, &encoding); + else { - output = PyString_AsString (string); - length = PyString_Size (string); - type = builtin_type (gdbarch)->builtin_char; + string = python_string_to_target_python_string (py_str); + if (string) + { + output = PyString_AsString (string); + length = PyString_Size (string); + type = builtin_type (gdbarch)->builtin_char; + } + else + gdbpy_print_stack (); + + } + + if (output) + { + if (is_lazy || (hint && !strcmp (hint, "string"))) + LA_PRINT_STRING (stream, type, output, length, encoding, + 0, options); + else + fputs_filtered (output, stream); } else gdbpy_print_stack (); - } - - if (output) - { - if (is_lazy || (hint && !strcmp (hint, "string"))) - LA_PRINT_STRING (stream, type, output, length, encoding, - 0, options); + if (string) + Py_DECREF (string); else - fputs_filtered (output, stream); - } - else - gdbpy_print_stack (); + xfree (output); - if (string) - Py_DECREF (string); - else - xfree (output); - - xfree (encoding); - Py_DECREF (py_str); + xfree (encoding); + Py_DECREF (py_str); + } } else if (replacement) { @@ -245,6 +258,8 @@ print_string_repr (PyObject *printer, const char *hint, } else gdbpy_print_stack (); + + return is_py_none; } static void @@ -323,12 +338,14 @@ push_dummy_python_frame () } /* Helper for apply_val_pretty_printer that formats children of the - printer, if any exist. */ + printer, if any exist. If is_py_none is true, then nothing has + been printed by to_string, and format output accordingly. */ static void print_children (PyObject *printer, const char *hint, struct ui_file *stream, int recurse, const struct value_print_options *options, - const struct language_defn *language) + const struct language_defn *language, + int is_py_none) { int is_map, is_array, done_flag, pretty; unsigned int i; @@ -408,7 +425,13 @@ print_children (PyObject *printer, const char *hint, 2. Arrays. Always print a ",". 3. Other. Always print a ",". */ if (i == 0) - fputs_filtered (" = {", stream); + { + if (is_py_none) + fputs_filtered ("{", stream); + else + fputs_filtered (" = {", stream); + } + else if (! is_map || i % 2 == 0) fputs_filtered (pretty ? "," : ", ", stream); @@ -532,7 +555,7 @@ apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr, char *hint = NULL; struct cleanup *cleanups; int result = 0; - + int is_py_none = 0; cleanups = ensure_python_env (gdbarch, language); /* Instantiate the printer. */ @@ -557,9 +580,11 @@ apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr, make_cleanup (free_current_contents, &hint); /* Print the section */ - print_string_repr (printer, hint, stream, recurse, options, language, - gdbarch); - print_children (printer, hint, stream, recurse, options, language); + is_py_none = print_string_repr (printer, hint, stream, recurse, + options, language, gdbarch); + print_children (printer, hint, stream, recurse, options, language, + is_py_none); + result = 1; diff --git a/gdb/testsuite/gdb.python/py-mi.exp b/gdb/testsuite/gdb.python/py-mi.exp index 6589a62..973ff85 100644 --- a/gdb/testsuite/gdb.python/py-mi.exp +++ b/gdb/testsuite/gdb.python/py-mi.exp @@ -61,6 +61,16 @@ mi_list_varobj_children container { mi_delete_varobj container "delete varobj" +mi_create_dynamic_varobj nscont nstype \ + "create nscont varobj, no pretty-printing" + +mi_list_varobj_children nscont { + { nscont.len len 0 int } + { nscont.elements elements 1 "int ." } +} "examine nscont children=0, no pretty-printing" + +mi_delete_varobj nscont "delete varobj" + mi_gdb_test "-enable-pretty-printing" "" mi_create_varobj_checked string string_1 \ @@ -239,4 +249,29 @@ mi_continue_to_line \ mi_varobj_update_with_type_change container int 0 "update after type change" + +mi_continue_to_line \ + [gdb_get_line_number {break to inspect struct and union} ${testfile}.c] \ + "step to outer breakpoint" + +mi_create_dynamic_varobj nscont nstype \ + "create nstype varobj" + +mi_list_varobj_children nscont { + { {nscont.\[0\]} {\[0\]} 0 int } + { {nscont.\[1\]} {\[1\]} 0 int } +} "list children after setting update range" + +mi_gdb_test "-var-set-visualizer nscont None" \ + "\\^done" \ + "clear visualizer" + +mi_gdb_test "-var-update nscont" \ + "\\^done,changelist=\\\[\\\]" \ + "varobj update after clearing" + +mi_gdb_test "-var-set-visualizer nscont gdb.default_visualizer" \ + "\\^done" \ + "choose default visualizer" + remote_file host delete ${remote_python_file} diff --git a/gdb/testsuite/gdb.python/py-prettyprint.c b/gdb/testsuite/gdb.python/py-prettyprint.c index e1f696f..f461bb1 100644 --- a/gdb/testsuite/gdb.python/py-prettyprint.c +++ b/gdb/testsuite/gdb.python/py-prettyprint.c @@ -119,6 +119,15 @@ typedef struct string_repr /* This lets us avoid malloc. */ int array[100]; +int narray[10]; + +struct justchildren +{ + int len; + int *elements; +}; + +typedef struct justchildren nostring_type; struct container { @@ -196,7 +205,9 @@ main () const struct string_repr cstring = { { "const string" } }; /* Clearing by being `static' could invoke an other GDB C++ bug. */ struct nullstr nullstr; - + nostring_type nstype; + nstype.elements = narray; + nstype.len = 0; init_ss(&ss, 1, 2); init_ss(ssa+0, 3, 4); @@ -249,5 +260,9 @@ main () do_nothing (); #endif + nstype.elements[0] = 7; + nstype.elements[1] = 42; + nstype.len = 2; + return 0; /* break to inspect struct and union */ } diff --git a/gdb/testsuite/gdb.python/py-prettyprint.exp b/gdb/testsuite/gdb.python/py-prettyprint.exp index 414362b..2c14c59 100644 --- a/gdb/testsuite/gdb.python/py-prettyprint.exp +++ b/gdb/testsuite/gdb.python/py-prettyprint.exp @@ -101,6 +101,7 @@ proc run_lang_tests {lang} { gdb_test "print estring" "\"embedded x\\\\201\\\\202\\\\203\\\\204\"" gdb_test "print c" " = container \"container\" with 2 elements = {$nl *.0. = 23,$nl *.1. = 72$nl}" + gdb_test "print nstype" " = {$nl *.0. = 7,$nl *.1. = 42$nl}" gdb_test "continue" "Program exited normally\." remote_file host delete ${remote_python_file} diff --git a/gdb/testsuite/gdb.python/py-prettyprint.py b/gdb/testsuite/gdb.python/py-prettyprint.py index 979d4ad..44bfc49 100644 --- a/gdb/testsuite/gdb.python/py-prettyprint.py +++ b/gdb/testsuite/gdb.python/py-prettyprint.py @@ -53,6 +53,33 @@ class ContainerPrinter: def children(self): return self._iterator(self.val['elements'], self.val['len']) +# Test a printer where to_string is None +class NoStringContainerPrinter: + class _iterator: + def __init__ (self, pointer, len): + self.start = pointer + self.pointer = pointer + self.end = pointer + len + + def __iter__(self): + return self + + def next(self): + if self.pointer == self.end: + raise StopIteration + result = self.pointer + self.pointer = self.pointer + 1 + return ('[%d]' % int (result - self.start), result.dereference()) + + def __init__(self, val): + self.val = val + + def to_string(self): + return None + + def children(self): + return self._iterator(self.val['elements'], self.val['len']) + class pp_s: def __init__(self, val): self.val = val @@ -190,8 +217,10 @@ def register_pretty_printers (): # both the C and C++ cases. pretty_printers_dict[re.compile ('^struct string_repr$')] = string_print pretty_printers_dict[re.compile ('^struct container$')] = ContainerPrinter + pretty_printers_dict[re.compile ('^struct justchildren$')] = NoStringContainerPrinter pretty_printers_dict[re.compile ('^string_repr$')] = string_print pretty_printers_dict[re.compile ('^container$')] = ContainerPrinter + pretty_printers_dict[re.compile ('^justchildren$')] = NoStringContainerPrinter pretty_printers_dict[re.compile ('^struct ns$')] = pp_ns pretty_printers_dict[re.compile ('^ns$')] = pp_ns