2010-01-13 Phil Muldoon <pmuldoon@redhat.com>

PR python/10705

	* python/python-internal.h: Add lazy_string_object_type
	definition.
	(create_lazy_string_object, gdbpy_initialize_lazy_string)
	(gdbpy_is_lazystring, gdbpy_extract_lazy_string): Define.
	* python/py-value.c (valpy_lazy_string): New function.
	(convert_value_from_python): Add lazy string conversion.
	* python/py-prettyprint.c (pretty_print_one_value): Check if
	return is also a lazy string.
	(print_string_repr): Add lazy string printing branch.
	(print_children): Likewise.
	* python/py-lazy-string.c: New file. Implement lazy strings.
	* python/python.c (_initialize_python): Call
	gdbpy_initialize_lazy_string.
	* varobj.c (value_get_print_value): Add lazy string printing
	branch.  Account for encoding.
	* c-lang.c (c_printstr): Account for new encoding argument.  If
	encoding is NULL, find encoding suited for type, otherwise use
	user encoding.
	* language.h (language_defn): Add encoding argument.
	(LA_PRINT_STRING): Likewise.
	* language.c (unk_lang_printstr): Update to reflect new encoding
	argument to language_defn.
	* ada-lang.h (ada_printstr): Likewise.
	* c-lang.h (c_printstr): Likewise.
	* p-lang.h (pascal_printstr);
	* f-lang.c (f_printstr): Likewise.
	* m2-lang.c (m2_printstr): Likewise.
	* objc-lang.c (objc_printstr): Likewise.
	* p-lang.c (pascal_printstr): Likewise.
	* scm-lang.c (scm_printstr): Likewise.
	* c-valprint.c (c_val_print): Update LA_PRINT_STRING call for
	encoding argument.
	* ada-valprint.c (ada_printstr): Likewise.
	* f-valprint.c (f_val_print): Likewise
	* m2-valprint.c (m2_val_print): Likewise.
	* p-valprint.c (pascal_val_print): Likewise.
	* expprint.c (print_subexp_standard): Likewise.
	* valprint.c (val_print_string): Likewise.
	* Makefile.in (SUBDIR_PYTHON_OBS): Add py-lazy-string.
	(SUBDIR_PYTHON_SRCS): Likewise.
	(py-lazy-string.o): New rule.

2010-01-13  Phil Muldoon  <pmuldoon@redhat.com>

	* gdb.texinfo (Values From Inferior): Document lazy_string value
	method.
	(Python API): Add Lazy strings menu item.
	(Lazy Strings In Python): New node.

2010-01-13  Phil Muldoon  <pmuldoon@redhat.com>

	* gdb.python/py-value.exp (test_lazy_strings): Add lazy string test.
	* gdb.python/py-prettyprint.py (pp_ls): New printer.
	* gdb.python/py-prettyprint.exp (run_lang_tests): Add lazy string
	test.
	* gdb.python/py-prettyprint.c: Define lazystring test structure.
	* gdb.python/py-mi.exp: Add lazy string test.
This commit is contained in:
Phil Muldoon 2010-01-14 08:03:37 +00:00
parent 009f105539
commit be759fcf73
35 changed files with 647 additions and 51 deletions

View file

@ -1,3 +1,50 @@
2010-01-13 Phil Muldoon <pmuldoon@redhat.com>
PR python/10705
* python/python-internal.h: Add lazy_string_object_type
definition.
(create_lazy_string_object, gdbpy_initialize_lazy_string)
(gdbpy_is_lazystring, gdbpy_extract_lazy_string): Define.
* python/py-value.c (valpy_lazy_string): New function.
(convert_value_from_python): Add lazy string conversion.
* python/py-prettyprint.c (pretty_print_one_value): Check if
return is also a lazy string.
(print_string_repr): Add lazy string printing branch.
(print_children): Likewise.
* python/py-lazy-string.c: New file. Implement lazy strings.
* python/python.c (_initialize_python): Call
gdbpy_initialize_lazy_string.
* varobj.c (value_get_print_value): Add lazy string printing
branch. Account for encoding.
* c-lang.c (c_printstr): Account for new encoding argument. If
encoding is NULL, find encoding suited for type, otherwise use
user encoding.
* language.h (language_defn): Add encoding argument.
(LA_PRINT_STRING): Likewise.
* language.c (unk_lang_printstr): Update to reflect new encoding
argument to language_defn.
* ada-lang.h (ada_printstr): Likewise.
* c-lang.h (c_printstr): Likewise.
* p-lang.h (pascal_printstr);
* f-lang.c (f_printstr): Likewise.
* m2-lang.c (m2_printstr): Likewise.
* objc-lang.c (objc_printstr): Likewise.
* p-lang.c (pascal_printstr): Likewise.
* scm-lang.c (scm_printstr): Likewise.
* c-valprint.c (c_val_print): Update LA_PRINT_STRING call for
encoding argument.
* ada-valprint.c (ada_printstr): Likewise.
* f-valprint.c (f_val_print): Likewise
* m2-valprint.c (m2_val_print): Likewise.
* p-valprint.c (pascal_val_print): Likewise.
* expprint.c (print_subexp_standard): Likewise.
* valprint.c (val_print_string): Likewise.
* Makefile.in (SUBDIR_PYTHON_OBS): Add py-lazy-string.
(SUBDIR_PYTHON_SRCS): Likewise.
(py-lazy-string.o): New rule.
2010-01-13 Doug Evans <dje@google.com>
* mi/mi-main.c (list_available_thread_groups): Avoid "may be used

