* [patch] Support counted strings and embedded nulls in value.string
@ 2009-06-30 16:37 Phil Muldoon
2009-07-06 17:36 ` Tom Tromey
0 siblings, 1 reply; 6+ messages in thread
From: Phil Muldoon @ 2009-06-30 16:37 UTC (permalink / raw)
To: gdb-patches ml
[-- Attachment #1: Type: text/plain, Size: 2676 bytes --]
This patch adds two related elements to the pretty-printer python
support. This patch already exists in the archer-tromey-python branch
of the archer repository, and here is my submission for the FSF repository.
The first element of the patch adds counted string support to the
value.string method by an optional length parameter; the second element
preserves the length of the string and respects embedded nulls in the
case where a string is regarded as "counted". This allows the
preservation of embedded nulls in python value strings as long as a
length is specified. If an explicit length is not provided, it reverts
to the old behaviour of regarding the first null as a sting terminator.
Originally this patch was written as two separate patches:
The counted string support is discussed here in the archer archives:
http://sourceware.org/ml/archer/2009-q2/msg00017.html
And the preservation and embedded nulls in the counted string scenario
is here:
http://sourceware.org/ml/archer/2009-q2/msg00111.html
Regards
Phil
ChangeLog
2009-06-30 Phil Muldoon <pmuldoon@redhat.com>
* 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-prettyprint.c (pretty_print_one_value): Likewise.
(print_string_repr): Refactor to logic to account for PyObject
returned strings.
(apply_varobj_pretty_printer): Likewise.
* python/python-value.c (valpy_string): Parse length keyword. Use
length keyword in LA_GET_STRING.
* varobj.c (value_get_print_value): Refactor logic to account for
PyObject returned strings.
* c-lang.c (c_get_string): If the length parameter is specified,
use that. Return value in characters. Update comments.
* language.h: Update c_get_string prototype comments.
Testsuite ChangeLog:
2009-06-30 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.
* gdb.python/python-value.exp (test_value_in_inferior): Add
variable length string fetch tests.
* gdb.python/python-value.c (main): Add strings for string fetch tests.
Documentation ChangeLog
2009-06-30 Phil Muldoon <pmuldoon@redhat.com>
* gdb.texinfo (Values From Inferior): Add length parameter
description.
[-- Attachment #2: gdb_upstream_counted_and_null_string.patch --]
[-- Type: text/plain, Size: 24968 bytes --]
Index: c-lang.c
===================================================================
RCS file: /cvs/src/src/gdb/c-lang.c,v
retrieving revision 1.72
diff -u -r1.72 c-lang.c
--- c-lang.c 23 Jun 2009 16:26:04 -0000 1.72
+++ c-lang.c 30 Jun 2009 13:05:43 -0000
@@ -591,18 +591,17 @@
}
/* Obtain a C string from the inferior storing it in a newly allocated
- buffer in BUFFER, which should be freed by the caller. The string is
- read until a null character is found. If VALUE is an array with known
- length, the function will not read past the end of the array. LENGTH
- will contain the size of the string in bytes (not counting the null
- character).
-
- Assumes strings are terminated by a null character. The size of a character
- is determined by the length of the target type of the pointer or array.
- This means that a null byte present in a multi-byte character will not
- terminate the string unless the whole character is null.
-
- CHARSET is always set to the target charset. */
+ buffer in BUFFER, which should be freed by the caller. If LENGTH
+ is specified at -1, the string is read until a null character of
+ the appropriate width is found, otherwise the string is read to the
+ length of characters specified. The size of a character is
+ determined by the length of the target type of the pointer or
+ array. If VALUE is an array with a known length, the function will
+ not read past the end of the array.
+ On completion, LENGTH will be set to the size of the string read in
+ characters. (If a length of -1 is specified, the length returned
+ will not include the null character). CHARSET is always set to the
+ target charset. */
void
c_get_string (struct value *value, gdb_byte **buffer, int *length,
@@ -612,6 +611,7 @@
unsigned int fetchlimit;
struct type *type = check_typedef (value_type (value));
struct type *element_type = TYPE_TARGET_TYPE (type);
+ int req_length = *length;
if (element_type == NULL)
goto error;
@@ -647,7 +647,7 @@
width = TYPE_LENGTH (element_type);
- /* If the string lives in GDB's memory intead of the inferior's, then we
+ /* If the string lives in GDB's memory instead of the inferior's, then we
just need to copy it to BUFFER. Also, since such strings are arrays
with known size, FETCHLIMIT will hold the size of the array. */
if ((VALUE_LVAL (value) == not_lval
@@ -657,12 +657,17 @@
int i;
const gdb_byte *contents = value_contents (value);
- /* Look for a null character. */
- for (i = 0; i < fetchlimit; i++)
- if (extract_unsigned_integer (contents + i * width, width) == 0)
- break;
+ /* If a length is specified, use that. */
+ if (*length >= 0)
+ i = *length;
+ else
+ /* Otherwise, look for a null character. */
+ for (i = 0; i < fetchlimit; i++)
+ if (extract_unsigned_integer (contents + i * width, width) == 0)
+ break;
- /* I is now either the number of non-null characters, or FETCHLIMIT. */
+ /* I is now either a user-defined length, the number of non-null
+ characters, or FETCHLIMIT. */
*length = i * width;
*buffer = xmalloc (*length);
memcpy (*buffer, contents, *length);
@@ -670,7 +675,7 @@
}
else
{
- err = read_string (value_as_address (value), -1, width, fetchlimit,
+ err = read_string (value_as_address (value), *length, width, fetchlimit,
buffer, length);
if (err)
{
@@ -680,10 +685,21 @@
}
}
- /* If the last character is null, subtract it from LENGTH. */
- if (*length > 0
- && extract_unsigned_integer (*buffer + *length - width, width) == 0)
- *length -= width;
+ /* If the LENGTH is specified at -1, we want to return the string
+ length up to the terminating null character. If an actual length
+ was specified, we want to return the length of exactly what was
+ read. */
+ if (req_length == -1)
+ /* If the last character is null, subtract it from LENGTH. */
+ if (*length > 0
+ && extract_unsigned_integer (*buffer + *length - width, width) == 0)
+ *length -= width;
+
+ /* The read_string function will return the number of bytes read.
+ If length returned from read_string was > 0, return the number of
+ characters read by dividing the number of bytes by width. */
+ if (*length != 0)
+ *length = *length / width;
*charset = target_charset ();
Index: language.h
===================================================================
RCS file: /cvs/src/src/gdb/language.h,v
retrieving revision 1.57
diff -u -r1.57 language.h
--- language.h 20 Mar 2009 23:04:33 -0000 1.57
+++ language.h 30 Jun 2009 13:06:09 -0000
@@ -284,10 +284,15 @@
int (*la_pass_by_reference) (struct type *type);
/* Obtain a string from the inferior, storing it in a newly allocated
- buffer in BUFFER, which should be freed by the caller. LENGTH will
- hold the size in bytes of the string (only actual characters, excluding
- an eventual terminating null character). CHARSET will hold the encoding
- used in the string. */
+ buffer in BUFFER, which should be freed by the caller. If LENGTH
+ is specified at -1, the string is read until a null character
+ of the appropriate width is found - otherwise the string is
+ read to the length of characters specified.
+ On completion, LENGTH will hold the size of the string in characters.
+ If a LENGTH of -1 was specified it will count only actual
+ characters, excluding any eventual terminating null character.
+ Otherwise LENGTH will include all characters - including any nulls.
+ CHARSET will hold the encoding used in the string. */
void (*la_get_string) (struct value *value, gdb_byte **buffer, int *length,
const char **charset);
Index: varobj.c
===================================================================
RCS file: /cvs/src/src/gdb/varobj.c,v
retrieving revision 1.136
diff -u -r1.136 varobj.c
--- varobj.c 29 Jun 2009 13:24:41 -0000 1.136
+++ varobj.c 30 Jun 2009 13:06:43 -0000
@@ -2232,8 +2232,9 @@
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;
@@ -2247,6 +2248,7 @@
char *hint;
struct value *replacement;
int string_print = 0;
+ PyObject *output = NULL;
hint = gdbpy_get_display_hint (value_formatter);
if (hint)
@@ -2256,15 +2258,27 @@
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);
}
@@ -2280,8 +2294,7 @@
{
make_cleanup (xfree, thevalue);
LA_PRINT_STRING (stb, builtin_type (current_gdbarch)->builtin_char,
- (gdb_byte *) thevalue, strlen (thevalue),
- 0, &opts);
+ thevalue, len, 0, &opts);
}
else
common_val_print (value, stb, 0, &opts, current_language);
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.602
diff -u -r1.602 gdb.texinfo
--- doc/gdb.texinfo 28 Jun 2009 18:53:12 -0000 1.602
+++ doc/gdb.texinfo 30 Jun 2009 13:06:57 -0000
@@ -18896,7 +18896,7 @@
value pointed to by @code{foo}.
@end defmethod
-@defmethod Value string @r{[}encoding@r{]} @r{[}errors@r{]}
+@defmethod Value string @r{[}encoding@r{]} @r{[}errors@r{]} @r{[}length@r{]}
If this @code{gdb.Value} represents a string, then this method
converts the contents to a Python string. Otherwise, this method will
throw an exception.
@@ -18907,7 +18907,9 @@
For C-like languages, a value is a string if it is a pointer to or an
array of characters or ints. The string is assumed to be terminated
-by a zero of the appropriate width.
+by a zero of the appropriate width. However if the optional length
+argument is given, the string will be converted beyond any embedded
+nulls up to the length specified.
If the optional @var{encoding} argument is given, it must be a string
naming the encoding of the string in the @code{gdb.Value}, such as
@@ -18921,6 +18923,9 @@
The optional @var{errors} argument is the same as the corresponding
argument to Python's @code{string.decode} method.
+
+If the optional @var{length} argument is given, the string will be
+fetched and converted to the given length.
@end defmethod
@end table
Index: python/python-internal.h
===================================================================
RCS file: /cvs/src/src/gdb/python/python-internal.h,v
retrieving revision 1.15
diff -u -r1.15 python-internal.h
--- python/python-internal.h 28 May 2009 01:09:20 -0000 1.15
+++ python/python-internal.h 30 Jun 2009 13:07:12 -0000
@@ -107,14 +107,15 @@
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);
/* 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);
char *gdbpy_get_display_hint (PyObject *printer);
PyObject *gdbpy_default_visualizer (PyObject *self, PyObject *args);
Index: python/python-prettyprint.c
===================================================================
RCS file: /cvs/src/src/gdb/python/python-prettyprint.c,v
retrieving revision 1.3
diff -u -r1.3 python-prettyprint.c
--- python/python-prettyprint.c 28 May 2009 16:30:39 -0000 1.3
+++ python/python-prettyprint.c 30 Jun 2009 13:07:13 -0000
@@ -121,34 +121,35 @@
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;
+ *out_value = 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
- *out_value = convert_value_from_python (result);
- Py_DECREF (result);
+ if (! gdbpy_is_string (result))
+ {
+ *out_value = convert_value_from_python (result);
+ if (PyErr_Occurred ())
+ *out_value = NULL;
+ Py_DECREF (result);
+ result = NULL;
+ }
}
}
- return output;
+ return result;
}
/* Return the display hint for the object printer, PRINTER. Return
@@ -183,19 +184,28 @@
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, builtin_type (current_gdbarch)->builtin_char,
- (gdb_byte *) output, strlen (output),
- 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);
+
+ if (hint && !strcmp (hint, "string"))
+ LA_PRINT_STRING (stream, builtin_type (current_gdbarch)->builtin_char,
+ output, len, 0, options);
+ else
+ fputs_filtered (output, stream);
+ Py_DECREF (string);
+ }
+ else
+ gdbpy_print_stack ();
+ Py_DECREF (py_str);
}
else if (replacement)
common_val_print (replacement, stream, recurse, options, language);
@@ -510,28 +520,31 @@
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
Index: python/python-utils.c
===================================================================
RCS file: /cvs/src/src/gdb/python/python-utils.c,v
retrieving revision 1.6
diff -u -r1.6 python-utils.c
--- python/python-utils.c 26 Feb 2009 20:45:21 -0000 1.6
+++ python/python-utils.c 30 Jun 2009 13:07:13 -0000
@@ -121,6 +121,23 @@
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.
@@ -132,6 +149,16 @@
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.
@@ -151,6 +178,24 @@
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.
Index: python/python-value.c
===================================================================
RCS file: /cvs/src/src/gdb/python/python-value.c,v
retrieving revision 1.18
diff -u -r1.18 python-value.c
--- python/python-value.c 29 Jun 2009 13:24:41 -0000 1.18
+++ python/python-value.c 30 Jun 2009 13:07:13 -0000
@@ -189,13 +189,16 @@
return obj->type;
}
-/* Implementation of gdb.Value.string ([encoding] [, errors]) -> string
- Return Unicode string with value contents. If ENCODING is not given,
- the string is assumed to be encoded in the target's charset. */
+/* Implementation of gdb.Value.string ([encoding] [, errors]
+ [, length]) -> string. Return Unicode string with value contents.
+ If ENCODING is not given, the string is assumed to be encoded in
+ the target's charset. If LENGTH is provided, only fetch string to
+ the length provided. */
+
static PyObject *
valpy_string (PyObject *self, PyObject *args, PyObject *kw)
{
- int length, ret = 0;
+ int length = -1, ret = 0;
gdb_byte *buffer;
struct value *value = ((value_object *) self)->value;
volatile struct gdb_exception except;
@@ -204,10 +207,10 @@
const char *errors = NULL;
const char *user_encoding = NULL;
const char *la_encoding = NULL;
- static char *keywords[] = { "encoding", "errors" };
+ static char *keywords[] = { "encoding", "errors", "length" };
- if (!PyArg_ParseTupleAndKeywords (args, kw, "|ss", keywords,
- &user_encoding, &errors))
+ if (!PyArg_ParseTupleAndKeywords (args, kw, "|ssi", keywords,
+ &user_encoding, &errors, &length))
return NULL;
TRY_CATCH (except, RETURN_MASK_ALL)
@@ -939,7 +942,7 @@
{ "cast", valpy_cast, METH_VARARGS, "Cast the value to the supplied type." },
{ "dereference", valpy_dereference, METH_NOARGS, "Dereferences the value." },
{ "string", (PyCFunction) valpy_string, METH_VARARGS | METH_KEYWORDS,
- "string ([encoding] [, errors]) -> string\n\
+ "string ([encoding] [, errors] [, length]) -> string\n\
Return Unicode string representation of the value." },
{NULL} /* Sentinel */
};
Index: testsuite/gdb.python/python-prettyprint.c
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.python/python-prettyprint.c,v
retrieving revision 1.1
diff -u -r1.1 python-prettyprint.c
--- testsuite/gdb.python/python-prettyprint.c 28 May 2009 01:05:14 -0000 1.1
+++ testsuite/gdb.python/python-prettyprint.c 30 Jun 2009 13:07:41 -0000
@@ -27,6 +27,11 @@
struct s b;
};
+struct ns {
+ const char *null_str;
+ int length;
+};
+
#ifdef __cplusplus
struct S : public s {
int zs;
@@ -156,6 +161,10 @@
init_ss(ssa+0, 3, 4);
init_ss(ssa+1, 5, 6);
+ struct ns ns;
+ ns.null_str = "embedded\0null\0string";
+ ns.length = 20;
+
#ifdef __cplusplus
S cps;
Index: testsuite/gdb.python/python-prettyprint.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.python/python-prettyprint.exp,v
retrieving revision 1.1
diff -u -r1.1 python-prettyprint.exp
--- testsuite/gdb.python/python-prettyprint.exp 28 May 2009 01:05:14 -0000 1.1
+++ testsuite/gdb.python/python-prettyprint.exp 30 Jun 2009 13:07:41 -0000
@@ -78,6 +78,7 @@
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\\\\0null\\\\0string\""
}
gdb_test "print x" " = $hex \"this is x\""
Index: testsuite/gdb.python/python-prettyprint.py
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.python/python-prettyprint.py,v
retrieving revision 1.1
diff -u -r1.1 python-prettyprint.py
--- testsuite/gdb.python/python-prettyprint.py 28 May 2009 01:05:14 -0000 1.1
+++ testsuite/gdb.python/python-prettyprint.py 30 Jun 2009 13:07:41 -0000
@@ -92,6 +92,19 @@
def to_string (self):
return "pp class name: " + self.val.type.tag
+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."
@@ -145,6 +158,8 @@
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 ()
Index: testsuite/gdb.python/python-value.c
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.python/python-value.c,v
retrieving revision 1.4
diff -u -r1.4 python-value.c
--- testsuite/gdb.python/python-value.c 28 May 2009 00:47:20 -0000 1.4
+++ testsuite/gdb.python/python-value.c 30 Jun 2009 13:07:41 -0000
@@ -44,6 +44,8 @@
struct s s;
union u u;
PTR x = &s;
+ char st[17] = "divide et impera";
+ char nullst[17] = "divide\0et\0impera";
s.a = 3;
s.b = 5;
Index: testsuite/gdb.python/python-value.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.python/python-value.exp,v
retrieving revision 1.8
diff -u -r1.8 python-value.exp
--- testsuite/gdb.python/python-value.exp 28 May 2009 00:47:20 -0000 1.8
+++ testsuite/gdb.python/python-value.exp 30 Jun 2009 13:07:41 -0000
@@ -234,6 +234,25 @@
# Test address attribute
gdb_test "python print 'result =', arg0.address" "= 0x\[\[:xdigit:\]\]+" "Test address attribute"
+
+ # Test string fetches, both partial and whole.
+ gdb_test "print st" "\"divide et impera\""
+ gdb_py_test_silent_cmd "python st = gdb.history (0)" "get value from history" 1
+ gdb_test "python print st.string ()" "divide et impera" "Test string with no length"
+ gdb_test "python print st.string (length = -1)" "divide et impera" "Test string (length = -1) is all of the string"
+ gdb_test "python print st.string (length = 6)" "divide"
+ gdb_test "python print \"---\"+st.string (length = 0)+\"---\"" "------" "Test string (length = 0) is empty"
+ gdb_test "python print len(st.string (length = 0))" "0" "Test length is 0"
+
+
+ # Fetch a string that has embedded nulls.
+ gdb_test "print nullst" "\"divide\\\\0et\\\\0impera\".*"
+ gdb_py_test_silent_cmd "python nullst = gdb.history (0)" "get value from history" 1
+ gdb_test "python print nullst.string ()" "divide" "Test string to first null"
+ # Python cannot print strings that contain the null (\0) character.
+ # For the purposes of this test, use repr()
+ gdb_py_test_silent_cmd "python nullst = nullst.string (length = 9)" "get string beyond null" 1
+ gdb_test "python print repr(nullst)" "u'divide\\\\x00et'"
}
# A few objfile tests.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [patch] Support counted strings and embedded nulls in value.string
2009-06-30 16:37 [patch] Support counted strings and embedded nulls in value.string Phil Muldoon
@ 2009-07-06 17:36 ` Tom Tromey
2009-07-07 7:32 ` Phil Muldoon
0 siblings, 1 reply; 6+ messages in thread
From: Tom Tromey @ 2009-07-06 17:36 UTC (permalink / raw)
To: Phil Muldoon; +Cc: gdb-patches
Phil> This patch adds two related elements to the pretty-printer python
Phil> support. This patch already exists in the archer-tromey-python branch
Phil> of the archer repository, and here is my submission for the FSF
Phil> repository.
Thanks.
Phil> Index: c-lang.c
[...]
Phil> /* Obtain a C string from the inferior storing it in a newly allocated
[...]
Phil> + buffer in BUFFER, which should be freed by the caller. If LENGTH
Phil> + is specified at -1, the string is read until a null character of
This should mention *LENGTH, not LENGTH.
I think this comment (and the similar comment in language.h) would be
clearer if it mentioned that LENGTH is both an in- and out-parameter.
Phil> Index: python/python-prettyprint.c
Phil> + /* Apply a pretty-printer for the varobj code. PRINTER_OBJ is the
Phil> + print object. It must have a 'to_string' method (but this is
Phil> + checked by varobj, not here) which takes no arguments and
Phil> + returns a string. The printer will return a value and in the case
Phil> + of a Python string being returned, this function will return a
Phil> + PyObject containing the string. For any other type, *REPLACEMENT is
Phil> + set to the replacement value and this function returns NULL. On
Phil> + error, *REPLACEMENT is set to NULL and this function also returns
Phil> + NULL. */
I noticed recently that this entire comment is shifted over by a space.
Could you move it back?
The code bits are approved with those two changes.
It still needs a doc review.
Tom
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [patch] Support counted strings and embedded nulls in value.string
2009-07-06 17:36 ` Tom Tromey
@ 2009-07-07 7:32 ` Phil Muldoon
2009-07-07 19:28 ` Eli Zaretskii
0 siblings, 1 reply; 6+ messages in thread
From: Phil Muldoon @ 2009-07-07 7:32 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
On 07/06/2009 06:36 PM, Tom Tromey wrote:
> Phil> /* Obtain a C string from the inferior storing it in a newly allocated
>
> [...]
>
> Phil> + buffer in BUFFER, which should be freed by the caller. If LENGTH
> Phil> + is specified at -1, the string is read until a null character of
>
> This should mention *LENGTH, not LENGTH.
> I think this comment (and the similar comment in language.h) would be
> clearer if it mentioned that LENGTH is both an in- and out-parameter.
>
>
Ok.
> Phil> Index: python/python-prettyprint.c
> Phil> + /* Apply a pretty-printer for the varobj code. PRINTER_OBJ is the
> Phil> + print object. It must have a 'to_string' method (but this is
> Phil> + checked by varobj, not here) which takes no arguments and
> Phil> + returns a string. The printer will return a value and in the case
> Phil> + of a Python string being returned, this function will return a
> Phil> + PyObject containing the string. For any other type, *REPLACEMENT is
> Phil> + set to the replacement value and this function returns NULL. On
> Phil> + error, *REPLACEMENT is set to NULL and this function also returns
> Phil> + NULL. */
>
> I noticed recently that this entire comment is shifted over by a space.
> Could you move it back?
>
Ok.
> The code bits are approved with those two changes.
> It still needs a doc review.
>
I've made the two changes above. Pending Eli's response, I'll check this
patch in.
Regards
Phil
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [patch] Support counted strings and embedded nulls in value.string
2009-07-07 7:32 ` Phil Muldoon
@ 2009-07-07 19:28 ` Eli Zaretskii
2009-07-07 19:51 ` Phil Muldoon
0 siblings, 1 reply; 6+ messages in thread
From: Eli Zaretskii @ 2009-07-07 19:28 UTC (permalink / raw)
To: Phil Muldoon; +Cc: tromey, gdb-patches
> Date: Tue, 07 Jul 2009 08:32:21 +0100
> From: Phil Muldoon <pmuldoon@redhat.com>
> CC: gdb-patches@sourceware.org
>
> Pending Eli's response, I'll check this patch in.
Sorry, I missed that because you sent the patch as binary attachment.
The patch for the manual is okay, with one comment. I don't
understand the last sentence in this hunk:
For C-like languages, a value is a string if it is a pointer to or an
array of characters or ints. The string is assumed to be terminated
-by a zero of the appropriate width.
+by a zero of the appropriate width. However if the optional length
+argument is given, the string will be converted beyond any embedded
+nulls up to the length specified.
What does it mean ``converted beyond any embedded nulls''?
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [patch] Support counted strings and embedded nulls in value.string
2009-07-07 19:28 ` Eli Zaretskii
@ 2009-07-07 19:51 ` Phil Muldoon
2009-07-07 19:56 ` Eli Zaretskii
0 siblings, 1 reply; 6+ messages in thread
From: Phil Muldoon @ 2009-07-07 19:51 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: tromey, gdb-patches
On 07/07/2009 08:27 PM, Eli Zaretskii wrote:
>> Date: Tue, 07 Jul 2009 08:32:21 +0100
>> From: Phil Muldoon<pmuldoon@redhat.com>
>> CC: gdb-patches@sourceware.org
>>
>> Pending Eli's response, I'll check this patch in.
>>
>
> Sorry, I missed that because you sent the patch as binary attachment.
>
Thanks. I'm not sure what this means, I attached the patch as an
attachment just like all the others I've sent. I don't think I've
changed any behaviour in any/all patches I've sent as attachments? What
did you see?
> The patch for the manual is okay, with one comment. I don't
> understand the last sentence in this hunk:
>
> For C-like languages, a value is a string if it is a pointer to or an
> array of characters or ints. The string is assumed to be terminated
> -by a zero of the appropriate width.
> +by a zero of the appropriate width. However if the optional length
> +argument is given, the string will be converted beyond any embedded
> +nulls up to the length specified.
>
> What does it mean ``converted beyond any embedded nulls''?
>
I'll add a clearer description; it does assume too much user C string
knowledge, and the wording is unclear. What I was trying to convey was
the string will be converted up to the the optional length, ignoring any
nulls (as a null in a C string context traditionally conveys the end of
a string).
Regards
Phil
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [patch] Support counted strings and embedded nulls in value.string
2009-07-07 19:51 ` Phil Muldoon
@ 2009-07-07 19:56 ` Eli Zaretskii
0 siblings, 0 replies; 6+ messages in thread
From: Eli Zaretskii @ 2009-07-07 19:56 UTC (permalink / raw)
To: Phil Muldoon; +Cc: tromey, gdb-patches
> Date: Tue, 07 Jul 2009 20:51:16 +0100
> From: Phil Muldoon <pmuldoon@redhat.com>
> CC: tromey@redhat.com, gdb-patches@sourceware.org
>
> > Sorry, I missed that because you sent the patch as binary attachment.
> >
>
>
> Thanks. I'm not sure what this means, I attached the patch as an
> attachment just like all the others I've sent. I don't think I've
> changed any behaviour in any/all patches I've sent as attachments? What
> did you see?
Never mind, that was just a lame attempt at saying sorry.
> What I was trying to convey was the string will be converted up to
> the the optional length, ignoring any nulls
That's exactly what you should say, it is crystal clear that way.
Thanks.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2009-07-07 19:56 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-06-30 16:37 [patch] Support counted strings and embedded nulls in value.string Phil Muldoon
2009-07-06 17:36 ` Tom Tromey
2009-07-07 7:32 ` Phil Muldoon
2009-07-07 19:28 ` Eli Zaretskii
2009-07-07 19:51 ` Phil Muldoon
2009-07-07 19:56 ` Eli Zaretskii
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox