2010-01-13 Phil Muldoon <pmuldoon@redhat.com>
authorPhil Muldoon <pmuldoon@redhat.com>
Thu, 14 Jan 2010 08:03:37 +0000 (08:03 +0000)
committerPhil Muldoon <pmuldoon@redhat.com>
Thu, 14 Jan 2010 08:03:37 +0000 (08:03 +0000)
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.

35 files changed:
gdb/ChangeLog
gdb/Makefile.in
gdb/ada-lang.h
gdb/ada-valprint.c
gdb/c-lang.c
gdb/c-lang.h
gdb/c-valprint.c
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/expprint.c
gdb/f-lang.c
gdb/f-valprint.c
gdb/language.c
gdb/language.h
gdb/m2-lang.c
gdb/m2-valprint.c
gdb/objc-lang.c
gdb/p-lang.c
gdb/p-lang.h
gdb/p-valprint.c
gdb/python/py-lazy-string.c [new file with mode: 0644]
gdb/python/py-prettyprint.c
gdb/python/py-value.c
gdb/python/python-internal.h
gdb/python/python.c
gdb/scm-lang.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.python/py-mi.exp
gdb/testsuite/gdb.python/py-prettyprint.c
gdb/testsuite/gdb.python/py-prettyprint.exp
gdb/testsuite/gdb.python/py-prettyprint.py
gdb/testsuite/gdb.python/py-value.c
gdb/testsuite/gdb.python/py-value.exp
gdb/valprint.c
gdb/varobj.c

index ba57323f93abab7b1365885291df96be9ba10244..becaa547b177851154f7cb003e881fa2ca9adad0 100644 (file)
@@ -1,3 +1,50 @@
+2010-01-13  Phil Muldoon  <pmuldoon@redhat.com>
+
+       PR python/10705
+
+       * python/python-internal.h: Add lazy_string_object_type
+       definition.
+       (create_lazy_string_object, gdbpy_initialize_lazy_string)
+       (gdbpy_is_lazystring, gdbpy_extract_lazy_string): Define.
+       * python/py-value.c (valpy_lazy_string): New function.
+       (convert_value_from_python): Add lazy string conversion.
+       * python/py-prettyprint.c (pretty_print_one_value): Check if
+       return is also a lazy string.
+       (print_string_repr): Add lazy string printing branch.
+       (print_children): Likewise.
+       * python/py-lazy-string.c: New file. Implement lazy strings.
+       * python/python.c (_initialize_python): Call
+       gdbpy_initialize_lazy_string.
+       * varobj.c (value_get_print_value): Add lazy string printing
+       branch.  Account for encoding.
+       * c-lang.c (c_printstr): Account for new encoding argument.  If
+       encoding is NULL, find encoding suited for type, otherwise use
+       user encoding.
+       * language.h (language_defn): Add encoding argument.
+       (LA_PRINT_STRING): Likewise.
+       * language.c (unk_lang_printstr): Update to reflect new encoding
+       argument to language_defn.
+       * ada-lang.h (ada_printstr): Likewise.
+       * c-lang.h (c_printstr): Likewise.
+       * p-lang.h (pascal_printstr);
+       * f-lang.c (f_printstr): Likewise.
+       * m2-lang.c (m2_printstr): Likewise.
+       * objc-lang.c (objc_printstr): Likewise.
+       * p-lang.c (pascal_printstr): Likewise.
+       * scm-lang.c (scm_printstr): Likewise.
+       * c-valprint.c (c_val_print): Update LA_PRINT_STRING call for
+       encoding argument.
+       * ada-valprint.c (ada_printstr): Likewise.
+       * f-valprint.c (f_val_print): Likewise
+       * m2-valprint.c (m2_val_print): Likewise.
+       * p-valprint.c (pascal_val_print): Likewise.
+       * expprint.c (print_subexp_standard): Likewise.
+       * valprint.c (val_print_string): Likewise.
+       * Makefile.in (SUBDIR_PYTHON_OBS): Add py-lazy-string.
+       (SUBDIR_PYTHON_SRCS): Likewise.
+       (py-lazy-string.o): New rule.
+
+
 2010-01-13  Doug Evans  <dje@google.com>
 
        * mi/mi-main.c (list_available_thread_groups): Avoid "may be used
index 31a0f76f7386c54b2ba826d4675774642b8fa35f..ff8b86e430cf3f318e93420b3fb0e4137553fdcb 100644 (file)
@@ -270,6 +270,7 @@ SUBDIR_PYTHON_OBS = \
        py-cmd.o \
        py-frame.o \
        py-function.o \
+       py-lazy-string.o \
        py-objfile.o \
        py-prettyprint.o \
        py-type.o \
@@ -280,6 +281,7 @@ SUBDIR_PYTHON_SRCS = \
        python/py-cmd.c \
        python/py-frame.c \
        python/py-function.c \
+       python/py-lazy-string.c \
        python/py-objfile.c \
        python/py-prettyprint.c \
        python/py-type.c \
