public inbox for archer@sourceware.org
 help / color / mirror / Atom feed
* [python][patch] Preserve string length, and embedded-nulls in pretty-print string emission.
@ 2009-05-22 20:23 Phil Muldoon
  2009-05-27 17:35 ` Tom Tromey
  0 siblings, 1 reply; 20+ messages in thread
From: Phil Muldoon @ 2009-05-22 20:23 UTC (permalink / raw)
  To: Project Archer

[-- Attachment #1: Type: text/plain, Size: 3455 bytes --]

This  patch is the second and final patch for supporting 
counted/embedded-null strings within the Python pretty-printers.

The first patch thread can be found here:

http://sourceware.org/ml/archer/2009-q2/msg00017.html

This patch focuses on string emission and the preservation of embedded 
nulls within counted strings.  This comprises of preserving the string 
length as reported from Python,  and the avoidance of string library 
calls like strlen, or xstrdup. The patch is shallow, but touches many 
parts of the printing code. I elected to alter convert_value_from_python 
to return the length of a string - if the value is a string - via an out 
parameter. Also as Tom pointed out previously, the string length has to 
be captured at conversion and passed back up through the call chain to 
convert_value_from_python. This touches a lot of Python string 
convenience functions, but not all of them.  In this patch, I choose  to 
convert only the convenience functions that this patch required,.  There 
may be a good argument to convert them all to carry string length as an 
explicit parameter. For this patch, I decided not to do it for brevity, 
but will be pleased to do it if the community/maintainer think it would 
be a good idea.

This patch is tested on x8664, and introduces no known regressions. It 
applies cleanly to archer-tromey-python branch.

I look forward to your comments.

Regards

Phil

ChangeLog

2009-05-22  Phil Muldoon  <pmuldoon@redhat.com>

    * python/lib/gdb/libstdcxx/v6/printers.py
    (StdStringPrinter.to_string): Extract length from header.  Use in
    string extraction.
    * python/python-frame.c (frapy_read_var): Update
    python_string_to_target_string call.
    * python//python-function.c (fnpy_call): Update
    convert_value_from_python call.
    * python/python-inferior.c (add_pattern_element): Likewise.
    * python/python-value.c (valpy_new, valpy_getitem, valpy_binop)
    (valpy_richcompare): Likewise.
    (convert_value_from_python): Add size parameter.  Write size
    parameter if value conversion is a string.
    * python/python-internal.h (convert_value_from_python)
    (unicode_to_target_string, python_string_to_target_string)
    (apply_varobj_pretty_printer): Update definitions to include
    a size parameter.
    * python/python-utils.c (unicode_to_encoded_string): Add size to
    parameter list.  Write size when completed.
    (unicode_to_target_string): Likewise.
    (python_string_to_target_string): Likewise.
    (apply_varobj_pretty_printer): Return a size.
    * python/python.c (pretty_print_one_value): Only use
    convert_value_from_python with a size.
    (print_string_repr): Capture size of string, and refactor to use
    a value only approach.
    (print_children): Use size of string.
    (apply_varobj_pretty_printer): Likewise.
    * value.c (value_from_string): New len parameter. Use over
    parameter over strlen call.
    * value.h (value_from_string): Update definition.
    * varobj.c (update_dynamic_varobj_children): Update
    convert_value_from_python_call.
    (value_get_print_value): Refactor to use returned value length.
    
Testsuite ChangeLog:

2009-05-22  Phil Muldoon  <pmuldoon@redhat.com>

    * gdb.python/python-prettyprint.c: Add counted null string
    variable.
    * gdb.python/python-prettyprint.exp: Print null string. Test for
    embedded nulls.
    * gdb.python/python-prettyprint.py (StdStringPrinter): New
    Function.

[-- Attachment #2: rc_nullstr_output.patch --]
[-- Type: text/x-patch, Size: 22225 bytes --]

diff --git a/gdb/python/lib/gdb/libstdcxx/v6/printers.py b/gdb/python/lib/gdb/libstdcxx/v6/printers.py
index 2bd2593..0f2d64e 100644
--- a/gdb/python/lib/gdb/libstdcxx/v6/printers.py
+++ b/gdb/python/lib/gdb/libstdcxx/v6/printers.py
@@ -465,10 +465,20 @@ class StdStringPrinter:
         # Look up the target encoding as late as possible.
         encoding = self.encoding
         if encoding is None:
-            encoding = gdb.parameter('target-charset')
-        elif isinstance(encoding, WideEncoding):
+            encoding = gdb.parameter ('target-charset')
+        elif isinstance (encoding, WideEncoding):
             encoding = encoding.value
-        return self.val['_M_dataplus']['_M_p'].string(encoding)
+        type = self.val.type
+        if type.code == gdb.TYPE_CODE_REF:
+            type = type.target ()
+
+        ptr = self.val ['_M_dataplus']['_M_p']
+        realtype = type.unqualified ().strip_typedefs ()
+        reptype = gdb.lookup_type (str (realtype) + '::_Rep').pointer ()
+        header = ptr.cast(reptype) - 1
+        len = header.dereference ()['_M_length']
+
+        return self.val['_M_dataplus']['_M_p'].string (encoding, length = len)
 
     def display_hint (self):
         return 'string'
diff --git a/gdb/python/python-frame.c b/gdb/python/python-frame.c
index ad03c46..9615166 100644
--- a/gdb/python/python-frame.c
+++ b/gdb/python/python-frame.c
@@ -395,7 +395,7 @@ frapy_read_var (PyObject *self, PyObject *args)
       struct cleanup *cleanup;
       volatile struct gdb_exception except;
 
-      var_name = python_string_to_target_string (sym_obj);
+      var_name = python_string_to_target_string (sym_obj, NULL);
       if (!var_name)
 	return NULL;
       cleanup = make_cleanup (xfree, var_name);
diff --git a/gdb/python/python-function.c b/gdb/python/python-function.c
index 4a85a33..ac7c3d8 100644
--- a/gdb/python/python-function.c
+++ b/gdb/python/python-function.c
@@ -83,7 +83,7 @@ fnpy_call (void *cookie, int argc, struct value **argv)
       error (_("Error while executing Python code."));
     }
 
-  value = convert_value_from_python (result);
+  value = convert_value_from_python (result, NULL);
   if (value == NULL)
     {
       Py_DECREF (result);
diff --git a/gdb/python/python-inferior.c b/gdb/python/python-inferior.c
index a08be7b..009f1e3 100644
--- a/gdb/python/python-inferior.c
+++ b/gdb/python/python-inferior.c
@@ -625,7 +625,7 @@ add_pattern_element (PyObject *obj, int size, char **pattern_buf,
     {
       /* See if we can convert from a Python object to a GDB value.  */
 
-      struct value *v = convert_value_from_python (obj);
+      struct value *v = convert_value_from_python (obj, NULL);
 
       if (v)
 	add_value_pattern (v, size, pattern_buf, pattern_buf_end,
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 29e55dd..2752930 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -112,7 +112,7 @@ PyObject *objfpy_get_printers (PyObject *, void *);
 struct block *block_object_to_block (PyObject *obj);
 struct symbol *symbol_object_to_symbol (PyObject *obj);
 struct value *value_object_to_value (PyObject *self);
-struct value *convert_value_from_python (PyObject *obj);
+struct value *convert_value_from_python (PyObject *obj, int *size);
 struct type *type_object_to_type (PyObject *obj);
 
 PyObject *gdbpy_get_hook_function (const char *);
@@ -167,8 +167,8 @@ PyObject *gdbpy_parameter_value (enum var_types, void *);
 void gdbpy_print_stack (void);
 
 PyObject *python_string_to_unicode (PyObject *obj);
-char *unicode_to_target_string (PyObject *unicode_str);
-char *python_string_to_target_string (PyObject *obj);
+char *unicode_to_target_string (PyObject *unicode_str, int *size);
+char *python_string_to_target_string (PyObject *obj, int *size);
 char *python_string_to_host_string (PyObject *obj);
 PyObject *target_string_to_unicode (const gdb_byte *str, int length);
 int gdbpy_is_string (PyObject *obj);
@@ -177,7 +177,7 @@ int gdbpy_is_value_object (PyObject *obj);
 
 /* Note that these are declared here, and not in python.h with the
    other pretty-printer functions, because they refer to PyObject.  */
-char *apply_varobj_pretty_printer (PyObject *print_obj,
+int apply_varobj_pretty_printer (PyObject *print_obj,
 				   struct value **replacement);
 PyObject *gdbpy_get_varobj_pretty_printer (struct value *value);
 PyObject *gdbpy_instantiate_printer (PyObject *cons, PyObject *value);
diff --git a/gdb/python/python-utils.c b/gdb/python/python-utils.c
index f9c9486..c4c1139 100644
--- a/gdb/python/python-utils.c
+++ b/gdb/python/python-utils.c
@@ -100,45 +100,57 @@ python_string_to_unicode (PyObject *obj)
 }
 
 /* Returns a newly allocated string with the contents of the given unicode
-   string object converted to a named charset.  If an error occurs during
-   the conversion, NULL will be returned and a python exception will be set.
+   string object converted to a named charset.  The parameter *SIZE
+   will be set to the size of the string.  If *SIZE is NULL no size
+   information will be returned.  If an error occurs during the
+   conversion, NULL will be returned and a python exception will be
+   set.
 
    The caller is responsible for xfree'ing the string.  */
 static char *
-unicode_to_encoded_string (PyObject *unicode_str, const char *charset)
+unicode_to_encoded_string (PyObject *unicode_str, const char *charset, int *size)
 {
-  char *result;
+  char *result = NULL;
   PyObject *string;
+  Py_ssize_t str_size;
 
   /* Translate string to named charset.  */
   string = PyUnicode_AsEncodedString (unicode_str, charset, NULL);
   if (string == NULL)
     return NULL;
 
-  result = xstrdup (PyString_AsString (string));
+  str_size = PyString_Size (string) + 1;
+  result = xmemdup (PyString_AsString (string), str_size, str_size);
+  if (size != NULL)
+    *size = str_size;
 
   Py_DECREF (string);
 
   return result;
 }
 
-/* Returns a newly allocated string with the contents of the given unicode
-   string object converted to the target's charset.  If an error occurs during
-   the conversion, NULL will be returned and a python exception will be set.
+/* Returns a newly allocated string with the contents of the given
+   unicode string object converted to the target's charset.  The
+   parameter *SIZE will be set to the size of the string.  If *SIZE is
+   NULL no size information will be returned.  If an error occurs
+   during the conversion, NULL will be returned and a python exception
+   will be set.
 
    The caller is responsible for xfree'ing the string.  */
 char *
-unicode_to_target_string (PyObject *unicode_str)
+unicode_to_target_string (PyObject *unicode_str, int *size)
 {
-  return unicode_to_encoded_string (unicode_str, target_charset ());
+  return unicode_to_encoded_string (unicode_str, target_charset (), size);
 }
 
 /* Converts a python string (8-bit or unicode) to a target string in
-   the target's charset.  Returns NULL on error, with a python exception set.
+   the target's charset.  The parameter *SIZE will be set to the
+   size of the string.  If *SIZE is NULL no size information will be
+   returned.  Returns NULL on error, with a python exception set.
 
    The caller is responsible for xfree'ing the string.  */
 char *
-python_string_to_target_string (PyObject *obj)
+python_string_to_target_string (PyObject *obj, int *size)
 {
   PyObject *str;
   char *result;
@@ -147,7 +159,7 @@ python_string_to_target_string (PyObject *obj)
   if (str == NULL)
     return NULL;
 
-  result = unicode_to_target_string (str);
+  result = unicode_to_target_string (str, size);
   Py_DECREF (str);
   return result;
 }
@@ -166,7 +178,7 @@ python_string_to_host_string (PyObject *obj)
   if (str == NULL)
     return NULL;
 
-  result = unicode_to_encoded_string (str, host_charset ()); 
+  result = unicode_to_encoded_string (str, host_charset (), NULL);
   Py_DECREF (str);
   return result;
 }
diff --git a/gdb/python/python-value.c b/gdb/python/python-value.c
index 743e6a6..eae858f 100644
--- a/gdb/python/python-value.c
+++ b/gdb/python/python-value.c
@@ -112,7 +112,7 @@ valpy_new (PyTypeObject *subtype, PyObject *args, PyObject *keywords)
       return NULL;
     }
 
-  value = convert_value_from_python (PyTuple_GetItem (args, 0));
+  value = convert_value_from_python (PyTuple_GetItem (args, 0), NULL);
   if (value == NULL)
     {
       subtype->tp_free (value_obj);
@@ -293,7 +293,7 @@ valpy_getitem (PyObject *self, PyObject *key)
 	  /* Assume we are attempting an array access, and let the
 	     value code throw an exception if the index has an invalid
 	     type.  */
-	  struct value *idx = convert_value_from_python (key);
+	  struct value *idx = convert_value_from_python (key, NULL);
 	  if (idx == NULL)
 	    return NULL;
 
@@ -397,11 +397,11 @@ valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other)
 	 to us as the OTHER argument, and SELF will be an entirely different
 	 kind of object, altogether.  Because of this, we can't assume self is
 	 a gdb.Value object and need to convert it from python as well.  */
-      arg1 = convert_value_from_python (self);
+      arg1 = convert_value_from_python (self, NULL);
       if (arg1 == NULL)
 	break;
 
-      arg2 = convert_value_from_python (other);
+      arg2 = convert_value_from_python (other, NULL);
       if (arg2 == NULL)
 	break;
 
@@ -666,7 +666,7 @@ valpy_richcompare (PyObject *self, PyObject *other, int op)
 
   TRY_CATCH (except, RETURN_MASK_ALL)
     {
-      value_other = convert_value_from_python (other);
+      value_other = convert_value_from_python (other, NULL);
       if (value_other == NULL)
 	return NULL;
 
@@ -824,10 +824,13 @@ value_object_to_value (PyObject *self)
 }
 
 /* Try to convert a Python value to a gdb value.  If the value cannot
-   be converted, set a Python exception and return NULL.  */
+   be converted, set a Python exception and return NULL.  The
+   parameter *SIZE will be set to the size of the string if the
+   Python value is a string.  If *SIZE is NULL or the value from
+   Python is not a string, the *SIZE  parameter will not be set.  */
 
 struct value *
-convert_value_from_python (PyObject *obj)
+convert_value_from_python (PyObject *obj, int *size)
 {
   struct value *value = NULL; /* -Wall */
   PyObject *target_str, *unicode_str;
@@ -896,14 +899,17 @@ convert_value_from_python (PyObject *obj)
       else if (gdbpy_is_string (obj))
 	{
 	  char *s;
+	  int str_size = 0;
 
-	  s = python_string_to_target_string (obj);
+	  s = python_string_to_target_string (obj, &str_size);
 	  if (s != NULL)
 	    {
 	      old = make_cleanup (xfree, s);
-	      value = value_from_string (s);
+	      value = value_from_string (s, str_size);
 	      do_cleanups (old);
 	    }
+	  if (size != NULL)
+	    *size = str_size;
 	}
       else if (PyObject_TypeCheck (obj, &value_object_type))
 	value = value_copy (((value_object *) obj)->value);
diff --git a/gdb/python/python.c b/gdb/python/python.c
index e97bef8..041f08e 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -826,15 +826,15 @@ find_pretty_printer (PyObject *value)
   return function;
 }
 
-/* Pretty-print a single value, via the printer object PRINTER.  If
-   the function returns a string, an xmalloc()d copy is returned.
-   Otherwise, if the function returns a value, a *OUT_VALUE is set to
-   the value, and NULL is returned.  On error, *OUT_VALUE is set to
-   NULL and NULL is returned.  */
-static char *
+/* Pretty-print a single value, via the printer object PRINTER.
+   The value output is written to *OUT_VALUE,  If the written
+   *OUT_VALUE contains a string, the function will return the length
+   of the string.  On error, *OUT_VALUE is set to NULL.  */
+static int
 pretty_print_one_value (PyObject *printer, struct value **out_value)
 {
   char *output = NULL;
+  int size = 0;
   volatile struct gdb_exception except;
 
   TRY_CATCH (except, RETURN_MASK_ALL)
@@ -844,23 +844,15 @@ 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))
-	    output = python_string_to_host_string (result);
-	  else if (PyObject_TypeCheck (result, &value_object_type))
-	    {
-	      /* If we just call convert_value_from_python for this
-		 type, we won't know who owns the result.  For this
-		 one case we need to copy the resulting value.  */
-	      struct value *v = value_object_to_value (result);
-	      *out_value = value_copy (v);
-	    }
-	  else
-	    *out_value = convert_value_from_python (result);
+	  *out_value = convert_value_from_python (result, &size);
+	  if (PyErr_Occurred ())
+	      *out_value = NULL;
+
 	  Py_DECREF (result);
 	}
     }
 
-  return output;
+  return size;
 }
 
 /* Instantiate a pretty-printer given a constructor, CONS, and a
@@ -906,21 +898,24 @@ print_string_repr (PyObject *printer, const char *hint,
 		   const struct value_print_options *options,
 		   const struct language_defn *language)
 {
-  char *output;
+  gdb_byte *output = NULL;
+  int str_length = 0;
   struct value *replacement = NULL;
+  const char *la_encoding = language->la_name;
 
-  output = pretty_print_one_value (printer, &replacement);
-  if (output)
-    {
-      if (hint && !strcmp (hint, "string"))
-	LA_PRINT_STRING (stream, (gdb_byte *) output, strlen (output),
-			 1, 0, options);
-      else
-	fputs_filtered (output, stream);
-      xfree (output);
-    }
-  else if (replacement)
-    common_val_print (replacement, stream, recurse, options, language);
+  str_length = pretty_print_one_value (printer, &replacement);
+  if (replacement)
+    if (str_length > 0)
+      {
+	LA_GET_STRING (replacement, &output, &str_length, &la_encoding);
+	if (hint && !strcmp (hint, "string"))
+	  LA_PRINT_STRING (stream, output, str_length, 1, 0, options);
+	else
+	  fputs_filtered (output, stream);
+	xfree (output);
+      }
+    else
+      common_val_print (replacement, stream, recurse, options, language);
   else
     gdbpy_print_stack ();
 }
@@ -1141,7 +1136,7 @@ print_children (PyObject *printer, const char *hint,
 	}
       else
 	{
-	  struct value *value = convert_value_from_python (py_v);
+	  struct value *value = convert_value_from_python (py_v, NULL);
 
 	  if (value == NULL)
 	    {
@@ -1235,25 +1230,28 @@ apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr,
 /* Apply a pretty-printer for the varobj code.  PRINTER_OBJ is the
    print object.  It must have a 'to_string' method (but this is
    checked by varobj, not here) which takes no arguments and
-   returns a string.  This function returns an xmalloc()d string if
-   the printer returns a string.  The printer may return a replacement
-   value instead; in this case *REPLACEMENT is set to the replacement
-   value, and this function returns NULL.  On error, *REPLACEMENT is
-   set to NULL and this function also returns NULL.  */
-char *
+   returns a string.  The printer will return a value and
+   *REPLACEMENT is set to the replacement value. If the replacement
+   value contains a string, this function will return the length of
+   the string.  On error, *REPLACEMENT is set to NULL and
+   this function also returns NULL.  */
+
+int
 apply_varobj_pretty_printer (PyObject *printer_obj,
 			     struct value **replacement)
 {
-  char *result;
+  int size = 0;
   PyGILState_STATE state = PyGILState_Ensure ();
 
   *replacement = NULL;
-  result = pretty_print_one_value (printer_obj, replacement);
-  if (result == NULL);
+  size = pretty_print_one_value (printer_obj, replacement);
+
+  if (replacement == NULL);
     gdbpy_print_stack ();
+
   PyGILState_Release (state);
 
-  return result;
+  return size;
 }
 
 /* Find a pretty-printer object for the varobj module.  Returns a new
diff --git a/gdb/testsuite/gdb.python/python-prettyprint.c b/gdb/testsuite/gdb.python/python-prettyprint.c
index 0d9110d..3cceef0 100644
--- a/gdb/testsuite/gdb.python/python-prettyprint.c
+++ b/gdb/testsuite/gdb.python/python-prettyprint.c
@@ -30,6 +30,9 @@ struct ss
 };
 
 #ifdef __cplusplus
+
+#include <string>
+
 struct S : public s {
   int zs;
 };
@@ -75,6 +78,8 @@ class Derived : public Vbase1, public Vbase2, public Vbase3
     }
 };
 
+std::string cplus_str ("embedded\0null\0string",20);
+
 #endif
 
 typedef struct string_repr
diff --git a/gdb/testsuite/gdb.python/python-prettyprint.exp b/gdb/testsuite/gdb.python/python-prettyprint.exp
index 47d2fa8..0c5518c 100644
--- a/gdb/testsuite/gdb.python/python-prettyprint.exp
+++ b/gdb/testsuite/gdb.python/python-prettyprint.exp
@@ -75,6 +75,8 @@ proc run_lang_tests {lang} {
 	gdb_test "print ref" "= a=<15> b=< a=<8> b=<$hex>>"
 	gdb_test "print derived" \
 	    " = \{.*<Vbase1> = pp class name: Vbase1.*<Vbase2> = \{.*<VirtualTest> = pp value variable is: 1,.*members of Vbase2:.*_vptr.Vbase2 = $hex.*<Vbase3> = \{.*members of Vbase3.*members of Derived:.*value = 2.*"
+	gdb_test "print cplus_str" "embedded\\\\000null\\\\000string.*"
+
     }
 
     gdb_test "print x" " = $hex \"this is x\""
diff --git a/gdb/testsuite/gdb.python/python-prettyprint.py b/gdb/testsuite/gdb.python/python-prettyprint.py
index 82e5331..5d74987 100644
--- a/gdb/testsuite/gdb.python/python-prettyprint.py
+++ b/gdb/testsuite/gdb.python/python-prettyprint.py
@@ -99,6 +99,32 @@ class pp_nullstr:
     def to_string(self):
         return self.val['s'].string(gdb.parameter('target-charset'))
 
+class StdStringPrinter:
+    "Print a std::basic_string of some kind"
+
+    def __init__(self, encoding, val):
+        self.encoding = encoding
+        self.val = val
+
+    def to_string(self):
+        # Look up the target encoding as late as possible.
+        encoding = gdb.parameter('target-charset')
+
+        type = self.val.type
+        if type.code == gdb.TYPE_CODE_REF:
+            type = type.target ()
+
+        ptr = self.val['_M_dataplus']['_M_p']
+        realtype = type.unqualified ().strip_typedefs()
+        reptype = gdb.lookup_type (str (realtype) + '::_Rep').pointer ()
+        header = ptr.cast(reptype) - 1
+        len = header.dereference()['_M_length']
+
+        return self.val['_M_dataplus']['_M_p'].string(encoding, length = len)
+
+    def display_hint (self):
+        return 'string'
+
 def lookup_function (val):
     "Look-up and return a pretty-printer that can print val."
 
@@ -155,6 +181,8 @@ def register_pretty_printers ():
     pretty_printers_dict[re.compile ('^string_repr$')] = string_print
     pretty_printers_dict[re.compile ('^container$')] = ContainerPrinter
     
+    pretty_printers_dict[re.compile('^std::basic_string<char,.*>$')] = lambda val: StdStringPrinter(None, val)
+
 pretty_printers_dict = {}
 
 register_pretty_printers ()
diff --git a/gdb/value.c b/gdb/value.c
index fd05f07..5f4731e 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -1849,13 +1849,13 @@ value_from_pointer (struct type *type, CORE_ADDR addr)
 /* Create a value for a string constant to be stored locally
    (not in the inferior's memory space, but in GDB memory).
    This is analogous to value_from_longest, which also does not
-   use inferior memory.  String shall NOT contain embedded nulls.  */
+   use inferior memory.  LEN is the length of the string *PTR
+   from which the value will be created.  */
 
 struct value *
-value_from_string (char *ptr)
+value_from_string (char *ptr, int len)
 {
   struct value *val;
-  int len = strlen (ptr);
   int lowbound = current_language->string_lower_bound;
   struct type *string_char_type;
   struct type *rangetype;
diff --git a/gdb/value.h b/gdb/value.h
index fd0d2c9..38c1289 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -295,7 +295,7 @@ extern struct value *value_from_pointer (struct type *type, CORE_ADDR addr);
 extern struct value *value_from_double (struct type *type, DOUBLEST num);
 extern struct value *value_from_decfloat (struct type *type,
 					  const gdb_byte *decbytes);
-extern struct value *value_from_string (char *string);
+extern struct value *value_from_string (char *string, int len);
 
 extern struct value *value_at (struct type *type, CORE_ADDR addr);
 extern struct value *value_at_lazy (struct type *type, CORE_ADDR addr);
diff --git a/gdb/varobj.c b/gdb/varobj.c
index 49b4a43..fb2b2b1 100644
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -893,7 +893,7 @@ update_dynamic_varobj_children (struct varobj *var,
 	  v = value_copy (v);
 	}
       else
-	v = convert_value_from_python (py_v);
+	v = convert_value_from_python (py_v, NULL);
 
       /* TODO: This assume the name of the i-th child never changes.  */
 
@@ -2250,9 +2250,10 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
   long dummy;
   struct ui_file *stb;
   struct cleanup *old_chain;
-  char *thevalue = NULL;
+  gdb_byte *thevalue = NULL;
   struct value_print_options opts;
-
+  int length = 0;
+  const char *la_encoding = current_language->la_name;
   if (value == NULL)
     return NULL;
 
@@ -2274,15 +2275,19 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
 	    xfree (hint);
 	  }
 
-	thevalue = apply_varobj_pretty_printer (value_formatter,
+	length = apply_varobj_pretty_printer (value_formatter,
 						&replacement);
-	if (thevalue && !string_print)
-	  {
-	    PyGILState_Release (state);
-	    return thevalue;
-	  }
+
 	if (replacement)
 	  value = replacement;
+
+	if ((length > 0) && (!string_print))
+         {
+	   LA_GET_STRING (value, &thevalue, &length, &la_encoding);
+           PyGILState_Release (state);
+           return thevalue;
+         }
+
       }
     PyGILState_Release (state);
   }
@@ -2294,10 +2299,11 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
   get_formatted_print_options (&opts, format_code[(int) format]);
   opts.deref_ref = 0;
   opts.raw = 1;
-  if (thevalue)
+  if (length > 0)
     {
+      LA_GET_STRING (value, &thevalue, &length, &la_encoding);
       make_cleanup (xfree, thevalue);
-      LA_PRINT_STRING (stb, (gdb_byte *) thevalue, strlen (thevalue),
+      LA_PRINT_STRING (stb, (gdb_byte *) thevalue, length,
 		       1, 0, &opts);
     }
   else

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [python][patch] Preserve string length, and embedded-nulls in pretty-print string emission.
  2009-05-22 20:23 [python][patch] Preserve string length, and embedded-nulls in pretty-print string emission Phil Muldoon
@ 2009-05-27 17:35 ` Tom Tromey
  2009-05-27 18:24   ` Phil Muldoon
  0 siblings, 1 reply; 20+ messages in thread
From: Tom Tromey @ 2009-05-27 17:35 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: Project Archer

Phil> +convert_value_from_python (PyObject *obj, int *size)

I don't understand why this needs the additional argument.
It seems to me that the size is implicit in the returned value.

Phil> +	  if (PyErr_Occurred ())
Phil> +	      *out_value = NULL;

This looks like it is indented improperly.

Phil> +  str_length = pretty_print_one_value (printer, &replacement);
Phil> +  if (replacement)
Phil> +    if (str_length > 0)
Phil> +      {
Phil> +	LA_GET_STRING (replacement, &output, &str_length, &la_encoding);
Phil> +	if (hint && !strcmp (hint, "string"))
Phil> +	  LA_PRINT_STRING (stream, output, str_length, 1, 0, options);
Phil> +	else
Phil> +	  fputs_filtered (output, stream);
Phil> +	xfree (output);

Why do we need LA_GET_STRING here?  Aren't the string contents already
in the value?

There are a couple cases like this.

Also, why check "str_length > 0".  A string might have length 0.
I think instead you probably want some kind of type check.

Phil>    *replacement = NULL;
Phil> -  result = pretty_print_one_value (printer_obj, replacement);
Phil> -  if (result == NULL);
Phil> +  size = pretty_print_one_value (printer_obj, replacement);
Phil> +
Phil> +  if (replacement == NULL);
Phil>      gdbpy_print_stack ();

This should check *replacement; 'replacement' can never be NULL.

Phil> +std::string cplus_str ("embedded\0null\0string",20);

A test relying on std::string is not very robust -- std::string may
change over time, breaking the test.  Instead, it is better to write
custom test code and a printer to match.  That way, we control the
implementation.

Tom

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [python][patch] Preserve string length, and embedded-nulls in pretty-print string emission.
  2009-05-27 17:35 ` Tom Tromey
