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:
parent
009f105539
commit
be759fcf73
35 changed files with 647 additions and 51 deletions
|
@ -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>
|
2010-01-13 Doug Evans <dje@google.com>
|
||||||
|
|
||||||
* mi/mi-main.c (list_available_thread_groups): Avoid "may be used
|
* mi/mi-main.c (list_available_thread_groups): Avoid "may be used
|
||||||
|
|
|
@ -270,6 +270,7 @@ SUBDIR_PYTHON_OBS = \
|
||||||
py-cmd.o \
|
py-cmd.o \
|
||||||
py-frame.o \
|
py-frame.o \
|
||||||
py-function.o \
|
py-function.o \
|
||||||
|
py-lazy-string.o \
|
||||||
py-objfile.o \
|
py-objfile.o \
|
||||||
py-prettyprint.o \
|
py-prettyprint.o \
|
||||||
py-type.o \
|
py-type.o \
|
||||||
|
@ -280,6 +281,7 @@ SUBDIR_PYTHON_SRCS = \
|
||||||
python/py-cmd.c \
|
python/py-cmd.c \
|
||||||
python/py-frame.c \
|
python/py-frame.c \
|
||||||
python/py-function.c \
|
python/py-function.c \
|
||||||
|
python/py-lazy-string.c \
|
||||||
python/py-objfile.c \
|
python/py-objfile.c \
|
||||||
python/py-prettyprint.c \
|
python/py-prettyprint.c \
|
||||||
python/py-type.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
|
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-function.c
|
||||||
$(POSTCOMPILE)
|
$(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
|
py-objfile.o: $(srcdir)/python/py-objfile.c
|
||||||
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-objfile.c
|
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-objfile.c
|
||||||
$(POSTCOMPILE)
|
$(POSTCOMPILE)
|
||||||
|
|
|
@ -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_printchar (int, struct type *, struct ui_file *);
|
||||||
|
|
||||||
extern void ada_printstr (struct ui_file *, struct type *, const gdb_byte *,
|
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 *);
|
const struct value_print_options *);
|
||||||
|
|
||||||
struct value *ada_convert_actual (struct value *actual,
|
struct value *ada_convert_actual (struct value *actual,
|
||||||
|
|
|
@ -556,7 +556,7 @@ printstr (struct ui_file *stream, struct type *elttype, const gdb_byte *string,
|
||||||
|
|
||||||
void
|
void
|
||||||
ada_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
|
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)
|
const struct value_print_options *options)
|
||||||
{
|
{
|
||||||
printstr (stream, type, string, length, force_ellipses, TYPE_LENGTH (type),
|
printstr (stream, type, string, length, force_ellipses, TYPE_LENGTH (type),
|
||||||
|
|
|
@ -369,7 +369,7 @@ c_printchar (int c, struct type *type, struct ui_file *stream)
|
||||||
|
|
||||||
void
|
void
|
||||||
c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
|
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)
|
const struct value_print_options *options)
|
||||||
{
|
{
|
||||||
enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
|
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 obstack wchar_buf, output;
|
||||||
struct cleanup *cleanup;
|
struct cleanup *cleanup;
|
||||||
enum c_string_type str_type;
|
enum c_string_type str_type;
|
||||||
|
const char *type_encoding;
|
||||||
const char *encoding;
|
const char *encoding;
|
||||||
struct wchar_iterator *iter;
|
struct wchar_iterator *iter;
|
||||||
int finished = 0;
|
int finished = 0;
|
||||||
|
@ -395,7 +396,7 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
|
||||||
width, byte_order) == 0))
|
width, byte_order) == 0))
|
||||||
length--;
|
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)
|
switch (str_type)
|
||||||
{
|
{
|
||||||
case C_STRING:
|
case C_STRING:
|
||||||
|
@ -411,6 +412,8 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
encoding = (user_encoding && *user_encoding) ? user_encoding : type_encoding;
|
||||||
|
|
||||||
if (length == 0)
|
if (length == 0)
|
||||||
{
|
{
|
||||||
fputs_filtered ("\"\"", stream);
|
fputs_filtered ("\"\"", stream);
|
||||||
|
|
|
@ -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,
|
extern void c_printstr (struct ui_file * stream, struct type *elttype,
|
||||||
const gdb_byte *string, unsigned int length,
|
const gdb_byte *string, unsigned int length,
|
||||||
int force_ellipses,
|
const char *user_encoding, int force_ellipses,
|
||||||
const struct value_print_options *options);
|
const struct value_print_options *options);
|
||||||
|
|
||||||
extern void c_language_arch_info (struct gdbarch *gdbarch,
|
extern void c_language_arch_info (struct gdbarch *gdbarch,
|
||||||
|
|
|
@ -198,7 +198,8 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
|
||||||
}
|
}
|
||||||
|
|
||||||
LA_PRINT_STRING (stream, unresolved_elttype,
|
LA_PRINT_STRING (stream, unresolved_elttype,
|
||||||
valaddr + embedded_offset, len, 0, options);
|
valaddr + embedded_offset, len,
|
||||||
|
NULL, 0, options);
|
||||||
i = len;
|
i = len;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -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>
|
2010-01-13 Vladimir Prus <vladimir@codesourcery.com>
|
||||||
|
|
||||||
* gdb.texinfo (GDB/MI Thread Information): New.
|
* gdb.texinfo (GDB/MI Thread Information): New.
|
||||||
|
|
|
@ -19420,6 +19420,7 @@ situation, a Python @code{KeyboardInterrupt} exception is thrown.
|
||||||
* Functions In Python:: Writing new convenience functions.
|
* Functions In Python:: Writing new convenience functions.
|
||||||
* Objfiles In Python:: Object files.
|
* Objfiles In Python:: Object files.
|
||||||
* Frames In Python:: Acessing inferior stack frames from Python.
|
* Frames In Python:: Acessing inferior stack frames from Python.
|
||||||
|
* Lazy Strings In Python:: Python representation of lazy strings.
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
@node Basic Python
|
@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
|
If the optional @var{length} argument is given, the string will be
|
||||||
fetched and converted to the given length.
|
fetched and converted to the given length.
|
||||||
@end defmethod
|
@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
|
@end table
|
||||||
|
|
||||||
@node Types In Python
|
@node Types In Python
|
||||||
|
@ -20631,6 +20656,61 @@ be a string.
|
||||||
@end defmethod
|
@end defmethod
|
||||||
@end table
|
@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
|
@node Interpreters
|
||||||
@chapter Command Interpreters
|
@chapter Command Interpreters
|
||||||
@cindex command interpreters
|
@cindex command interpreters
|
||||||
|
|
|
@ -188,7 +188,7 @@ print_subexp_standard (struct expression *exp, int *pos,
|
||||||
additional parameter to LA_PRINT_STRING. -fnf */
|
additional parameter to LA_PRINT_STRING. -fnf */
|
||||||
get_user_print_options (&opts);
|
get_user_print_options (&opts);
|
||||||
LA_PRINT_STRING (stream, builtin_type (exp->gdbarch)->builtin_char,
|
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;
|
return;
|
||||||
|
|
||||||
|
@ -207,7 +207,7 @@ print_subexp_standard (struct expression *exp, int *pos,
|
||||||
fputs_filtered ("@\"", stream);
|
fputs_filtered ("@\"", stream);
|
||||||
get_user_print_options (&opts);
|
get_user_print_options (&opts);
|
||||||
LA_PRINT_STRING (stream, builtin_type (exp->gdbarch)->builtin_char,
|
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);
|
fputs_filtered ("\"", stream);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -293,7 +293,7 @@ print_subexp_standard (struct expression *exp, int *pos,
|
||||||
struct value_print_options opts;
|
struct value_print_options opts;
|
||||||
get_user_print_options (&opts);
|
get_user_print_options (&opts);
|
||||||
LA_PRINT_STRING (stream, builtin_type (exp->gdbarch)->builtin_char,
|
LA_PRINT_STRING (stream, builtin_type (exp->gdbarch)->builtin_char,
|
||||||
tempstr, nargs - 1, 0, &opts);
|
tempstr, nargs - 1, NULL, 0, &opts);
|
||||||
(*pos) = pc;
|
(*pos) = pc;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -143,7 +143,7 @@ f_printchar (int c, struct type *type, struct ui_file *stream)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
f_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
|
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)
|
const struct value_print_options *options)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
|
@ -259,7 +259,7 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
|
||||||
case TYPE_CODE_STRING:
|
case TYPE_CODE_STRING:
|
||||||
f77_get_dynamic_length_of_aggregate (type);
|
f77_get_dynamic_length_of_aggregate (type);
|
||||||
LA_PRINT_STRING (stream, builtin_type (gdbarch)->builtin_char,
|
LA_PRINT_STRING (stream, builtin_type (gdbarch)->builtin_char,
|
||||||
valaddr, TYPE_LENGTH (type), 0, options);
|
valaddr, TYPE_LENGTH (type), NULL, 0, options);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TYPE_CODE_ARRAY:
|
case TYPE_CODE_ARRAY:
|
||||||
|
|
|
@ -1083,7 +1083,7 @@ unk_lang_printchar (int c, struct type *type, struct ui_file *stream)
|
||||||
static void
|
static void
|
||||||
unk_lang_printstr (struct ui_file *stream, struct type *type,
|
unk_lang_printstr (struct ui_file *stream, struct type *type,
|
||||||
const gdb_byte *string, unsigned int length,
|
const gdb_byte *string, unsigned int length,
|
||||||
int force_ellipses,
|
const char *encoding, int force_ellipses,
|
||||||
const struct value_print_options *options)
|
const struct value_print_options *options)
|
||||||
{
|
{
|
||||||
error (_("internal error - unimplemented function unk_lang_printstr called."));
|
error (_("internal error - unimplemented function unk_lang_printstr called."));
|
||||||
|
|
|
@ -190,7 +190,7 @@ struct language_defn
|
||||||
|
|
||||||
void (*la_printstr) (struct ui_file * stream, struct type *elttype,
|
void (*la_printstr) (struct ui_file * stream, struct type *elttype,
|
||||||
const gdb_byte *string, unsigned int length,
|
const gdb_byte *string, unsigned int length,
|
||||||
int force_ellipses,
|
const char *encoding, int force_ellipses,
|
||||||
const struct value_print_options *);
|
const struct value_print_options *);
|
||||||
|
|
||||||
void (*la_emitchar) (int ch, struct type *chtype,
|
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) \
|
#define LA_PRINT_CHAR(ch, type, stream) \
|
||||||
(current_language->la_printchar(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, \
|
(current_language->la_printstr(stream, elttype, string, length, \
|
||||||
force_ellipses,options))
|
encoding, force_ellipses,options))
|
||||||
#define LA_EMIT_CHAR(ch, type, stream, quoter) \
|
#define LA_EMIT_CHAR(ch, type, stream, quoter) \
|
||||||
(current_language->la_emitchar(ch, type, stream, quoter))
|
(current_language->la_emitchar(ch, type, stream, quoter))
|
||||||
#define LA_GET_STRING(value, buffer, length, chartype, encoding) \
|
#define LA_GET_STRING(value, buffer, length, chartype, encoding) \
|
||||||
|
|
|
@ -104,7 +104,7 @@ m2_printchar (int c, struct type *type, struct ui_file *stream)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
m2_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
|
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)
|
const struct value_print_options *options)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
|
@ -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),
|
LA_PRINT_STRING (stream, TYPE_TARGET_TYPE (type),
|
||||||
valaddr + embedded_offset, len, 0,
|
valaddr + embedded_offset, len, NULL,
|
||||||
options);
|
0, options);
|
||||||
i = len;
|
i = len;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -343,7 +343,7 @@ objc_printchar (int c, struct type *type, struct ui_file *stream)
|
||||||
static void
|
static void
|
||||||
objc_printstr (struct ui_file *stream, struct type *type,
|
objc_printstr (struct ui_file *stream, struct type *type,
|
||||||
const gdb_byte *string, unsigned int length,
|
const gdb_byte *string, unsigned int length,
|
||||||
int force_ellipses,
|
const char *encoding, int force_ellipses,
|
||||||
const struct value_print_options *options)
|
const struct value_print_options *options)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
|
@ -214,7 +214,7 @@ pascal_printchar (int c, struct type *type, struct ui_file *stream)
|
||||||
void
|
void
|
||||||
pascal_printstr (struct ui_file *stream, struct type *type,
|
pascal_printstr (struct ui_file *stream, struct type *type,
|
||||||
const gdb_byte *string, unsigned int length,
|
const gdb_byte *string, unsigned int length,
|
||||||
int force_ellipses,
|
const char *encoding, int force_ellipses,
|
||||||
const struct value_print_options *options)
|
const struct value_print_options *options)
|
||||||
{
|
{
|
||||||
enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
|
enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
|
||||||
|
|
|
@ -54,7 +54,7 @@ extern int
|
||||||
extern void pascal_printchar (int, struct type *, struct ui_file *);
|
extern void pascal_printchar (int, struct type *, struct ui_file *);
|
||||||
|
|
||||||
extern void pascal_printstr (struct ui_file *, struct type *, const gdb_byte *,
|
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 *);
|
const struct value_print_options *);
|
||||||
|
|
||||||
extern struct type **const (pascal_builtin_types[]);
|
extern struct type **const (pascal_builtin_types[]);
|
||||||
|
|
|
@ -104,7 +104,7 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr,
|
||||||
}
|
}
|
||||||
|
|
||||||
LA_PRINT_STRING (stream, TYPE_TARGET_TYPE (type),
|
LA_PRINT_STRING (stream, TYPE_TARGET_TYPE (type),
|
||||||
valaddr + embedded_offset, len, 0,
|
valaddr + embedded_offset, len, NULL, 0,
|
||||||
options);
|
options);
|
||||||
i = len;
|
i = len;
|
||||||
}
|
}
|
||||||
|
@ -306,7 +306,9 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr,
|
||||||
&string_pos, &char_type, NULL))
|
&string_pos, &char_type, NULL))
|
||||||
{
|
{
|
||||||
len = extract_unsigned_integer (valaddr + embedded_offset + length_pos, length_size, byte_order);
|
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
|
else
|
||||||
pascal_object_print_value_fields (type, valaddr + embedded_offset, address, stream,
|
pascal_object_print_value_fields (type, valaddr + embedded_offset, address, stream,
|
||||||
|
|
291
gdb/python/py-lazy-string.c
Normal file
291
gdb/python/py-lazy-string.c
Normal 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 */
|
||||||
|
};
|
|
@ -121,6 +121,8 @@ find_pretty_printer (PyObject *value)
|
||||||
|
|
||||||
return function;
|
return function;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Pretty-print a single value, via the printer object PRINTER.
|
/* Pretty-print a single value, via the printer object PRINTER.
|
||||||
If the function returns a string, a PyObject containing the string
|
If the function returns a string, a PyObject containing the string
|
||||||
is returned. Otherwise, if the function returns a value,
|
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);
|
result = PyObject_CallMethodObjArgs (printer, gdbpy_to_string_cst, NULL);
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
if (! gdbpy_is_string (result))
|
if (! gdbpy_is_string (result) && ! gdbpy_is_lazy_string (result))
|
||||||
{
|
{
|
||||||
*out_value = convert_value_from_python (result);
|
*out_value = convert_value_from_python (result);
|
||||||
if (PyErr_Occurred ())
|
if (PyErr_Occurred ())
|
||||||
|
@ -191,21 +193,47 @@ print_string_repr (PyObject *printer, const char *hint,
|
||||||
py_str = pretty_print_one_value (printer, &replacement);
|
py_str = pretty_print_one_value (printer, &replacement);
|
||||||
if (py_str)
|
if (py_str)
|
||||||
{
|
{
|
||||||
PyObject *string = python_string_to_target_python_string (py_str);
|
gdb_byte *output = NULL;
|
||||||
if (string)
|
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);
|
string = python_string_to_target_python_string (py_str);
|
||||||
int len = PyString_Size (string);
|
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
|
else
|
||||||
fputs_filtered (output, stream);
|
fputs_filtered (output, stream);
|
||||||
Py_DECREF (string);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
gdbpy_print_stack ();
|
gdbpy_print_stack ();
|
||||||
|
|
||||||
|
if (string)
|
||||||
|
Py_DECREF (string);
|
||||||
|
else
|
||||||
|
xfree (output);
|
||||||
|
|
||||||
|
xfree (encoding);
|
||||||
Py_DECREF (py_str);
|
Py_DECREF (py_str);
|
||||||
}
|
}
|
||||||
else if (replacement)
|
else if (replacement)
|
||||||
|
@ -422,15 +450,30 @@ print_children (PyObject *printer, const char *hint,
|
||||||
fputs_filtered (" = ", stream);
|
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);
|
gdb_byte *output = NULL;
|
||||||
if (! text)
|
|
||||||
gdbpy_print_stack ();
|
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
|
else
|
||||||
{
|
{
|
||||||
fputs_filtered (text, stream);
|
output = python_string_to_host_string (py_v);
|
||||||
xfree (text);
|
fputs_filtered (output, stream);
|
||||||
|
xfree (output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -220,6 +220,36 @@ valpy_get_type (PyObject *self, void *closure)
|
||||||
return obj->type;
|
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]
|
/* Implementation of gdb.Value.string ([encoding] [, errors]
|
||||||
[, length]) -> string. Return Unicode string with value contents.
|
[, length]) -> string. Return Unicode string with value contents.
|
||||||
If ENCODING is not given, the string is assumed to be encoded in
|
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))
|
else if (PyObject_TypeCheck (obj, &value_object_type))
|
||||||
value = value_copy (((value_object *) obj)->value);
|
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
|
else
|
||||||
PyErr_Format (PyExc_TypeError, _("Could not convert Python object: %s"),
|
PyErr_Format (PyExc_TypeError, _("Could not convert Python object: %s"),
|
||||||
PyString_AsString (PyObject_Str (obj)));
|
PyString_AsString (PyObject_Str (obj)));
|
||||||
|
@ -1001,6 +1038,9 @@ static PyGetSetDef value_object_getset[] = {
|
||||||
static PyMethodDef value_object_methods[] = {
|
static PyMethodDef value_object_methods[] = {
|
||||||
{ "cast", valpy_cast, METH_VARARGS, "Cast the value to the supplied type." },
|
{ "cast", valpy_cast, METH_VARARGS, "Cast the value to the supplied type." },
|
||||||
{ "dereference", valpy_dereference, METH_NOARGS, "Dereferences the value." },
|
{ "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", (PyCFunction) valpy_string, METH_VARARGS | METH_KEYWORDS,
|
||||||
"string ([encoding] [, errors] [, length]) -> string\n\
|
"string ([encoding] [, errors] [, length]) -> string\n\
|
||||||
Return Unicode string representation of the value." },
|
Return Unicode string representation of the value." },
|
||||||
|
|
|
@ -71,6 +71,8 @@ PyObject *gdbpy_history (PyObject *self, PyObject *args);
|
||||||
PyObject *gdbpy_frame_stop_reason_string (PyObject *, PyObject *);
|
PyObject *gdbpy_frame_stop_reason_string (PyObject *, PyObject *);
|
||||||
PyObject *gdbpy_selected_frame (PyObject *self, PyObject *args);
|
PyObject *gdbpy_selected_frame (PyObject *self, PyObject *args);
|
||||||
PyObject *gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw);
|
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 *value_to_value_object (struct value *v);
|
||||||
PyObject *type_to_type_object (struct type *);
|
PyObject *type_to_type_object (struct type *);
|
||||||
|
@ -88,6 +90,7 @@ void gdbpy_initialize_commands (void);
|
||||||
void gdbpy_initialize_types (void);
|
void gdbpy_initialize_types (void);
|
||||||
void gdbpy_initialize_functions (void);
|
void gdbpy_initialize_functions (void);
|
||||||
void gdbpy_initialize_objfile (void);
|
void gdbpy_initialize_objfile (void);
|
||||||
|
void gdbpy_initialize_lazy_string (void);
|
||||||
|
|
||||||
struct cleanup *make_cleanup_py_decref (PyObject *py);
|
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);
|
char *python_string_to_host_string (PyObject *obj);
|
||||||
PyObject *target_string_to_unicode (const gdb_byte *str, int length);
|
PyObject *target_string_to_unicode (const gdb_byte *str, int length);
|
||||||
int gdbpy_is_string (PyObject *obj);
|
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
|
/* Note that these are declared here, and not in python.h with the
|
||||||
other pretty-printer functions, because they refer to PyObject. */
|
other pretty-printer functions, because they refer to PyObject. */
|
||||||
|
|
|
@ -623,6 +623,7 @@ Enables or disables auto-loading of Python code when an object is opened."),
|
||||||
gdbpy_initialize_functions ();
|
gdbpy_initialize_functions ();
|
||||||
gdbpy_initialize_types ();
|
gdbpy_initialize_types ();
|
||||||
gdbpy_initialize_objfile ();
|
gdbpy_initialize_objfile ();
|
||||||
|
gdbpy_initialize_lazy_string ();
|
||||||
|
|
||||||
PyRun_SimpleString ("import gdb");
|
PyRun_SimpleString ("import gdb");
|
||||||
PyRun_SimpleString ("gdb.pretty_printers = []");
|
PyRun_SimpleString ("gdb.pretty_printers = []");
|
||||||
|
|
|
@ -48,7 +48,7 @@ scm_printchar (int c, struct type *type, struct ui_file *stream)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
scm_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
|
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)
|
const struct value_print_options *options)
|
||||||
{
|
{
|
||||||
fprintf_filtered (stream, "\"%s\"", string);
|
fprintf_filtered (stream, "\"%s\"", string);
|
||||||
|
|
|
@ -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>
|
2010-01-13 Vladimir Prus <vladimir@codesourcery.com>
|
||||||
|
|
||||||
* lib/mi-support.exp (mi_check_thread_states): Handle
|
* lib/mi-support.exp (mi_check_thread_states): Handle
|
||||||
|
|
|
@ -67,6 +67,10 @@ mi_create_varobj_checked string string_1 \
|
||||||
"struct string_repr" \
|
"struct string_repr" \
|
||||||
"create string_1 varobj"
|
"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\"" ".*" \
|
mi_gdb_test "-data-evaluate-expression \"string_1 = string_2\"" ".*" \
|
||||||
"assign string_1 from string_2"
|
"assign string_1 from string_2"
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,10 @@ struct ns {
|
||||||
int length;
|
int length;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct lazystring {
|
||||||
|
const char *lazy_str;
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
struct S : public s {
|
struct S : public s {
|
||||||
int zs;
|
int zs;
|
||||||
|
@ -193,6 +197,7 @@ main ()
|
||||||
/* Clearing by being `static' could invoke an other GDB C++ bug. */
|
/* Clearing by being `static' could invoke an other GDB C++ bug. */
|
||||||
struct nullstr nullstr;
|
struct nullstr nullstr;
|
||||||
|
|
||||||
|
|
||||||
init_ss(&ss, 1, 2);
|
init_ss(&ss, 1, 2);
|
||||||
init_ss(ssa+0, 3, 4);
|
init_ss(ssa+0, 3, 4);
|
||||||
init_ss(ssa+1, 5, 6);
|
init_ss(ssa+1, 5, 6);
|
||||||
|
@ -202,6 +207,9 @@ main ()
|
||||||
ns.null_str = "embedded\0null\0string";
|
ns.null_str = "embedded\0null\0string";
|
||||||
ns.length = 20;
|
ns.length = 20;
|
||||||
|
|
||||||
|
struct lazystring estring;
|
||||||
|
estring.lazy_str = "embedded x\201\202\203\204" ;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
S cps;
|
S cps;
|
||||||
|
|
||||||
|
|
|
@ -102,6 +102,7 @@ proc run_lang_tests {lang} {
|
||||||
gdb_test "print x" " = \"this is x\""
|
gdb_test "print x" " = \"this is x\""
|
||||||
gdb_test "print cstring" " = \"const string\""
|
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 "print c" " = container \"container\" with 2 elements = {$nl *.0. = 23,$nl *.1. = 72$nl}"
|
||||||
|
|
||||||
gdb_test "continue" "Program exited normally\."
|
gdb_test "continue" "Program exited normally\."
|
||||||
|
|
|
@ -112,6 +112,18 @@ class pp_ns:
|
||||||
def display_hint (self):
|
def display_hint (self):
|
||||||
return 'string'
|
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:
|
class pp_outer:
|
||||||
"Print struct 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 ('^struct ns$')] = pp_ns
|
||||||
pretty_printers_dict[re.compile ('^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 ('^struct outerstruct$')] = pp_outer
|
||||||
pretty_printers_dict[re.compile ('^outerstruct$')] = pp_outer
|
pretty_printers_dict[re.compile ('^outerstruct$')] = pp_outer
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,8 @@ main (int argc, char *argv[])
|
||||||
PTR x = &s;
|
PTR x = &s;
|
||||||
char st[17] = "divide et impera";
|
char st[17] = "divide et impera";
|
||||||
char nullst[17] = "divide\0et\0impera";
|
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 a[3] = {1,2,3};
|
||||||
int *p = a;
|
int *p = a;
|
||||||
int i = 2;
|
int i = 2;
|
||||||
|
|
|
@ -255,6 +255,19 @@ proc test_value_in_inferior {} {
|
||||||
gdb_test "python print repr(nullst)" "u'divide\\\\x00et'"
|
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.
|
# A few objfile tests.
|
||||||
proc test_objfiles {} {
|
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"
|
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_value_in_inferior
|
||||||
|
test_lazy_strings
|
||||||
test_value_after_death
|
test_value_after_death
|
||||||
|
|
||||||
# The following test recompiles the binary to test either C or C++
|
# The following test recompiles the binary to test either C or C++
|
||||||
|
|
|
@ -1452,7 +1452,8 @@ val_print_string (struct type *elttype, CORE_ADDR addr, int len,
|
||||||
{
|
{
|
||||||
fputs_filtered (" ", stream);
|
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)
|
if (errcode != 0)
|
||||||
|
|
36
gdb/varobj.c
36
gdb/varobj.c
|
@ -2453,11 +2453,15 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
|
||||||
struct cleanup *old_chain;
|
struct cleanup *old_chain;
|
||||||
gdb_byte *thevalue = NULL;
|
gdb_byte *thevalue = NULL;
|
||||||
struct value_print_options opts;
|
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)
|
if (value == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
gdbarch = get_type_arch (value_type (value));
|
||||||
#if HAVE_PYTHON
|
#if HAVE_PYTHON
|
||||||
{
|
{
|
||||||
struct cleanup *back_to = varobj_ensure_python_env (var);
|
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);
|
&replacement);
|
||||||
if (output)
|
if (output)
|
||||||
{
|
{
|
||||||
PyObject *py_str
|
if (gdbpy_is_lazy_string (output))
|
||||||
= python_string_to_target_python_string (output);
|
|
||||||
if (py_str)
|
|
||||||
{
|
{
|
||||||
char *s = PyString_AsString (py_str);
|
thevalue = gdbpy_extract_lazy_string (output, &type,
|
||||||
len = PyString_Size (py_str);
|
&len, &encoding);
|
||||||
thevalue = xmemdup (s, len + 1, len + 1);
|
string_print = 1;
|
||||||
Py_DECREF (py_str);
|
}
|
||||||
|
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);
|
Py_DECREF (output);
|
||||||
}
|
}
|
||||||
if (thevalue && !string_print)
|
if (thevalue && !string_print)
|
||||||
{
|
{
|
||||||
do_cleanups (back_to);
|
do_cleanups (back_to);
|
||||||
|
xfree (encoding);
|
||||||
return thevalue;
|
return thevalue;
|
||||||
}
|
}
|
||||||
if (replacement)
|
if (replacement)
|
||||||
|
@ -2521,10 +2536,9 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
|
||||||
opts.raw = 1;
|
opts.raw = 1;
|
||||||
if (thevalue)
|
if (thevalue)
|
||||||
{
|
{
|
||||||
struct gdbarch *gdbarch = get_type_arch (value_type (value));
|
|
||||||
make_cleanup (xfree, thevalue);
|
make_cleanup (xfree, thevalue);
|
||||||
LA_PRINT_STRING (stb, builtin_type (gdbarch)->builtin_char,
|
make_cleanup (xfree, encoding);
|
||||||
thevalue, len, 0, &opts);
|
LA_PRINT_STRING (stb, type, thevalue, len, encoding, 0, &opts);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
common_val_print (value, stb, 0, &opts, current_language);
|
common_val_print (value, stb, 0, &opts, current_language);
|
||||||
|
|
Loading…
Reference in a new issue