View file

@ -270,6 +270,7 @@ SUBDIR_PYTHON_OBS = \
py-cmd.o \
py-frame.o \
py-function.o \
py-lazy-string.o \
py-objfile.o \
py-prettyprint.o \
py-type.o \
@ -280,6 +281,7 @@ SUBDIR_PYTHON_SRCS = \
python/py-cmd.c \
python/py-frame.c \
python/py-function.c \
python/py-lazy-string.c \
python/py-objfile.c \
python/py-prettyprint.c \
python/py-type.c \
@ -1980,6 +1982,10 @@ py-function.o: $(srcdir)/python/py-function.c
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-function.c
$(POSTCOMPILE)
py-lazy-string.o: $(srcdir)/python/py-lazy-string.c
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-lazy-string.c
$(POSTCOMPILE)
py-objfile.o: $(srcdir)/python/py-objfile.c
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-objfile.c
$(POSTCOMPILE)

View file

@ -174,7 +174,7 @@ extern void ada_emit_char (int, struct type *, struct ui_file *, int, int);
extern void ada_printchar (int, struct type *, struct ui_file *);
extern void ada_printstr (struct ui_file *, struct type *, const gdb_byte *,
unsigned int, int,
unsigned int, const char *, int,
const struct value_print_options *);
struct value *ada_convert_actual (struct value *actual,

View file

@ -556,7 +556,7 @@ printstr (struct ui_file *stream, struct type *elttype, const gdb_byte *string,
void
ada_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
unsigned int length, int force_ellipses,
unsigned int length, const char *encoding, int force_ellipses,
const struct value_print_options *options)
{
printstr (stream, type, string, length, force_ellipses, TYPE_LENGTH (type),

View file

@ -369,7 +369,7 @@ c_printchar (int c, struct type *type, struct ui_file *stream)
void
c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
unsigned int length, int force_ellipses,
unsigned int length, const char *user_encoding, int force_ellipses,
const struct value_print_options *options)
{
enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
@ -381,6 +381,7 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
struct obstack wchar_buf, output;
struct cleanup *cleanup;
enum c_string_type str_type;
const char *type_encoding;
const char *encoding;
struct wchar_iterator *iter;
int finished = 0;
@ -395,7 +396,7 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
width, byte_order) == 0))
length--;
str_type = classify_type (type, byte_order, &encoding) & ~C_CHAR;
str_type = classify_type (type, byte_order, &type_encoding) & ~C_CHAR;
switch (str_type)
{
case C_STRING:
@ -411,6 +412,8 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
break;
}
encoding = (user_encoding && *user_encoding) ? user_encoding : type_encoding;
if (length == 0)
{
fputs_filtered ("\"\"", stream);

View file

@ -81,7 +81,7 @@ extern void c_printchar (int, struct type *, struct ui_file *);
extern void c_printstr (struct ui_file * stream, struct type *elttype,
const gdb_byte *string, unsigned int length,
int force_ellipses,
const char *user_encoding, int force_ellipses,
const struct value_print_options *options);
extern void c_language_arch_info (struct gdbarch *gdbarch,

View file

@ -198,7 +198,8 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
}
LA_PRINT_STRING (stream, unresolved_elttype,
valaddr + embedded_offset, len, 0, options);
valaddr + embedded_offset, len,
NULL, 0, options);
i = len;
}
else

View file

@ -1,3 +1,10 @@
2010-01-13 Phil Muldoon <pmuldoon@redhat.com>
* gdb.texinfo (Values From Inferior): Document lazy_string value
method.
(Python API): Add Lazy strings menu item.
(Lazy Strings In Python): New node.
2010-01-13 Vladimir Prus <vladimir@codesourcery.com>
* gdb.texinfo (GDB/MI Thread Information): New.

View file

