This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [python][patch] PR pyton/11381


On 04/09/2010 04:48 PM, Tom Tromey wrote:
>>>>>> "Phil" == Phil Muldoon <pmuldoon@redhat.com> 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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]