@@ -1980,6 +1982,10 @@ py-function.o: $(srcdir)/python/py-function.c
        $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-function.c
        $(POSTCOMPILE)
 
+py-lazy-string.o: $(srcdir)/python/py-lazy-string.c
+       $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-lazy-string.c
+       $(POSTCOMPILE)
+
 py-objfile.o: $(srcdir)/python/py-objfile.c
        $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-objfile.c
        $(POSTCOMPILE)
index 5568ed0da77aa523caf0630a5b82976cb3a249fd..552f13cc0d18fece6baba2e17b1df3c2a116e846 100644 (file)
@@ -174,7 +174,7 @@ extern void ada_emit_char (int, struct type *, struct ui_file *, int, int);
 extern void ada_printchar (int, struct type *, struct ui_file *);
 
 extern void ada_printstr (struct ui_file *, struct type *, const gdb_byte *,
-                         unsigned int, int,
+                         unsigned int, const char *, int,
                          const struct value_print_options *);
 
 struct value *ada_convert_actual (struct value *actual,
index 6e112d6cb20b6fa6c7d994fe3b2fd00f74e61e70..55901008475eacf668d99fb83fbf9c6d89dcc7b0 100644 (file)
@@ -556,7 +556,7 @@ printstr (struct ui_file *stream, struct type *elttype, const gdb_byte *string,
 
 void
 ada_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
-             unsigned int length, int force_ellipses,
+             unsigned int length, const char *encoding, int force_ellipses,
              const struct value_print_options *options)
 {
   printstr (stream, type, string, length, force_ellipses, TYPE_LENGTH (type),
index 66a9901362bde61d8d68027fd1c4e82bf0b6adc7..d620881b0d832e17d46773e8f2d379744cb8e006 100644 (file)
@@ -369,7 +369,7 @@ c_printchar (int c, struct type *type, struct ui_file *stream)
 
 void
 c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
-           unsigned int length, int force_ellipses,
+           unsigned int length, const char *user_encoding, int force_ellipses,
            const struct value_print_options *options)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
@@ -381,6 +381,7 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
   struct obstack wchar_buf, output;
   struct cleanup *cleanup;
   enum c_string_type str_type;
+  const char *type_encoding;
   const char *encoding;
   struct wchar_iterator *iter;
   int finished = 0;
@@ -395,7 +396,7 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
                                    width, byte_order) == 0))
     length--;
 
-  str_type = classify_type (type, byte_order, &encoding) & ~C_CHAR;
+  str_type = classify_type (type, byte_order, &type_encoding) & ~C_CHAR;
   switch (str_type)
     {
     case C_STRING:
@@ -411,6 +412,8 @@ c_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
       break;
     }
 
+  encoding = (user_encoding && *user_encoding) ? user_encoding : type_encoding;
+
   if (length == 0)
     {
       fputs_filtered ("\"\"", stream);
index c2c525279d22877096ff486428f4dbaaa89fdc46..d567e81d76cfffb212538c2744c0d1c8d7c5347e 100644 (file)
@@ -81,7 +81,7 @@ extern void c_printchar (int, struct type *, struct ui_file *);
 
 extern void c_printstr (struct ui_file * stream, struct type *elttype,
                        const gdb_byte *string, unsigned int length,
-                       int force_ellipses,
+                       const char *user_encoding, int force_ellipses,
                        const struct value_print_options *options);
 
 extern void c_language_arch_info (struct gdbarch *gdbarch,
index b32f5a6a4d9a6c40adb1d992a297586e3eaff515..00c3c9ae1c22af5710291244f4de6985d497f97e 100644 (file)
@@ -198,7 +198,8 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
                }
 
              LA_PRINT_STRING (stream, unresolved_elttype,
-                              valaddr + embedded_offset, len, 0, options);
+                              valaddr + embedded_offset, len,
+                              NULL, 0, options);
              i = len;
            }
          else
index ae9ce2a27390fd3878fb9a066af05df841693ea8..8b5d162f50ad11e80301f88a02683bc7cdb890b0 100644 (file)
@@ -1,3 +1,10 @@
+2010-01-13  Phil Muldoon  <pmuldoon@redhat.com>
+
+       * gdb.texinfo (Values From Inferior): Document lazy_string value
+       method.
+       (Python API): Add Lazy strings menu item.
+       (Lazy Strings In Python): New node.
+
 2010-01-13  Vladimir Prus  <vladimir@codesourcery.com>
 
        * gdb.texinfo (GDB/MI Thread Information): New.
index 02e2bbd942dc6b40a7880ea347b5d948f7b7aaab..253e251914d30a1b03d078b0ead4b029fd8adac5 100644 (file)
@@ -19420,6 +19420,7 @@ situation, a Python @code{KeyboardInterrupt} exception is thrown.
 * Functions In Python::         Writing new convenience functions.
 * Objfiles In Python::          Object files.
 * Frames In Python::            Acessing inferior stack frames from Python.
+* Lazy Strings In Python::      Python representation of lazy strings.
 @end menu
 
 @node Basic Python