@ -19420,6 +19420,7 @@ situation, a Python @code{KeyboardInterrupt} exception is thrown.
* Functions In Python:: Writing new convenience functions.
* Objfiles In Python:: Object files.
* Frames In Python:: Acessing inferior stack frames from Python.
* Lazy Strings In Python:: Python representation of lazy strings.
@end menu
@node Basic Python
@ -19694,6 +19695,30 @@ 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
@defmethod Value lazy_string @r{[}encoding@r{]} @r{[}length@r{]}
If this @code{gdb.Value} represents a string, then this method
converts the contents to a @code{gdb.LazyString} (@pxref{Lazy Strings
In Python}). Otherwise, this method will throw an exception.
If the optional @var{encoding} argument is given, it must be a string
naming the encoding of the @code{gdb.LazyString}. Some examples are:
@samp{ascii}, @samp{iso-8859-6} or @samp{utf-8}. If the
@var{encoding} argument is an encoding that @value{GDBN} does
recognize, @value{GDBN} will raise an error.
When a lazy string is printed, the @value{GDBN} encoding machinery is
used to convert the string during printing. If the optional
@var{encoding} argument is not provided, or is an empty string,
@value{GDBN} will automatically select the encoding most suitable for
the string type. For further information on encoding in @value{GDBN}
please see @ref{Character Sets}.
If the optional @var{length} argument is given, the string will be
fetched and encoded to the length of characters specified. If
the @var{length} argument is not provided, the string will be fetched
and encoded until a null of appropriate width is found.
@end defmethod
@end table
@node Types In Python
@ -20631,6 +20656,61 @@ be a string.
@end defmethod
@end table
@node Lazy Strings In Python
@subsubsection Python representation of lazy strings.
@cindex lazy strings in python
@tindex gdb.LazyString
A @dfn{lazy string} is a string whose contents is not retrieved or
encoded until it is needed.
A @code{gdb.LazyString} is represented in @value{GDBN} as an
@code{address} that points to a region of memory, an @code{encoding}
that will be used to encode that region of memory, and a @code{length}
to delimit the region of memory that represents the string. The
difference between a @code{gdb.LazyString} and a string wrapped within
a @code{gdb.Value} is that a @code{gdb.LazyString} will be treated
differently by @value{GDBN} when printing. A @code{gdb.LazyString} is
retrieved and encoded during printing, while a @code{gdb.Value}
wrapping a string is immediately retrieved and encoded on creation.
A @code{gdb.LazyString} object has the following functions:
@defmethod LazyString value
Convert the @code{gdb.LazyString} to a @code{gdb.Value}. This value
will point to the string in memory, but will lose all the delayed
retrieval, encoding and handling that @value{GDBN} applies to a
@code{gdb.LazyString}.
@end defmethod
@defivar LazyString address
This attribute holds the address of the string. This attribute is not
writable.
@end defivar
@defivar LazyString length
This attribute holds the length of the string in characters. If the
length is -1, then the string will be fetched and encoded up to the
first null of appropriate width. This attribute is not writable.
@end defivar
@defivar LazyString encoding
This attribute holds the encoding that will be applied to the string
when the string is printed by @value{GDBN}. If the encoding is not
set, or contains an empty string, then @value{GDBN} will select the
most appropriate encoding when the string is printed. This attribute
is not writable.
@end defivar
@defivar LazyString type
This attribute holds the type that is represented by the lazy string's
type. For a lazy string this will always be a pointer type. To
resolve this to the lazy string's character type, use the type's
@code{target} method. @xref{Types In Python}. This attribute is not
writable.
@end defivar
@node Interpreters
@chapter Command Interpreters
@cindex command interpreters

View file

@ -188,7 +188,7 @@ print_subexp_standard (struct expression *exp, int *pos,
additional parameter to LA_PRINT_STRING. -fnf */
get_user_print_options (&opts);
LA_PRINT_STRING (stream, builtin_type (exp->gdbarch)->builtin_char,
&exp->elts[pc + 2].string, nargs, 0, &opts);
&exp->elts[pc + 2].string, nargs, NULL, 0, &opts);
}
return;
@ -207,7 +207,7 @@ print_subexp_standard (struct expression *exp, int *pos,
fputs_filtered ("@\"", stream);
get_user_print_options (&opts);
LA_PRINT_STRING (stream, builtin_type (exp->gdbarch)->builtin_char,
&exp->elts[pc + 2].string, nargs, 0, &opts);
&exp->elts[pc + 2].string, nargs, NULL, 0, &opts);
fputs_filtered ("\"", stream);
}
return;
@ -293,7 +293,7 @@ print_subexp_standard (struct expression *exp, int *pos,
struct value_print_options opts;
get_user_print_options (&opts);
LA_PRINT_STRING (stream, builtin_type (exp->gdbarch)->builtin_char,
tempstr, nargs - 1, 0, &opts);
tempstr, nargs - 1, NULL, 0, &opts);
(*pos) = pc;
}
else

View file

@ -143,7 +143,7 @@ f_printchar (int c, struct type *type, struct ui_file *stream)
static void
f_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
unsigned int length, int force_ellipses,
unsigned int length, const char *encoding, int force_ellipses,
const struct value_print_options *options)
{
unsigned int i;

View file

@ -259,7 +259,7 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
case TYPE_CODE_STRING:
f77_get_dynamic_length_of_aggregate (type);
LA_PRINT_STRING (stream, builtin_type (gdbarch)->builtin_char,
valaddr, TYPE_LENGTH (type), 0, options);
valaddr, TYPE_LENGTH (type), NULL, 0, options);
break;
case TYPE_CODE_ARRAY:

