[patch][python] Implement Python lazy strings (PR 10705)

Phil Muldoon
2010-01-08T14:52:39Z

This patch was originally sent to Project Archer. Previous reference
here:

http://sourceware.org/ml/archer/2009-q4/msg00123.html

The changes asked for there have been implemented into the new
generated patch.

This patch implements Python lazy strings, and also alters the Python
pretty-printing process to handle them accordingly. A Python lazy
string, as implemented here is a pointer, an optional encoding and an
optional length. The contents of the lazy string are not retrieved
until printing, and additionally, they are not encoded with Python's
codec machinery. The are encoded with GDB's encoding machinery at
time of printing. This patch allows Paul's example:

print estring
$1 = "embedded x\201\202\203\204

To be processed correctly through the Python pretty-printing code.

This patch is mainly in response to:

http://sourceware.org/bugzilla/show_bug.cgi?id=10705

Though it will not fix pretty-printers attempting to print
uninitialized data in a backtrace. But it should handle that data as
well as GDB's own printing and encoding mechanisms do now.

There is a small patch required to enable lazy strings with the
libstdc++ printers. I'll submit that when this patch is accepted
upstream. But if you want to try them now, you have to remove the
encoding logic in the std::string printer (we let GDB decide the
encoding, it is more accurate). And also return a lazy_string(length
= len) from the printer over a string().

Tested on X86_64 on archer-tromey-python branch with no regressions.

Cheers,

Phil

--

ChangeLog:

2010-01-08 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)
(is_lazystring, 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 (is_lazy_string): New function.
(extract_lazy_string): Likewise.
(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.

gdb/testsuite ChangeLog:

2010-01-08 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.

gdb/doc ChangeLog:

2010-01-08 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.

--

Index: gdb/Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.1107
diff -u -r1.1107 Makefile.in
--- gdb/Makefile.in 1 Jan 2010 07:31:28 -0000 1.1107
+++ gdb/Makefile.in 8 Jan 2010 14:22:11 -0000
@@ -270,6 +270,7 @@
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 @@
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 \
@@ -1979,6 +1981,10 @@
$(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)
Index: gdb/ada-lang.h
===================================================================
RCS file: /cvs/src/src/gdb/ada-lang.h,v
retrieving revision 1.49
diff -u -r1.49 ada-lang.h
--- gdb/ada-lang.h 1 Jan 2010 07:31:29 -0000 1.49
+++ gdb/ada-lang.h 8 Jan 2010 14:22:11 -0000
@@ -174,7 +174,7 @@
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,
Index: gdb/ada-valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/ada-valprint.c,v
retrieving revision 1.56
diff -u -r1.56 ada-valprint.c
--- gdb/ada-valprint.c 1 Jan 2010 07:31:29 -0000 1.56
+++ gdb/ada-valprint.c 8 Jan 2010 14:22:12 -0000
@@ -556,7 +556,7 @@

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),
Index: gdb/c-lang.c
===================================================================
RCS file: /cvs/src/src/gdb/c-lang.c,v
retrieving revision 1.79
diff -u -r1.79 c-lang.c
--- gdb/c-lang.c 1 Jan 2010 07:31:30 -0000 1.79
+++ gdb/c-lang.c 8 Jan 2010 14:22:13 -0000
@@ -369,7 +369,7 @@

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 @@
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 @@
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 @@
break;
}

+ encoding = (user_encoding && *user_encoding) ? user_encoding : type_encoding;
+
if (length == 0)
{
fputs_filtered ("\"\"", stream);
Index: gdb/c-lang.h
===================================================================
RCS file: /cvs/src/src/gdb/c-lang.h,v
retrieving revision 1.25
diff -u -r1.25 c-lang.h
--- gdb/c-lang.h 1 Jan 2010 07:31:30 -0000 1.25
+++ gdb/c-lang.h 8 Jan 2010 14:22:13 -0000
@@ -81,7 +81,7 @@

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,
Index: gdb/c-valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/c-valprint.c,v
retrieving revision 1.64
diff -u -r1.64 c-valprint.c
--- gdb/c-valprint.c 1 Jan 2010 07:31:30 -0000 1.64
+++ gdb/c-valprint.c 8 Jan 2010 14:22:14 -0000
@@ -198,7 +198,8 @@
}