@ 2009-05-27 18:24   ` Phil Muldoon
  2009-05-27 20:22     ` Tom Tromey
  0 siblings, 1 reply; 20+ messages in thread
From: Phil Muldoon @ 2009-05-27 18:24 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Project Archer

Tom Tromey wrote:
> Phil> +convert_value_from_python (PyObject *obj, int *size)
>
> I don't understand why this needs the additional argument.
> It seems to me that the size is implicit in the returned value.
>   


This function returns a struct value. If that value contains a string 
with embedded nulls, is there a way to determine the size of the 
"gdb_byte *contents"? I might have missed a method - or the obvious - 
but this is the reason for the out parameter. If the parameter size is 
not NULL, the size of the string is returned there.


> Phil> +	  if (PyErr_Occurred ())
> Phil> +	      *out_value = NULL;
>
> This looks like it is indented improperly.
>   


Ok, thanks.


> Phil> +  str_length = pretty_print_one_value (printer, &replacement);
> Phil> +  if (replacement)
> Phil> +    if (str_length > 0)
> Phil> +      {
> Phil> +	LA_GET_STRING (replacement, &output, &str_length, &la_encoding);
> Phil> +	if (hint && !strcmp (hint, "string"))
> Phil> +	  LA_PRINT_STRING (stream, output, str_length, 1, 0, options);
> Phil> +	else
> Phil> +	  fputs_filtered (output, stream);
> Phil> +	xfree (output);
>
> Why do we need LA_GET_STRING here?  Aren't the string contents already
> in the value?
>   

I'll look at this a little more closely. But I use this to extract a 
string with embedded nulls with a concrete length. Do I misread your 
thoughts here? Or are you suggesting we just pass in value->contents to 
LA_PRINT_STRING?

> Also, why check "str_length > 0".  A string might have length 0.
> I think instead you probably want some kind of type check.
>   

Ok, thanks.

> Phil>    *replacement = NULL;
> Phil> -  result = pretty_print_one_value (printer_obj, replacement);
> Phil> -  if (result == NULL);
> Phil> +  size = pretty_print_one_value (printer_obj, replacement);
> Phil> +
> Phil> +  if (replacement == NULL);
> Phil>      gdbpy_print_stack ();
>
> This should check *replacement; 'replacement' can never be NULL.
>   


Ok, thanks.

> Phil> +std::string cplus_str ("embedded\0null\0string",20);
>
> A test relying on std::string is not very robust -- std::string may
> change over time, breaking the test.  Instead, it is better to write
> custom test code and a printer to match.  That way, we control the
> implementation.
>   


Ok thanks for the pointer. Can you please elaborate a bit more?

Regards

Phil

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [python][patch] Preserve string length, and embedded-nulls in pretty-print string emission.
  2009-05-27 18:24   ` Phil Muldoon
@ 2009-05-27 20:22     ` Tom Tromey
  2009-06-01 16:26       ` Phil Muldoon
  0 siblings, 1 reply; 20+ messages in thread
From: Tom Tromey @ 2009-05-27 20:22 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: Project Archer

Phil> This function returns a struct value. If that value contains a
Phil> string with embedded nulls, is there a way to determine the size
Phil> of the "gdb_byte *contents"?

I think: TYPE_LENGTH (value_type (value))
That should get you the size in bytes.
You may need to convert to characters, I'm not sure.

Tom> Why do we need LA_GET_STRING here?  Aren't the string contents already
Tom> in the value?

Phil> I'll look at this a little more closely. But I use this to extract a
Phil> string with embedded nulls with a concrete length. Do I misread your
Phil> thoughts here? Or are you suggesting we just pass in value->contents
Phil> to LA_PRINT_STRING?

Yeah, I think that would be the way to go.

Tom> A test relying on std::string is not very robust -- std::string may
Tom> change over time, breaking the test.  Instead, it is better to write
Tom> custom test code and a printer to match.  That way, we control the
Tom> implementation.

Phil> Ok thanks for the pointer. Can you please elaborate a bit more?

Suppose std::string changes in some future libstdc++.  In that case,
we would have a printer in the test suite that would be incorrect.
This would lead to test failures, even though the gdb code under test
is actually functioning perfectly.

So, rather than using std::string, just write a simple counted string
object of some kind and use it in the test.

Tom

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [python][patch] Preserve string length, and embedded-nulls in pretty-print string emission.
  2009-05-27 20:22     ` Tom Tromey
@ 2009-06-01 16:26       ` Phil Muldoon
  2009-06-02  5:11         ` Thiago Jung Bauermann
  2009-06-02 15:38         ` Jonas Maebe
  0 siblings, 2 replies; 20+ messages in thread
From: Phil Muldoon @ 2009-06-01 16:26 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Project Archer

Tom Tromey wrote:
> Phil> This function returns a struct value. If that value contains a
> Phil> string with embedded nulls, is there a way to determine the size
> Phil> of the "gdb_byte *contents"?
>
> I think: TYPE_LENGTH (value_type (value))
> That should get you the size in bytes.
> You may need to convert to characters, I'm not sure.
>   
All,

Tom and I talked a little about this on irc, so I'll replicate the 
conversation here.

The TYPE_LENGTH (value_type (value)) works great, thanks. But there are 
some further issues. In the pretty-printing code there are three 
branches of logic:

- if it has a "string" display hint, use LA_PRINT_STRING;
- if it does not have a hint, but it is string, use fputs_filtered;
- for all other value cases, use common_val_print.

Two of these cases require a definite identification that the value 
holds a string. I guess in the first case you could rely on the hint, 
but the second case is troublesome. As far as I know there is no 
convenient universal way to determine if the contents of a value are a 
string. Using: TYPE_CODE (value_type (value)) will either return 
TYPE_CODE_STRING, or TYPE_CODE_ARRAY (or PTR) depending on how the 
string is constructed. If it returns ARRAY, how do we determine that it 
is a string? In c-valprint there is a private convenience routine 
called: textual_element_type that tests for this, but it does not work 
with wide strings, and is very C string specific. So that is no good.

The last time we know that it is a string "for sure" is in 
convert_value_from_python which converts a PyObject into a gdb value. 
Right now in my patch, if it is a string the length is returned via 
out-parameter in: convert_value_from_python. This is, in effect, a flag. 
But it now seems less than optimal to design an out-parameter around one 
troublesome type. Should convert_value_from_python write an 
out-parameter with TYPE_CODE_* that matches the value type (and in the 
case of a string, always return TYPE_CODE_STRING regardless of how the 
string is constructed?)

Or are there other ideas out there?

Regards

Phil


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [python][patch] Preserve string length, and embedded-nulls in pretty-print string emission.
  2009-06-01 16:26       ` Phil Muldoon
@ 2009-06-02  5:11         ` Thiago Jung Bauermann
  2009-06-02 23:46           ` Tom Tromey
  2009-06-02 15:38         ` Jonas Maebe
  1 sibling, 1 reply; 20+ messages in thread
From: Thiago Jung Bauermann @ 2009-06-02  5:11 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: Tom Tromey, Project Archer

Em Seg, 2009-06-01 às 17:26 +0100, Phil Muldoon escreveu:
> Or are there other ideas out there?

Without thinking too much about this (i.e. FWIW): perhaps having a new
struct language method LA_CAN_PRINT_AS_STRING?
-- 
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [python][patch] Preserve string length, and embedded-nulls in pretty-print string emission.
  2009-06-01 16:26       ` Phil Muldoon
  2009-06-02  5:11         ` Thiago Jung Bauermann
@ 2009-06-02 15:38         ` Jonas Maebe
  2009-06-02 20:48           ` Phil Muldoon
  1 sibling, 1 reply; 20+ messages in thread
From: Jonas Maebe @ 2009-06-02 15:38 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: Tom Tromey, Project Archer


On 01 Jun 2009, at 18:26, Phil Muldoon wrote:

> The TYPE_LENGTH (value_type (value)) works great, thanks.

Shouldn't you add a check_typedef() in between?


Jonas

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [python][patch] Preserve string length, and embedded-nulls in pretty-print string emission.
  2009-06-02 15:38         ` Jonas Maebe
@ 2009-06-02 20:48           ` Phil Muldoon
  0 siblings, 0 replies; 20+ messages in thread
From: Phil Muldoon @ 2009-06-02 20:48 UTC (permalink / raw)
  To: Jonas Maebe; +Cc: Tom Tromey, Project Archer

Jonas Maebe wrote:
>
> On 01 Jun 2009, at 18:26, Phil Muldoon wrote:
>
>> The TYPE_LENGTH (value_type (value)) works great, thanks.
>
> Shouldn't you add a check_typedef() in between?
>

Probably, I was roughly quoting. I'm still wrestling with string 
identification in a value. I'd be happy just to worry about just its 
length at this point ;)

Regards

Phil

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [python][patch] Preserve string length, and embedded-nulls in pretty-print string emission.
  2009-06-02  5:11         ` Thiago Jung Bauermann
@ 2009-06-02 23:46           ` Tom Tromey
  2009-06-08 10:31             ` Phil Muldoon
  0 siblings, 1 reply; 20+ messages in thread
From: Tom Tromey @ 2009-06-02 23:46 UTC (permalink / raw)
  To: Thiago Jung Bauermann; +Cc: Phil Muldoon, Project Archer

>>>>> "Thiago" == Thiago Jung Bauermann <bauerman@br.ibm.com> writes:

>> Or are there other ideas out there?

Thiago> Without thinking too much about this (i.e. FWIW): perhaps having a new
Thiago> struct language method LA_CAN_PRINT_AS_STRING?

That seems like a lot of work for a case where we know we have a
Python string and we just want to print it using the language's string
printer.

Maybe we should just go back to having a special case in
pretty_print_one_value, but have it return a PyObject in the string
case.

Tom

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [python][patch] Preserve string length, and embedded-nulls in pretty-print string emission.
  2009-06-02 23:46           ` Tom Tromey
@ 2009-06-08 10:31             ` Phil Muldoon
  2009-06-11 17:12               ` Tom Tromey
  0 siblings, 1 reply; 20+ messages in thread
From: Phil Muldoon @ 2009-06-08 10:31 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Thiago Jung Bauermann, Project Archer

[-- Attachment #1: Type: text/plain, Size: 2210 bytes --]

Tom Tromey wrote:
>>> Or are there other ideas out there?
>>>       
>
> Thiago> Without thinking too much about this (i.e. FWIW): perhaps having a new
> Thiago> struct language method LA_CAN_PRINT_AS_STRING?
>
> That seems like a lot of work for a case where we know we have a
> Python string and we just want to print it using the language's string
> printer.
>
> Maybe we should just go back to having a special case in
> pretty_print_one_value, but have it return a PyObject in the string
> case.
>   

Here is a patch that returns a PyObject in the string case. It also 
incorporate the changes requested in Tom's review. I've included the 
python printers.py changes for context, though they will not form part 
of the patch (later diverted to libstdcxx).

What do you think?

Regards

Phil

ChangeLog

2009-06-08 Phil Muldoon <pmuldoon@redhat.com>

* python/lib/gdb/libstdcxx/v6/printers.py
(StdStringPrinter.to_string): Extract length from header. Use in
string extraction.
* python/python-frame.c (frapy_read_var): Update
python_string_to_target_string call.
* python/python-internal.h (unicode_to_target_string,
(python_string_to_target_string):
Update definitions to include a size parameter.
* python/python-utils.c (unicode_to_encoded_string): Add size to
parameter list. Write size when completed.
(unicode_to_target_string): Likewise.
(python_string_to_target_string): Likewise.
(apply_varobj_pretty_printer): Return a PyObject if object is a
string.
* python/python.c (pretty_print_one_value): Likewise.
(print_string_repr): Refactor to logic to account for PyObject
returned strings.
(apply_varobj_pretty_printer): Likewise.
* value.c (value_from_string): New len parameter. Use over
strlen call.
* value.h (value_from_string): Update definition.
* varobj.c (update_dynamic_varobj_children): Update
convert_value_from_python_call.
(value_get_print_value): Refactor logic to account for PyObject
returned strings.

Testsuite ChangeLog:

2009-06-08 Phil Muldoon <pmuldoon@redhat.com>

* gdb.python/python-prettyprint.c: Add counted null string
structure.
* gdb.python/python-prettyprint.exp: Print null string. Test for
embedded nulls.
* gdb.python/python-prettyprint.py (pp_ns): New
Function.


[-- Attachment #2: string_pyobject.patch --]
[-- Type: text/x-patch, Size: 17930 bytes --]

diff --git a/gdb/python/lib/gdb/libstdcxx/v6/printers.py b/gdb/python/lib/gdb/libstdcxx/v6/printers.py
index 2bd2593..6bf4f3b 100644
--- a/gdb/python/lib/gdb/libstdcxx/v6/printers.py
+++ b/gdb/python/lib/gdb/libstdcxx/v6/printers.py
@@ -468,7 +468,17 @@ class StdStringPrinter:
             encoding = gdb.parameter('target-charset')
         elif isinstance(encoding, WideEncoding):
             encoding = encoding.value
-        return self.val['_M_dataplus']['_M_p'].string(encoding)
+        type = self.val.type
+        if type.code == gdb.TYPE_CODE_REF:
+            type = type.target ()
+
+        ptr = self.val ['_M_dataplus']['_M_p']
+        realtype = type.unqualified ().strip_typedefs ()
+        reptype = gdb.lookup_type (str (realtype) + '::_Rep').pointer ()
+        header = ptr.cast(reptype) - 1
+        len = header.dereference ()['_M_length']
+
+        return self.val['_M_dataplus']['_M_p'].string (encoding, length = len)
 
     def display_hint (self):
         return 'string'
diff --git a/gdb/python/python-frame.c b/gdb/python/python-frame.c
index ad03c46..9615166 100644
--- a/gdb/python/python-frame.c
+++ b/gdb/python/python-frame.c
@@ -395,7 +395,7 @@ frapy_read_var (PyObject *self, PyObject *args)
       struct cleanup *cleanup;
       volatile struct gdb_exception except;
 
-      var_name = python_string_to_target_string (sym_obj);
+      var_name = python_string_to_target_string (sym_obj, NULL);
       if (!var_name)
 	return NULL;
       cleanup = make_cleanup (xfree, var_name);
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 29e55dd..8203795 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -167,8 +167,8 @@ PyObject *gdbpy_parameter_value (enum var_types, void *);
 void gdbpy_print_stack (void);
 
 PyObject *python_string_to_unicode (PyObject *obj);
-char *unicode_to_target_string (PyObject *unicode_str);
-char *python_string_to_target_string (PyObject *obj);
+char *unicode_to_target_string (PyObject *unicode_str, int *size);
+char *python_string_to_target_string (PyObject *obj, int *size);
 char *python_string_to_host_string (PyObject *obj);
 PyObject *target_string_to_unicode (const gdb_byte *str, int length);
 int gdbpy_is_string (PyObject *obj);
@@ -177,8 +177,8 @@ int gdbpy_is_value_object (PyObject *obj);
 
 /* Note that these are declared here, and not in python.h with the
    other pretty-printer functions, because they refer to PyObject.  */
-char *apply_varobj_pretty_printer (PyObject *print_obj,
-				   struct value **replacement);
+PyObject *apply_varobj_pretty_printer (PyObject *print_obj,
+				       struct value **replacement);
 PyObject *gdbpy_get_varobj_pretty_printer (struct value *value);
 PyObject *gdbpy_instantiate_printer (PyObject *cons, PyObject *value);
 char *gdbpy_get_display_hint (PyObject *printer);
diff --git a/gdb/python/python-utils.c b/gdb/python/python-utils.c
index f9c9486..11a9e54 100644
--- a/gdb/python/python-utils.c
+++ b/gdb/python/python-utils.c
@@ -100,45 +100,57 @@ python_string_to_unicode (PyObject *obj)
 }
 
 /* Returns a newly allocated string with the contents of the given unicode
-   string object converted to a named charset.  If an error occurs during
-   the conversion, NULL will be returned and a python exception will be set.
+   string object converted to a named charset.  The parameter *SIZE
+   will be set to the size of the string.  If *SIZE is NULL no size
+   information will be returned.  If an error occurs during the
+   conversion, NULL will be returned and a python exception will be
+   set.
 
    The caller is responsible for xfree'ing the string.  */
 static char *
-unicode_to_encoded_string (PyObject *unicode_str, const char *charset)
+unicode_to_encoded_string (PyObject *unicode_str, const char *charset, int *size)
 {
   char *result;
   PyObject *string;
+  Py_ssize_t str_size;
 
   /* Translate string to named charset.  */
   string = PyUnicode_AsEncodedString (unicode_str, charset, NULL);
   if (string == NULL)
     return NULL;
 
-  result = xstrdup (PyString_AsString (string));
+  str_size = PyString_Size (string) + 1;
+  result = xmemdup (PyString_AsString (string), str_size, str_size);
+  if (size != NULL)
+    *size = str_size;
 
   Py_DECREF (string);
 
   return result;
 }
 
-/* Returns a newly allocated string with the contents of the given unicode
-   string object converted to the target's charset.  If an error occurs during
-   the conversion, NULL will be returned and a python exception will be set.
+/* Returns a newly allocated string with the contents of the given
+   unicode string object converted to the target's charset.  The
+   parameter *SIZE will be set to the size of the string.  If *SIZE is
+   NULL no size information will be returned.  If an error occurs
+   during the conversion, NULL will be returned and a python exception
+   will be set.
 
    The caller is responsible for xfree'ing the string.  */
 char *
-unicode_to_target_string (PyObject *unicode_str)
+unicode_to_target_string (PyObject *unicode_str, int *size)
 {
-  return unicode_to_encoded_string (unicode_str, target_charset ());
+  return unicode_to_encoded_string (unicode_str, target_charset (), size);
 }
 
 /* Converts a python string (8-bit or unicode) to a target string in
-   the target's charset.  Returns NULL on error, with a python exception set.
+   the target's charset.  The parameter *SIZE will be set to the
+   size of the string.  If *SIZE is NULL no size information will be
+   returned.  Returns NULL on error, with a python exception set.
 
    The caller is responsible for xfree'ing the string.  */
 char *
-python_string_to_target_string (PyObject *obj)
+python_string_to_target_string (PyObject *obj, int *size)
 {
   PyObject *str;
   char *result;
@@ -147,7 +159,7 @@ python_string_to_target_string (PyObject *obj)
   if (str == NULL)
     return NULL;
 
-  result = unicode_to_target_string (str);
+  result = unicode_to_target_string (str, size);
   Py_DECREF (str);
   return result;
 }
@@ -166,7 +178,7 @@ python_string_to_host_string (PyObject *obj)
   if (str == NULL)
     return NULL;
 
-  result = unicode_to_encoded_string (str, host_charset ()); 
+  result = unicode_to_encoded_string (str, host_charset (), NULL);
   Py_DECREF (str);
   return result;
 }
diff --git a/gdb/python/python-value.c b/gdb/python/python-value.c
index 743e6a6..7c107f5 100644
--- a/gdb/python/python-value.c
+++ b/gdb/python/python-value.c
@@ -896,12 +896,13 @@ convert_value_from_python (PyObject *obj)
       else if (gdbpy_is_string (obj))
 	{
 	  char *s;
+	  int str_size = 0;
 
-	  s = python_string_to_target_string (obj);
+	  s = python_string_to_target_string (obj, &str_size);
 	  if (s != NULL)
 	    {
 	      old = make_cleanup (xfree, s);
-	      value = value_from_string (s);
+	      value = value_from_string (s, str_size);
 	      do_cleanups (old);
 	    }
 	}
diff --git a/gdb/python/python.c b/gdb/python/python.c
index e97bef8..24f4351 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -826,41 +826,40 @@ find_pretty_printer (PyObject *value)
   return function;
 }
 
-/* Pretty-print a single value, via the printer object PRINTER.  If
-   the function returns a string, an xmalloc()d copy is returned.
-   Otherwise, if the function returns a value, a *OUT_VALUE is set to
-   the value, and NULL is returned.  On error, *OUT_VALUE is set to
-   NULL and NULL is returned.  */
-static char *
+/* 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.  */
+static PyObject *
 pretty_print_one_value (PyObject *printer, struct value **out_value)
 {
-  char *output = NULL;
   volatile struct gdb_exception except;
+  PyObject *result = NULL;
+  int is_string = 0;
 
   TRY_CATCH (except, RETURN_MASK_ALL)
     {
-      PyObject *result;
-
       result = PyObject_CallMethodObjArgs (printer, gdbpy_to_string_cst, NULL);
       if (result)
 	{
-	  if (gdbpy_is_string (result))
-	    output = python_string_to_host_string (result);
-	  else if (PyObject_TypeCheck (result, &value_object_type))
+	  is_string = gdbpy_is_string (result);
+	  if (! is_string)
 	    {
-	      /* If we just call convert_value_from_python for this
-		 type, we won't know who owns the result.  For this
-		 one case we need to copy the resulting value.  */
-	      struct value *v = value_object_to_value (result);
-	      *out_value = value_copy (v);
+	      *out_value = convert_value_from_python (result);
+	      Py_DECREF (result);
+	      if (PyErr_Occurred ())
+		*out_value = NULL;
 	    }
-	  else
-	    *out_value = convert_value_from_python (result);
-	  Py_DECREF (result);
 	}
+      else
+	*out_value = NULL;
     }
 
-  return output;
+  if (is_string)
+    return result;
+
+  return NULL;
 }
 
 /* Instantiate a pretty-printer given a constructor, CONS, and a
@@ -906,18 +905,26 @@ print_string_repr (PyObject *printer, const char *hint,
 		   const struct value_print_options *options,
 		   const struct language_defn *language)
 {
-  char *output;
   struct value *replacement = NULL;
+  PyObject *py_str = NULL;
 
-  output = pretty_print_one_value (printer, &replacement);
-  if (output)
+  py_str = pretty_print_one_value (printer, &replacement);
+  if (py_str)
     {
-      if (hint && !strcmp (hint, "string"))
-	LA_PRINT_STRING (stream, (gdb_byte *) output, strlen (output),
-			 1, 0, options);
-      else
-	fputs_filtered (output, stream);
-      xfree (output);
+      int len;
+      gdb_byte *output;
+      output = python_string_to_target_string (py_str, &len);
+      if (output)
+	{
+	  struct cleanup *old = make_cleanup (xfree, output);
+	  if (hint && !strcmp (hint, "string"))
+	    LA_PRINT_STRING (stream, output,
+			     len, 1, 0, options);
+	  else
+	    fputs_filtered (output, stream);
+	  do_cleanups (old);
+	}
+      Py_DECREF (py_str);
     }
   else if (replacement)
     common_val_print (replacement, stream, recurse, options, language);
@@ -1232,28 +1239,31 @@ apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr,
   return result;
 }
 
-/* Apply a pretty-printer for the varobj code.  PRINTER_OBJ is the
-   print object.  It must have a 'to_string' method (but this is
-   checked by varobj, not here) which takes no arguments and
-   returns a string.  This function returns an xmalloc()d string if
-   the printer returns a string.  The printer may return a replacement
-   value instead; in this case *REPLACEMENT is set to the replacement
-   value, and this function returns NULL.  On error, *REPLACEMENT is
-   set to NULL and this function also returns NULL.  */
-char *
+ /* Apply a pretty-printer for the varobj code.  PRINTER_OBJ is the
+    print object.  It must have a 'to_string' method (but this is
+    checked by varobj, not here) which takes no arguments and
+    returns a string.  The printer will return a value and in the case
+    of a Python string being returned, this function will return a
+    PyObject containg the string.  For any other type, *REPLACEMENT is
+    set to the replacement value and this function returns NULL.  On
+    error, *REPLACEMENT is set to NULL and this function also returns
+    NULL.  */
+PyObject *
 apply_varobj_pretty_printer (PyObject *printer_obj,
 			     struct value **replacement)
 {
-  char *result;
+  int size = 0;
   PyGILState_STATE state = PyGILState_Ensure ();
+  PyObject *py_str = NULL;
 
   *replacement = NULL;
-  result = pretty_print_one_value (printer_obj, replacement);
-  if (result == NULL);
+  py_str  = pretty_print_one_value (printer_obj, replacement);
+
+  if (replacement == NULL && py_str == NULL)
     gdbpy_print_stack ();
   PyGILState_Release (state);
 
-  return result;
+  return py_str;
 }
 
 /* Find a pretty-printer object for the varobj module.  Returns a new
diff --git a/gdb/testsuite/gdb.python/python-prettyprint.c b/gdb/testsuite/gdb.python/python-prettyprint.c
index 0d9110d..5cc35be 100644
--- a/gdb/testsuite/gdb.python/python-prettyprint.c
+++ b/gdb/testsuite/gdb.python/python-prettyprint.c
@@ -29,6 +29,11 @@ struct ss
   struct s b;
 };
 
+struct ns {
+  const char *null_str;
+  int length;
+};
+
 #ifdef __cplusplus
 struct S : public s {
   int zs;
@@ -166,6 +171,10 @@ main ()
   init_ss(ssa+1, 5, 6);
   memset (&nullstr, 0, sizeof nullstr);
 
+  struct ns  ns;
+  ns.null_str = "embedded\0null\0string";
+  ns.length = 20;
+
 #ifdef __cplusplus
   S cps;
 
diff --git a/gdb/testsuite/gdb.python/python-prettyprint.exp b/gdb/testsuite/gdb.python/python-prettyprint.exp
index 47d2fa8..b2dc85d 100644
--- a/gdb/testsuite/gdb.python/python-prettyprint.exp
+++ b/gdb/testsuite/gdb.python/python-prettyprint.exp
@@ -75,6 +75,7 @@ proc run_lang_tests {lang} {
 	gdb_test "print ref" "= a=<15> b=< a=<8> b=<$hex>>"
 	gdb_test "print derived" \
 	    " = \{.*<Vbase1> = pp class name: Vbase1.*<Vbase2> = \{.*<VirtualTest> = pp value variable is: 1,.*members of Vbase2:.*_vptr.Vbase2 = $hex.*<Vbase3> = \{.*members of Vbase3.*members of Derived:.*value = 2.*"
+	gdb_test "print ns " "\"embedded\\\\000null\\\\000string\""
     }
 
     gdb_test "print x" " = $hex \"this is x\""
diff --git a/gdb/testsuite/gdb.python/python-prettyprint.py b/gdb/testsuite/gdb.python/python-prettyprint.py
index 82e5331..c3e0dc4 100644
--- a/gdb/testsuite/gdb.python/python-prettyprint.py
+++ b/gdb/testsuite/gdb.python/python-prettyprint.py
@@ -99,6 +99,19 @@ class pp_nullstr:
     def to_string(self):
         return self.val['s'].string(gdb.parameter('target-charset'))
 
+class pp_ns:
+    "Print a std::basic_string of some kind"
+
+    def __init__(self, val):
+        self.val = val
+
+    def to_string(self):
+        len = self.val['length']
+        return self.val['null_str'].string (gdb.parameter ('target-charset'), length = len)
+
+    def display_hint (self):
+        return 'string'
+
 def lookup_function (val):
     "Look-up and return a pretty-printer that can print val."
 
@@ -155,6 +168,8 @@ def register_pretty_printers ():
     pretty_printers_dict[re.compile ('^string_repr$')] = string_print
     pretty_printers_dict[re.compile ('^container$')] = ContainerPrinter
     
+    pretty_printers_dict[re.compile ('^struct ns$')]  = pp_ns
+    pretty_printers_dict[re.compile ('^ns$')]  = pp_ns
 pretty_printers_dict = {}
 
 register_pretty_printers ()
diff --git a/gdb/value.c b/gdb/value.c
index fd05f07..5f4731e 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -1849,13 +1849,13 @@ value_from_pointer (struct type *type, CORE_ADDR addr)
 /* Create a value for a string constant to be stored locally
    (not in the inferior's memory space, but in GDB memory).
    This is analogous to value_from_longest, which also does not
-   use inferior memory.  String shall NOT contain embedded nulls.  */
+   use inferior memory.  LEN is the length of the string *PTR
+   from which the value will be created.  */
 
 struct value *
-value_from_string (char *ptr)
+value_from_string (char *ptr, int len)
 {
   struct value *val;
-  int len = strlen (ptr);
   int lowbound = current_language->string_lower_bound;
   struct type *string_char_type;
   struct type *rangetype;
diff --git a/gdb/value.h b/gdb/value.h
index fd0d2c9..38c1289 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -295,7 +295,7 @@ extern struct value *value_from_pointer (struct type *type, CORE_ADDR addr);
 extern struct value *value_from_double (struct type *type, DOUBLEST num);
 extern struct value *value_from_decfloat (struct type *type,
 					  const gdb_byte *decbytes);
-extern struct value *value_from_string (char *string);
+extern struct value *value_from_string (char *string, int len);
 
 extern struct value *value_at (struct type *type, CORE_ADDR addr);
 extern struct value *value_at_lazy (struct type *type, CORE_ADDR addr);
diff --git a/gdb/varobj.c b/gdb/varobj.c
index 49b4a43..e176ecd 100644
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -2250,8 +2250,9 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
   long dummy;
   struct ui_file *stb;
   struct cleanup *old_chain;
-  char *thevalue = NULL;
+  gdb_byte *thevalue = NULL;
   struct value_print_options opts;
+  int len = 0;
 
   if (value == NULL)
     return NULL;
@@ -2265,6 +2266,7 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
 	char *hint;
 	struct value *replacement;
 	int string_print = 0;
+	PyObject *py_str = NULL;
 
 	hint = gdbpy_get_display_hint (value_formatter);
 	if (hint)
@@ -2274,15 +2276,22 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
 	    xfree (hint);
 	  }
 
-	thevalue = apply_varobj_pretty_printer (value_formatter,
-						&replacement);
-	if (thevalue && !string_print)
+	py_str = apply_varobj_pretty_printer (value_formatter, &replacement);
+
+	if (py_str)
 	  {
-	    PyGILState_Release (state);
-	    return thevalue;
+	    thevalue = python_string_to_target_string (py_str, &len);
+	    Py_DECREF(py_str);
 	  }
+
 	if (replacement)
 	  value = replacement;
+
+	if (thevalue && !string_print)
+         {
+           PyGILState_Release (state);
+           return thevalue;
+         }
       }
     PyGILState_Release (state);
   }
@@ -2294,11 +2303,11 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
   get_formatted_print_options (&opts, format_code[(int) format]);
   opts.deref_ref = 0;
   opts.raw = 1;
+
   if (thevalue)
     {
       make_cleanup (xfree, thevalue);
-      LA_PRINT_STRING (stb, (gdb_byte *) thevalue, strlen (thevalue),
-		       1, 0, &opts);
+      LA_PRINT_STRING (stb, thevalue, len, 1, 0, &opts);
     }
   else
     common_val_print (value, stb, 0, &opts, current_language);

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [python][patch] Preserve string length, and embedded-nulls in pretty-print string emission.
  2009-06-08 10:31             ` Phil Muldoon
@ 2009-06-11 17:12               ` Tom Tromey
  2009-06-15 20:50                 ` Phil Muldoon
  0 siblings, 1 reply; 20+ messages in thread
From: Tom Tromey @ 2009-06-11 17:12 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: Thiago Jung Bauermann, Project Archer

>>>>> "Phil" == Phil Muldoon <pmuldoon@redhat.com> writes:

Phil> +unicode_to_encoded_string (PyObject *unicode_str, const char *charset, int *size)

[...]

Phil> +  str_size = PyString_Size (string) + 1;
Phil> +  result = xmemdup (PyString_AsString (string), str_size, str_size);
Phil> +  if (size != NULL)
Phil> +    *size = str_size;
 
How about a variant of this function that just returns the
intermediate 'string' PyObject?

Phil> +  int is_string = 0;
 
Phil> -	  if (gdbpy_is_string (result))
Phil> -	    output = python_string_to_host_string (result);
Phil> -	  else if (PyObject_TypeCheck (result, &value_object_type))
Phil> +	  is_string = gdbpy_is_string (result);
Phil> +	  if (! is_string)

I think the previous code was clearer.  Don't introduce is_string,
instead...

Phil> +	      Py_DECREF (result);

Set 'result = NULL' here.

Phil> +      output = python_string_to_target_string (py_str, &len);
Phil> +      if (output)
Phil> +	{
Phil> +	  struct cleanup *old = make_cleanup (xfree, output);

Adding a new unicode_to_target_string variant (or
python_string_to_target_string, or whatever is nicest) means you can
avoid an allocation here.

Phil> --- a/gdb/varobj.c
Phil> +	    Py_DECREF(py_str);

Space before open paren.

Otherwise I think this is looking good.  Thanks.

Tom

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [python][patch] Preserve string length, and embedded-nulls in pretty-print string emission.
  2009-06-11 17:12               ` Tom Tromey
@ 2009-06-15 20:50                 ` Phil Muldoon
  2009-06-16 12:44                   ` Phil Muldoon
  0 siblings, 1 reply; 20+ messages in thread
From: Phil Muldoon @ 2009-06-15 20:50 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Thiago Jung Bauermann, Project Archer

On 06/11/2009 06:11 PM, Tom Tromey wrote:


Hi Tom

Thanks for the comments. Most are done, but I have some further 
questions with others.


> Phil>  +  int is_string = 0;
>
> Phil>  -	  if (gdbpy_is_string (result))
> Phil>  -	    output = python_string_to_host_string (result);
> Phil>  -	  else if (PyObject_TypeCheck (result,&value_object_type))
> Phil>  +	  is_string = gdbpy_is_string (result);
> Phil>  +	  if (! is_string)
>
> I think the previous code was clearer.  Don't introduce is_string,
> instead...
>    


Agreed, fixed.


> Phil>  +	      Py_DECREF (result);
>
> Set 'result = NULL' here.
>    


Likewise


> Phil>  +unicode_to_encoded_string (PyObject *unicode_str, const char *charset, int *size)
>
> [...]
>
> Phil>  +  str_size = PyString_Size (string) + 1;
> Phil>  +  result = xmemdup (PyString_AsString (string), str_size, str_size);
> Phil>  +  if (size != NULL)
> Phil>  +    *size = str_size;
>
> How about a variant of this function that just returns the
> intermediate 'string' PyObject?
>    

To avoid the use of an out-parameter? I can see the use of returning an 
encoded version of the the unicode PyObject string, but if you wanted 
that, why would you just not call:

PyUnicode_AsEncodedString directly? Wouldn't the following:

static PyObject*
unicode_to_encoded_string (PyObject *unicode_str, const char *charset)
{
return PyUnicode_AsEncodedString (unicode_str, charset, NULL);
}

Be the same equivalent? What would the purpose of a new variant achieve 
there?


> Phil>  +      output = python_string_to_target_string (py_str,&len);
> Phil>  +      if (output)
> Phil>  +	{
> Phil>  +	  struct cleanup *old = make_cleanup (xfree, output);
>
> Adding a new unicode_to_target_string variant (or
> python_string_to_target_string, or whatever is nicest) means you can
> avoid an allocation here.
>    


Similar to above, I'm not sure what you mean here. 
python_string_to_target_string does more than than the previous hunk 
comment, but eventually will have to be converted to char * to pass 
through the LA_PRINT_STRING that is directly below this code?



> Phil>  --- a/gdb/varobj.c
> Phil>  +	    Py_DECREF(py_str);
>
> Space before open paren.
>
>    

Fixed thanks!

Regards

Phil

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [python][patch] Preserve string length, and embedded-nulls in pretty-print string emission.
  2009-06-15 20:50                 ` Phil Muldoon
@ 2009-06-16 12:44                   ` Phil Muldoon
  2009-06-16 18:07                     ` Tom Tromey
  0 siblings, 1 reply; 20+ messages in thread
From: Phil Muldoon @ 2009-06-16 12:44 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Thiago Jung Bauermann, Project Archer

On 06/15/2009 09:49 PM, Phil Muldoon wrote:
> On 06/11/2009 06:11 PM, Tom Tromey wrote: Phil> 
> +unicode_to_encoded_string (PyObject *unicode_str, const char 
> *charset, int *size)
>>
>> [...]
>>
>> Phil> + str_size = PyString_Size (string) + 1;
>> Phil> + result = xmemdup (PyString_AsString (string), str_size, 
>> str_size);
>> Phil> + if (size != NULL)
>> Phil> + *size = str_size;
>>
>> How about a variant of this function that just returns the
>> intermediate 'string' PyObject?
>
>
>> Phil> + output = python_string_to_target_string (py_str,&len);
>> Phil> + if (output)
>> Phil> + {
>> Phil> + struct cleanup *old = make_cleanup (xfree, output);
>>
>> Adding a new unicode_to_target_string variant (or
>> python_string_to_target_string, or whatever is nicest) means you can
>> avoid an allocation here.
>
>

I decided to take a crack at the mechanics of this change this morning. 
This produces the following hunks (in rough). I can see how just 
borrowing the underlying data from the PyObject avoids an allocation 
(the results of PyString_AsString must not be deallocated, etc). Is this 
what you had in mind? I ended up having to add 3 new variant string 
methods for this in the end.


/* Instantiate a pretty-printer given a constructor, CONS, and a
@@ -906,18 +901,27 @@ print_string_repr (PyObject *printer, const char 
*hint,
const struct value_print_options *options,
const struct language_defn *language)
{
- char *output;
struct value *replacement = NULL;
+ PyObject *py_str = NULL;

- output = pretty_print_one_value (printer, &replacement);
- if (output)
+ py_str = pretty_print_one_value (printer, &replacement);
+ if (py_str)
{
- if (hint && !strcmp (hint, "string"))
- LA_PRINT_STRING (stream, (gdb_byte *) output, strlen (output),
- 1, 0, options);
- else
- fputs_filtered (output, stream);
- xfree (output);
+ int len;
+ PyObject *string = NULL;
+ string = python_string_to_target_pystring (py_str, &len);
+ if (string)
+ {
+ gdb_byte *output = PyString_AsString (string);
+ if (hint && !strcmp (hint, "string"))
+ LA_PRINT_STRING (stream, output,
+ len, 1, 0, options);
+ else
+ fputs_filtered (output, stream);
+ Py_DECREF (string);
+ }
+ Py_DECREF (py_str);
}
else if (replacement)
common_val_print (replacement, stream, recurse, options, language);
@@ -1232,28 +1236,31 @@ apply_val_pretty_printer (struct type *type, 
const gdb_byte *valaddr,
return result;
}


+/* Returns a PyObject with the contents of the given unicode
+ string object converted to a named charset. The parameter *SIZE
+ will be set to the size of the string. If *SIZE is NULL no size
+ information will be returned. If an error occurs during the
+ conversion, NULL will be returned and a python exception will be
+ set. */
+static PyObject *
+unicode_to_encoded_pystring (PyObject *unicode_str, const char 
*charset, int *size)
+{
+ PyObject *string;
+
+ /* Translate string to named charset. */
+
+ string = PyUnicode_AsEncodedString (unicode_str, charset, NULL);
+ if (string == NULL)
+ return NULL;
+
+ *size = PyString_Size (string) + 1;
+ return string;
+}


+/* Returns a PyObject with the contents of the given
+ unicode string object converted to the target's charset. The
+ parameter *SIZE will be set to the size of the string. If *SIZE is
+ NULL no size information will be returned. If an error occurs
+ during the conversion, NULL will be returned and a python exception
+ will be set. */
+PyObject *
+unicode_to_target_pystring (PyObject *unicode_str, int *size)
+{
+ return unicode_to_encoded_pystring (unicode_str, target_charset (), size);
+}


+/* Converts a python string (8-bit or unicode) to a target string in
+ the target's charset. The parameter *SIZE will be set to the
+ size of the string. If *SIZE is NULL no size information will be
+ returned. Returns NULL on error, with a python exception set. */
+PyObject *
+python_string_to_target_pystring (PyObject *obj, int *size)
+{
+ PyObject *str;
+ PyObject *result;
+
+ str = python_string_to_unicode (obj);
+ if (str == NULL)
+ return NULL;
+
+ result = unicode_to_target_pystring (str, size);
+ Py_DECREF (str);
+ return result;
+}

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [python][patch] Preserve string length, and embedded-nulls in pretty-print string emission.
  2009-06-16 12:44                   ` Phil Muldoon
@ 2009-06-16 18:07                     ` Tom Tromey
  2009-06-18 12:20                       ` Phil Muldoon
  0 siblings, 1 reply; 20+ messages in thread
From: Tom Tromey @ 2009-06-16 18:07 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: Thiago Jung Bauermann, Project Archer

Phil> I decided to take a crack at the mechanics of this change this
Phil> morning. This produces the following hunks (in rough). I can see how
Phil> just borrowing the underlying data from the PyObject avoids an
Phil> allocation (the results of PyString_AsString must not be deallocated,
Phil> etc). Is this what you had in mind?

Yeah, something like that.

Tom

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [python][patch] Preserve string length, and embedded-nulls in pretty-print string emission.
  2009-06-16 18:07                     ` Tom Tromey
@ 2009-06-18 12:20                       ` Phil Muldoon
  2009-06-18 20:17                         ` Tom Tromey
  2009-06-18 20:21                         ` Tom Tromey
  0 siblings, 2 replies; 20+ messages in thread
From: Phil Muldoon @ 2009-06-18 12:20 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Thiago Jung Bauermann, Project Archer

[-- Attachment #1: Type: text/plain, Size: 1690 bytes --]

On 06/16/2009 07:07 PM, Tom Tromey wrote:
> Phil>  I decided to take a crack at the mechanics of this change this
> Phil>  morning. This produces the following hunks (in rough). I can see how
> Phil>  just borrowing the underlying data from the PyObject avoids an
> Phil>  allocation (the results of PyString_AsString must not be deallocated,
> Phil>  etc). Is this what you had in mind?
>    

This patch scraps the first value-only approach and as discussed 
completely implements the string in PyObject approach. Now strings are 
kept in a PyObject (along with their associated length data) until they 
are printed, or used in some other way.


What do you think?

Regards

Phil


2009-06-18 Phil Muldoon <pmuldoon@redhat.com>

* python/lib/gdb/libstdcxx/v6/printers.py
(StdStringPrinter.to_string): Extract length from header. Use in
string extraction.
* python/python-internal.h (apply_varobj_pretty_printer): Update
definition.
(python_string_to_target_python_string): Add definition.
* python/python-utils.c (unicode_to_encoded_python_string)
(unicode_to_target_python_string)
(python_string_to_target_python_string): New Functions.
* python/python.c : (print_string_repr): Refactor to logic to account for
PyObject returned strings.
(pretty_print_one_value): Likewise
(apply_varobj_pretty_printer): Likewise.
* varobj.c (value_get_print_value): Refactor logic to account for
PyObject returned strings.

Testsuite ChangeLog:

2009-06-18 Phil Muldoon <pmuldoon@redhat.com>

* gdb.python/python-prettyprint.c: Add counted null string
structure.
* gdb.python/python-prettyprint.exp: Print null string. Test for
embedded nulls.
* gdb.python/python-prettyprint.py (pp_ns): New
Function.


[-- Attachment #2: strings_as_pyobjects.patch --]
[-- Type: text/plain, Size: 14181 bytes --]

diff --git a/gdb/python/lib/gdb/libstdcxx/v6/printers.py b/gdb/python/lib/gdb/libstdcxx/v6/printers.py
index 2bd2593..6bf4f3b 100644
--- a/gdb/python/lib/gdb/libstdcxx/v6/printers.py
+++ b/gdb/python/lib/gdb/libstdcxx/v6/printers.py
@@ -468,7 +468,17 @@ class StdStringPrinter:
             encoding = gdb.parameter('target-charset')
         elif isinstance(encoding, WideEncoding):
             encoding = encoding.value
-        return self.val['_M_dataplus']['_M_p'].string(encoding)
+        type = self.val.type
+        if type.code == gdb.TYPE_CODE_REF:
+            type = type.target ()
+
+        ptr = self.val ['_M_dataplus']['_M_p']
+        realtype = type.unqualified ().strip_typedefs ()
+        reptype = gdb.lookup_type (str (realtype) + '::_Rep').pointer ()
+        header = ptr.cast(reptype) - 1
+        len = header.dereference ()['_M_length']
+
+        return self.val['_M_dataplus']['_M_p'].string (encoding, length = len)
 
     def display_hint (self):
         return 'string'
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 29e55dd..1d90722 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -169,6 +169,7 @@ void gdbpy_print_stack (void);
 PyObject *python_string_to_unicode (PyObject *obj);
 char *unicode_to_target_string (PyObject *unicode_str);
 char *python_string_to_target_string (PyObject *obj);
+PyObject *python_string_to_target_python_string (PyObject *obj);
 char *python_string_to_host_string (PyObject *obj);
 PyObject *target_string_to_unicode (const gdb_byte *str, int length);
 int gdbpy_is_string (PyObject *obj);
@@ -177,8 +178,8 @@ int gdbpy_is_value_object (PyObject *obj);
 
 /* Note that these are declared here, and not in python.h with the
    other pretty-printer functions, because they refer to PyObject.  */
-char *apply_varobj_pretty_printer (PyObject *print_obj,
-				   struct value **replacement);
+PyObject *apply_varobj_pretty_printer (PyObject *print_obj,
+				       struct value **replacement);
 PyObject *gdbpy_get_varobj_pretty_printer (struct value *value);
 PyObject *gdbpy_instantiate_printer (PyObject *cons, PyObject *value);
 char *gdbpy_get_display_hint (PyObject *printer);
diff --git a/gdb/python/python-utils.c b/gdb/python/python-utils.c
index f9c9486..45c74a5 100644
--- a/gdb/python/python-utils.c
+++ b/gdb/python/python-utils.c
@@ -122,6 +122,23 @@ unicode_to_encoded_string (PyObject *unicode_str, const char *charset)
   return result;
 }
 
+/* Returns a PyObject with the contents of the given unicode string
+   object converted to a named charset.  If an error occurs during
+   the conversion, NULL will be returned and a python exception will
+   be set.  */
+static PyObject *
+unicode_to_encoded_python_string (PyObject *unicode_str, const char *charset)
+{
+  PyObject *string;
+
+  /* Translate string to named charset.  */
+  string = PyUnicode_AsEncodedString (unicode_str, charset, NULL);
+  if (string == NULL)
+    return NULL;
+
+  return string;
+}
+
 /* Returns a newly allocated string with the contents of the given unicode
    string object converted to the target's charset.  If an error occurs during
    the conversion, NULL will be returned and a python exception will be set.
@@ -133,6 +150,16 @@ unicode_to_target_string (PyObject *unicode_str)
   return unicode_to_encoded_string (unicode_str, target_charset ());
 }
 
+/* Returns a PyObject with the contents of the given unicode string
+   object converted to the target's charset.  If an error occurs
+   during the conversion, NULL will be returned and a python exception
+   will be set.  */
+PyObject *
+unicode_to_target_python_string (PyObject *unicode_str)
+{
+  return unicode_to_encoded_python_string (unicode_str, target_charset ());
+}
+
 /* Converts a python string (8-bit or unicode) to a target string in
    the target's charset.  Returns NULL on error, with a python exception set.
 
@@ -152,6 +179,24 @@ python_string_to_target_string (PyObject *obj)
   return result;
 }
 
+/* Converts a python string (8-bit or unicode) to a target string in the
+   target's charset.  Returns NULL on error, with a python exception
+   set.  */
+PyObject *
+python_string_to_target_python_string (PyObject *obj)
+{
+  PyObject *str;
+  PyObject *result;
+
+  str = python_string_to_unicode (obj);
+  if (str == NULL)
+    return NULL;
+
+  result = unicode_to_target_python_string (str);
+  Py_DECREF (str);
+  return result;
+}
+
 /* Converts a python string (8-bit or unicode) to a target string in
    the host's charset.  Returns NULL on error, with a python exception set.
 
diff --git a/gdb/python/python.c b/gdb/python/python.c
index e97bef8..d13952f 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -826,41 +826,36 @@ find_pretty_printer (PyObject *value)
   return function;
 }
 
-/* Pretty-print a single value, via the printer object PRINTER.  If
-   the function returns a string, an xmalloc()d copy is returned.
-   Otherwise, if the function returns a value, a *OUT_VALUE is set to
-   the value, and NULL is returned.  On error, *OUT_VALUE is set to
-   NULL and NULL is returned.  */
-static char *
+/* 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.  */
+static PyObject *
 pretty_print_one_value (PyObject *printer, struct value **out_value)
 {
-  char *output = NULL;
   volatile struct gdb_exception except;
+  PyObject *result = NULL;
 
   TRY_CATCH (except, RETURN_MASK_ALL)
     {
-      PyObject *result;
-
       result = PyObject_CallMethodObjArgs (printer, gdbpy_to_string_cst, NULL);
       if (result)
 	{
-	  if (gdbpy_is_string (result))
-	    output = python_string_to_host_string (result);
-	  else if (PyObject_TypeCheck (result, &value_object_type))
+	  if (! gdbpy_is_string (result))
 	    {
-	      /* If we just call convert_value_from_python for this
-		 type, we won't know who owns the result.  For this
-		 one case we need to copy the resulting value.  */
-	      struct value *v = value_object_to_value (result);
-	      *out_value = value_copy (v);
+	      *out_value = convert_value_from_python (result);
+	      Py_DECREF (result);
+	      result = NULL;
+	      if (PyErr_Occurred ())
+		*out_value = NULL;
 	    }
-	  else
-	    *out_value = convert_value_from_python (result);
-	  Py_DECREF (result);
 	}
+      else
+	*out_value = NULL;
     }
 
-  return output;
+  return result;
 }
 
 /* Instantiate a pretty-printer given a constructor, CONS, and a
@@ -906,18 +901,26 @@ print_string_repr (PyObject *printer, const char *hint,
 		   const struct value_print_options *options,
 		   const struct language_defn *language)
 {
-  char *output;
   struct value *replacement = NULL;
+  PyObject *py_str = NULL;
 
-  output = pretty_print_one_value (printer, &replacement);
-  if (output)
+  py_str = pretty_print_one_value (printer, &replacement);
+  if (py_str)
     {
-      if (hint && !strcmp (hint, "string"))
-	LA_PRINT_STRING (stream, (gdb_byte *) output, strlen (output),
-			 1, 0, options);
-      else
-	fputs_filtered (output, stream);
-      xfree (output);
+      PyObject *string = python_string_to_target_python_string (py_str);
+      if (string)
+	{
+	  gdb_byte *output = PyString_AsString (string);
+	  int len = PyString_Size (string) + 1;
+
+	  if (hint && !strcmp (hint, "string"))
+	    LA_PRINT_STRING (stream, output,
+			     len, 1, 0, options);
+	  else
+	    fputs_filtered (output, stream);
+	  Py_DECREF (string);
+	}
+      Py_DECREF (py_str);
     }
   else if (replacement)
     common_val_print (replacement, stream, recurse, options, language);
@@ -1232,28 +1235,31 @@ apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr,
   return result;
 }
 
-/* Apply a pretty-printer for the varobj code.  PRINTER_OBJ is the
-   print object.  It must have a 'to_string' method (but this is
-   checked by varobj, not here) which takes no arguments and
-   returns a string.  This function returns an xmalloc()d string if
-   the printer returns a string.  The printer may return a replacement
-   value instead; in this case *REPLACEMENT is set to the replacement
-   value, and this function returns NULL.  On error, *REPLACEMENT is
-   set to NULL and this function also returns NULL.  */
-char *
+ /* Apply a pretty-printer for the varobj code.  PRINTER_OBJ is the
+    print object.  It must have a 'to_string' method (but this is
+    checked by varobj, not here) which takes no arguments and
+    returns a string.  The printer will return a value and in the case
+    of a Python string being returned, this function will return a
+    PyObject containing the string.  For any other type, *REPLACEMENT is
+    set to the replacement value and this function returns NULL.  On
+    error, *REPLACEMENT is set to NULL and this function also returns
+    NULL.  */
+PyObject *
 apply_varobj_pretty_printer (PyObject *printer_obj,
 			     struct value **replacement)
 {
-  char *result;
+  int size = 0;
   PyGILState_STATE state = PyGILState_Ensure ();
+  PyObject *py_str = NULL;
 
   *replacement = NULL;
-  result = pretty_print_one_value (printer_obj, replacement);
-  if (result == NULL);
+  py_str  = pretty_print_one_value (printer_obj, replacement);
+
+  if (replacement == NULL && py_str == NULL)
     gdbpy_print_stack ();
   PyGILState_Release (state);
 
-  return result;
+  return py_str;
 }
 
 /* Find a pretty-printer object for the varobj module.  Returns a new
diff --git a/gdb/testsuite/gdb.python/python-prettyprint.c b/gdb/testsuite/gdb.python/python-prettyprint.c
index 0d9110d..5cc35be 100644
--- a/gdb/testsuite/gdb.python/python-prettyprint.c
+++ b/gdb/testsuite/gdb.python/python-prettyprint.c
@@ -29,6 +29,11 @@ struct ss
   struct s b;
 };
 
+struct ns {
+  const char *null_str;
+  int length;
+};
+
 #ifdef __cplusplus
 struct S : public s {
   int zs;
@@ -166,6 +171,10 @@ main ()
   init_ss(ssa+1, 5, 6);
   memset (&nullstr, 0, sizeof nullstr);
 
+  struct ns  ns;
+  ns.null_str = "embedded\0null\0string";
+  ns.length = 20;
+
 #ifdef __cplusplus
   S cps;
 
diff --git a/gdb/testsuite/gdb.python/python-prettyprint.exp b/gdb/testsuite/gdb.python/python-prettyprint.exp
index 47d2fa8..b2dc85d 100644
--- a/gdb/testsuite/gdb.python/python-prettyprint.exp
+++ b/gdb/testsuite/gdb.python/python-prettyprint.exp
@@ -75,6 +75,7 @@ proc run_lang_tests {lang} {
 	gdb_test "print ref" "= a=<15> b=< a=<8> b=<$hex>>"
 	gdb_test "print derived" \
 	    " = \{.*<Vbase1> = pp class name: Vbase1.*<Vbase2> = \{.*<VirtualTest> = pp value variable is: 1,.*members of Vbase2:.*_vptr.Vbase2 = $hex.*<Vbase3> = \{.*members of Vbase3.*members of Derived:.*value = 2.*"
+	gdb_test "print ns " "\"embedded\\\\000null\\\\000string\""
     }
 
     gdb_test "print x" " = $hex \"this is x\""
diff --git a/gdb/testsuite/gdb.python/python-prettyprint.py b/gdb/testsuite/gdb.python/python-prettyprint.py
index 82e5331..c3e0dc4 100644
--- a/gdb/testsuite/gdb.python/python-prettyprint.py
+++ b/gdb/testsuite/gdb.python/python-prettyprint.py
@@ -99,6 +99,19 @@ class pp_nullstr:
     def to_string(self):
         return self.val['s'].string(gdb.parameter('target-charset'))
 
+class pp_ns:
+    "Print a std::basic_string of some kind"
+
+    def __init__(self, val):
+        self.val = val
+
+    def to_string(self):
+        len = self.val['length']
+        return self.val['null_str'].string (gdb.parameter ('target-charset'), length = len)
+
+    def display_hint (self):
+        return 'string'
+
 def lookup_function (val):
     "Look-up and return a pretty-printer that can print val."
 
@@ -155,6 +168,8 @@ def register_pretty_printers ():
     pretty_printers_dict[re.compile ('^string_repr$')] = string_print
     pretty_printers_dict[re.compile ('^container$')] = ContainerPrinter
     
+    pretty_printers_dict[re.compile ('^struct ns$')]  = pp_ns
+    pretty_printers_dict[re.compile ('^ns$')]  = pp_ns
 pretty_printers_dict = {}
 
 register_pretty_printers ()
diff --git a/gdb/varobj.c b/gdb/varobj.c
index 49b4a43..75f3f17 100644
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -2250,8 +2250,9 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
   long dummy;
   struct ui_file *stb;
   struct cleanup *old_chain;
-  char *thevalue = NULL;
+  gdb_byte *thevalue = NULL;
   struct value_print_options opts;
+  int len = 0;
 
   if (value == NULL)
     return NULL;
@@ -2265,6 +2266,7 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
 	char *hint;
 	struct value *replacement;
 	int string_print = 0;
+	PyObject *output = NULL;
 
 	hint = gdbpy_get_display_hint (value_formatter);
 	if (hint)
@@ -2274,15 +2276,27 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
 	    xfree (hint);
 	  }
 
-	thevalue = apply_varobj_pretty_printer (value_formatter,
-						&replacement);
-	if (thevalue && !string_print)
+	output = apply_varobj_pretty_printer (value_formatter, &replacement);
+
+	if (output)
 	  {
-	    PyGILState_Release (state);
-	    return thevalue;
+	    PyObject *py_str = python_string_to_target_python_string (output);
+	    if (py_str)
+	      {
+		char *s = PyString_AsString (py_str);
+		len = PyString_Size (py_str) + 1;
+		thevalue = xmemdup (s, len, len);
+		Py_DECREF (py_str);
+	      }
+	    Py_DECREF (output);
 	  }
 	if (replacement)
 	  value = replacement;
+	if (thevalue && !string_print)
+         {
+           PyGILState_Release (state);
+           return thevalue;
+         }
       }
     PyGILState_Release (state);
   }
@@ -2297,8 +2311,7 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
   if (thevalue)
     {
       make_cleanup (xfree, thevalue);
-      LA_PRINT_STRING (stb, (gdb_byte *) thevalue, strlen (thevalue),
-		       1, 0, &opts);
+      LA_PRINT_STRING (stb, thevalue, len, 1, 0, &opts);
     }
   else
     common_val_print (value, stb, 0, &opts, current_language);

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [python][patch] Preserve string length, and embedded-nulls in pretty-print string emission.
  2009-06-18 12:20                       ` Phil Muldoon
@ 2009-06-18 20:17                         ` Tom Tromey
  2009-06-18 20:21                         ` Tom Tromey
  1 sibling, 0 replies; 20+ messages in thread
From: Tom Tromey @ 2009-06-18 20:17 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: Thiago Jung Bauermann, Project Archer

Phil> +      PyObject *string = python_string_to_target_python_string (py_str);
Phil> +      if (string)
Phil> +	{
Phil> +	  gdb_byte *output = PyString_AsString (string);
Phil> +	  int len = PyString_Size (string) + 1;
Phil> +
Phil> +	  if (hint && !strcmp (hint, "string"))
Phil> +	    LA_PRINT_STRING (stream, output,
Phil> +			     len, 1, 0, options);
Phil> +	  else
Phil> +	    fputs_filtered (output, stream);
Phil> +	  Py_DECREF (string);
Phil> +	}

This needs an 'else' case to call gdbpy_print_stack.

Also, why the '+ 1' in the computation of 'len'?
Won't this make LA_PRINT_STRING print one too many bytes?

Phil> +PyObject *
Phil>  apply_varobj_pretty_printer (PyObject *printer_obj,
Phil>  			     struct value **replacement)
Phil>  {
Phil> -  char *result;
Phil> +  int size = 0;
Phil>    PyGILState_STATE state = PyGILState_Ensure ();
Phil> +  PyObject *py_str = NULL;
 
Phil>    *replacement = NULL;
Phil> -  result = pretty_print_one_value (printer_obj, replacement);
Phil> -  if (result == NULL);
Phil> +  py_str  = pretty_print_one_value (printer_obj, replacement);
Phil> +
Phil> +  if (replacement == NULL && py_str == NULL)
Phil>      gdbpy_print_stack ();
Phil>    PyGILState_Release (state);
 
Phil> -  return result;
Phil> +  return py_str;
Phil>  }
 
Phil>  /* Find a pretty-printer object for the varobj module.  Returns a new
Phil> diff --git a/gdb/testsuite/gdb.python/python-prettyprint.c b/gdb/testsuite/gdb.python/python-prettyprint.c
Phil> index 0d9110d..5cc35be 100644
Phil> --- a/gdb/testsuite/gdb.python/python-prettyprint.c
Phil> +++ b/gdb/testsuite/gdb.python/python-prettyprint.c
Phil> @@ -29,6 +29,11 @@ struct ss
Phil>    struct s b;
Phil>  };
 
Phil> +struct ns {
Phil> +  const char *null_str;
Phil> +  int length;
Phil> +};
Phil> +
Phil>  #ifdef __cplusplus
Phil>  struct S : public s {
Phil>    int zs;
Phil> @@ -166,6 +171,10 @@ main ()
Phil>    init_ss(ssa+1, 5, 6);
Phil>    memset (&nullstr, 0, sizeof nullstr);
 
Phil> +  struct ns  ns;
Phil> +  ns.null_str = "embedded\0null\0string";
Phil> +  ns.length = 20;
Phil> +
Phil>  #ifdef __cplusplus
Phil>    S cps;
 
Phil> diff --git a/gdb/testsuite/gdb.python/python-prettyprint.exp b/gdb/testsuite/gdb.python/python-prettyprint.exp
Phil> index 47d2fa8..b2dc85d 100644
Phil> --- a/gdb/testsuite/gdb.python/python-prettyprint.exp
Phil> +++ b/gdb/testsuite/gdb.python/python-prettyprint.exp
Phil> @@ -75,6 +75,7 @@ proc run_lang_tests {lang} {
Phil>  	gdb_test "print ref" "= a=<15> b=< a=<8> b=<$hex>>"
Phil>  	gdb_test "print derived" \
Phil>  	    " = \{.*<Vbase1> = pp class name: Vbase1.*<Vbase2> = \{.*<VirtualTest> = pp value variable is: 1,.*members of Vbase2:.*_vptr.Vbase2 = $hex.*<Vbase3> = \{.*members of Vbase3.*members of Derived:.*value = 2.*"
Phil> +	gdb_test "print ns " "\"embedded\\\\000null\\\\000string\""
Phil>      }
 
Phil>      gdb_test "print x" " = $hex \"this is x\""
Phil> diff --git a/gdb/testsuite/gdb.python/python-prettyprint.py b/gdb/testsuite/gdb.python/python-prettyprint.py
Phil> index 82e5331..c3e0dc4 100644
Phil> --- a/gdb/testsuite/gdb.python/python-prettyprint.py
Phil> +++ b/gdb/testsuite/gdb.python/python-prettyprint.py
Phil> @@ -99,6 +99,19 @@ class pp_nullstr:
Phil>      def to_string(self):
Phil>          return self.val['s'].string(gdb.parameter('target-charset'))
 
Phil> +class pp_ns:
Phil> +    "Print a std::basic_string of some kind"
Phil> +
Phil> +    def __init__(self, val):
Phil> +        self.val = val
Phil> +
Phil> +    def to_string(self):
Phil> +        len = self.val['length']
Phil> +        return self.val['null_str'].string (gdb.parameter ('target-charset'), length = len)
Phil> +
Phil> +    def display_hint (self):
Phil> +        return 'string'
Phil> +
Phil>  def lookup_function (val):
Phil>      "Look-up and return a pretty-printer that can print val."
 
Phil> @@ -155,6 +168,8 @@ def register_pretty_printers ():
Phil>      pretty_printers_dict[re.compile ('^string_repr$')] = string_print
Phil>      pretty_printers_dict[re.compile ('^container$')] = ContainerPrinter
     
Phil> +    pretty_printers_dict[re.compile ('^struct ns$')]  = pp_ns
Phil> +    pretty_printers_dict[re.compile ('^ns$')]  = pp_ns
Phil>  pretty_printers_dict = {}
 
Phil>  register_pretty_printers ()
Phil> diff --git a/gdb/varobj.c b/gdb/varobj.c
Phil> index 49b4a43..75f3f17 100644
Phil> --- a/gdb/varobj.c
Phil> +++ b/gdb/varobj.c
Phil> @@ -2250,8 +2250,9 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
Phil>    long dummy;
Phil>    struct ui_file *stb;
Phil>    struct cleanup *old_chain;
Phil> -  char *thevalue = NULL;
Phil> +  gdb_byte *thevalue = NULL;
Phil>    struct value_print_options opts;
Phil> +  int len = 0;
 
Phil>    if (value == NULL)
Phil>      return NULL;
Phil> @@ -2265,6 +2266,7 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
Phil>  	char *hint;
Phil>  	struct value *replacement;
Phil>  	int string_print = 0;
Phil> +	PyObject *output = NULL;
 
Phil>  	hint = gdbpy_get_display_hint (value_formatter);
Phil>  	if (hint)
Phil> @@ -2274,15 +2276,27 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
Phil>  	    xfree (hint);
Phil>  	  }
 
Phil> -	thevalue = apply_varobj_pretty_printer (value_formatter,
Phil> -						&replacement);
Phil> -	if (thevalue && !string_print)
Phil> +	output = apply_varobj_pretty_printer (value_formatter, &replacement);
Phil> +
Phil> +	if (output)
Phil>  	  {
Phil> -	    PyGILState_Release (state);
Phil> -	    return thevalue;
Phil> +	    PyObject *py_str = python_string_to_target_python_string (output);
Phil> +	    if (py_str)
Phil> +	      {
Phil> +		char *s = PyString_AsString (py_str);
Phil> +		len = PyString_Size (py_str) + 1;
Phil> +		thevalue = xmemdup (s, len, len);
Phil> +		Py_DECREF (py_str);
Phil> +	      }
Phil> +	    Py_DECREF (output);
Phil>  	  }
Phil>  	if (replacement)
Phil>  	  value = replacement;
Phil> +	if (thevalue && !string_print)
Phil> +         {
Phil> +           PyGILState_Release (state);
Phil> +           return thevalue;
Phil> +         }
Phil>        }
Phil>      PyGILState_Release (state);
Phil>    }
Phil> @@ -2297,8 +2311,7 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
Phil>    if (thevalue)
Phil>      {
Phil>        make_cleanup (xfree, thevalue);
Phil> -      LA_PRINT_STRING (stb, (gdb_byte *) thevalue, strlen (thevalue),
Phil> -		       1, 0, &opts);
Phil> +      LA_PRINT_STRING (stb, thevalue, len, 1, 0, &opts);
Phil>      }
Phil>    else
Phil>      common_val_print (value, stb, 0, &opts, current_language);

Tom

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [python][patch] Preserve string length, and embedded-nulls in pretty-print string emission.
  2009-06-18 12:20                       ` Phil Muldoon
  2009-06-18 20:17                         ` Tom Tromey
@ 2009-06-18 20:21                         ` Tom Tromey
  2009-06-23 14:37                           ` Phil Muldoon
  1 sibling, 1 reply; 20+ messages in thread
From: Tom Tromey @ 2009-06-18 20:21 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: Thiago Jung Bauermann, Project Archer

Oops, I hit send too soon on that last note.
This is the same, but with more comments.

Phil> +      PyObject *string = python_string_to_target_python_string (py_str);
Phil> +      if (string)
Phil> +	{
Phil> +	  gdb_byte *output = PyString_AsString (string);
Phil> +	  int len = PyString_Size (string) + 1;
Phil> +
Phil> +	  if (hint && !strcmp (hint, "string"))
Phil> +	    LA_PRINT_STRING (stream, output,
Phil> +			     len, 1, 0, options);
Phil> +	  else
Phil> +	    fputs_filtered (output, stream);
Phil> +	  Py_DECREF (string);
Phil> +	}

This needs an 'else' case to call gdbpy_print_stack.

Also, why the '+ 1' in the computation of 'len'?
Won't this make LA_PRINT_STRING print one too many bytes?

Phil> +PyObject *
Phil>  apply_varobj_pretty_printer (PyObject *printer_obj,
Phil>  			     struct value **replacement)
Phil>  {

[...]

Phil> +  if (replacement == NULL && py_str == NULL)

'replacement' cannot be NULL here.
You want '*replacement'.

Phil> @@ -2274,15 +2276,27 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,

[...]

Phil> +		char *s = PyString_AsString (py_str);
Phil> +		len = PyString_Size (py_str) + 1;
Phil> +		thevalue = xmemdup (s, len, len);

Here you do want to copy size+1 bytes, but...

Phil> +      LA_PRINT_STRING (stb, thevalue, len, 1, 0, &opts);

... here I think you wan to just print size bytes.

Tom

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [python][patch] Preserve string length, and embedded-nulls in pretty-print string emission.
  2009-06-18 20:21                         ` Tom Tromey
@ 2009-06-23 14:37                           ` Phil Muldoon
  2009-06-23 16:37                             ` Tom Tromey
  0 siblings, 1 reply; 20+ messages in thread
From: Phil Muldoon @ 2009-06-23 14:37 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Thiago Jung Bauermann, Project Archer

[-- Attachment #1: Type: text/plain, Size: 1669 bytes --]

On 06/18/2009 09:21 PM, Tom Tromey wrote:

Hi Tom

> This needs an 'else' case to call gdbpy_print_stack.
>
> Also, why the '+ 1' in the computation of 'len'?
> Won't this make LA_PRINT_STRING print one too many bytes?
>
>    

...

> Phil>  +  if (replacement == NULL&&  py_str == NULL)
>
> 'replacement' cannot be NULL here.
> You want '*replacement'.
>
>    

> Phil>  +		thevalue = xmemdup (s, len, len);
>
> Here you do want to copy size+1 bytes, but...
>
> Phil>  +      LA_PRINT_STRING (stb, thevalue, len, 1, 0,&opts);
>
> ... here I think you wan to just print size bytes.
>    



I've implemented requested changes. What do you think?

Regards

Phil

2009-06-23 Phil Muldoon <pmuldoon@redhat.com>

* python/lib/gdb/libstdcxx/v6/printers.py
(StdStringPrinter.to_string): Extract length from header. Use in
string extraction.
* python/python-internal.h (apply_varobj_pretty_printer): Update
definition.
(python_string_to_target_python_string): Add definition.
* python/python-utils.c (unicode_to_encoded_python_string)
(unicode_to_target_python_string)
(python_string_to_target_python_string): New Functions.
* python/python.c (pretty_print_one_value): Likewise.
(print_string_repr): Refactor to logic to account for PyObject
returned strings.
(apply_varobj_pretty_printer): Likewise.
* varobj.c (value_get_print_value): Refactor logic to account for
PyObject returned strings.

Testsuite ChangeLog:

2009-06-23 Phil Muldoon <pmuldoon@redhat.com>

* gdb.python/python-prettyprint.c: Add counted null string
structure.
* gdb.python/python-prettyprint.exp: Print null string. Test for
embedded nulls.
* gdb.python/python-prettyprint.py (pp_ns): New
Function.




[-- Attachment #2: pystring_review.patch --]
[-- Type: text/plain, Size: 15493 bytes --]

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 517b4f2..ee64066 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,32 @@
+
+2009-06-08 Phil Muldoon <pmuldoon@redhat.com>
+
+	* python/lib/gdb/libstdcxx/v6/printers.py
+	(StdStringPrinter.to_string): Extract length from header. Use in
+	string extraction.
+	* python/python-internal.h (apply_varobj_pretty_printer): Update
+	definition.
+	(python_string_to_target_python_string): Add definition.
+	* python/python-utils.c (unicode_to_encoded_python_string)
+	(unicode_to_target_python_string)
+	(python_string_to_target_python_string): New Functions.
+	* python/python.c (pretty_print_one_value): Likewise.
+	(print_string_repr): Refactor to logic to account for PyObject
+	returned strings.
+	(apply_varobj_pretty_printer): Likewise.
+	* varobj.c (value_get_print_value): Refactor logic to account for
+	PyObject returned strings.
+
+Testsuite ChangeLog:
+
+2009-06-08 Phil Muldoon <pmuldoon@redhat.com>
+
+	* gdb.python/python-prettyprint.c: Add counted null string
+	structure.
+	* gdb.python/python-prettyprint.exp: Print null string. Test for
+	embedded nulls.
+	* gdb.python/python-prettyprint.py (pp_ns): New
+	Function.
 2009-02-08  Jim Blandy  <jimb@red-bean.com>
 
 	* python/python-value.c (convert_value_from_python):
diff --git a/gdb/python/lib/gdb/libstdcxx/v6/printers.py b/gdb/python/lib/gdb/libstdcxx/v6/printers.py
index 2bd2593..6bf4f3b 100644
--- a/gdb/python/lib/gdb/libstdcxx/v6/printers.py
+++ b/gdb/python/lib/gdb/libstdcxx/v6/printers.py
@@ -468,7 +468,17 @@ class StdStringPrinter:
             encoding = gdb.parameter('target-charset')
         elif isinstance(encoding, WideEncoding):
             encoding = encoding.value
-        return self.val['_M_dataplus']['_M_p'].string(encoding)
+        type = self.val.type
+        if type.code == gdb.TYPE_CODE_REF:
+            type = type.target ()
+
+        ptr = self.val ['_M_dataplus']['_M_p']
+        realtype = type.unqualified ().strip_typedefs ()
+        reptype = gdb.lookup_type (str (realtype) + '::_Rep').pointer ()
+        header = ptr.cast(reptype) - 1
+        len = header.dereference ()['_M_length']
+
+        return self.val['_M_dataplus']['_M_p'].string (encoding, length = len)
 
     def display_hint (self):
         return 'string'
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 29e55dd..1d90722 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -169,6 +169,7 @@ void gdbpy_print_stack (void);
 PyObject *python_string_to_unicode (PyObject *obj);
 char *unicode_to_target_string (PyObject *unicode_str);
 char *python_string_to_target_string (PyObject *obj);
+PyObject *python_string_to_target_python_string (PyObject *obj);
 char *python_string_to_host_string (PyObject *obj);
 PyObject *target_string_to_unicode (const gdb_byte *str, int length);
 int gdbpy_is_string (PyObject *obj);
@@ -177,8 +178,8 @@ int gdbpy_is_value_object (PyObject *obj);
 
 /* Note that these are declared here, and not in python.h with the
    other pretty-printer functions, because they refer to PyObject.  */
-char *apply_varobj_pretty_printer (PyObject *print_obj,
-				   struct value **replacement);
+PyObject *apply_varobj_pretty_printer (PyObject *print_obj,
+				       struct value **replacement);
 PyObject *gdbpy_get_varobj_pretty_printer (struct value *value);
 PyObject *gdbpy_instantiate_printer (PyObject *cons, PyObject *value);
 char *gdbpy_get_display_hint (PyObject *printer);
diff --git a/gdb/python/python-utils.c b/gdb/python/python-utils.c
index f9c9486..45c74a5 100644
--- a/gdb/python/python-utils.c
+++ b/gdb/python/python-utils.c
@@ -122,6 +122,23 @@ unicode_to_encoded_string (PyObject *unicode_str, const char *charset)
   return result;
 }
 
+/* Returns a PyObject with the contents of the given unicode string
+   object converted to a named charset.  If an error occurs during
+   the conversion, NULL will be returned and a python exception will
+   be set.  */
+static PyObject *
+unicode_to_encoded_python_string (PyObject *unicode_str, const char *charset)
+{
+  PyObject *string;
+
+  /* Translate string to named charset.  */
+  string = PyUnicode_AsEncodedString (unicode_str, charset, NULL);
+  if (string == NULL)
+    return NULL;
+
+  return string;
+}
+
 /* Returns a newly allocated string with the contents of the given unicode
    string object converted to the target's charset.  If an error occurs during
    the conversion, NULL will be returned and a python exception will be set.
@@ -133,6 +150,16 @@ unicode_to_target_string (PyObject *unicode_str)
   return unicode_to_encoded_string (unicode_str, target_charset ());
 }
 
+/* Returns a PyObject with the contents of the given unicode string
+   object converted to the target's charset.  If an error occurs
+   during the conversion, NULL will be returned and a python exception
+   will be set.  */
+PyObject *
+unicode_to_target_python_string (PyObject *unicode_str)
+{
+  return unicode_to_encoded_python_string (unicode_str, target_charset ());
+}
+
 /* Converts a python string (8-bit or unicode) to a target string in
    the target's charset.  Returns NULL on error, with a python exception set.
 
@@ -152,6 +179,24 @@ python_string_to_target_string (PyObject *obj)
   return result;
 }
 
+/* Converts a python string (8-bit or unicode) to a target string in the
+   target's charset.  Returns NULL on error, with a python exception
+   set.  */
+PyObject *
+python_string_to_target_python_string (PyObject *obj)
+{
+  PyObject *str;
+  PyObject *result;
+
+  str = python_string_to_unicode (obj);
+  if (str == NULL)
+    return NULL;
+
+  result = unicode_to_target_python_string (str);
+  Py_DECREF (str);
+  return result;
+}
+
 /* Converts a python string (8-bit or unicode) to a target string in
    the host's charset.  Returns NULL on error, with a python exception set.
 
diff --git a/gdb/python/python.c b/gdb/python/python.c
index e97bef8..dbaaaa9 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -826,41 +826,36 @@ find_pretty_printer (PyObject *value)
   return function;
 }
 
-/* Pretty-print a single value, via the printer object PRINTER.  If
-   the function returns a string, an xmalloc()d copy is returned.
-   Otherwise, if the function returns a value, a *OUT_VALUE is set to
-   the value, and NULL is returned.  On error, *OUT_VALUE is set to
-   NULL and NULL is returned.  */
-static char *
+/* 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.  */
+static PyObject *
 pretty_print_one_value (PyObject *printer, struct value **out_value)
 {
-  char *output = NULL;
   volatile struct gdb_exception except;
+  PyObject *result = NULL;
 
   TRY_CATCH (except, RETURN_MASK_ALL)
     {
-      PyObject *result;
-
       result = PyObject_CallMethodObjArgs (printer, gdbpy_to_string_cst, NULL);
       if (result)
 	{
-	  if (gdbpy_is_string (result))
-	    output = python_string_to_host_string (result);
-	  else if (PyObject_TypeCheck (result, &value_object_type))
+	  if (! gdbpy_is_string (result))
 	    {
-	      /* If we just call convert_value_from_python for this
-		 type, we won't know who owns the result.  For this
-		 one case we need to copy the resulting value.  */
-	      struct value *v = value_object_to_value (result);
-	      *out_value = value_copy (v);
+	      *out_value = convert_value_from_python (result);
+	      Py_DECREF (result);
+	      result = NULL;
+	      if (PyErr_Occurred ())
+		*out_value = NULL;
 	    }
-	  else
-	    *out_value = convert_value_from_python (result);
-	  Py_DECREF (result);
 	}
+      else
+	*out_value = NULL;
     }
 
-  return output;
+  return result;
 }
 
 /* Instantiate a pretty-printer given a constructor, CONS, and a
@@ -906,18 +901,28 @@ print_string_repr (PyObject *printer, const char *hint,
 		   const struct value_print_options *options,
 		   const struct language_defn *language)
 {
-  char *output;
   struct value *replacement = NULL;
+  PyObject *py_str = NULL;
 
-  output = pretty_print_one_value (printer, &replacement);
-  if (output)
+  py_str = pretty_print_one_value (printer, &replacement);
+  if (py_str)
     {
-      if (hint && !strcmp (hint, "string"))
-	LA_PRINT_STRING (stream, (gdb_byte *) output, strlen (output),
-			 1, 0, options);
+      PyObject *string = python_string_to_target_python_string (py_str);
+      if (string)
+	{
+	  gdb_byte *output = PyString_AsString (string);
+	  int len = PyString_Size (string);
+
+	  if (hint && !strcmp (hint, "string"))
+	    LA_PRINT_STRING (stream, output,
+			     len, 1, 0, options);
+	  else
+	    fputs_filtered (output, stream);
+	  Py_DECREF (string);
+	}
       else
-	fputs_filtered (output, stream);
-      xfree (output);
+	gdbpy_print_stack ();
+      Py_DECREF (py_str);
     }
   else if (replacement)
     common_val_print (replacement, stream, recurse, options, language);
@@ -1232,28 +1237,31 @@ apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr,
   return result;
 }
 
-/* Apply a pretty-printer for the varobj code.  PRINTER_OBJ is the
-   print object.  It must have a 'to_string' method (but this is
-   checked by varobj, not here) which takes no arguments and
-   returns a string.  This function returns an xmalloc()d string if
-   the printer returns a string.  The printer may return a replacement
-   value instead; in this case *REPLACEMENT is set to the replacement
-   value, and this function returns NULL.  On error, *REPLACEMENT is
-   set to NULL and this function also returns NULL.  */
-char *
+ /* Apply a pretty-printer for the varobj code.  PRINTER_OBJ is the
+    print object.  It must have a 'to_string' method (but this is
+    checked by varobj, not here) which takes no arguments and
+    returns a string.  The printer will return a value and in the case
+    of a Python string being returned, this function will return a
+    PyObject containing the string.  For any other type, *REPLACEMENT is
+    set to the replacement value and this function returns NULL.  On
+    error, *REPLACEMENT is set to NULL and this function also returns
+    NULL.  */
+PyObject *
 apply_varobj_pretty_printer (PyObject *printer_obj,
 			     struct value **replacement)
 {
-  char *result;
+  int size = 0;
   PyGILState_STATE state = PyGILState_Ensure ();
+  PyObject *py_str = NULL;
 
   *replacement = NULL;
-  result = pretty_print_one_value (printer_obj, replacement);
-  if (result == NULL);
+  py_str  = pretty_print_one_value (printer_obj, replacement);
+
+  if (*replacement == NULL && py_str == NULL)
     gdbpy_print_stack ();
   PyGILState_Release (state);
 
-  return result;
+  return py_str;
 }
 
 /* Find a pretty-printer object for the varobj module.  Returns a new
diff --git a/gdb/testsuite/gdb.python/python-prettyprint.c b/gdb/testsuite/gdb.python/python-prettyprint.c
index 0d9110d..5cc35be 100644
--- a/gdb/testsuite/gdb.python/python-prettyprint.c
+++ b/gdb/testsuite/gdb.python/python-prettyprint.c
@@ -29,6 +29,11 @@ struct ss
   struct s b;
 };
 
+struct ns {
+  const char *null_str;
+  int length;
+};
+
 #ifdef __cplusplus
 struct S : public s {
   int zs;
@@ -166,6 +171,10 @@ main ()
   init_ss(ssa+1, 5, 6);
   memset (&nullstr, 0, sizeof nullstr);
 
+  struct ns  ns;
+  ns.null_str = "embedded\0null\0string";
+  ns.length = 20;
+
 #ifdef __cplusplus
   S cps;
 
diff --git a/gdb/testsuite/gdb.python/python-prettyprint.exp b/gdb/testsuite/gdb.python/python-prettyprint.exp
index 47d2fa8..b2dc85d 100644
--- a/gdb/testsuite/gdb.python/python-prettyprint.exp
+++ b/gdb/testsuite/gdb.python/python-prettyprint.exp
@@ -75,6 +75,7 @@ proc run_lang_tests {lang} {
 	gdb_test "print ref" "= a=<15> b=< a=<8> b=<$hex>>"
 	gdb_test "print derived" \
 	    " = \{.*<Vbase1> = pp class name: Vbase1.*<Vbase2> = \{.*<VirtualTest> = pp value variable is: 1,.*members of Vbase2:.*_vptr.Vbase2 = $hex.*<Vbase3> = \{.*members of Vbase3.*members of Derived:.*value = 2.*"
+	gdb_test "print ns " "\"embedded\\\\000null\\\\000string\""
     }
 
     gdb_test "print x" " = $hex \"this is x\""
diff --git a/gdb/testsuite/gdb.python/python-prettyprint.py b/gdb/testsuite/gdb.python/python-prettyprint.py
index 82e5331..c3e0dc4 100644
--- a/gdb/testsuite/gdb.python/python-prettyprint.py
+++ b/gdb/testsuite/gdb.python/python-prettyprint.py
@@ -99,6 +99,19 @@ class pp_nullstr:
     def to_string(self):
         return self.val['s'].string(gdb.parameter('target-charset'))
 
+class pp_ns:
+    "Print a std::basic_string of some kind"
+
+    def __init__(self, val):
+        self.val = val
+
+    def to_string(self):
+        len = self.val['length']
+        return self.val['null_str'].string (gdb.parameter ('target-charset'), length = len)
+
+    def display_hint (self):
+        return 'string'
+
 def lookup_function (val):
     "Look-up and return a pretty-printer that can print val."
 
@@ -155,6 +168,8 @@ def register_pretty_printers ():
     pretty_printers_dict[re.compile ('^string_repr$')] = string_print
     pretty_printers_dict[re.compile ('^container$')] = ContainerPrinter
     
+    pretty_printers_dict[re.compile ('^struct ns$')]  = pp_ns
+    pretty_printers_dict[re.compile ('^ns$')]  = pp_ns
 pretty_printers_dict = {}
 
 register_pretty_printers ()
diff --git a/gdb/varobj.c b/gdb/varobj.c
index 49b4a43..a6b045d 100644
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -2250,8 +2250,9 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
   long dummy;
   struct ui_file *stb;
   struct cleanup *old_chain;
-  char *thevalue = NULL;
+  gdb_byte *thevalue = NULL;
   struct value_print_options opts;
+  int len = 0;
 
   if (value == NULL)
     return NULL;
@@ -2265,6 +2266,7 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
 	char *hint;
 	struct value *replacement;
 	int string_print = 0;
+	PyObject *output = NULL;
 
 	hint = gdbpy_get_display_hint (value_formatter);
 	if (hint)
@@ -2274,15 +2276,27 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
 	    xfree (hint);
 	  }
 
-	thevalue = apply_varobj_pretty_printer (value_formatter,
-						&replacement);
-	if (thevalue && !string_print)
+	output = apply_varobj_pretty_printer (value_formatter, &replacement);
+
+	if (output)
 	  {
-	    PyGILState_Release (state);
-	    return thevalue;
+	    PyObject *py_str = python_string_to_target_python_string (output);
+	    if (py_str)
+	      {
+		char *s = PyString_AsString (py_str);
+		len = PyString_Size (py_str);
+		thevalue = xmemdup (s, len + 1, len + 1);
+		Py_DECREF (py_str);
+	      }
+	    Py_DECREF (output);
 	  }
 	if (replacement)
 	  value = replacement;
+	if (thevalue && !string_print)
+         {
+           PyGILState_Release (state);
+           return thevalue;
+         }
       }
     PyGILState_Release (state);
   }
@@ -2297,8 +2311,7 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
   if (thevalue)
     {
       make_cleanup (xfree, thevalue);
-      LA_PRINT_STRING (stb, (gdb_byte *) thevalue, strlen (thevalue),
-		       1, 0, &opts);
+      LA_PRINT_STRING (stb, thevalue, len, 1, 0, &opts);
     }
   else
     common_val_print (value, stb, 0, &opts, current_language);

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [python][patch] Preserve string length, and embedded-nulls in pretty-print string emission.
  2009-06-23 14:37                           ` Phil Muldoon
@ 2009-06-23 16:37                             ` Tom Tromey
  2009-06-23 16:56                               ` Phil Muldoon
  0 siblings, 1 reply; 20+ messages in thread
From: Tom Tromey @ 2009-06-23 16:37 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: Thiago Jung Bauermann, Project Archer

>>>>> "Phil" == Phil Muldoon <pmuldoon@redhat.com> writes:

Phil> I've implemented requested changes. What do you think?

Looks good!

Phil> * python/lib/gdb/libstdcxx/v6/printers.py

The rule I've been following for this stuff is that a libstdc++
printer can't go in until the needed code is in gdb CVS.
So, it is time to submit these last couple of changes upstream :-)

Tom

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [python][patch] Preserve string length, and embedded-nulls in pretty-print string emission.
  2009-06-23 16:37                             ` Tom Tromey
@ 2009-06-23 16:56                               ` Phil Muldoon
  0 siblings, 0 replies; 20+ messages in thread
From: Phil Muldoon @ 2009-06-23 16:56 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Thiago Jung Bauermann, Project Archer

On 06/23/2009 05:37 PM, Tom Tromey wrote:
>>>>>> "Phil" == Phil Muldoon<pmuldoon@redhat.com>  writes:
>>>>>>              
>
> Phil>  I've implemented requested changes. What do you think?
>
> Looks good!
>    


Great! I'll check this in to the archer branch. I'll prepare and merge 
this patch and the previous "counted string" patch for submission to GDB 
soon after ...


> Phil>  * python/lib/gdb/libstdcxx/v6/printers.py
>
> The rule I've been following for this stuff is that a libstdc++
> printer can't go in until the needed code is in gdb CVS.
> So, it is time to submit these last couple of changes upstream :-)
>    

And then I'll submit these changes to libstdc++ later, post approval of 
the previous GDB submit.

Regards

Phil

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2009-06-23 16:56 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-05-22 20:23 [python][patch] Preserve string length, and embedded-nulls in pretty-print string emission Phil Muldoon
2009-05-27 17:35 ` Tom Tromey
2009-05-27 18:24   ` Phil Muldoon
2009-05-27 20:22     ` Tom Tromey
2009-06-01 16:26       ` Phil Muldoon
2009-06-02  5:11         ` Thiago Jung Bauermann
2009-06-02 23:46           ` Tom Tromey
2009-06-08 10:31             ` Phil Muldoon
2009-06-11 17:12               ` Tom Tromey
2009-06-15 20:50                 ` Phil Muldoon
2009-06-16 12:44                   ` Phil Muldoon
2009-06-16 18:07                     ` Tom Tromey
2009-06-18 12:20                       ` Phil Muldoon
2009-06-18 20:17                         ` Tom Tromey
2009-06-18 20:21                         ` Tom Tromey
2009-06-23 14:37                           ` Phil Muldoon
2009-06-23 16:37                             ` Tom Tromey
2009-06-23 16:56                               ` Phil Muldoon
2009-06-02 15:38         ` Jonas Maebe
2009-06-02 20:48           ` Phil Muldoon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).