View file

@ -1083,7 +1083,7 @@ unk_lang_printchar (int c, struct type *type, struct ui_file *stream)
static void
unk_lang_printstr (struct ui_file *stream, struct type *type,
const gdb_byte *string, unsigned int length,
int force_ellipses,
const char *encoding, int force_ellipses,
const struct value_print_options *options)
{
error (_("internal error - unimplemented function unk_lang_printstr called."));

View file

@ -190,7 +190,7 @@ struct language_defn
void (*la_printstr) (struct ui_file * stream, struct type *elttype,
const gdb_byte *string, unsigned int length,
int force_ellipses,
const char *encoding, int force_ellipses,
const struct value_print_options *);
void (*la_emitchar) (int ch, struct type *chtype,
@ -389,9 +389,9 @@ extern enum language set_language (enum language);
#define LA_PRINT_CHAR(ch, type, stream) \
(current_language->la_printchar(ch, type, stream))
#define LA_PRINT_STRING(stream, elttype, string, length, force_ellipses,options) \
#define LA_PRINT_STRING(stream, elttype, string, length, encoding, force_ellipses,options) \
(current_language->la_printstr(stream, elttype, string, length, \
force_ellipses,options))
encoding, force_ellipses,options))
#define LA_EMIT_CHAR(ch, type, stream, quoter) \
(current_language->la_emitchar(ch, type, stream, quoter))
#define LA_GET_STRING(value, buffer, length, chartype, encoding) \

View file

@ -104,7 +104,7 @@ m2_printchar (int c, struct type *type, struct ui_file *stream)
static void
m2_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
unsigned int length, int force_ellipses,
unsigned int length, const char *encoding, int force_ellipses,
const struct value_print_options *options)
{
unsigned int i;

View file

@ -360,8 +360,8 @@ m2_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
}
LA_PRINT_STRING (stream, TYPE_TARGET_TYPE (type),
valaddr + embedded_offset, len, 0,
options);
valaddr + embedded_offset, len, NULL,
0, options);
i = len;
}
else

View file

@ -343,7 +343,7 @@ objc_printchar (int c, struct type *type, struct ui_file *stream)
static void
objc_printstr (struct ui_file *stream, struct type *type,
const gdb_byte *string, unsigned int length,
int force_ellipses,
const char *encoding, int force_ellipses,
const struct value_print_options *options)
{
unsigned int i;

View file

@ -214,7 +214,7 @@ pascal_printchar (int c, struct type *type, struct ui_file *stream)
void
pascal_printstr (struct ui_file *stream, struct type *type,
const gdb_byte *string, unsigned int length,
int force_ellipses,
const char *encoding, int force_ellipses,
const struct value_print_options *options)
{
enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));

View file

@ -54,7 +54,7 @@ extern int
extern void pascal_printchar (int, struct type *, struct ui_file *);
extern void pascal_printstr (struct ui_file *, struct type *, const gdb_byte *,
unsigned int, int,
unsigned int, const char *, int,
const struct value_print_options *);
extern struct type **const (pascal_builtin_types[]);

View file