LA_PRINT_STRING (stream, unresolved_elttype,
- valaddr + embedded_offset, len, 0, options);
+ valaddr + embedded_offset, len,
+ NULL, 0, options);
i = len;
}
else
Index: gdb/expprint.c
===================================================================
RCS file: /cvs/src/src/gdb/expprint.c,v
retrieving revision 1.40
diff -u -r1.40 expprint.c
--- gdb/expprint.c 1 Jan 2010 07:31:31 -0000 1.40
+++ gdb/expprint.c 8 Jan 2010 14:22:14 -0000
@@ -188,7 +188,7 @@
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 @@
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 @@
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
Index: gdb/f-lang.c
===================================================================
RCS file: /cvs/src/src/gdb/f-lang.c,v
retrieving revision 1.58
diff -u -r1.58 f-lang.c
--- gdb/f-lang.c 1 Jan 2010 07:31:31 -0000 1.58
+++ gdb/f-lang.c 8 Jan 2010 14:22:14 -0000
@@ -143,7 +143,7 @@

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;
Index: gdb/f-valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/f-valprint.c,v
retrieving revision 1.54
diff -u -r1.54 f-valprint.c
--- gdb/f-valprint.c 1 Jan 2010 07:31:31 -0000 1.54
+++ gdb/f-valprint.c 8 Jan 2010 14:22:15 -0000
@@ -259,7 +259,7 @@
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:
Index: gdb/language.c
===================================================================
RCS file: /cvs/src/src/gdb/language.c,v
retrieving revision 1.93
diff -u -r1.93 language.c
--- gdb/language.c 1 Jan 2010 07:31:36 -0000 1.93
+++ gdb/language.c 8 Jan 2010 14:22:16 -0000
@@ -1083,7 +1083,7 @@
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."));
Index: gdb/language.h
===================================================================
RCS file: /cvs/src/src/gdb/language.h,v
retrieving revision 1.61
diff -u -r1.61 language.h
--- gdb/language.h 1 Jan 2010 07:31:36 -0000 1.61
+++ gdb/language.h 8 Jan 2010 14:22:16 -0000
@@ -190,7 +190,7 @@

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 @@

#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) \
Index: gdb/m2-lang.c
===================================================================
RCS file: /cvs/src/src/gdb/m2-lang.c,v
retrieving revision 1.53
diff -u -r1.53 m2-lang.c
--- gdb/m2-lang.c 1 Jan 2010 07:31:37 -0000 1.53
+++ gdb/m2-lang.c 8 Jan 2010 14:22:17 -0000
@@ -104,7 +104,7 @@

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;
Index: gdb/m2-valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/m2-valprint.c,v
retrieving revision 1.25
diff -u -r1.25 m2-valprint.c
--- gdb/m2-valprint.c 1 Jan 2010 07:31:37 -0000 1.25
+++ gdb/m2-valprint.c 8 Jan 2010 14:22:17 -0000
@@ -360,8 +360,8 @@
}