@@ -19694,6 +19695,30 @@ argument to Python's @code{string.decode} method.
 If the optional @var{length} argument is given, the string will be
 fetched and converted to the given length.
 @end defmethod
+
+@defmethod Value lazy_string @r{[}encoding@r{]} @r{[}length@r{]}
+If this @code{gdb.Value} represents a string, then this method
+converts the contents to a @code{gdb.LazyString} (@pxref{Lazy Strings
+In Python}).  Otherwise, this method will throw an exception.
+
+If the optional @var{encoding} argument is given, it must be a string
+naming the encoding of the @code{gdb.LazyString}.  Some examples are:
+@samp{ascii}, @samp{iso-8859-6} or @samp{utf-8}.  If the
+@var{encoding} argument is an encoding that @value{GDBN} does
+recognize, @value{GDBN} will raise an error.
+
+When a lazy string is printed, the @value{GDBN} encoding machinery is
+used to convert the string during printing.  If the optional
+@var{encoding} argument is not provided, or is an empty string,
+@value{GDBN} will automatically select the encoding most suitable for
+the string type.  For further information on encoding in @value{GDBN}
+please see @ref{Character Sets}.
+
+If the optional @var{length} argument is given, the string will be
+fetched and encoded to the length of characters specified.  If
+the @var{length} argument is not provided, the string will be fetched
+and encoded until a null of appropriate width is found.
+@end defmethod
 @end table
 
 @node Types In Python
@@ -20631,6 +20656,61 @@ be a string.
 @end defmethod
 @end table
 
+@node Lazy Strings In Python
+@subsubsection Python representation of lazy strings.
+
+@cindex lazy strings in python
+@tindex gdb.LazyString
+
+A @dfn{lazy string} is a string whose contents is not retrieved or
+encoded until it is needed.
+
+A @code{gdb.LazyString} is represented in @value{GDBN} as an
+@code{address} that points to a region of memory, an @code{encoding}
+that will be used to encode that region of memory, and a @code{length}
+to delimit the region of memory that represents the string.  The
+difference between a @code{gdb.LazyString} and a string wrapped within
+a @code{gdb.Value} is that a @code{gdb.LazyString} will be treated
+differently by @value{GDBN} when printing.  A @code{gdb.LazyString} is
+retrieved and encoded during printing, while a @code{gdb.Value}
+wrapping a string is immediately retrieved and encoded on creation.
+
+A @code{gdb.LazyString} object has the following functions:
+
+@defmethod LazyString value
+Convert the @code{gdb.LazyString} to a @code{gdb.Value}.  This value
+will point to the string in memory, but will lose all the delayed
+retrieval, encoding and handling that @value{GDBN} applies to a
+@code{gdb.LazyString}.
+@end defmethod
+
+@defivar LazyString address
+This attribute holds the address of the string.  This attribute is not
+writable.
+@end defivar
+
+@defivar LazyString length
+This attribute holds the length of the string in characters.  If the
+length is -1, then the string will be fetched and encoded up to the
+first null of appropriate width.  This attribute is not writable.
+@end defivar
+
+@defivar LazyString encoding
+This attribute holds the encoding that will be applied to the string
+when the string is printed by @value{GDBN}.  If the encoding is not
+set, or contains an empty string,  then @value{GDBN} will select the
+most appropriate encoding when the string is printed.  This attribute
+is not writable.
+@end defivar
+
+@defivar LazyString type
+This attribute holds the type that is represented by the lazy string's
+type.  For a lazy string this will always be a pointer type.  To
+resolve this to the lazy string's character type, use the type's
+@code{target} method.  @xref{Types In Python}.  This attribute is not
+writable.
+@end defivar
+
 @node Interpreters
 @chapter Command Interpreters
 @cindex command interpreters
index 98df0708c347451d7d19b7de782cdc4a1ffdb2d5..8c72fc3afdf0e32e2c268e148ad50fa6a0c18885 100644 (file)
@@ -188,7 +188,7 @@ print_subexp_standard (struct expression *exp, int *pos,
           additional parameter to LA_PRINT_STRING.  -fnf */
        get_user_print_options (&opts);
        LA_PRINT_STRING (stream, builtin_type (exp->gdbarch)->builtin_char,
-                        &exp->elts[pc + 2].string, nargs, 0, &opts);
+                        &exp->elts[pc + 2].string, nargs, NULL, 0, &opts);
       }
       return;
 
@@ -207,7 +207,7 @@ print_subexp_standard (struct expression *exp, int *pos,
        fputs_filtered ("@\"", stream);
        get_user_print_options (&opts);
        LA_PRINT_STRING (stream, builtin_type (exp->gdbarch)->builtin_char,
-                        &exp->elts[pc + 2].string, nargs, 0, &opts);
+                        &exp->elts[pc + 2].string, nargs, NULL, 0, &opts);
        fputs_filtered ("\"", stream);
       }
       return;