@ -104,7 +104,7 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr,
}
LA_PRINT_STRING (stream, TYPE_TARGET_TYPE (type),
valaddr + embedded_offset, len, 0,
valaddr + embedded_offset, len, NULL, 0,
options);
i = len;
}
@ -306,7 +306,9 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr,
&string_pos, &char_type, NULL))
{
len = extract_unsigned_integer (valaddr + embedded_offset + length_pos, length_size, byte_order);
LA_PRINT_STRING (stream, char_type, valaddr + embedded_offset + string_pos, len, 0, options);
LA_PRINT_STRING (stream, char_type,
valaddr + embedded_offset + string_pos,
len, NULL, 0, options);
}
else
pascal_object_print_value_fields (type, valaddr + embedded_offset, address, stream,

291
gdb/python/py-lazy-string.c Normal file
View file

@ -0,0 +1,291 @@
/* Python interface to lazy strings.
Copyright (C) 2010 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "python-internal.h"
#include "charset.h"
#include "value.h"
#include "exceptions.h"
#include "valprint.h"
#include "language.h"
typedef struct {
PyObject_HEAD
/* Holds the address of the lazy string. */
CORE_ADDR address;
/* Holds the encoding that will be applied to the string
when the string is printed by GDB. If the encoding is set
to None then GDB will select the most appropriate
encoding when the sting is printed. */
char *encoding;
/* Holds the length of the string in characters. If the
length is -1, then the string will be fetched and encoded up to
the first null of appropriate width. */
long length;
/* This attribute holds the type that is represented by the lazy
string's type. */
struct type *type;
} lazy_string_object;
static PyTypeObject lazy_string_object_type;
static PyObject *
stpy_get_address (PyObject *self, void *closure)
{
lazy_string_object *self_string = (lazy_string_object *) self;
return PyLong_FromUnsignedLongLong (self_string->address);
}
static PyObject *
stpy_get_encoding (PyObject *self, void *closure)
{
lazy_string_object *self_string = (lazy_string_object *) self;
PyObject *result;
/* An encoding can be set to NULL by the user, so check before
attempting a Python FromString call. If NULL return Py_None. */
if (self_string->encoding)
result = PyString_FromString (self_string->encoding);
else
{
result = Py_None;
Py_INCREF (result);
}
return result;
}
static PyObject *
stpy_get_length (PyObject *self, void *closure)
{
lazy_string_object *self_string = (lazy_string_object *) self;
return PyLong_FromLong (self_string->length);
}
PyObject *
stpy_get_type (PyObject *self, void *closure)
{
lazy_string_object *str_obj = (lazy_string_object *) self;
return type_to_type_object (str_obj->type);
}
static PyObject *
stpy_convert_to_value (PyObject *self, PyObject *args)
{
lazy_string_object *self_string = (lazy_string_object *) self;
struct value *val;
val = value_at_lazy (self_string->type, self_string->address);
return value_to_value_object (val);
}
static void
stpy_dealloc (PyObject *self)
{
lazy_string_object *self_string = (lazy_string_object *) self;
xfree (self_string->encoding);
}
PyObject *
gdbpy_create_lazy_string_object (CORE_ADDR address, long length,
const char *encoding, struct type *type)
{
lazy_string_object *str_obj = NULL;
if (address == 0)
{
PyErr_SetString (PyExc_MemoryError,
"Cannot create a lazy string from a GDB-side string.");
return NULL;
}
if (!type)
{
PyErr_SetString (PyExc_RuntimeError,
"A lazy string's type cannot be NULL.");
return NULL;
}
str_obj = PyObject_New (lazy_string_object, &lazy_string_object_type);
if (!str_obj)
return NULL;
str_obj->address = address;
str_obj->length = length;
if (encoding == NULL || !strcmp (encoding, ""))
str_obj->encoding = NULL;
else
str_obj->encoding = xstrdup (encoding);
str_obj->type = type;
return (PyObject *) str_obj;
}
void
gdbpy_initialize_lazy_string (void)
{
if (PyType_Ready (&lazy_string_object_type) < 0)
return;
Py_INCREF (&lazy_string_object_type);
}
/* Determine whether the printer object pointed to by OBJ is a
Python lazy string. */
int
gdbpy_is_lazy_string (PyObject *result)
{
return PyObject_TypeCheck (result, &lazy_string_object_type);
}
/* Extract and return the actual string from the lazy string object
STRING. Addtionally, the string type is written to *STR_TYPE, the
string length is written to *LENGTH, and the string encoding is
written to *ENCODING. On error, NULL is returned. The caller is
responsible for freeing the returned buffer. */
gdb_byte *
gdbpy_extract_lazy_string (PyObject *string, struct type **str_type,
long *length, char **encoding)
{
int width;
int bytes_read;
gdb_byte *buffer = NULL;
int errcode = 0;
CORE_ADDR addr;
struct gdbarch *gdbarch;
enum bfd_endian byte_order;
PyObject *py_len = NULL, *py_encoding = NULL;
PyObject *py_addr = NULL, *py_type = NULL;
volatile struct gdb_exception except;
py_len = PyObject_GetAttrString (string, "length");
py_encoding = PyObject_GetAttrString (string, "encoding");
py_addr = PyObject_GetAttrString (string, "address");
py_type = PyObject_GetAttrString (string, "type");
/* A NULL encoding, length, address or type is not ok. */
if (!py_len || !py_encoding || !py_addr || !py_type)
goto error;
*length = PyLong_AsLong (py_len);
addr = PyLong_AsLongLong (py_addr);
/* If the user supplies Py_None an encoding, set encoding to NULL.
This will trigger the resulting LA_PRINT_CALL to automatically
select an encoding. */
if (py_encoding == Py_None)
*encoding = NULL;
else
*encoding = xstrdup (PyString_AsString (py_encoding));
*str_type = type_object_to_type (py_type);
gdbarch = get_type_arch (*str_type);
byte_order = gdbarch_byte_order (gdbarch);
width = TYPE_LENGTH (*str_type);
TRY_CATCH (except, RETURN_MASK_ALL)
{
errcode = read_string (addr, *length, width,
*length, byte_order, &buffer,
&bytes_read);
}
if (except.reason < 0)
{
PyErr_Format (except.reason == RETURN_QUIT \
? PyExc_KeyboardInterrupt : PyExc_RuntimeError, \
"%s", except.message); \
goto error;
}
if (errcode)
goto error;
*length = bytes_read / width;
Py_DECREF (py_encoding);
Py_DECREF (py_len);
Py_DECREF (py_addr);
Py_DECREF (py_type);
return buffer;
error:
Py_XDECREF (py_encoding);
Py_XDECREF (py_len);
Py_XDECREF (py_addr);
Py_XDECREF (py_type);
xfree (buffer);
*length = 0;
*str_type = NULL;
return NULL;
}
static PyMethodDef lazy_string_object_methods[] = {
{ "value", stpy_convert_to_value, METH_NOARGS,
"Create a (lazy) value that contains a pointer to the string." },
{NULL} /* Sentinel */
};
static PyGetSetDef lazy_string_object_getset[] = {
{ "address", stpy_get_address, NULL, "Address of the string.", NULL },
{ "encoding", stpy_get_encoding, NULL, "Encoding of the string.", NULL },
{ "length", stpy_get_length, NULL, "Length of the string.", NULL },
{ "type", stpy_get_type, NULL, "Type associated with the string.", NULL },
{ NULL } /* Sentinel */
};
static PyTypeObject lazy_string_object_type = {
PyObject_HEAD_INIT (NULL)
0, /*ob_size*/
"gdb.LazyString", /*tp_name*/
sizeof (lazy_string_object), /*tp_basicsize*/
0, /*tp_itemsize*/
stpy_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
"GDB lazy string object", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
lazy_string_object_methods, /* tp_methods */
0, /* tp_members */
lazy_string_object_getset /* tp_getset */
};