LA_PRINT_STRING (stream, TYPE_TARGET_TYPE (type),
- valaddr + embedded_offset, len, 0,
- options);
+ valaddr + embedded_offset, len, NULL,
+ 0, options);
i = len;
}
else
Index: gdb/objc-lang.c
===================================================================
RCS file: /cvs/src/src/gdb/objc-lang.c,v
retrieving revision 1.85
diff -u -r1.85 objc-lang.c
--- gdb/objc-lang.c 1 Jan 2010 07:31:38 -0000 1.85
+++ gdb/objc-lang.c 8 Jan 2010 14:22:18 -0000
@@ -343,7 +343,7 @@
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;
Index: gdb/p-lang.c
===================================================================
RCS file: /cvs/src/src/gdb/p-lang.c,v
retrieving revision 1.49
diff -u -r1.49 p-lang.c
--- gdb/p-lang.c 1 Jan 2010 07:31:38 -0000 1.49
+++ gdb/p-lang.c 8 Jan 2010 14:22:18 -0000
@@ -214,7 +214,7 @@
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));
Index: gdb/p-lang.h
===================================================================
RCS file: /cvs/src/src/gdb/p-lang.h,v
retrieving revision 1.20
diff -u -r1.20 p-lang.h
--- gdb/p-lang.h 1 Jan 2010 07:31:38 -0000 1.20
+++ gdb/p-lang.h 8 Jan 2010 14:22:19 -0000
@@ -54,7 +54,7 @@
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[]);
Index: gdb/p-valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/p-valprint.c,v
retrieving revision 1.66
diff -u -r1.66 p-valprint.c
--- gdb/p-valprint.c 1 Jan 2010 07:31:38 -0000 1.66
+++ gdb/p-valprint.c 8 Jan 2010 14:22:20 -0000
@@ -104,7 +104,7 @@
}

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 @@
&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,
Index: gdb/scm-lang.c
===================================================================
RCS file: /cvs/src/src/gdb/scm-lang.c,v
retrieving revision 1.58
diff -u -r1.58 scm-lang.c
--- gdb/scm-lang.c 1 Jan 2010 07:31:41 -0000 1.58
+++ gdb/scm-lang.c 8 Jan 2010 14:22:20 -0000
@@ -48,7 +48,7 @@

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);
Index: gdb/valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/valprint.c,v
retrieving revision 1.88
diff -u -r1.88 valprint.c
--- gdb/valprint.c 1 Jan 2010 07:31:43 -0000 1.88
+++ gdb/valprint.c 8 Jan 2010 14:22:21 -0000
@@ -1451,7 +1451,8 @@
{
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)
Index: gdb/varobj.c
===================================================================
RCS file: /cvs/src/src/gdb/varobj.c,v
retrieving revision 1.152
diff -u -r1.152 varobj.c
--- gdb/varobj.c 1 Jan 2010 07:31:44 -0000 1.152
+++ gdb/varobj.c 8 Jan 2010 14:22:23 -0000
@@ -2453,11 +2453,15 @@
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,28 @@
&replacement);
if (output)
{
- PyObject *py_str
- = python_string_to_target_python_string (output);
- if (py_str)
+ if (is_lazy_string (output))
+ thevalue = extract_lazy_string (output, &type,
+ &len, &encoding);
+ else
{
- char *s = PyString_AsString (py_str);
- len = PyString_Size (py_str);
- thevalue = xmemdup (s, len + 1, len + 1);
- Py_DECREF (py_str);
+ 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 +2533,9 @@
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);
Index: gdb/doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.656
diff -u -r1.656 gdb.texinfo
--- gdb/doc/gdb.texinfo 6 Jan 2010 20:31:28 -0000 1.656
+++ gdb/doc/gdb.texinfo 8 Jan 2010 14:22:47 -0000
@@ -19416,6 +19416,7 @@
* 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
@@ -19690,6 +19691,27 @@
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:
+@code{"ascii"}, @code{"iso-8859-6"} or @code{"utf-8"}.
+
+When a lazy string is printed, the @value{GDBN} codec machinery is
+used to convert the string during printing. If @var{encoding} is
+set to @code{None}, or if @var{encoding} is an empty string,
+@value{GDBN} will automatically select the encoding most suitable for
+the string type.
+
+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
@@ -20627,6 +20649,54 @@
@end defmethod
@end table

+@node Lazy Strings In Python
+@subsubsection Python representation of lazy strings.
+
+@cindex lazy strings in python
+@tindex gdb.LazyString
+A @code{gdb.LazyString} can be defined 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 set
+to @code{None} then @value{GDBN} will select the most appropriate
+encoding when the sting 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. This attribute is not writable.
+@end defivar
+
@node Interpreters
@chapter Command Interpreters
@cindex command interpreters
Index: gdb/python/py-lazy-string.c
===================================================================
RCS file: gdb/python/py-lazy-string.c
diff -N gdb/python/py-lazy-string.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gdb/python/py-lazy-string.c 8 Jan 2010 14:22:48 -0000
@@ -0,0 +1,196 @@
+/* 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"
+
+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 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);
+}
+
+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;
+}
+
+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);
+}
+
+void
+gdbpy_initialize_lazy_string (void)
+{
+ if (PyType_Ready (&lazy_string_object_type) < 0)
+ return;
+
+ Py_INCREF (&lazy_string_object_type);
+}
+
+\f
+
+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 */
+};
+
+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 */
+};
Index: gdb/python/py-prettyprint.c
===================================================================
RCS file: /cvs/src/src/gdb/python/py-prettyprint.c,v
retrieving revision 1.3
diff -u -r1.3 py-prettyprint.c
--- gdb/python/py-prettyprint.c 1 Jan 2010 07:31:50 -0000 1.3
+++ gdb/python/py-prettyprint.c 8 Jan 2010 14:22:48 -0000
@@ -121,6 +121,100 @@