@@ -293,7 +293,7 @@ print_subexp_standard (struct expression *exp, int *pos,
          struct value_print_options opts;
          get_user_print_options (&opts);
          LA_PRINT_STRING (stream, builtin_type (exp->gdbarch)->builtin_char,
-                          tempstr, nargs - 1, 0, &opts);
+                          tempstr, nargs - 1, NULL, 0, &opts);
          (*pos) = pc;
        }
       else
index 7a992ad8f1992a3618ea28d26728270ff0b25fe6..b914b491529b21f57c9581d2ff0ef5b519dd9614 100644 (file)
@@ -143,7 +143,7 @@ f_printchar (int c, struct type *type, struct ui_file *stream)
 
 static void
 f_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
-           unsigned int length, int force_ellipses,
+           unsigned int length, const char *encoding, int force_ellipses,
            const struct value_print_options *options)
 {
   unsigned int i;
index de086f88a9bd74f74420b6ff799ed8f37c7563a7..9bd3640b5c724e65004394612ad7bc830413b0f7 100644 (file)
@@ -259,7 +259,7 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
     case TYPE_CODE_STRING:
       f77_get_dynamic_length_of_aggregate (type);
       LA_PRINT_STRING (stream, builtin_type (gdbarch)->builtin_char,
-                      valaddr, TYPE_LENGTH (type), 0, options);
+                      valaddr, TYPE_LENGTH (type), NULL, 0, options);
       break;
 
     case TYPE_CODE_ARRAY:
index 3500a97b7a3062aff1e9b3e8cae8a1e7534c9389..dcd70b09147c10a5959a06ec9d28e10383d93eb4 100644 (file)
@@ -1083,7 +1083,7 @@ unk_lang_printchar (int c, struct type *type, struct ui_file *stream)
 static void
 unk_lang_printstr (struct ui_file *stream, struct type *type,
                   const gdb_byte *string, unsigned int length,
-                  int force_ellipses,
+                  const char *encoding, int force_ellipses,
                   const struct value_print_options *options)
 {
   error (_("internal error - unimplemented function unk_lang_printstr called."));
index 7772412f050430c51a842a338eef245568bfae0c..aaefb036383a059b294eed6bca4712ddd2e50946 100644 (file)
@@ -190,7 +190,7 @@ struct language_defn
 
     void (*la_printstr) (struct ui_file * stream, struct type *elttype,
                         const gdb_byte *string, unsigned int length,
-                        int force_ellipses,
+                        const char *encoding, int force_ellipses,
                         const struct value_print_options *);
 
     void (*la_emitchar) (int ch, struct type *chtype,
@@ -389,9 +389,9 @@ extern enum language set_language (enum language);
 
 #define LA_PRINT_CHAR(ch, type, stream) \
   (current_language->la_printchar(ch, type, stream))
-#define LA_PRINT_STRING(stream, elttype, string, length, force_ellipses,options) \
+#define LA_PRINT_STRING(stream, elttype, string, length, encoding, force_ellipses,options) \
   (current_language->la_printstr(stream, elttype, string, length, \
-                                force_ellipses,options))
+                                encoding, force_ellipses,options))
 #define LA_EMIT_CHAR(ch, type, stream, quoter) \
   (current_language->la_emitchar(ch, type, stream, quoter))
 #define LA_GET_STRING(value, buffer, length, chartype, encoding) \
index 1f8322e707f0fa2aea9504b8f52ca19db9ec32d5..80e9bf90d1fa3aab29ed009cc7e3c863cd92fe3f 100644 (file)
@@ -104,7 +104,7 @@ m2_printchar (int c, struct type *type, struct ui_file *stream)
 
 static void
 m2_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
-            unsigned int length, int force_ellipses,
+            unsigned int length, const char *encoding, int force_ellipses,
             const struct value_print_options *options)
 {
   unsigned int i;
index a1c6899365508cc4379551969c6e0afbf3297f20..8db3b75f389cc384e752168d0ffc12062ce0e729 100644 (file)
@@ -360,8 +360,8 @@ m2_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
                }
 
              LA_PRINT_STRING (stream, TYPE_TARGET_TYPE (type),
-                              valaddr + embedded_offset, len, 0,
-                              options);
+                              valaddr + embedded_offset, len, NULL,
+                              0, options);
              i = len;
            }
          else