View file

@ -121,6 +121,8 @@ find_pretty_printer (PyObject *value)
return function;
}
/* 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,
@ -138,7 +140,7 @@ 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))
if (! gdbpy_is_string (result) && ! gdbpy_is_lazy_string (result))
{
*out_value = convert_value_from_python (result);
if (PyErr_Occurred ())
@ -191,21 +193,47 @@ print_string_repr (PyObject *printer, const char *hint,
py_str = pretty_print_one_value (printer, &replacement);
if (py_str)
{
PyObject *string = python_string_to_target_python_string (py_str);
if (string)
gdb_byte *output = NULL;
long length;
struct type *type;
char *encoding = NULL;
PyObject *string = NULL;
int is_lazy;
is_lazy = gdbpy_is_lazy_string (py_str);
if (is_lazy)
output = gdbpy_extract_lazy_string (py_str, &type, &length, &encoding);
else
{
gdb_byte *output = PyString_AsString (string);
int len = PyString_Size (string);
string = python_string_to_target_python_string (py_str);
if (string)
{
output = PyString_AsString (string);
length = PyString_Size (string);
type = builtin_type (gdbarch)->builtin_char;
}
else
gdbpy_print_stack ();
if (hint && !strcmp (hint, "string"))
LA_PRINT_STRING (stream, builtin_type (gdbarch)->builtin_char,
output, len, 0, options);
}
if (output)
{
if (is_lazy || (hint && !strcmp (hint, "string")))
LA_PRINT_STRING (stream, type, output, length, encoding,
0, options);
else
fputs_filtered (output, stream);
Py_DECREF (string);
}
else
gdbpy_print_stack ();
if (string)
Py_DECREF (string);
else
xfree (output);
xfree (encoding);
Py_DECREF (py_str);
}
else if (replacement)
@ -422,15 +450,30 @@ print_children (PyObject *printer, const char *hint,
fputs_filtered (" = ", stream);
}
if (gdbpy_is_string (py_v))
if (gdbpy_is_lazy_string (py_v) || gdbpy_is_string (py_v))
{
char *text = python_string_to_host_string (py_v);
if (! text)
gdbpy_print_stack ();
gdb_byte *output = NULL;
if (gdbpy_is_lazy_string (py_v))
{
struct type *type;
long length;
char *encoding = NULL;
output = gdbpy_extract_lazy_string (py_v, &type,
&length, &encoding);
if (!output)
gdbpy_print_stack ();
LA_PRINT_STRING (stream, type, output, length, encoding,
0, options);
xfree (encoding);
xfree (output);
}
else
{
fputs_filtered (text, stream);
xfree (text);
output = python_string_to_host_string (py_v);
fputs_filtered (output, stream);
xfree (output);
}
}
else

View file

@ -220,6 +220,36 @@ valpy_get_type (PyObject *self, void *closure)
return obj->type;
}
/* Implementation of gdb.Value.lazy_string ([encoding] [, length]) ->
string. Return a PyObject representing a lazy_string_object type.
A lazy string is a pointer to a string with an optional encoding and
length. If ENCODING is not given, encoding is set to None. If an
ENCODING is provided the encoding parameter is set to ENCODING, but
the string is not encoded. If LENGTH is provided then the length
parameter is set to LENGTH, otherwise length will be set to -1 (first
null of appropriate with). */
static PyObject *
valpy_lazy_string (PyObject *self, PyObject *args, PyObject *kw)
{
int length = -1;
struct value *value = ((value_object *) self)->value;
const char *user_encoding = NULL;
static char *keywords[] = { "encoding", "length", NULL };
PyObject *str_obj;
if (!PyArg_ParseTupleAndKeywords (args, kw, "|si", keywords,
&user_encoding, &length))
return NULL;
if (TYPE_CODE (value_type (value)) == TYPE_CODE_PTR)
value = value_ind (value);
str_obj = gdbpy_create_lazy_string_object (value_address (value), length,
user_encoding, value_type (value));
return (PyObject *) str_obj;
}
/* 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
@ -939,6 +969,13 @@ convert_value_from_python (PyObject *obj)
}
else if (PyObject_TypeCheck (obj, &value_object_type))
value = value_copy (((value_object *) obj)->value);
else if (gdbpy_is_lazy_string (obj))
{
PyObject *result;
PyObject *function = PyString_FromString ("value");
result = PyObject_CallMethodObjArgs (obj, function, NULL);
value = value_copy (((value_object *) result)->value);
}
else
PyErr_Format (PyExc_TypeError, _("Could not convert Python object: %s"),
PyString_AsString (PyObject_Str (obj)));
@ -1001,6 +1038,9 @@ static PyGetSetDef value_object_getset[] = {
static PyMethodDef value_object_methods[] = {
{ "cast", valpy_cast, METH_VARARGS, "Cast the value to the supplied type." },
{ "dereference", valpy_dereference, METH_NOARGS, "Dereferences the value." },
{ "lazy_string", (PyCFunction) valpy_lazy_string, METH_VARARGS | METH_KEYWORDS,
"lazy_string ([encoding] [, length]) -> lazy_string\n\
Return a lazy string representation of the value." },
{ "string", (PyCFunction) valpy_string, METH_VARARGS | METH_KEYWORDS,
"string ([encoding] [, errors] [, length]) -> string\n\
Return Unicode string representation of the value." },

View file

@ -71,6 +71,8 @@ PyObject *gdbpy_history (PyObject *self, PyObject *args);
PyObject *gdbpy_frame_stop_reason_string (PyObject *, PyObject *);
PyObject *gdbpy_selected_frame (PyObject *self, PyObject *args);
PyObject *gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw);
PyObject *gdbpy_create_lazy_string_object (CORE_ADDR address, long length,
const char *encoding, struct type *type);
PyObject *value_to_value_object (struct value *v);
PyObject *type_to_type_object (struct type *);
@ -88,6 +90,7 @@ void gdbpy_initialize_commands (void);
void gdbpy_initialize_types (void);
void gdbpy_initialize_functions (void);
void gdbpy_initialize_objfile (void);
void gdbpy_initialize_lazy_string (void);
struct cleanup *make_cleanup_py_decref (PyObject *py);
@ -117,6 +120,10 @@ 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);
int gdbpy_is_lazy_string (PyObject *result);
gdb_byte *gdbpy_extract_lazy_string (PyObject *string,
struct type **str_type,
long *length, char **encoding);
/* Note that these are declared here, and not in python.h with the
other pretty-printer functions, because they refer to PyObject. */