return function;
}
+
+/* Determine whether the printer object pointed to by OBJ is a
+ Python lazy string. */
+int
+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. Additionally, 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 *
+extract_lazy_string (PyObject *string, struct type **str_type,
+ long *length, char **encoding)
+{
+ struct value *output;
+ int width;
+ int bytes_read;
+ gdb_byte *buffer = NULL;
+ int errcode = 0;
+ struct gdbarch *gdbarch;
+ enum bfd_endian byte_order;
+ PyObject *py_len = NULL, *py_encoding = NULL;
+ volatile struct gdb_exception except;
+
+ output = convert_value_from_python (string);
+
+ /* Lazy strings are pointers, so point to the actual string
+ data. */
+ if (TYPE_CODE (value_type (output)) == TYPE_CODE_PTR)
+ output = value_ind (output);
+
+ py_len = PyObject_GetAttrString (string, "length");
+ py_encoding = PyObject_GetAttrString (string, "encoding");
+
+ /* A NULL encoding or length is not ok. */
+ if (!py_len || !py_encoding)
+ goto error;
+
+ *length = PyLong_AsLong (py_len);
+
+ /* 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 = value_type (output);
+ 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 (value_address (output), *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_len);
+ Py_XDECREF (py_encoding);
+
+ return buffer;
+
+ error:
+ Py_XDECREF (py_encoding);
+ Py_XDECREF (py_len);
+ xfree (buffer);
+ *length = 0;
+ *str_type = NULL;
+ return NULL;
+}
+
+
+
/* 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 +232,7 @@
result = PyObject_CallMethodObjArgs (printer, gdbpy_to_string_cst, NULL);
if (result)
{
- if (! gdbpy_is_string (result))
+ if (! gdbpy_is_string (result) && ! is_lazy_string (result))
{
*out_value = convert_value_from_python (result);
if (PyErr_Occurred ())
@@ -191,21 +285,48 @@
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 = 0;
+
+ is_lazy = is_lazy_string (py_str);
+ if (is_lazy)
+ output = extract_lazy_string (py_str, &type, &length,
+ &encoding);
+ else
+ {
+ string = python_string_to_target_python_string (py_str);
+ if (string)
+ {
+ output = PyString_AsString (string);
+ length = PyString_Size (string);
+ type = builtin_type (gdbarch)->builtin_char;
+ }
+ else
+ gdbpy_print_stack ();
+
+ }
+
+ if (output)
{
- gdb_byte *output = PyString_AsString (string);
- int len = PyString_Size (string);
-
- if (hint && !strcmp (hint, "string"))
- LA_PRINT_STRING (stream, builtin_type (gdbarch)->builtin_char,
- output, len, 0, options);
+ 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 +543,28 @@
fputs_filtered (" = ", stream);
}

- if (gdbpy_is_string (py_v))
+ if (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;
+ struct type *type;
+ long length;
+ char *encoding = NULL;
+
+ if (is_lazy_string (py_v))
+ {
+ output = 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
Index: gdb/python/py-value.c
===================================================================
RCS file: /cvs/src/src/gdb/python/py-value.c,v
retrieving revision 1.6
diff -u -r1.6 py-value.c
--- gdb/python/py-value.c 1 Jan 2010 07:31:50 -0000 1.6
+++ gdb/python/py-value.c 8 Jan 2010 14:22:49 -0000
@@ -220,6 +220,33 @@
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;
+
+ 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 +966,13 @@
}
else if (PyObject_TypeCheck (obj, &value_object_type))
value = value_copy (((value_object *) obj)->value);
+ else if (PyObject_TypeCheck (obj, &lazy_string_object_type))
+ {
+ 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 +1035,9 @@
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." },
Index: gdb/python/python-internal.h
===================================================================
RCS file: /cvs/src/src/gdb/python/python-internal.h,v
retrieving revision 1.18
diff -u -r1.18 python-internal.h
--- gdb/python/python-internal.h 1 Jan 2010 07:31:50 -0000 1.18
+++ gdb/python/python-internal.h 8 Jan 2010 14:22:49 -0000
@@ -66,11 +66,14 @@

extern PyObject *gdb_module;
extern PyTypeObject value_object_type;
+extern PyTypeObject lazy_string_object_type;

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 +91,7 @@
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 +121,11 @@
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 is_lazy_string (PyObject *result);
+gdb_byte *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. */
@@ -125,6 +134,7 @@
PyObject *gdbpy_get_varobj_pretty_printer (struct value *value);
char *gdbpy_get_display_hint (PyObject *printer);
PyObject *gdbpy_default_visualizer (PyObject *self, PyObject *args);
+PyObject *execute_pretty_printer (PyObject *printer);

extern PyObject *gdbpy_doc_cst;
extern PyObject *gdbpy_children_cst;
Index: gdb/python/python.c
===================================================================
RCS file: /cvs/src/src/gdb/python/python.c,v
retrieving revision 1.22
diff -u -r1.22 python.c
--- gdb/python/python.c 1 Jan 2010 07:31:50 -0000 1.22
+++ gdb/python/python.c 8 Jan 2010 14:22:49 -0000
@@ -623,6 +623,7 @@
gdbpy_initialize_functions ();
gdbpy_initialize_types ();
gdbpy_initialize_objfile ();
+ gdbpy_initialize_lazy_string ();

PyRun_SimpleString ("import gdb");
PyRun_SimpleString ("gdb.pretty_printers = []");
Index: gdb/testsuite/gdb.python/py-mi.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.python/py-mi.exp,v
retrieving revision 1.4
diff -u -r1.4 py-mi.exp
--- gdb/testsuite/gdb.python/py-mi.exp 1 Jan 2010 07:32:05 -0000 1.4
+++ gdb/testsuite/gdb.python/py-mi.exp 8 Jan 2010 14:22:51 -0000
@@ -67,6 +67,10 @@
"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"

Index: gdb/testsuite/gdb.python/py-prettyprint.c
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.python/py-prettyprint.c,v
retrieving revision 1.3
diff -u -r1.3 py-prettyprint.c
--- gdb/testsuite/gdb.python/py-prettyprint.c 1 Jan 2010 07:32:05 -0000 1.3
+++ gdb/testsuite/gdb.python/py-prettyprint.c 8 Jan 2010 14:22:51 -0000
@@ -34,6 +34,10 @@
int length;
};