index bbaf75785bd0072dcd319df0b6af9005468a9b31..a050f154ce66c78ceea4d34744475b1d18a12066 100644 (file)
@@ -343,7 +343,7 @@ objc_printchar (int c, struct type *type, struct ui_file *stream)
 static void
 objc_printstr (struct ui_file *stream, struct type *type,
               const gdb_byte *string, unsigned int length,
-              int force_ellipses,
+              const char *encoding, int force_ellipses,
               const struct value_print_options *options)
 {
   unsigned int i;
index 0121190c68d46b94c9db8b2c4adf2477ec444aa3..c768d1bec3dc3ed6ed2cbfbe1499d085f9e8c7db 100644 (file)
@@ -214,7 +214,7 @@ pascal_printchar (int c, struct type *type, struct ui_file *stream)
 void
 pascal_printstr (struct ui_file *stream, struct type *type,
                 const gdb_byte *string, unsigned int length,
-                int force_ellipses,
+                const char *encoding, int force_ellipses,
                 const struct value_print_options *options)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
index 10c45dbeef7770dc38faea71bc3afb5ae0cd06b5..4090caac2d4b7e30ea5c99f6127f281e7b3dda45 100644 (file)
@@ -54,7 +54,7 @@ extern int
 extern void pascal_printchar (int, struct type *, struct ui_file *);
 
 extern void pascal_printstr (struct ui_file *, struct type *, const gdb_byte *,
-                            unsigned int, int,
+                            unsigned int, const char *, int,
                             const struct value_print_options *);
 
 extern struct type **const (pascal_builtin_types[]);
index 3f801a98097236cec986cabffa33eb61267257a1..260b97d09d0bc8d63b42f46fda72e82155d420f2 100644 (file)
@@ -104,7 +104,7 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr,
                }
 
              LA_PRINT_STRING (stream, TYPE_TARGET_TYPE (type),
-                              valaddr + embedded_offset, len, 0,
+                              valaddr + embedded_offset, len, NULL, 0,
                               options);
              i = len;
            }
@@ -306,7 +306,9 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr,
                                      &string_pos, &char_type, NULL))
            {
              len = extract_unsigned_integer (valaddr + embedded_offset + length_pos, length_size, byte_order);
-             LA_PRINT_STRING (stream, char_type, valaddr + embedded_offset + string_pos, len, 0, options);
+             LA_PRINT_STRING (stream, char_type, 
+                              valaddr + embedded_offset + string_pos,
+                              len, NULL, 0, options);
            }
          else
            pascal_object_print_value_fields (type, valaddr + embedded_offset, address, stream,
diff --git a/gdb/python/py-lazy-string.c b/gdb/python/py-lazy-string.c
new file mode 100644 (file)
index 0000000..c845273
--- /dev/null
@@ -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;
+}
+
+\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 */
+};
+
+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 */
+};
index 818cde1f4a2c51c9e4d46ec81dfa7c59be61ccbb..193f97cc114493e730c8e66dd02915d6bf5ede81 100644 (file)
@@ -121,6 +121,8 @@ find_pretty_printer (PyObject *value)
   
   return function;
 }