View file

@ -623,6 +623,7 @@ Enables or disables auto-loading of Python code when an object is opened."),
gdbpy_initialize_functions ();
gdbpy_initialize_types ();
gdbpy_initialize_objfile ();
gdbpy_initialize_lazy_string ();
PyRun_SimpleString ("import gdb");
PyRun_SimpleString ("gdb.pretty_printers = []");

View file

@ -48,7 +48,7 @@ scm_printchar (int c, struct type *type, struct ui_file *stream)
static void
scm_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
unsigned int length, int force_ellipses,
unsigned int length, const char *encoding, int force_ellipses,
const struct value_print_options *options)
{
fprintf_filtered (stream, "\"%s\"", string);

View file

@ -1,3 +1,12 @@
2010-01-13 Phil Muldoon <pmuldoon@redhat.com>
* gdb.python/py-value.exp (test_lazy_strings): Add lazy string test.
* gdb.python/py-prettyprint.py (pp_ls): New printer.
* gdb.python/py-prettyprint.exp (run_lang_tests): Add lazy string
test.
* gdb.python/py-prettyprint.c: Define lazystring test structure.
* gdb.python/py-mi.exp: Add lazy string test.
2010-01-13 Vladimir Prus <vladimir@codesourcery.com>
* lib/mi-support.exp (mi_check_thread_states): Handle

View file

@ -67,6 +67,10 @@ mi_create_varobj_checked string string_1 \
"struct string_repr" \
"create string_1 varobj"
mi_create_varobj_checked lstring estring \
"struct lazystring" \
"create estring varobj"
mi_gdb_test "-data-evaluate-expression \"string_1 = string_2\"" ".*" \
"assign string_1 from string_2"

View file

@ -34,6 +34,10 @@ struct ns {
int length;
};
struct lazystring {
const char *lazy_str;
};
#ifdef __cplusplus
struct S : public s {
int zs;
@ -193,6 +197,7 @@ main ()
/* Clearing by being `static' could invoke an other GDB C++ bug. */
struct nullstr nullstr;
init_ss(&ss, 1, 2);
init_ss(ssa+0, 3, 4);
init_ss(ssa+1, 5, 6);
@ -202,6 +207,9 @@ main ()
ns.null_str = "embedded\0null\0string";
ns.length = 20;
struct lazystring estring;
estring.lazy_str = "embedded x\201\202\203\204" ;
#ifdef __cplusplus
S cps;

View file

@ -102,6 +102,7 @@ proc run_lang_tests {lang} {
gdb_test "print x" " = \"this is x\""
gdb_test "print cstring" " = \"const string\""
gdb_test "print estring" "\"embedded x\\\\201\\\\202\\\\203\\\\204\""
gdb_test "print c" " = container \"container\" with 2 elements = {$nl *.0. = 23,$nl *.1. = 72$nl}"
gdb_test "continue" "Program exited normally\."

View file

@ -112,6 +112,18 @@ class pp_ns:
def display_hint (self):
return 'string'
class pp_ls:
"Print a std::basic_string of some kind"
def __init__(self, val):
self.val = val
def to_string(self):
return self.val['lazy_str'].lazy_string()
def display_hint (self):
return 'string'
class pp_outer:
"Print struct outer"
@ -184,6 +196,9 @@ def register_pretty_printers ():
pretty_printers_dict[re.compile ('^struct ns$')] = pp_ns
pretty_printers_dict[re.compile ('^ns$')] = pp_ns
pretty_printers_dict[re.compile ('^struct lazystring$')] = pp_ls
pretty_printers_dict[re.compile ('^lazystring$')] = pp_ls
pretty_printers_dict[re.compile ('^struct outerstruct$')] = pp_outer
pretty_printers_dict[re.compile ('^outerstruct$')] = pp_outer

View file

@ -53,6 +53,8 @@ main (int argc, char *argv[])
PTR x = &s;
char st[17] = "divide et impera";
char nullst[17] = "divide\0et\0impera";
const char *sptr = "pointer";
const char *embed = "embedded x\201\202\203\204";
int a[3] = {1,2,3};
int *p = a;
int i = 2;

View file

@ -255,6 +255,19 @@ proc test_value_in_inferior {} {
gdb_test "python print repr(nullst)" "u'divide\\\\x00et'"
}
proc test_lazy_strings {} {
global hex
gdb_test "print sptr" "\"pointer\""
gdb_py_test_silent_cmd "python sptr = gdb.history (0)" "Get value from history" 1
gdb_py_test_silent_cmd "python lstr = sptr.lazy_string()" "Aquire lazy string" 1
gdb_test "python print lstr.type" "const char \*." "Test type name equality"
gdb_test "python print sptr.type" "const char \*." "Test type name equality"
}
# A few objfile tests.
proc test_objfiles {} {
gdb_test "python\nok=False\nfor file in gdb.objfiles():\n if 'py-value' in file.filename:\n ok=True\nprint ok\nend" "True"
@ -402,6 +415,7 @@ if ![runto_main] then {
}
test_value_in_inferior
test_lazy_strings
test_value_after_death
# The following test recompiles the binary to test either C or C++

View file

@ -1452,7 +1452,8 @@ val_print_string (struct type *elttype, CORE_ADDR addr, int len,
{
fputs_filtered (" ", stream);
}
LA_PRINT_STRING (stream, elttype, buffer, bytes_read / width, force_ellipsis, options);
LA_PRINT_STRING (stream, elttype, buffer, bytes_read / width,
NULL, force_ellipsis, options);
}
if (errcode != 0)

View file

@ -2453,11 +2453,15 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
struct cleanup *old_chain;
gdb_byte *thevalue = NULL;
struct value_print_options opts;
int len = 0;
struct type *type = NULL;
long len = 0;
char *encoding = NULL;
struct gdbarch *gdbarch = NULL;
if (value == NULL)
return NULL;
gdbarch = get_type_arch (value_type (value));
#if HAVE_PYTHON
{
struct cleanup *back_to = varobj_ensure_python_env (var);
@ -2489,20 +2493,31 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
&replacement);
if (output)
{
PyObject *py_str
= python_string_to_target_python_string (output);
if (py_str)
if (gdbpy_is_lazy_string (output))
{
char *s = PyString_AsString (py_str);
len = PyString_Size (py_str);
thevalue = xmemdup (s, len + 1, len + 1);
Py_DECREF (py_str);
thevalue = gdbpy_extract_lazy_string (output, &type,
&len, &encoding);
string_print = 1;
}
else
{
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);
type = builtin_type (gdbarch)->builtin_char;
Py_DECREF (py_str);
}
}
Py_DECREF (output);
}
if (thevalue && !string_print)
{
do_cleanups (back_to);
xfree (encoding);
return thevalue;
}
if (replacement)
@ -2521,10 +2536,9 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
opts.raw = 1;
if (thevalue)
{
struct gdbarch *gdbarch = get_type_arch (value_type (value));
make_cleanup (xfree, thevalue);
LA_PRINT_STRING (stb, builtin_type (gdbarch)->builtin_char,
thevalue, len, 0, &opts);
make_cleanup (xfree, encoding);
LA_PRINT_STRING (stb, type, thevalue, len, encoding, 0, &opts);
}
else
common_val_print (value, stb, 0, &opts, current_language);