+struct lazystring {
+ const char *lazy_str;
+};
+
#ifdef __cplusplus
struct S : public s {
int zs;
@@ -193,6 +197,7 @@
/* 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 @@
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;

Index: gdb/testsuite/gdb.python/py-prettyprint.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.python/py-prettyprint.exp,v
retrieving revision 1.5
diff -u -r1.5 py-prettyprint.exp
--- gdb/testsuite/gdb.python/py-prettyprint.exp 1 Jan 2010 07:32:05 -0000 1.5
+++ gdb/testsuite/gdb.python/py-prettyprint.exp 8 Jan 2010 14:22:51 -0000
@@ -102,6 +102,7 @@
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\."
Index: gdb/testsuite/gdb.python/py-prettyprint.py
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.python/py-prettyprint.py,v
retrieving revision 1.3
diff -u -r1.3 py-prettyprint.py
--- gdb/testsuite/gdb.python/py-prettyprint.py 1 Jan 2010 07:32:05 -0000 1.3
+++ gdb/testsuite/gdb.python/py-prettyprint.py 8 Jan 2010 14:22:51 -0000
@@ -112,6 +112,18 @@
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 @@
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

Index: gdb/testsuite/gdb.python/py-value.c
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.python/py-value.c,v
retrieving revision 1.3
diff -u -r1.3 py-value.c
--- gdb/testsuite/gdb.python/py-value.c 1 Jan 2010 07:32:06 -0000 1.3
+++ gdb/testsuite/gdb.python/py-value.c 8 Jan 2010 14:22:51 -0000
@@ -53,6 +53,8 @@
PTR x = &s;
char st[17] = "divide et impera";
char nullst[17] = "divide\0et\0impera";
+ const char *sptr = "pointer";
+
int a[3] = {1,2,3};
int *p = a;
int i = 2;
Index: gdb/testsuite/gdb.python/py-value.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.python/py-value.exp,v
retrieving revision 1.4
diff -u -r1.4 py-value.exp
--- gdb/testsuite/gdb.python/py-value.exp 1 Jan 2010 07:32:06 -0000 1.4
+++ gdb/testsuite/gdb.python/py-value.exp 8 Jan 2010 14:22:52 -0000
@@ -255,6 +255,22 @@
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 "print /d &sptr" "Get string address" 1
+ gdb_py_test_silent_cmd "python saddr = 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.address == saddr" "True." "Test address equality"
+ gdb_test "python print lstr.type" "const char \*." "Test type name equality"
+ gdb_test "python print sptr.type" "const char \*." "Test type name equality"
+ gdb_test "python print lstr.value()" "\"pointer\"" "Test value fetch"
+}
+
+
# 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 +418,7 @@
}

test_value_in_inferior
+test_lazy_strings
test_value_after_death

# The following test recompiles the binary to test either C or C++