+
+
 /* Pretty-print a single value, via the printer object PRINTER.
    If the function returns a string, a PyObject containing the string
    is returned.  Otherwise, if the function returns a value,
@@ -138,7 +140,7 @@ pretty_print_one_value (PyObject *printer, struct value **out_value)
       result = PyObject_CallMethodObjArgs (printer, gdbpy_to_string_cst, NULL);
       if (result)
        {
-         if (! gdbpy_is_string (result))
+         if (! gdbpy_is_string (result) && ! gdbpy_is_lazy_string (result))
            {
              *out_value = convert_value_from_python (result);
              if (PyErr_Occurred ())
@@ -191,21 +193,47 @@ print_string_repr (PyObject *printer, const char *hint,
   py_str = pretty_print_one_value (printer, &replacement);
   if (py_str)
     {
-      PyObject *string = python_string_to_target_python_string (py_str);
-      if (string)
+      gdb_byte *output = NULL;
+      long length;
+      struct type *type;
+      char *encoding = NULL;
+      PyObject *string = NULL;
+      int is_lazy;
+      
+      is_lazy = gdbpy_is_lazy_string (py_str);
+      if (is_lazy)
+       output = gdbpy_extract_lazy_string (py_str, &type, &length, &encoding);
+      else
        {
-         gdb_byte *output = PyString_AsString (string);
-         int len = PyString_Size (string);
+         string = python_string_to_target_python_string (py_str);
+         if (string)
+           {
+             output = PyString_AsString (string);
+             length = PyString_Size (string);
+             type = builtin_type (gdbarch)->builtin_char;
+           }
+         else
+           gdbpy_print_stack ();
          
-         if (hint && !strcmp (hint, "string"))
-           LA_PRINT_STRING (stream, builtin_type (gdbarch)->builtin_char,
-                            output, len, 0, options);
+       }
+      
+      if (output)
+       {
+         if (is_lazy || (hint && !strcmp (hint, "string")))
+           LA_PRINT_STRING (stream, type, output, length, encoding,
+                            0, options);
          else
            fputs_filtered (output, stream);
-         Py_DECREF (string);
        }
       else
        gdbpy_print_stack ();
+      
+      if (string)
+       Py_DECREF (string);
+      else
+       xfree (output);
+      
+      xfree (encoding);
       Py_DECREF (py_str);
     }
   else if (replacement)
@@ -422,15 +450,30 @@ print_children (PyObject *printer, const char *hint,
          fputs_filtered (" = ", stream);
        }
 
-      if (gdbpy_is_string (py_v))
+      if (gdbpy_is_lazy_string (py_v) || gdbpy_is_string (py_v))
        {
-         char *text = python_string_to_host_string (py_v);
-         if (! text)
-           gdbpy_print_stack ();
+         gdb_byte *output = NULL;
+
+         if (gdbpy_is_lazy_string (py_v))
+           {
+             struct type *type;
+             long length;
+             char *encoding = NULL;
+
+             output = gdbpy_extract_lazy_string (py_v, &type,
+                                                 &length, &encoding);
+             if (!output)
+               gdbpy_print_stack ();
+             LA_PRINT_STRING (stream, type, output, length, encoding,
+                              0, options);
+             xfree (encoding);
+             xfree (output);
+           }
          else
            {
-             fputs_filtered (text, stream);
-             xfree (text);
+             output = python_string_to_host_string (py_v);
+             fputs_filtered (output, stream);
+             xfree (output);
            }
        }
       else
index af649b0cc52eb733adfa695257e21b59524e057e..a792819d5511d523d0db3ac4722d9d96752a18d9 100644 (file)
@@ -220,6 +220,36 @@ valpy_get_type (PyObject *self, void *closure)
   return obj->type;
 }
 
+/* Implementation of gdb.Value.lazy_string ([encoding] [, length]) ->
+   string.  Return a PyObject representing a lazy_string_object type.
+   A lazy string is a pointer to a string with an optional encoding and
+   length.  If ENCODING is not given, encoding is set to None.  If an
+   ENCODING is provided the encoding parameter is set to ENCODING, but
+   the string is not encoded.  If LENGTH is provided then the length
+   parameter is set to LENGTH, otherwise length will be set to -1 (first
+   null of appropriate with).  */
+static PyObject *
+valpy_lazy_string (PyObject *self, PyObject *args, PyObject *kw)
+{
+  int length = -1;
+  struct value *value = ((value_object *) self)->value;
+  const char *user_encoding = NULL;
+  static char *keywords[] = { "encoding", "length", NULL };
+  PyObject *str_obj;
+
+  if (!PyArg_ParseTupleAndKeywords (args, kw, "|si", keywords,
+                                   &user_encoding, &length))
+    return NULL;
+
+  if (TYPE_CODE (value_type (value)) == TYPE_CODE_PTR)
+    value = value_ind (value);
+
+  str_obj = gdbpy_create_lazy_string_object (value_address (value), length,
+                                            user_encoding, value_type (value));
+
+  return (PyObject *) str_obj;
+}
+
 /* Implementation of gdb.Value.string ([encoding] [, errors]
    [, length]) -> string.  Return Unicode string with value contents.
    If ENCODING is not given, the string is assumed to be encoded in
@@ -939,6 +969,13 @@ convert_value_from_python (PyObject *obj)
        }
       else if (PyObject_TypeCheck (obj, &value_object_type))
        value = value_copy (((value_object *) obj)->value);
+      else if (gdbpy_is_lazy_string (obj))
+       {
+         PyObject *result;
+         PyObject *function = PyString_FromString ("value");
+         result = PyObject_CallMethodObjArgs (obj, function,  NULL);
+         value = value_copy (((value_object *) result)->value);
+       }
       else
        PyErr_Format (PyExc_TypeError, _("Could not convert Python object: %s"),
                      PyString_AsString (PyObject_Str (obj)));
@@ -1001,6 +1038,9 @@ static PyGetSetDef value_object_getset[] = {
 static PyMethodDef value_object_methods[] = {
   { "cast", valpy_cast, METH_VARARGS, "Cast the value to the supplied type." },
   { "dereference", valpy_dereference, METH_NOARGS, "Dereferences the value." },
+  { "lazy_string", (PyCFunction) valpy_lazy_string, METH_VARARGS | METH_KEYWORDS,
+    "lazy_string ([encoding]  [, length]) -> lazy_string\n\
+Return a lazy string representation of the value." },
   { "string", (PyCFunction) valpy_string, METH_VARARGS | METH_KEYWORDS,
     "string ([encoding] [, errors] [, length]) -> string\n\
 Return Unicode string representation of the value." },
index 62ed538367a145c7a3dd00e5f4b019c98df16fce..9196f08e2510ad8f52b634bb1e2364d0e1db6cb0 100644 (file)
@@ -71,6 +71,8 @@ PyObject *gdbpy_history (PyObject *self, PyObject *args);
 PyObject *gdbpy_frame_stop_reason_string (PyObject *, PyObject *);
 PyObject *gdbpy_selected_frame (PyObject *self, PyObject *args);
 PyObject *gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw);
+PyObject *gdbpy_create_lazy_string_object (CORE_ADDR address, long length,
+                                          const char *encoding, struct type *type);
 
 PyObject *value_to_value_object (struct value *v);
 PyObject *type_to_type_object (struct type *);
@@ -88,6 +90,7 @@ void gdbpy_initialize_commands (void);
 void gdbpy_initialize_types (void);
 void gdbpy_initialize_functions (void);
 void gdbpy_initialize_objfile (void);
+void gdbpy_initialize_lazy_string (void);
 
 struct cleanup *make_cleanup_py_decref (PyObject *py);
 
@@ -117,6 +120,10 @@ PyObject *python_string_to_target_python_string (PyObject *obj);
 char *python_string_to_host_string (PyObject *obj);
 PyObject *target_string_to_unicode (const gdb_byte *str, int length);
 int gdbpy_is_string (PyObject *obj);
+int gdbpy_is_lazy_string (PyObject *result);
+gdb_byte *gdbpy_extract_lazy_string (PyObject *string,
+                                    struct type **str_type, 
+                                    long *length, char **encoding);
 
 /* Note that these are declared here, and not in python.h with the
    other pretty-printer functions, because they refer to PyObject.  */
index 2ac9e992d0726eb6edf3711e9d44fb3015389f0a..827372c0cb495d50d75ddd3d5674a3d8b7aa4162 100644 (file)
@@ -623,6 +623,7 @@ Enables or disables auto-loading of Python code when an object is opened."),
   gdbpy_initialize_functions ();
   gdbpy_initialize_types ();
   gdbpy_initialize_objfile ();
+  gdbpy_initialize_lazy_string ();
 
   PyRun_SimpleString ("import gdb");
   PyRun_SimpleString ("gdb.pretty_printers = []");
index 5d2cafe368f1b6618f1f1bc4c363bf0baa9c0c7f..1d05f8a2050d1f042794a56de51138e3f3a63121 100644 (file)
@@ -48,7 +48,7 @@ scm_printchar (int c, struct type *type, struct ui_file *stream)
 
 static void
 scm_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
-             unsigned int length, int force_ellipses,
+             unsigned int length, const char *encoding, int force_ellipses,
              const struct value_print_options *options)
 {
   fprintf_filtered (stream, "\"%s\"", string);
index d40a2ffb78e99c3b6645c444cbf4c9efd6b6a366..0d440c6e249f9bb7de1fce488c1312e7716b136d 100644 (file)
@@ -1,3 +1,12 @@
+2010-01-13  Phil Muldoon  <pmuldoon@redhat.com>
+
+       * gdb.python/py-value.exp (test_lazy_strings): Add lazy string test.
+       * gdb.python/py-prettyprint.py (pp_ls): New printer.
+       * gdb.python/py-prettyprint.exp (run_lang_tests): Add lazy string
+       test.
+       * gdb.python/py-prettyprint.c: Define lazystring test structure.
+       * gdb.python/py-mi.exp: Add lazy string test.
+
 2010-01-13  Vladimir Prus  <vladimir@codesourcery.com>
 
        * lib/mi-support.exp (mi_check_thread_states): Handle
index 8c78429f51729886f517b2bd004106a491b68b14..5f25fe62da14698e73e6e991cb6cb876886e3fb4 100644 (file)
@@ -67,6 +67,10 @@ mi_create_varobj_checked string string_1 \
     "struct string_repr" \
     "create string_1 varobj"
 
+mi_create_varobj_checked lstring estring \
+    "struct lazystring" \
+    "create estring varobj"
+
 mi_gdb_test "-data-evaluate-expression \"string_1 = string_2\"" ".*" \
     "assign string_1 from string_2"
 
index 6547e01850423066d0723298ac1adbcdc537b30a..e1f696ff72343785b4aedba951e9f6ab50a641b0 100644 (file)
@@ -34,6 +34,10 @@ struct ns {
   int length;
 };
 
+struct lazystring {
+  const char *lazy_str;
+};
+
 #ifdef __cplusplus
 struct S : public s {
   int zs;
@@ -193,6 +197,7 @@ main ()
   /* Clearing by being `static' could invoke an other GDB C++ bug.  */
   struct nullstr nullstr;
 
+
   init_ss(&ss, 1, 2);
   init_ss(ssa+0, 3, 4);
   init_ss(ssa+1, 5, 6);
@@ -202,6 +207,9 @@ main ()
   ns.null_str = "embedded\0null\0string";
   ns.length = 20;
 
+  struct lazystring estring;
+  estring.lazy_str = "embedded x\201\202\203\204" ;
+
 #ifdef __cplusplus
   S cps;
 
index dfdee3a75f2841dd2f04dc2434e49c508e17edb9..26268950d4431003b3835fc1af3dc84fc3411641 100644 (file)
@@ -102,6 +102,7 @@ proc run_lang_tests {lang} {
     gdb_test "print x" " = \"this is x\""
     gdb_test "print cstring" " = \"const string\""
 
+    gdb_test "print estring" "\"embedded x\\\\201\\\\202\\\\203\\\\204\""
     gdb_test "print c" " = container \"container\" with 2 elements = {$nl *.0. = 23,$nl *.1. = 72$nl}"
 
     gdb_test "continue" "Program exited normally\."
index 85c50aaae17fec93ca292c59b9ab096ca800fbb9..9a0d1072b2de57c73f923f8cab879398035d4d46 100644 (file)
@@ -112,6 +112,18 @@ class pp_ns:
     def display_hint (self):
         return 'string'
 
+class pp_ls:
+    "Print a std::basic_string of some kind"
+
+    def __init__(self, val):
+        self.val = val
+
+    def to_string(self):
+        return self.val['lazy_str'].lazy_string()
+
+    def display_hint (self):
+        return 'string'
+
 class pp_outer:
     "Print struct outer"
 
@@ -184,6 +196,9 @@ def register_pretty_printers ():
     pretty_printers_dict[re.compile ('^struct ns$')]  = pp_ns
     pretty_printers_dict[re.compile ('^ns$')]  = pp_ns
 
+    pretty_printers_dict[re.compile ('^struct lazystring$')]  = pp_ls
+    pretty_printers_dict[re.compile ('^lazystring$')]  = pp_ls
+
     pretty_printers_dict[re.compile ('^struct outerstruct$')]  = pp_outer
     pretty_printers_dict[re.compile ('^outerstruct$')]  = pp_outer
 
index 6a5aa03608f195493d8c8c1467044cf1d90e0e19..80bc1e974fcfcfbb912bc9959625033291809c85 100644 (file)
@@ -53,6 +53,8 @@ main (int argc, char *argv[])
   PTR x = &s;
   char st[17] = "divide et impera";
   char nullst[17] = "divide\0et\0impera";
+  const char *sptr = "pointer";
+  const char *embed = "embedded x\201\202\203\204";
   int a[3] = {1,2,3};
   int *p = a;
   int i = 2;
index 4e890ec0c6300b4b397038e4644e12f6bffdf82f..aa4e519da8f4e811548acb75f5c279e8d3731ab2 100644 (file)
@@ -255,6 +255,19 @@ proc test_value_in_inferior {} {
   gdb_test "python print repr(nullst)" "u'divide\\\\x00et'"
 }
 
+proc test_lazy_strings {} {
+
+  global hex
+
+  gdb_test "print sptr" "\"pointer\""
+  gdb_py_test_silent_cmd "python sptr = gdb.history (0)" "Get value from history" 1
+
+  gdb_py_test_silent_cmd "python lstr = sptr.lazy_string()" "Aquire lazy string" 1
+  gdb_test "python print lstr.type" "const char \*." "Test type name equality"
+  gdb_test "python print sptr.type" "const char \*." "Test type name equality"
+}
+
+
 # A few objfile tests.
 proc test_objfiles {} {
     gdb_test "python\nok=False\nfor file in gdb.objfiles():\n  if 'py-value' in file.filename:\n    ok=True\nprint ok\nend" "True"
@@ -402,6 +415,7 @@ if ![runto_main] then {
 }
 
 test_value_in_inferior
+test_lazy_strings
 test_value_after_death
 
 # The following test recompiles the binary to test either C or C++
index 9468b2209453d0ee1236bd2cb2ac9c2db805b695..3f21ae4617a3a45d930eed651be4d66ec59b8a36 100644 (file)
@@ -1452,7 +1452,8 @@ val_print_string (struct type *elttype, CORE_ADDR addr, int len,
        {
          fputs_filtered (" ", stream);
        }
-      LA_PRINT_STRING (stream, elttype, buffer, bytes_read / width, force_ellipsis, options);
+      LA_PRINT_STRING (stream, elttype, buffer, bytes_read / width,
+                      NULL, force_ellipsis, options);
     }
 
   if (errcode != 0)
index 31b5680cb1300ca72e9134485670e2ae5f1b11d0..46d6b34f4a9779b443b5442d5f01283791f127d7 100644 (file)
@@ -2453,11 +2453,15 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
   struct cleanup *old_chain;
   gdb_byte *thevalue = NULL;
   struct value_print_options opts;
-  int len = 0;
+  struct type *type = NULL;
+  long len = 0;
+  char *encoding = NULL;
+  struct gdbarch *gdbarch = NULL;
 
   if (value == NULL)
     return NULL;
 
+  gdbarch = get_type_arch (value_type (value));
 #if HAVE_PYTHON
   {
     struct cleanup *back_to = varobj_ensure_python_env (var);
@@ -2489,20 +2493,31 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
                                                  &replacement);
            if (output)
              {
-               PyObject *py_str
-                 = python_string_to_target_python_string (output);
-               if (py_str)
+               if (gdbpy_is_lazy_string (output))
+                 {
+                   thevalue = gdbpy_extract_lazy_string (output, &type,
+                                                         &len, &encoding);
+                   string_print = 1;
+                 }
+               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 +2536,9 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
   opts.raw = 1;
   if (thevalue)
     {
-      struct gdbarch *gdbarch = get_type_arch (value_type (value));
       make_cleanup (xfree, thevalue);
-      LA_PRINT_STRING (stb, builtin_type (gdbarch)->builtin_char,
-                      thevalue, len, 0, &opts);
+      make_cleanup (xfree, encoding);
+      LA_PRINT_STRING (stb, type, thevalue, len, encoding, 0, &opts);
     }
   else
     common_val_print (value, stb, 0, &opts, current_language);