Re: Patch: implement new dynamic varobj spec

Tom Tromey
2009-09-14T21:29:53Z

>>>>> "Eli" == Eli Zaretskii <eliz@gnu.org> writes:

Eli> Then I don't see a need to have the "not limited to" part. When we
Eli> add more attributes, we should add them to the list.

Ok.

Tom> +For a dynamic varobj, this value cannot reliably be used to form an
Eli> Do we want to give the reader some hints as to how to achieve these
Eli> with dynamic varobjs?

>> There is no way to do these.

Eli> I suggest to say so, then.

Done.

Here's a new version with all your comments addressed.

Tom

2009-09-14 Tom Tromey <tromey@redhat.com>

* varobj.h (varobj_update_result_t) <new>: New field.
(varobj_get_child_range, varobj_set_child_range): Declare.
(varobj_list_children): Update.
(varobj_enable_pretty_printing, varobj_has_more)
(varobj_pretty_printed_p): Declare.
* varobj.c (pretty_printing): New global.
(varobj_enable_pretty_printing): New function.
(struct varobj_root) <from, to, constructor, child_iter,
saved_item>: New fields.
(varobj_create): Don't call install_default_visualizer.
(instantiate_pretty_printer): Don't use value_copy.
(varobj_has_more): New function.
(restrict_range): New function.
(install_dynamic_child): Likewise.
(dynamic_varobj_has_child_method): Likewise.
(update_dynamic_varobj_children): Remove 'new_and_unchanged'
argument; add 'new', 'unchanged', 'from', and 'to' arguments.
Rewrite.
(varobj_get_num_children): Call update_dynamic_varobj_children.
(varobj_list_children): Add 'from' and 'to' arguments. Ignore
result of update_dynamic_varobj_children. Don't call
install_default_visualizer. Restrict result range.
(varobj_add_child): Don't call install_default_visualizer.
(varobj_pretty_printed_p): New function.
(install_visualizer): Rewrite. Move earlier in file.
(install_default_visualizer): Likewise.
(construct_visualizer): New function.
(install_new_value_visualizer): Likewise.
(install_new_value): Don't call release_value. Special case
pretty-printed objects. Use value_incref. Rearrange "changed"
logic.
(varobj_get_child_range): New function.
(varobj_set_child_range): Likewise.
(varobj_set_visualizer): Rewrite.
(varobj_update): Rewrite pretty-printing logic.
(new_variable): Initialize new fields.
(free_variable): Destroy new fields.
(value_of_root): Copy 'from' and 'to'.
(my_value_of_variable): Handle pretty-printers.
(value_get_print_value): Rework pretty-printing logic.
(cplus_describe_child): Don't use release_value.
* mi/mi-cmds.h (mi_cmd_enable_pretty_printing)
(mi_cmd_var_set_update_range): Declare.
* mi/mi-cmds.c (mi_cmds): Add enable-pretty-printing and
var-set-update-range.
* mi/mi-cmd-var.c (print_varobj): Update. Emit "dynamic"
attribute.
(mi_cmd_var_create): Emit "has_more" attribute.
(mi_cmd_var_set_format): Plug memory leak.
(mi_print_value_p): Replace 'type' argument with 'var'. Handle
pretty-printed varobjs.
(mi_cmd_var_list_children): Accept 'from' and 'to' arguments.
Emit "has_more" attribute.
(mi_cmd_var_evaluate_expression): Plug memory leak.
(mi_cmd_var_assign): Likewise.
(varobj_update_one): Likewise. Emit "dynamic", "has_more", and
"new_children" attributes.
(mi_cmd_enable_pretty_printing): New function.
(mi_cmd_var_set_update_range): Likewise.

2009-09-14 Tom Tromey <tromey@redhat.com>

* gdb.texinfo (GDB/MI Variable Objects): Document
-enable-pretty-printing, -var-set-update-range, dynamic varobjs.
Expand -var-update documentation.

2009-09-14 Tom Tromey <tromey@redhat.com>

* lib/mi-support.exp (mi_create_varobj): Update.
(mi_create_floating_varobj): Likewise.
(mi_create_dynamic_varobj): New proc.
(mi_varobj_update): Update.
(mi_varobj_update_with_type_change): Likewise.
(mi_varobj_update_kv_helper): New proc.
(mi_varobj_update_dynamic_helper): Rewrite.
(mi_varobj_update_dynamic): New proc.
(mi_list_varobj_children): Update.
(mi_list_varobj_children_range): Add 'from' and 'to' arguments.
* gdb.python/python-prettyprint.py (pp_outer): New class.
(pp_nullstr): Likewise.
(lookup_function): Register new printers.
* gdb.python/python-prettyprint.c (struct substruct): New type.
(struct outerstruct): Likewise.
(substruct_test): New function.
(struct nullstr): New type.
(string_1, string_2): New globals.
(main): Add new tests.
* gdb.python/python-mi.exp: Added regression tests.
* gdb.mi/mi2-var-display.exp: Update.
* gdb.mi/mi2-var-cmd.exp: Update.
* gdb.mi/mi2-var-child.exp: Update.
* gdb.mi/mi2-var-block.exp: Update.
* gdb.mi/mi-var-invalidate.exp: Update.
* gdb.mi/mi-var-display.exp: Update.
* gdb.mi/mi-var-cmd.exp: Update.
* gdb.mi/mi-var-child.exp: Update.
* gdb.mi/mi-var-block.exp: Update.
* gdb.mi/mi-break.exp: Update.
* gdb.mi/gdb701.exp: Update.

diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 7b26675..559f5ed 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -23360,6 +23360,8 @@ access this functionality:
@item @strong{Operation}
@tab @strong{Description}

+@item @code{-enable-pretty-printing}
+@tab enable Python-based pretty-printing
@item @code{-var-create}
@tab create a variable object
@item @code{-var-delete}
@@ -23388,6 +23390,8 @@ access this functionality:
@tab update the variable and its children
@item @code{-var-set-frozen}
@tab set frozeness attribute
+@item @code{-var-set-update-range}
+@tab set range of children to display on update
@end multitable

In the next subsection we describe each operation in detail and suggest
@@ -23395,6 +23399,23 @@ how it can be used.

@subheading Description And Use of Operations on Variable Objects

+@subheading The @code{-enable-pretty-printing} Command
+@findex -enable-pretty-printing
+
+@smallexample
+-enable-pretty-printing
+@end smallexample
+
+@value{GDBN} allows Python-based visualizers to affect the output of the
+MI variable object commands. However, because there was no way to
+implement this in a fully backward-compatible way, a front end must
+request that this functionality be enabled.
+
+Once enabled, this feature cannot be disabled.
+
+Note that if Python support has not been compiled into @value{GDBN},
+this command will still succeed (and do nothing).
+
@subheading The @code{-var-create} Command
@findex -var-create

@@ -23434,15 +23455,56 @@ begin with a @samp{*}), or one of the following:
@samp{$@var{regname}} --- a CPU register name
@end itemize

+@cindex dynamic varobj
+A varobj's contents may be provided by a Python-based pretty-printer. In this
+case the varobj is known as a @dfn{dynamic varobj}. Dynamic varobjs
+have slightly different semantics in some cases. If the
+@code{-enable-pretty-printing} command is not sent, then @value{GDBN}
+will never create a dynamic varobj. This ensures backward
+compatibility for existing clients.
+
@subsubheading Result

-This operation returns the name, number of children and the type of the
-object created. Type is returned as a string as the ones generated by
-the @value{GDBN} CLI. If a fixed variable object is bound to a
-specific thread, the thread is is also printed:
+This operation returns attributes of the newly-created varobj. These
+are:
+
+@table @samp
+@item name
+The name of the varobj.
+
+@item numchild
+The number of children of the varobj. This number is not necessarily
+reliable for a dynamic varobj. Instead, you must examine the
+@samp{has_more} attribute.
+
+@item value
+The varobj's scalar value. For a varobj whose type is some sort of
+aggregate (e.g., a @code{struct}), or for a dynamic varobj, this value
+will not be interesting.
+
+@item type
+The varobj's type. This is a string representation of the type, as
+would be printed by the @value{GDBN} CLI.
+
+@item thread-id
+If a variable object is bound to a specific thread, then this is the
+thread's identifier.
+
+@item has_more
+For a dynamic varobj, this indicates whether there appear to be any
+children available. For a non-dynamic varobj, this will be 0.
+
+@item dynamic
+This attribute will be present and have the value @samp{1} if the
+varobj is a dynamic varobj. If the varobj is not a dynamic varobj,
+then this attribute will not be present.
+@end table
+
+Typical output will look like this:

@smallexample
- name="@var{name}",numchild="@var{N}",type="@var{type}",thread-id="@var{M}"
+ name="@var{name}",numchild="@var{N}",type="@var{type}",thread-id="@var{M}",
+ has_more="@var{has_more}"
@end smallexample

@@ -23520,6 +23582,10 @@ Returns the number of children of a variable object @var{name}:
numchild=@var{n}
@end smallexample

+Note that this number is not completely reliable for a dynamic varobj.
+It will return the current number of children, but more children may
+be available.
+

@subheading The @code{-var-list-children} Command
@findex -var-list-children
@@ -23527,7 +23593,7 @@ Returns the number of children of a variable object @var{name}:
@subsubheading Synopsis

@smallexample
- -var-list-children [@var{print-values}] @var{name}
+ -var-list-children [@var{print-values}] @var{name} [@var{from} @var{to}]
@end smallexample
@anchor{-var-list-children}

@@ -23540,6 +23606,22 @@ values; and if it is 2 or @code{--simple-values} print the name and
value for simple data types and just the name for arrays, structures
and unions.

+@var{from} and @var{to}, if specified, indicate the range of children
+to report. If @var{from} or @var{to} is less than zero, the range is
+reset and all children will be reported. Otherwise, children starting
+at @var{from} (zero-based) and up to and excluding @var{to} will be
+reported.
+
+If a child range is requested, it will only affect the current call to
+@code{-var-list-children}, but not future calls to @code{-var-update}.
+For this, you must instead use @code{-var-set-update-range}. The
+intent of this approach is to enable a front end to implement any
+update approach it likes; for example, scrolling a view may cause the
+front end to request more children with @code{-var-list-children}, and
+then the front end could call @code{-var-set-update-range} with a
+different range to ensure that future updates are restricted to just
+the visible items.
+
For each child the following results are returned:

@table @var
@@ -23551,13 +23633,21 @@ Name of the variable object created for this child.
The expression to be shown to the user by the front end to designate this child.
For example this may be the name of a structure member.

+For a dynamic varobj, this value cannot be used to form an
+expression. There is no way to do this at all with a dynamic varobj.
+
For C/C@t{++} structures there are several pseudo children returned to
designate access qualifiers. For these pseudo children @var{exp} is
@samp{public}, @samp{private}, or @samp{protected}. In this case the
type and value are not present.

+A dynamic varobj will not report the access qualifying
+pseudo-children, regardless of the language. This information is not
+available at all with a dynamic varobj.
+
@item numchild
-Number of children this child has.
+Number of children this child has. For a dynamic varobj, this will be
+0.

@item type
The type of the child.
@@ -23573,6 +23663,19 @@ Otherwise this result is not present.
If the variable object is frozen, this variable will be present with a value of 1.
@end table

+The result may have its own attributes:
+
+@table @samp
+@item displayhint
+A dynamic varobj can supply a display hint to the front end. The
+value comes directly from the Python pretty-printer object's
+@code{display_hint} method. @xref{Pretty Printing}.
+
+@item has_more
+This is an integer attribute which is nonzero if there are children
+remaining after the end of the selected range.
+@end table
+
@subsubheading Example

@smallexample
@@ -23649,6 +23752,9 @@ result can be used only for UI presentation. Typical use of
the @code{-var-info-path-expression} command is creating a
watchpoint from a variable object.

+This command is currently not valid for children of a dynamic varobj,
+and will give an error when invoked on one.
+
For example, suppose @code{C} is a C@t{++} class, derived from class
@code{Base}, and that the @code{Base} class has a member called
@code{m_size}. Assume a variable @code{c} is has the type of
@@ -23754,21 +23860,25 @@ With the @samp{*} parameter, if a variable object is bound to a
currently running thread, it will not be updated, without any
diagnostic.

-@subsubheading Example
+If @code{-var-set-update-range} was previously used on a varobj, then
+only the selected range of children will be reported.

-@smallexample
-(gdb)
--var-assign var1 3
-^done,value="3"
-(gdb)
--var-update --all-values var1
-^done,changelist=[@{name="var1",value="3",in_scope="true",
-type_changed="false"@}]
-(gdb)
-@end smallexample
+@code{-var-update} reports all the changed varobjs in a tuple named
+@samp{changelist}.

+Each item in the change list is itself a tuple holding:
+
+@table @samp
+@item name
+The name of the varobj.
+
+@item value
+If values were requested for this update, then this field will be
+present and will hold the value of the varobj.
+
+@item in_scope
@anchor{-var-update}
-The field in_scope may take three values:
+This field is a string which may take one of three values:

@table @code
@item "true"
@@ -23790,6 +23900,61 @@ objects.
In the future new values may be added to this list so the front should
be prepared for this possibility. @xref{GDB/MI Development and Front Ends, ,@sc{GDB/MI} Development and Front Ends}.

+@item type_changed
+This is only present if the varobj is still valid. If the type
+changed, then this will be the string @samp{true}; otherwise it will
+be @samp{false}.
+
+@item new_type
+If the varobj's type changed, then this field will be present and will
+hold the new type.
+
+@item new_num_children
+For a dynamic varobj, if the number of children changed, or if the
+type changed, this will be the new number of children.
+
+The @samp{numchild} field in other varobj responses is generally not
+valid for a dynamic varobj -- it will show the number of children that
+@value{GDBN} knows about, but because dynamic varobjs lazily
+instantiate their children, this will not reflect the number of
+children which may be available.
+
+The @samp{new_num_children} attribute only reports changes to the
+number of children known by @value{GDBN}. This is the only way to
+detect whether an update has removed children (which necessarily can
+only happen at the end of the update range).
+
+@item displayhint
+The display hint, if any.
+
+@item has_more
+This is an integer value, which will be 1 if there are more children
+available outside the varobj's update range.
+
+@item dynamic
+This attribute will be present and have the value @samp{1} if the
+varobj is a dynamic varobj. If the varobj is not a dynamic varobj,
+then this attribute will not be present.
+
+@item new_children
+If new children were added to a dynamic varobj within the selected
+update range (as set by @code{-var-set-update-range}), then they will
+be listed in this attribute.
+@end table
+
+@subsubheading Example
+
+@smallexample
+(gdb)
+-var-assign var1 3
+^done,value="3"
+(gdb)
+-var-update --all-values var1
+^done,changelist=[@{name="var1",value="3",in_scope="true",
+type_changed="false"@}]
+(gdb)
+@end smallexample
+
@subheading The @code{-var-set-frozen} Command
@findex -var-set-frozen
@anchor{-var-set-frozen}
@@ -23821,6 +23986,32 @@ Unfreezing a variable does not update it, only subsequent
(gdb)
@end smallexample

+@subheading The @code{-var-set-update-range} command
+@findex -var-set-update-range
+@anchor{-var-set-update-range}
+
+@subsubheading Synopsis
+
+@smallexample
+ -var-set-update-range @var{name} @var{from} @var{to}
+@end smallexample
+
+Set the range of children to be returned by future invocations of
+@code{-var-update}.
+
+@var{from} and @var{to} indicate the range of children to report. If
+@var{from} or @var{to} is less than zero, the range is reset and all
+children will be reported. Otherwise, children starting at @var{from}
+(zero-based) and up to and excluding @var{to} will be reported.
+
+@subsubheading Example
+
+@smallexample
+(gdb)
+-var-set-update-range V 1 2
+^done
+@end smallexample
+
@subheading The @code{-var-set-visualizer} command
@findex -var-set-visualizer
@anchor{-var-set-visualizer}
diff --git a/gdb/mi/mi-cmd-var.c b/gdb/mi/mi-cmd-var.c
index 0cf03d9..ede928c 100644
--- a/gdb/mi/mi-cmd-var.c
+++ b/gdb/mi/mi-cmd-var.c
@@ -41,7 +41,7 @@ static void varobj_update_one (struct varobj *var,
enum print_values print_values,
int explicit);

-static int mi_print_value_p (struct type *type, enum print_values print_values);
+static int mi_print_value_p (struct varobj *var, enum print_values print_values);

/* Print variable object VAR. The PRINT_VALUES parameter controls
if the value should be printed. The PRINT_EXPRESSION parameter
@@ -59,8 +59,12 @@ print_varobj (struct varobj *var, enum print_values print_values,
ui_out_field_string (uiout, "exp", varobj_get_expression (var));
ui_out_field_int (uiout, "numchild", varobj_get_num_children (var));

- if (mi_print_value_p (varobj_get_gdb_type (var), print_values))
- ui_out_field_string (uiout, "value", varobj_get_value (var));
+ if (mi_print_value_p (var, print_values))
+ {
+ char *val = varobj_get_value (var);
+ ui_out_field_string (uiout, "value", val);
+ xfree (val);
+ }

type = varobj_get_type (var);
if (type != NULL)
@@ -75,6 +79,9 @@ print_varobj (struct varobj *var, enum print_values print_values,

if (varobj_get_frozen (var))
ui_out_field_int (uiout, "frozen", 1);
+
+ if (varobj_pretty_printed_p (var))
+ ui_out_field_int (uiout, "dynamic", 1);
}

/* VAROBJ operations */
@@ -138,6 +145,8 @@ mi_cmd_var_create (char *command, char **argv, int argc)

print_varobj (var, PRINT_ALL_VALUES, 0 /* don't print expression */);

+ ui_out_field_int (uiout, "has_more", varobj_has_more (var, 0));
+
do_cleanups (old_cleanups);
}

@@ -223,6 +232,7 @@ mi_cmd_var_set_format (char *command, char **argv, int argc)
{
enum varobj_display_formats format;
struct varobj *var;
+ char *val;

if (argc != 2)
error (_("mi_cmd_var_set_format: Usage: NAME FORMAT."));
@@ -239,7 +249,9 @@ mi_cmd_var_set_format (char *command, char **argv, int argc)
ui_out_field_string (uiout, "format", varobj_format_string[(int) format]);

/* Report the value in the new format */
- ui_out_field_string (uiout, "value", varobj_get_value (var));
+ val = varobj_get_value (var);
+ ui_out_field_string (uiout, "value", val);
+ xfree (val);
}

void
@@ -337,11 +349,12 @@ Must be: 0 or \"%s\", 1 or \"%s\", 2 or \"%s\""),
}

/* Return 1 if given the argument PRINT_VALUES we should display
- a value of type TYPE. */
+ the varobj VAR. */

static int
-mi_print_value_p (struct type *type, enum print_values print_values)
+mi_print_value_p (struct varobj *var, enum print_values print_values)
{
+ struct type *type;

if (print_values == PRINT_NO_VALUES)
return 0;
@@ -349,6 +362,10 @@ mi_print_value_p (struct type *type, enum print_values print_values)
if (print_values == PRINT_ALL_VALUES)
return 1;

+ if (varobj_pretty_printed_p (var))
+ return 1;
+
+ type = varobj_get_gdb_type (var);
if (type == NULL)
return 1;
else
@@ -369,24 +386,35 @@ mi_cmd_var_list_children (char *command, char **argv, int argc)
struct varobj *var;
VEC(varobj_p) *children;
struct varobj *child;
- struct cleanup *cleanup_children;
int numchild;
enum print_values print_values;
int ix;
+ int from, to;
char *display_hint;

- if (argc != 1 && argc != 2)
- error (_("mi_cmd_var_list_children: Usage: [PRINT_VALUES] NAME"));
+ if (argc < 1 || argc > 4)
+ error (_("mi_cmd_var_list_children: Usage: [PRINT_VALUES] NAME [FROM TO]"));

/* Get varobj handle, if a valid var obj name was specified */
- if (argc == 1)
+ if (argc == 1 || argc == 3)
var = varobj_get_handle (argv[0]);
else
var = varobj_get_handle (argv[1]);

- children = varobj_list_children (var);
- ui_out_field_int (uiout, "numchild", VEC_length (varobj_p, children));
- if (argc == 2)
+ if (argc > 2)
+ {
+ from = atoi (argv[argc - 2]);
+ to = atoi (argv[argc - 1]);
+ }
+ else
+ {
+ from = -1;
+ to = -1;
+ }
+
+ children = varobj_list_children (var, &from, &to);
+ ui_out_field_int (uiout, "numchild", to - from);
+ if (argc == 2 || argc == 4)
print_values = mi_parse_values_option (argv[0]);
else
print_values = PRINT_NO_VALUES;
@@ -398,21 +426,28 @@ mi_cmd_var_list_children (char *command, char **argv, int argc)
xfree (display_hint);
}

- if (VEC_length (varobj_p, children) == 0)
- return;
-
- if (mi_version (uiout) == 1)
- cleanup_children = make_cleanup_ui_out_tuple_begin_end (uiout, "children");
- else
- cleanup_children = make_cleanup_ui_out_list_begin_end (uiout, "children");
- for (ix = 0; VEC_iterate (varobj_p, children, ix, child); ++ix)
+ if (from < to)
{
- struct cleanup *cleanup_child;
- cleanup_child = make_cleanup_ui_out_tuple_begin_end (uiout, "child");
- print_varobj (child, print_values, 1 /* print expression */);
- do_cleanups (cleanup_child);
+ struct cleanup *cleanup_children;
+ if (mi_version (uiout) == 1)
+ cleanup_children
+ = make_cleanup_ui_out_tuple_begin_end (uiout, "children");
+ else
+ cleanup_children
+ = make_cleanup_ui_out_list_begin_end (uiout, "children");
+ for (ix = from;
+ ix < to && VEC_iterate (varobj_p, children, ix, child);
+ ++ix)
+ {
+ struct cleanup *cleanup_child;
+ cleanup_child = make_cleanup_ui_out_tuple_begin_end (uiout, "child");
+ print_varobj (child, print_values, 1 /* print expression */);
+ do_cleanups (cleanup_child);
+ }
+ do_cleanups (cleanup_children);
}
- do_cleanups (cleanup_children);
+
+ ui_out_field_int (uiout, "has_more", varobj_has_more (var, to));
}

void
@@ -538,16 +573,24 @@ mi_cmd_var_evaluate_expression (char *command, char **argv, int argc)
var = varobj_get_handle (argv[optind]);

if (formatFound)
- ui_out_field_string (uiout, "value", varobj_get_formatted_value (var, format));
+ {
+ char *val = varobj_get_formatted_value (var, format);
+ ui_out_field_string (uiout, "value", val);
+ xfree (val);
+ }
else
- ui_out_field_string (uiout, "value", varobj_get_value (var));
+ {
+ char *val = varobj_get_value (var);
+ ui_out_field_string (uiout, "value", val);
+ xfree (val);
+ }
}

void
mi_cmd_var_assign (char *command, char **argv, int argc)
{
struct varobj *var;
- char *expression;
+ char *expression, *val;

if (argc != 2)
error (_("mi_cmd_var_assign: Usage: NAME EXPRESSION."));
@@ -563,7 +606,9 @@ mi_cmd_var_assign (char *command, char **argv, int argc)
if (!varobj_set_value (var, expression))
error (_("mi_cmd_var_assign: Could not assign expression to variable object"));

- ui_out_field_string (uiout, "value", varobj_get_value (var));
+ val = varobj_get_value (var);
+ ui_out_field_string (uiout, "value", val);
+ xfree (val);
}

/* Type used for parameters passing to mi_cmd_var_update_iter. */
@@ -670,6 +715,7 @@ varobj_update_one (struct varobj *var, enum print_values print_values,
for (i = 0; VEC_iterate (varobj_update_result, changes, i, r); ++i)
{
char *display_hint;
+ int from, to;

if (mi_version (uiout) > 1)
cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
@@ -678,8 +724,12 @@ varobj_update_one (struct varobj *var, enum print_values print_values,
switch (r->status)
{
case VAROBJ_IN_SCOPE:
- if (mi_print_value_p (varobj_get_gdb_type (r->varobj), print_values))
- ui_out_field_string (uiout, "value", varobj_get_value (r->varobj));
+ if (mi_print_value_p (r->varobj, print_values))
+ {
+ char *val = varobj_get_value (r->varobj);
+ ui_out_field_string (uiout, "value", val);
+ xfree (val);
+ }
ui_out_field_string (uiout, "in_scope", "true");
break;
case VAROBJ_NOT_IN_SCOPE:
@@ -699,11 +749,11 @@ varobj_update_one (struct varobj *var, enum print_values print_values,
}

if (r->type_changed)
- {
- ui_out_field_string (uiout, "new_type", varobj_get_type (r->varobj));
- ui_out_field_int (uiout, "new_num_children",
- varobj_get_num_children (r->varobj));
- }
+ ui_out_field_string (uiout, "new_type", varobj_get_type (r->varobj));
+
+ if (r->type_changed || r->children_changed)
+ ui_out_field_int (uiout, "new_num_children",
+ varobj_get_num_children (r->varobj));

display_hint = varobj_get_display_hint (var);
if (display_hint)
@@ -712,28 +762,59 @@ varobj_update_one (struct varobj *var, enum print_values print_values,
xfree (display_hint);
}

- if (r->children_changed)
- {
- int ix;
- struct varobj *child;
- struct cleanup *cleanup =
- make_cleanup_ui_out_list_begin_end (uiout, "children");
+ if (varobj_pretty_printed_p (var))
+ ui_out_field_int (uiout, "dynamic", 1);

- VEC (varobj_p)* children = varobj_list_children (r->varobj);
+ varobj_get_child_range (r->varobj, &from, &to);
+ ui_out_field_int (uiout, "has_more",
+ varobj_has_more (r->varobj, to));

- for (ix = 0; VEC_iterate (varobj_p, children, ix, child); ++ix)
+ if (r->new)
+ {
+ int j;
+ varobj_p child;
+ struct cleanup *cleanup;
+
+ cleanup = make_cleanup_ui_out_list_begin_end (uiout, "new_children");
+ for (j = 0; VEC_iterate (varobj_p, r->new, j, child); ++j)
{
struct cleanup *cleanup_child;
cleanup_child = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
- print_varobj (child, print_values, 1 /* print expression */);
+ print_varobj (child, print_values, 1 /* print_expression */);
do_cleanups (cleanup_child);
}

do_cleanups (cleanup);
+ VEC_free (varobj_p, r->new);
+ r->new = NULL; /* Paranoia. */
}
-
+
if (mi_version (uiout) > 1)
do_cleanups (cleanup);
}
VEC_free (varobj_update_result, changes);
}
+
+void
+mi_cmd_enable_pretty_printing (char *command, char **argv, int argc)
+{
+ if (argc != 0)
+ error (_("mi_cmd_enable_pretty_printing: no arguments allowed"));
+ varobj_enable_pretty_printing ();
+}
+
+void
+mi_cmd_var_set_update_range (char *command, char **argv, int argc)
+{
+ struct varobj *var;
+ int from, to;
+
+ if (argc != 3)
+ error (_("mi_cmd_var_set_update_range: Usage: VAROBJ FROM TO"));
+
+ var = varobj_get_handle (argv[0]);
+ from = atoi (argv[1]);
+ to = atoi (argv[2]);
+
+ varobj_set_child_range (var, from, to);
+}
diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c
index dd3d803..8ba086c 100644
--- a/gdb/mi/mi-cmds.c
+++ b/gdb/mi/mi-cmds.c
@@ -52,6 +52,7 @@ struct mi_cmd mi_cmds[] =
{ "data-write-memory", { NULL, 0 }, mi_cmd_data_write_memory},
{ "data-write-register-values", { NULL, 0 }, mi_cmd_data_write_register_values},
{ "enable-timings", { NULL, 0 }, mi_cmd_enable_timings},
+ { "enable-pretty-printing", { NULL, 0 }, mi_cmd_enable_pretty_printing},
{ "environment-cd", { NULL, 0 }, mi_cmd_env_cd},
{ "environment-directory", { NULL, 0 }, mi_cmd_env_dir},
{ "environment-path", { NULL, 0 }, mi_cmd_env_path},
@@ -112,6 +113,7 @@ struct mi_cmd mi_cmds[] =
{ "var-list-children", { NULL, 0 }, mi_cmd_var_list_children},
{ "var-set-format", { NULL, 0 }, mi_cmd_var_set_format},
{ "var-set-frozen", { NULL, 0 }, mi_cmd_var_set_frozen},
+ { "var-set-update-range", { NULL, 0 }, mi_cmd_var_set_update_range },
{ "var-set-visualizer", { NULL, 0 }, mi_cmd_var_set_visualizer},
{ "var-show-attributes", { NULL, 0 }, mi_cmd_var_show_attributes},
{ "var-show-format", { NULL, 0 }, mi_cmd_var_show_format},
diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h
index 85ad0c4..dfab411 100644
--- a/gdb/mi/mi-cmds.h
+++ b/gdb/mi/mi-cmds.h
@@ -99,6 +99,8 @@ extern mi_cmd_argv_ftype mi_cmd_var_set_visualizer;
extern mi_cmd_argv_ftype mi_cmd_var_show_attributes;
extern mi_cmd_argv_ftype mi_cmd_var_show_format;
extern mi_cmd_argv_ftype mi_cmd_var_update;
+extern mi_cmd_argv_ftype mi_cmd_enable_pretty_printing;
+extern mi_cmd_argv_ftype mi_cmd_var_set_update_range;

/* Description of a single command. */

diff --git a/gdb/testsuite/gdb.mi/gdb701.exp b/gdb/testsuite/gdb.mi/gdb701.exp
index d4acdc2..244c731 100644
--- a/gdb/testsuite/gdb.mi/gdb701.exp
+++ b/gdb/testsuite/gdb.mi/gdb701.exp
@@ -54,7 +54,7 @@ mi_gdb_test "-var-list-children fooPtr" \

foreach i [list x y z] {
mi_gdb_test "-var-list-children fooPtr.$i" \
- "(&\".*\"\r\n)*\\^done,numchild=\"0\"" \
+ "(&\".*\"\r\n)*\\^done,numchild=\"0\",has_more=\"0\"" \
"list children of fooPtr.$i"
}

diff --git a/gdb/testsuite/gdb.mi/mi-break.exp b/gdb/testsuite/gdb.mi/mi-break.exp
index 619727d..8d06c0e 100644
--- a/gdb/testsuite/gdb.mi/mi-break.exp
+++ b/gdb/testsuite/gdb.mi/mi-break.exp
@@ -175,7 +175,7 @@ proc test_error {} {
# containing function call, the internal breakpoint created to handle
# function call would be reported, messing up MI output.
mi_gdb_test "-var-create V * return_1()" \
- "\\^done,name=\"V\",numchild=\"0\",value=\"1\",type=\"int\"" \
+ "\\^done,name=\"V\",numchild=\"0\",value=\"1\",type=\"int\",has_more=\"0\"" \
"create varobj for function call"

mi_gdb_test "-var-update *" \
diff --git a/gdb/testsuite/gdb.mi/mi-var-block.exp b/gdb/testsuite/gdb.mi/mi-var-block.exp
index 8806848..93ded26 100644
--- a/gdb/testsuite/gdb.mi/mi-var-block.exp
+++ b/gdb/testsuite/gdb.mi/mi-var-block.exp
@@ -74,7 +74,7 @@ mi_step_to "do_block_tests" "" "var-cmd.c" \
# Test: c_variable-3.4
# Desc: check foo, cb changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"foo\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"cb\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"foo\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"cb\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars: cb foo changed"

# step to "foo = 321;"
diff --git a/gdb/testsuite/gdb.mi/mi-var-child.exp b/gdb/testsuite/gdb.mi/mi-var-child.exp
index 1f4bdc6..eb6c456 100644
--- a/gdb/testsuite/gdb.mi/mi-var-child.exp
+++ b/gdb/testsuite/gdb.mi/mi-var-child.exp
@@ -680,7 +680,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \
# Test: c_variable-5.2
# Desc: check that integer changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"struct_declarations.integer\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"struct_declarations.integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars struct_declarations.integer"

# Step over:
@@ -693,7 +693,7 @@ mi_execute_to "exec-step 3" "end-stepping-range" do_children_tests {} ".*${srcfi
# Test: c_variable-5.3
# Desc: check that char_ptr changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"struct_declarations.char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.char_ptr.\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"struct_declarations.char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.char_ptr.\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars struct_declarations.char_ptr"

# Step over "struct_declarations.int_ptr_ptr = &foo;"
@@ -703,7 +703,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \
# Test: c_variable-5.4
# Desc: check that int_ptr_ptr and children changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr.\\*\\*weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr.\\*\\*int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr.\\*\\*weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr.\\*\\*int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars int_ptr_ptr and children changed"

# Step over "weird->long_array[0] = 1234;"
@@ -713,7 +713,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \
# Test: c_variable-5.5
# Desc: check that long_array[0] changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.0\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.0\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars struct_declarations.long_array.0 changed"

# Step over "struct_declarations.long_array[1] = 2345;"
@@ -723,7 +723,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \
# Test: c_variable-5.6
# Desc: check that long_array[1] changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.1\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.1\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars struct_declarations.long_array.1 changed"

# Step over "weird->long_array[2] = 3456;"
@@ -733,7 +733,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \
# Test: c_variable-5.7
# Desc: check that long_array[2] changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.2\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.2\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars struct_declarations.long_array.2 changed"

# Step over:
@@ -752,7 +752,7 @@ mi_execute_to "exec-step 7" "end-stepping-range" do_children_tests {} ".*${srcfi
# Test: c_variable-5.8
# Desc: check that long_array[3-9] changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.3\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.4\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.5\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.6\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.7\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.8\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.9\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.3\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.4\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.5\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.6\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.7\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.8\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.9\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars struct_declarations.long_array.3-9 changed"

@@ -763,7 +763,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \
# Test: c_variable-5.9
# Desc: check that func_ptr changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"struct_declarations.func_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"struct_declarations.func_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars struct_declarations.func_ptr changed"

# Step over "struct_declarations.long_array[10] = 3456";
@@ -771,7 +771,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \
[expr $line_dct_nothing + 2] "step \$line_dct_nothing + 2"

mi_gdb_test "-var-update --no-values *" \
- "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.10\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.10\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars struct_declarations.long_array.10 changed, don't print values."

# Step over "struct_declarations.long_array[11] = 5678";
@@ -780,7 +780,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \
$line_dct_a0_0 "step \$line_dct_a0_0"

mi_gdb_test "-var-update --all-values *" \
- "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.11\",value=\"5678\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.11\",value=\"5678\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars struct_declarations.long_array.11 changed, print values."

mi_list_varobj_children {struct_declarations.long_array --all-values} {
@@ -1121,7 +1121,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \
# Test: c_variable-5.47
# Desc: check that psnp->char_ptr (and [0].char_ptr) changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr.\\*\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr.\\*\\*\\*psnp->char_ptr.\\*\\*\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr.\\*\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr.\\*\\*\\*psnp->char_ptr.\\*\\*\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars psnp->char_ptr (and 0.char_ptr) changed"

# Step over "snp1.char_ptr = &c3;"
@@ -1131,7 +1131,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \
# Test: c_variable-5.48
# Desc: check that psnp->next->char_ptr (and [1].char_ptr) changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr.\\*\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr.\\*\\*\\*char_ptr.\\*\\*\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr.\\*\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr.\\*\\*\\*char_ptr.\\*\\*\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars psnp->next->char_ptr (and 1.char_ptr) changed"

@@ -1142,7 +1142,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \
# Test: c_variable-5.49
# Desc: check that psnp->next->next->char_ptr (and [2].char_ptr) changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.next.char_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.next.char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars psnp->next->next->char_ptr (and 2.char_ptr) changed"

@@ -1153,7 +1153,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \
# Test: c_variable-5.50
# Desc: check that psnp->long_ptr (and [0].long_ptr) changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr.\\*\\*\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr.\\*\\*\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars psnp->long_ptr (and 0.long_ptr) changed"

@@ -1181,7 +1181,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \
# Test: c_variable-5.52
# Desc: check that psnp->next->next->long_ptr (and [2].long_ptr) changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.next.long_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.next.long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars psnp->next->next->long_ptr (and 2.long_ptr) changed"

mi_prepare_inline_tests $srcfile
diff --git a/gdb/testsuite/gdb.mi/mi-var-cmd.exp b/gdb/testsuite/gdb.mi/mi-var-cmd.exp
index ad2e55c..6efb333 100644
--- a/gdb/testsuite/gdb.mi/mi-var-cmd.exp
+++ b/gdb/testsuite/gdb.mi/mi-var-cmd.exp
@@ -146,7 +146,7 @@ mi_step_to "do_locals_tests" "" "var-cmd.c" $line_dlt_linteger "step at do_local
# Test: c_variable-2.2
# Desc: check whether only linteger changed values
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars: linteger changed"

# Step over "lpinteger = &linteger;"
@@ -155,7 +155,7 @@ mi_step_to "do_locals_tests" "" "var-cmd.c" [expr $line_dlt_linteger + 1] "step
# Test: c_variable-2.3
# Desc: check whether only lpinteger changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"lpinteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"lpinteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars: lpinteger changed"

# Step over "lcharacter = 'a';"
@@ -164,7 +164,7 @@ mi_step_to "do_locals_tests" "" "var-cmd.c" [expr $line_dlt_linteger + 2] "step
# Test: c_variable-2.4
# Desc: check whether only lcharacter changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"lcharacter\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"lcharacter\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars: lcharacter changed"

# Step over "lpcharacter = &lcharacter;"
@@ -173,7 +173,7 @@ mi_step_to "do_locals_tests" "" "var-cmd.c" [expr $line_dlt_linteger + 3] "step
# Test: c_variable-2.5
# Desc: check whether only lpcharacter changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars: lpcharacter changed"

@@ -195,7 +195,7 @@ mi_execute_to "exec-step 9" "end-stepping-range" "do_locals_tests" "" \
# Desc: check whether llong, lplong, lfloat, lpfloat, ldouble, lpdouble, lsimple.integer,
# lsimple.unsigned_character lsimple.integer lsimple.character changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"lsimple.integer\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lsimple->integer\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lsimple.character\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lpdouble\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"ldouble\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lpfloat\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lfloat\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lplong\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"llong\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"lsimple.integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lsimple->integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lsimple.character\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lpdouble\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"ldouble\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lpfloat\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lfloat\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lplong\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"llong\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars: many changed"

# Step over:
@@ -212,7 +212,7 @@ mi_execute_to "exec-step 4" "end-stepping-range" "do_locals_tests" "" \
# Test: c_variable-2.7
# Desc: check whether (lsimple.signed_character, lsimple.char_ptr) lpsimple, func changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"func\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lpsimple\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"func\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lpsimple\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars: func and lpsimple changed"

# Step over
@@ -234,7 +234,7 @@ mi_execute_to "exec-step 8" "end-stepping-range" "do_locals_tests" "" \
# Note: this test also checks that lpsimple->integer and lsimple.integer have
# changed (they are the same)
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"lsimple.integer\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lsimple->integer\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lsimple.character\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"ldouble\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lfloat\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"llong\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lcharacter\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"lsimple.integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lsimple->integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lsimple.character\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"ldouble\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lfloat\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"llong\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lcharacter\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars: lsimple and others changed"

@@ -257,7 +257,7 @@ mi_gdb_test "-var-assign linteger 3333" \
# change.
set lpchar_update "\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\"\},"
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[($lpchar_update)?\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[($lpchar_update)?\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars: linteger changed after assign"

mi_gdb_test "-var-assign linteger 3333" \
@@ -277,7 +277,7 @@ mi_gdb_test "-var-assign lpinteger \"&linteger + 3\"" \
"assign to lpinteger"

mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"lpinteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"lpinteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars: lpinteger changed after assign"

mi_gdb_test "-var-update *" \
@@ -377,7 +377,7 @@ mi_gdb_test "-var-update *" \
"assign same value to func (update)"

mi_gdb_test "-var-create array_ptr * array_ptr" \
- "\\^done,name=\"array_ptr\",numchild=\"1\",value=\"$hex\",type=\"int \\*\"" \
+ "\\^done,name=\"array_ptr\",numchild=\"1\",value=\"$hex\",type=\"int \\*\",has_more=\"0\"" \
"create global variable array_ptr"

mi_gdb_test "-var-assign array_ptr array2" \
@@ -385,7 +385,7 @@ mi_gdb_test "-var-assign array_ptr array2" \
"assign array to pointer"

mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"array_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"array_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"assign array to pointer (update)"

mi_gdb_test "-var-assign array_ptr array2" \
@@ -439,7 +439,7 @@ mi_step_to "subroutine1" "\{name=\"i\",value=\".*\"\},\{name=\"l\",value=\".*\"\
# Test: c_variable-2.13
# Desc: change subroutine1 local i
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"i\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"i\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars: i changed"

mi_step_to "subroutine1" "\{name=\"i\",value=\".*\"\},\{name=\"l\",value=\".*\"\}" \
@@ -448,7 +448,7 @@ mi_step_to "subroutine1" "\{name=\"i\",value=\".*\"\},\{name=\"l\",value=\".*\"\
# Test: c_variable-2.14
# Desc: change do_locals_tests local llong
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"llong\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"llong\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars: llong changed"

set line_dlt_call_subroutine1 [gdb_get_line_number "subroutine1 (linteger, &llong);"]
@@ -458,7 +458,7 @@ mi_next_to "do_locals_tests" "" "var-cmd.c" \
# Test: c_variable-2.15
# Desc: check for out of scope subroutine1 locals
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"l\",in_scope=\"false\"\,type_changed=\"false\"},\{name=\"i\",in_scope=\"false\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"l\",in_scope=\"false\"\,type_changed=\"false\",has_more=\"0\"},\{name=\"i\",in_scope=\"false\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars: all now out of scope"

# Done with locals/globals tests. Erase all variables
@@ -550,14 +550,14 @@ mi_gdb_test "-var-create selected_a @ a" \
mi_continue_to incr_a

mi_gdb_test "-var-update selected_a" \
- "\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",type_changed=\"true\",new_type=\"char\",new_num_children=\"0\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",type_changed=\"true\",new_type=\"char\",new_num_children=\"0\",has_more=\"0\"\}\\\]" \
"update selected_a in incr_a"

mi_next "step a line in incr_a"
mi_next "return from incr_a to do_special_tests"

mi_gdb_test "-var-update selected_a" \
- "\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",type_changed=\"true\",new_type=\"int\",new_num_children=\"0\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",type_changed=\"true\",new_type=\"int\",new_num_children=\"0\",has_more=\"0\"\}\\\]" \
"update selected_a in do_special_tests"

mi_gdb_test "-file-exec-and-symbols ${binfile}" "\\^done" \
@@ -596,7 +596,7 @@ mi_check_varobj_value F 7 "check F inside callee"
# A varobj we fail to read during -var-update should be considered
# out of scope.
mi_gdb_test "-var-create null_ptr * **0" \
- {\^done,name="null_ptr",numchild="0",value=".*",type="int"} \
+ {\^done,name="null_ptr",numchild="0",value=".*",type="int",has_more="0"} \
"create null_ptr"

# Allow this to succeed, if address zero is readable, although it
@@ -644,7 +644,7 @@ mi_check_varobj_value "L" "{...}" "in-and-out-of-scope: check initial value"
mi_runto main

mi_gdb_test "-var-update L" \
- {\^done,changelist=\[{name="L",in_scope="false",type_changed="false"}\]} \
+ {\^done,changelist=\[{name="L",in_scope="false",type_changed="false",has_more="0"}\]} \
"in-and-out-of-scope: out of scope now"

mi_gdb_test "-var-update L" \
@@ -654,7 +654,7 @@ mi_gdb_test "-var-update L" \
mi_continue_to do_locals_tests

mi_gdb_test "-var-update L" \
- {\^done,changelist=\[{name="L",in_scope="true",type_changed="false"}\]} \
+ {\^done,changelist=\[{name="L",in_scope="true",type_changed="false",has_more="0"}\]} \
"in-and-out-of-scope: in scope now"

mi_gdb_test "-var-update L" \
diff --git a/gdb/testsuite/gdb.mi/mi-var-display.exp b/gdb/testsuite/gdb.mi/mi-var-display.exp
index 4b02e50..faa9172 100644
--- a/gdb/testsuite/gdb.mi/mi-var-display.exp
+++ b/gdb/testsuite/gdb.mi/mi-var-display.exp
@@ -558,7 +558,7 @@ mi_gdb_test "-var-info-num-children e" \
# Test: c_variable-7.55
# Desc: children of e
mi_gdb_test "-var-list-children e" \
- "\\^done,numchild=\"0\"" \
+ "\\^done,numchild=\"0\",has_more=\"0\"" \
"get children of e"

# Test: c_variable-7.60
@@ -600,7 +600,7 @@ mi_gdb_test "-var-info-num-children anone" \
# Test: c_variable-7.75
# Desc: children of anone
mi_gdb_test "-var-list-children anone" \
- "\\^done,numchild=\"0\"" \
+ "\\^done,numchild=\"0\",has_more=\"0\"" \
"get children of anone"

diff --git a/gdb/testsuite/gdb.mi/mi-var-invalidate.exp b/gdb/testsuite/gdb.mi/mi-var-invalidate.exp
index 05d46fa..4b95674 100644
--- a/gdb/testsuite/gdb.mi/mi-var-invalidate.exp
+++ b/gdb/testsuite/gdb.mi/mi-var-invalidate.exp
@@ -72,7 +72,7 @@ mi_runto main

# Check local variable is "invalid".
mi_gdb_test "-var-update linteger" \
- "\\^done,changelist=\\\[\{name=\"linteger\",in_scope=\"invalid\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"linteger\",in_scope=\"invalid\",has_more=\"0\"\}\\\]" \
"linteger not anymore in scope due to binary changes"

mi_gdb_test "-var-info-type linteger" \
@@ -97,7 +97,7 @@ mi_delete_breakpoints
mi_gdb_load ${binfile2}
# Check local variable are "invalid"
mi_gdb_test "-var-update linteger" \
- "\\^done,changelist=\\\[\{name=\"linteger\",in_scope=\"invalid\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"linteger\",in_scope=\"invalid\",has_more=\"0\"\}\\\]" \
"linteger not valid anymore due to binary changes"

mi_gdb_test "-var-info-type linteger" \
@@ -106,7 +106,7 @@ mi_gdb_test "-var-info-type linteger" \

# Check global variable are still correct.
mi_gdb_test "-var-update global_simple" \
- "\\^done,changelist=\\\[\{name=\"global_simple\",in_scope=\"invalid\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"global_simple\",in_scope=\"invalid\",has_more=\"0\"\}\\\]" \
"global_simple not anymore in scope due to binary changes"

mi_gdb_test "-var-info-type global_simple" \
diff --git a/gdb/testsuite/gdb.mi/mi2-var-block.exp b/gdb/testsuite/gdb.mi/mi2-var-block.exp
index 6bcfea3..9b3d08f 100644
--- a/gdb/testsuite/gdb.mi/mi2-var-block.exp
+++ b/gdb/testsuite/gdb.mi/mi2-var-block.exp
@@ -74,7 +74,7 @@ mi_step_to "do_block_tests" "" "var-cmd.c" \
# Test: c_variable-3.4
# Desc: check foo, cb changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"foo\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"cb\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"foo\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"cb\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars: cb foo changed"

# step to "foo = 321;"
diff --git a/gdb/testsuite/gdb.mi/mi2-var-child.exp b/gdb/testsuite/gdb.mi/mi2-var-child.exp
index 161b34f..0f9b4d4 100644
--- a/gdb/testsuite/gdb.mi/mi2-var-child.exp
+++ b/gdb/testsuite/gdb.mi/mi2-var-child.exp
@@ -1,4 +1,4 @@
-# Copyright 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation
+# Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2009 Free Software Foundation

# 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
@@ -680,7 +680,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \
# Test: c_variable-5.2
# Desc: check that integer changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"struct_declarations.integer\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"struct_declarations.integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars struct_declarations.integer"

# Step over:
@@ -693,7 +693,7 @@ mi_execute_to "exec-step 3" "end-stepping-range" do_children_tests {} {.*var-cmd
# Test: c_variable-5.3
# Desc: check that char_ptr changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"struct_declarations.char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.char_ptr.\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"struct_declarations.char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.char_ptr.\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars struct_declarations.char_ptr"

# Step over "struct_declarations.int_ptr_ptr = &foo;"
@@ -703,7 +703,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \
# Test: c_variable-5.4
# Desc: check that int_ptr_ptr and children changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr.\\*\\*weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr.\\*\\*int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr.\\*\\*weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr.\\*\\*int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars int_ptr_ptr and children changed"

# Step over "weird->long_array[0] = 1234;"
@@ -713,7 +713,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \
# Test: c_variable-5.5
# Desc: check that long_array[0] changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.0\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.0\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars struct_declarations.long_array.0 changed"

# Step over "struct_declarations.long_array[1] = 2345;"
@@ -723,7 +723,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \
# Test: c_variable-5.6
# Desc: check that long_array[1] changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.1\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.1\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars struct_declarations.long_array.1 changed"

# Step over "weird->long_array[2] = 3456;"
@@ -733,7 +733,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \
# Test: c_variable-5.7
# Desc: check that long_array[2] changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.2\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.2\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars struct_declarations.long_array.2 changed"

# Step over:
@@ -752,7 +752,7 @@ mi_execute_to "exec-step 7" "end-stepping-range" do_children_tests {} {.*var-cmd
# Test: c_variable-5.8
# Desc: check that long_array[3-9] changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.3\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.4\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.5\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.6\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.7\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.8\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.9\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.3\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.4\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.5\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.6\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.7\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.8\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.9\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars struct_declarations.long_array.3-9 changed"

@@ -764,7 +764,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \
# Test: c_variable-5.9
# Desc: check that func_ptr changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"struct_declarations.func_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"struct_declarations.func_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars struct_declarations.func_ptr changed"

# Delete all variables
@@ -1075,7 +1075,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \
# Test: c_variable-5.47
# Desc: check that psnp->char_ptr (and [0].char_ptr) changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr.\\*\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr.\\*\\*\\*psnp->char_ptr.\\*\\*\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr.\\*\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr.\\*\\*\\*psnp->char_ptr.\\*\\*\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars psnp->char_ptr (and 0.char_ptr) changed"

# Step over "snp1.char_ptr = &c3;"
@@ -1085,7 +1085,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \
# Test: c_variable-5.48
# Desc: check that psnp->next->char_ptr (and [1].char_ptr) changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr.\\*\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr.\\*\\*\\*char_ptr.\\*\\*\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr.\\*\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr.\\*\\*\\*char_ptr.\\*\\*\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars psnp->next->char_ptr (and 1.char_ptr) changed"

@@ -1096,7 +1096,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \
# Test: c_variable-5.49
# Desc: check that psnp->next->next->char_ptr (and [2].char_ptr) changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.next.char_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.next.char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars psnp->next->next->char_ptr (and 2.char_ptr) changed"

@@ -1107,7 +1107,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \
# Test: c_variable-5.50
# Desc: check that psnp->long_ptr (and [0].long_ptr) changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr.\\*\\*\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr.\\*\\*\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars psnp->long_ptr (and 0.long_ptr) changed"

@@ -1120,7 +1120,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \
# Why does this have a FIXME?
setup_xfail *-*-*
mi_gdb_test "-var-update *" \
- "FIXME\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.long_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "FIXME\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars psnp->next->long_ptr (and 1.long_ptr) changed"
clear_xfail *-*-*

@@ -1135,7 +1135,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \
# Test: c_variable-5.52
# Desc: check that psnp->next->next->long_ptr (and [2].long_ptr) changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.next.long_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.next.long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars psnp->next->next->long_ptr (and 2.long_ptr) changed"

diff --git a/gdb/testsuite/gdb.mi/mi2-var-cmd.exp b/gdb/testsuite/gdb.mi/mi2-var-cmd.exp
index dda77bb..e900d14 100644
--- a/gdb/testsuite/gdb.mi/mi2-var-cmd.exp
+++ b/gdb/testsuite/gdb.mi/mi2-var-cmd.exp
@@ -126,11 +126,6 @@ mi_gdb_test "-var-create int * int" \
"&\"Attempt to use a type name as an expression.\\\\n\".*\\^error,msg=\"mi_cmd_var_create: unable to create variable object\"" \
"create int"

-# The number 0 must be an invalid frame address and linteger a local variable.
-mi_gdb_test "-var-create invalidframe 0 linteger" \
- "\\^error,msg=\"Failed to find the specified frame\"" \
- "create variable with invalid FRAME-ADDR"
-

##### #####
# #
@@ -151,7 +146,7 @@ mi_step_to "do_locals_tests" "" "var-cmd.c" $line_dlt_linteger "step at do_local
# Test: c_variable-2.2
# Desc: check whether only linteger changed values
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars: linteger changed"

# Step over "lpinteger = &linteger;"
@@ -160,7 +155,7 @@ mi_step_to "do_locals_tests" "" "var-cmd.c" [expr $line_dlt_linteger + 1] "step
# Test: c_variable-2.3
# Desc: check whether only lpinteger changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"lpinteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"lpinteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars: lpinteger changed"

# Step over "lcharacter = 'a';"
@@ -169,7 +164,7 @@ mi_step_to "do_locals_tests" "" "var-cmd.c" [expr $line_dlt_linteger + 2] "step
# Test: c_variable-2.4
# Desc: check whether only lcharacter changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"lcharacter\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"lcharacter\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars: lcharacter changed"

# Step over "lpcharacter = &lcharacter;"
@@ -178,7 +173,7 @@ mi_step_to "do_locals_tests" "" "var-cmd.c" [expr $line_dlt_linteger + 3] "step
# Test: c_variable-2.5
# Desc: check whether only lpcharacter changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars: lpcharacter changed"

@@ -200,7 +195,7 @@ mi_execute_to "exec-step 9" "end-stepping-range" "do_locals_tests" "" \
# Desc: check whether llong, lplong, lfloat, lpfloat, ldouble, lpdouble, lsimple.integer,
# lsimple.unsigned_character lsimple.integer lsimple.character changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"lsimple.integer\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lsimple->integer\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lsimple.character\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lpdouble\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"ldouble\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lpfloat\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lfloat\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lplong\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"llong\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"lsimple.integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lsimple->integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lsimple.character\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lpdouble\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"ldouble\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lpfloat\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lfloat\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lplong\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"llong\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars: many changed"

# Step over:
@@ -217,7 +212,7 @@ mi_execute_to "exec-step 4" "end-stepping-range" "do_locals_tests" "" \
# Test: c_variable-2.7
# Desc: check whether (lsimple.signed_character, lsimple.char_ptr) lpsimple, func changed
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"func\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lpsimple\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"func\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lpsimple\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars: func and lpsimple changed"

# Step over
@@ -239,7 +234,7 @@ mi_execute_to "exec-step 8" "end-stepping-range" "do_locals_tests" "" \
# Note: this test also checks that lpsimple->integer and lsimple.integer have
# changed (they are the same)
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"lsimple.integer\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lsimple->integer\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lsimple.character\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"ldouble\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lfloat\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"llong\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lcharacter\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"lsimple.integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lsimple->integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lsimple.character\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"ldouble\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lfloat\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"llong\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lcharacter\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars: lsimple and others changed"

@@ -262,7 +257,7 @@ mi_gdb_test "-var-assign linteger 3333" \
# change.
set lpchar_update "\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\"\},"
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[($lpchar_update)?\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[($lpchar_update)?\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars: linteger changed after assign"

mi_gdb_test "-var-assign linteger 3333" \
@@ -282,7 +277,7 @@ mi_gdb_test "-var-assign lpinteger \"&linteger + 3\"" \
"assign to lpinteger"

mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"lpinteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"lpinteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars: lpinteger changed after assign"

mi_gdb_test "-var-update *" \
@@ -407,7 +402,7 @@ mi_step_to "subroutine1" "\{name=\"i\",value=\".*\"\},\{name=\"l\",value=\".*\"\
# Test: c_variable-2.13
# Desc: change subroutine1 local i
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"i\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"i\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars: i changed"

mi_step_to "subroutine1" "\{name=\"i\",value=\".*\"\},\{name=\"l\",value=\".*\"\}" \
@@ -416,7 +411,7 @@ mi_step_to "subroutine1" "\{name=\"i\",value=\".*\"\},\{name=\"l\",value=\".*\"\
# Test: c_variable-2.14
# Desc: change do_locals_tests local llong
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"llong\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"llong\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars: llong changed"

set line_dlt_call_subroutine1 [gdb_get_line_number "subroutine1 (linteger, &llong);"]
@@ -426,7 +421,7 @@ mi_next_to "do_locals_tests" "" "var-cmd.c" \
# Test: c_variable-2.15
# Desc: check for out of scope subroutine1 locals
mi_gdb_test "-var-update *" \
- "\\^done,changelist=\\\[\{name=\"l\",in_scope=\"false\"\,type_changed=\"false\"},\{name=\"i\",in_scope=\"false\",type_changed=\"false\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"l\",in_scope=\"false\"\,type_changed=\"false\",has_more=\"0\"},\{name=\"i\",in_scope=\"false\",type_changed=\"false\",has_more=\"0\"\}\\\]" \
"update all vars: all now out of scope"

# Done with locals/globals tests. Erase all variables
@@ -518,14 +513,14 @@ mi_gdb_test "-var-create selected_a @ a" \
mi_continue_to incr_a

mi_gdb_test "-var-update selected_a" \
- "\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",type_changed=\"true\",new_type=\"char\",new_num_children=\"0\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",type_changed=\"true\",new_type=\"char\",new_num_children=\"0\"\,has_more=\"0\"}\\\]" \
"update selected_a in incr_a"

mi_next "step a line in incr_a"
mi_next "return from incr_a to do_special_tests"

mi_gdb_test "-var-update selected_a" \
- "\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",type_changed=\"true\",new_type=\"int\",new_num_children=\"0\"\}\\\]" \
+ "\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",type_changed=\"true\",new_type=\"int\",new_num_children=\"0\",has_more=\"0\"\}\\\]" \
"update selected_a in do_special_tests"

mi_gdb_test "-file-exec-and-symbols ${binfile}" "\\^done" \
diff --git a/gdb/testsuite/gdb.mi/mi2-var-display.exp b/gdb/testsuite/gdb.mi/mi2-var-display.exp
index d6ce673..17e208a 100644
--- a/gdb/testsuite/gdb.mi/mi2-var-display.exp
+++ b/gdb/testsuite/gdb.mi/mi2-var-display.exp
@@ -557,7 +557,7 @@ mi_gdb_test "-var-info-num-children e" \
# Test: c_variable-7.55
# Desc: children of e
mi_gdb_test "-var-list-children e" \
- "\\^done,numchild=\"0\"" \
+ "\\^done,numchild=\"0\",has_more=\"0\"" \
"get children of e"

# Test: c_variable-7.60
@@ -599,7 +599,7 @@ mi_gdb_test "-var-info-num-children anone" \
# Test: c_variable-7.75
# Desc: children of anone
mi_gdb_test "-var-list-children anone" \
- "\\^done,numchild=\"0\"" \
+ "\\^done,numchild=\"0\",has_more=\"0\"" \
"get children of anone"

diff --git a/gdb/testsuite/gdb.python/py-mi.exp b/gdb/testsuite/gdb.python/py-mi.exp
index d3f44b2..30d6f32 100644
--- a/gdb/testsuite/gdb.python/py-mi.exp
+++ b/gdb/testsuite/gdb.python/py-mi.exp
@@ -48,23 +48,53 @@ mi_gdb_test "python execfile ('${srcdir}/${subdir}/${testfile}.py')" ""
mi_continue_to_line [gdb_get_line_number {MI breakpoint here} ${testfile}.c] \
"step to breakpoint"

-mi_create_floating_varobj container c "create container varobj"
+mi_create_dynamic_varobj container c \
+ "create container varobj, no pretty-printing"
+
+mi_list_varobj_children container {
+ { container.name name 1 string }
+ { container.len len 0 int }
+ { container.elements elements 1 "int ." }
+} "examine container children=0, no pretty-printing"
+
+mi_delete_varobj container "delete varobj"
+
+mi_gdb_test "-enable-pretty-printing" ""
+
+mi_create_varobj_checked string string_1 \
+ "struct string_repr" \
+ "create string_1 varobj"
+
+mi_gdb_test "-data-evaluate-expression \"string_1 = string_2\"" ".*" \
+ "assign string_1 from string_2"
+
+mi_gdb_test "-var-update string" \
+ "\\^done,changelist=\\\[{name=\"string\",in_scope=\"true\",type_changed=\"false\",dynamic=\"1\",has_more=\"0\"}\\\]" \
+ "update string varobj after assignment"
+
+mi_create_dynamic_varobj container c \
+ "create container varobj"

mi_list_varobj_children container {
} "examine container children=0"

mi_next "next over update 1"

-mi_varobj_update_dynamic container {
- { {container.\[0\]} {\[0\]} 0 int }
-} "varobj update 1"
+mi_varobj_update_dynamic container "varobj update 1" {
+ type_changed false new_num_children 1 dynamic 1 has_more 0
+} {
+} {
+ { name {container.\[0\]} exp {\[0\]} numchild 0 type int thread-id 1 }
+}

mi_next "next over update 2"

-mi_varobj_update_dynamic container {
- { {container.\[0\]} {\[0\]} 0 int }
- { {container.\[1\]} {\[1\]} 0 int }
-} "varobj update 2"
+mi_varobj_update_dynamic container "varobj update 2" {
+ type_changed false new_num_children 2 dynamic 1 has_more 0
+} {
+} {
+ { name {container.\[1\]} exp {\[1\]} numchild 0 type int thread-id 1 }
+}

mi_gdb_test "-var-set-visualizer container None" \
"\\^done" \
@@ -78,19 +108,124 @@ mi_gdb_test "-var-set-visualizer container gdb.default_visualizer" \
"\\^done" \
"choose default visualizer"

-mi_varobj_update_dynamic container {
- { {container.\[0\]} {\[0\]} 0 int }
- { {container.\[1\]} {\[1\]} 0 int }
-} "varobj update after choosing default"
+mi_varobj_update_dynamic container "varobj update after choosing default" {
+ type_changed false new_num_children 2 dynamic 1 has_more 0
+} {
+} {
+ { name {container.\[0\]} exp {\[0\]} numchild 0 type int thread-id 1 }
+ { name {container.\[1\]} exp {\[1\]} numchild 0 type int thread-id 1 }
+}

mi_gdb_test "-var-set-visualizer container ContainerPrinter" \
"\\^done" \
"choose visualizer using expression"

-mi_varobj_update_dynamic container {
+mi_varobj_update_dynamic container \
+ "varobj update after choosing via expression" {
+ type_changed false new_num_children 2 dynamic 1 has_more 0
+ } {
+ } {
+ { name {container.\[0\]} exp {\[0\]} numchild 0 type int thread-id 1 }
+ { name {container.\[1\]} exp {\[1\]} numchild 0 type int thread-id 1 }
+ }
+
+mi_list_varobj_children_range container 1 2 2 {
+ { {container.\[1\]} {\[1\]} 0 int }
+} "list varobj children after selecting child range"
+
+mi_list_varobj_children_range container -1 -1 2 {
{ {container.\[0\]} {\[0\]} 0 int }
{ {container.\[1\]} {\[1\]} 0 int }
-} "varobj update after choosing via expression"
+} "list varobj children after resetting child range"
+
+mi_next "next over update 3"
+
+mi_gdb_test "-var-set-update-range container 0 1" \
+ "\\^done" \
+ "set update range"
+
+# This should truncate the list.
+mi_list_varobj_children container {
+ { {container.\[0\]} {\[0\]} 0 int }
+} "list children after setting update range"
+
+# This should return just the items in [1,2).
+mi_list_varobj_children_range container 1 2 2 {
+ { {container.\[1\]} {\[1\]} 0 int }
+} "list selected children after setting range"
+
+# This should not be affected by the previous list-children request.
+mi_list_varobj_children container {
+ { {container.\[0\]} {\[0\]} 0 int }
+} "list children after listing selected range"
+
+mi_next "next over update 4"
+
+# This should only show the first child, because the update range has
+# been set.
+mi_varobj_update_dynamic container \
+ "update after next with restricted range" {
+ type_changed false new_num_children 1 dynamic 1 has_more 1
+ } {
+ { name {container.\[0\]} in_scope true type_changed false dynamic 1 has_more 0 }
+ } {
+ }
+
+mi_gdb_test "-var-set-update-range container 3 4" \
+ "\\^done" \
+ "set update range with non-zero start"
+
+# Elements were updated but should not be reported.
+mi_varobj_update_dynamic container \
+ "update varobj with change outside selected range" {
+ type_changed false new_num_children 3 dynamic 1 has_more 0
+ } {
+ } {
+ }
+
+mi_next "next over update 5"
+
+# Regression test: examine an object that has no children, then update
+# it to ensure that we don't print the children.
+mi_create_dynamic_varobj container2 c2 \
+ "create second container varobj"
+
+mi_gdb_test "-var-update container2" \
+ "\\^done,changelist=.." \
+ "update varobj, no children requested"
+
+mi_next "next over update 6"
+
+# Now container2 has an element -- and an update should mention that
+# it has_more. But, because we did not request children, we still
+# should not actually see them.
+mi_varobj_update_dynamic container2 \
+ "update varobj 2, no children requested" {
+ type_changed false dynamic 1 has_more 1
+ } {} {}
+
+mi_continue_to_line \
+ [gdb_get_line_number {MI outer breakpoint here} ${testfile}.c] \
+ "step to outer breakpoint"
+
+mi_create_dynamic_varobj outer outer \
+ "create outer varobj"
+
+mi_list_varobj_children outer {
+ { outer.s s 2 "struct substruct" }
+ { outer.x x 0 "int" }
+} "list children of outer"
+
+mi_list_varobj_children outer.s {
+ { outer.s.a a 0 int }
+ { outer.s.b b 0 int }
+} "list children of outer.s"
+
+mi_next "next over outer update"
+
+mi_gdb_test "-var-update outer" \
+ ".done,changelist=.{name=\"outer.s.a\",in_scope=\"true\",type_changed=\"false\",dynamic=\"1\",has_more=\"0\"}." \
+ "update after updating element of outer"

mi_continue_to_line \
[gdb_get_line_number {Another MI breakpoint} ${testfile}.c] \
diff --git a/gdb/testsuite/gdb.python/py-prettyprint.c b/gdb/testsuite/gdb.python/py-prettyprint.c
index 3cafc48..7f16400 100644
--- a/gdb/testsuite/gdb.python/py-prettyprint.c
+++ b/gdb/testsuite/gdb.python/py-prettyprint.c
@@ -15,6 +15,8 @@
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 <string.h>
+
struct s
{
int a;
@@ -80,6 +82,29 @@ class Derived : public Vbase1, public Vbase2, public Vbase3

#endif

+struct substruct {
+ int a;
+ int b;
+};
+
+struct outerstruct {
+ struct substruct s;
+ int x;
+};
+
+struct outerstruct
+substruct_test (void)
+{
+ struct outerstruct outer;
+ outer.s.a = 0;
+ outer.s.b = 0;
+ outer.x = 0;
+
+ outer.s.a = 3; /* MI outer breakpoint here */
+
+ return outer;
+}
+
typedef struct string_repr
{
struct whybother
@@ -148,6 +173,14 @@ void do_nothing(void)
c = 23; /* Another MI breakpoint */
}

+struct nullstr
+{
+ char *s;
+};
+
+struct string_repr string_1 = { { "one" } };
+struct string_repr string_2 = { { "two" } };
+
int
main ()
{
@@ -155,11 +188,15 @@ main ()
struct ss ssa[2];
string x = make_string ("this is x");
zzz_type c = make_container ("container");
+ zzz_type c2 = make_container ("container2");
const struct string_repr cstring = { { "const string" } };
+ /* 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);
+ memset (&nullstr, 0, sizeof nullstr);

struct ns ns;
ns.null_str = "embedded\0null\0string";
@@ -193,6 +230,14 @@ main ()
add_item (&c, 72);

#ifdef MI
+ add_item (&c, 1011);
+ c.elements[0] = 1023;
+ c.elements[0] = 2323;
+
+ add_item (&c2, 2222);
+ add_item (&c2, 3333);
+
+ substruct_test ();
do_nothing ();
#endif

diff --git a/gdb/testsuite/gdb.python/py-prettyprint.py b/gdb/testsuite/gdb.python/py-prettyprint.py
index bf009a1..2f070d8 100644
--- a/gdb/testsuite/gdb.python/py-prettyprint.py
+++ b/gdb/testsuite/gdb.python/py-prettyprint.py
@@ -92,6 +92,13 @@ class pp_vbase1:
def to_string (self):
return "pp class name: " + self.val.type.tag

+class pp_nullstr:
+ def __init__(self, val):
+ self.val = val
+
+ def to_string(self):
+ return self.val['s'].string(gdb.parameter('target-charset'))
+
class pp_ns:
"Print a std::basic_string of some kind"

@@ -105,11 +112,24 @@ class pp_ns:
def display_hint (self):
return 'string'

+class pp_outer:
+ "Print struct outer"
+
+ def __init__ (self, val):
+ self.val = val
+
+ def to_string (self):
+ return "x = %s" % self.val['x']
+
+ def children (self):
+ yield 's', self.val['s']
+ yield 'x', self.val['x']
+
def lookup_function (val):
"Look-up and return a pretty-printer that can print val."

# Get the type.
- type = val.type;
+ type = val.type

# If it points to a reference, get the reference.
if type.code == gdb.TYPE_CODE_REF:
@@ -148,6 +168,9 @@ def register_pretty_printers ():

pretty_printers_dict[re.compile ('^VirtualTest$')] = pp_multiple_virtual
pretty_printers_dict[re.compile ('^Vbase1$')] = pp_vbase1
+
+ pretty_printers_dict[re.compile ('^struct nullstr$')] = pp_nullstr
+ pretty_printers_dict[re.compile ('^nullstr$')] = pp_nullstr

# Note that we purposely omit the typedef names here.
# Printer lookup is based on canonical name.
@@ -160,6 +183,10 @@ 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 outerstruct$')] = pp_outer
+ pretty_printers_dict[re.compile ('^outerstruct$')] = pp_outer
+
pretty_printers_dict = {}

register_pretty_printers ()
diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp
index e691232..167a02c 100644
--- a/gdb/testsuite/lib/mi-support.exp
+++ b/gdb/testsuite/lib/mi-support.exp
@@ -1195,13 +1195,13 @@ proc mi_list_breakpoints { expected test } {
# Name cannot be "-".
proc mi_create_varobj { name expression testname } {
mi_gdb_test "-var-create $name * $expression" \
- "\\^done,name=\"$name\",numchild=\"\[0-9\]+\",value=\".*\",type=.*" \
+ "\\^done,name=\"$name\",numchild=\"\[0-9\]+\",value=\".*\",type=.*,has_more=\"0\"" \
$testname
}

proc mi_create_floating_varobj { name expression testname } {
mi_gdb_test "-var-create $name @ $expression" \
- "\\^done,name=\"$name\",numchild=\"\[0-9\]+\",value=\".*\",type=.*" \
+ "\\^done,name=\"$name\",numchild=\"\(-1\|\[0-9\]+\)\",value=\".*\",type=.*" \
$testname
}

@@ -1214,6 +1214,14 @@ proc mi_create_varobj_checked { name expression type testname } {
$testname
}

+# Same as mi_create_floating_varobj, but assumes the test is creating
+# a dynamic varobj that has children, so the value must be "{...}".
+proc mi_create_dynamic_varobj {name expression testname} {
+ mi_gdb_test "-var-create $name @ $expression" \
+ "\\^done,name=\"$name\",numchild=\"\(-1\|\[0-9\]+\)\",value=\"{\\.\\.\\.}\",type=.*" \
+ $testname
+}
+
# Deletes the specified NAME.
proc mi_delete_varobj { name testname } {
mi_gdb_test "-var-delete $name" \
@@ -1229,7 +1237,7 @@ proc mi_varobj_update { name expected testname } {
set er "\\^done,changelist=\\\["
set first 1
foreach item $expected {
- set v "{name=\"$item\",in_scope=\"true\",type_changed=\"false\"}"
+ set v "{name=\"$item\",in_scope=\"true\",type_changed=\"false\",has_more=\".\"}"
if {$first == 1} {
set er "$er$v"
set first 0
@@ -1244,22 +1252,70 @@ proc mi_varobj_update { name expected testname } {
}

proc mi_varobj_update_with_type_change { name new_type new_children testname } {
- set v "{name=\"$name\",in_scope=\"true\",type_changed=\"true\",new_type=\"$new_type\",new_num_children=\"$new_children\"}"
+ set v "{name=\"$name\",in_scope=\"true\",type_changed=\"true\",new_type=\"$new_type\",new_num_children=\"$new_children\",has_more=\".\"}"
set er "\\^done,changelist=\\\[$v\\\]"
verbose -log "Expecting: $er"
mi_gdb_test "-var-update $name" $er $testname
}

-# Update a dynamic varobj named NAME. CHILDREN is a list of children,
-# in the same form as mi_list_varobj_children. TESTNAME is the name
-# of the test.
-proc mi_varobj_update_dynamic {name children testname} {
- set children_exp_j [mi_child_regexp $children 0]
+# A helper that turns a key/value list into a regular expression
+# matching some MI output.
+proc mi_varobj_update_kv_helper {list} {
+ set first 1
+ set rx ""
+ foreach {key value} $list {
+ if {!$first} {
+ append rx ,
+ }
+ set first 0
+ if {$key == "new_children"} {
+ append rx "$key=\\\[$value\\\]"
+ } else {
+ append rx "$key=\"$value\""
+ }
+ }
+ return $rx
+}

- set er "\\^done,changelist=\\\["
+# A helper for mi_varobj_update_dynamic that computes a match
+# expression given a child list.
+proc mi_varobj_update_dynamic_helper {children} {
+ set crx ""

- append er "{name=\"$name\",in_scope=\"true\",type_changed=\"false\""
- append er ",children=\\\[$children_exp_j.*\\\]}\\\]"
+ set first 1
+ foreach child $children {
+ if {!$first} {
+ append crx ,
+ }
+ set first 0
+ append crx "{"
+ append crx [mi_varobj_update_kv_helper $child]
+ append crx "}"
+ }
+
+ return $crx
+}
+
+# Update a dynamic varobj named NAME. CHILDREN is a list of children
+# that have been updated; NEW_CHILDREN is a list of children that were
+# added to the primary varobj. Each child is a list of key/value
+# pairs that are expected. SELF is a key/value list holding
+# information about the varobj itself. TESTNAME is the name of the
+# test.
+proc mi_varobj_update_dynamic {name testname self children new_children} {
+ if {[llength $new_children]} {
+ set newrx [mi_varobj_update_dynamic_helper $new_children]
+ lappend self new_children $newrx
+ }
+ set selfrx [mi_varobj_update_kv_helper $self]
+ set crx [mi_varobj_update_dynamic_helper $children]
+
+ set er "\\^done,changelist=\\\[\{name=\"$name\",in_scope=\"true\""
+ append er ",$selfrx\}"
+ if {"$crx" != ""} {
+ append er ",$crx"
+ }
+ append er "\\\]"

verbose -log "Expecting: $er"
mi_gdb_test "-var-update $name" $er $testname
@@ -1329,14 +1385,13 @@ proc mi_child_regexp {children add_child} {
# have no value.
#
proc mi_list_varobj_children { varname children testname } {
- mi_list_varobj_children_range $varname [llength $children] $children \
+ mi_list_varobj_children_range $varname "" "" [llength $children] $children \
$testname
}

-# Like mi_list_varobj_children, but assumes that a subrange has been
-# selected with -var-set-child-range. NUMCHILDREN is the total number
-# of children.
-proc mi_list_varobj_children_range {varname numchildren children testname} {
+# Like mi_list_varobj_children, but sets a subrange. NUMCHILDREN is
+# the total number of children.
+proc mi_list_varobj_children_range {varname from to numchildren children testname} {
set options ""
if {[llength $varname] == 2} {
set options [lindex $varname 1]
@@ -1352,9 +1407,18 @@ proc mi_list_varobj_children_range {varname numchildren children testname} {
set expected "\\^done,numchild=\"0\""
}

+ if {"$to" == ""} {
+ append expected ",has_more=\"0\""
+ } elseif {$to >= 0 && $numchildren > $to} {
+ append expected ",has_more=\"1\""
+ } else {
+ append expected ",has_more=\"0\""
+ }
+
verbose -log "Expecting: $expected"

- mi_gdb_test "-var-list-children $options $varname" $expected $testname
+ mi_gdb_test "-var-list-children $options $varname $from $to" \
+ $expected $testname
}

# Verifies that variable object VARNAME has NUMBER children,
diff --git a/gdb/varobj.c b/gdb/varobj.c
index 603071f..e7fb589 100644
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -29,6 +29,7 @@

#include "gdb_assert.h"
#include "gdb_string.h"
+#include "gdb_regex.h"

#include "varobj.h"
#include "vec.h"
@@ -59,6 +60,15 @@ char *varobj_format_string[] =
/* String representations of gdb's known languages */
char *varobj_language_string[] = { "unknown", "C", "C++", "Java" };

+/* True if we want to allow Python-based pretty-printing. */
+static int pretty_printing = 0;
+
+void
+varobj_enable_pretty_printing (void)
+{
+ pretty_printing = 1;
+}
+
/* Data structures */

/* Every root variable has one of these structures saved in its
@@ -173,9 +183,31 @@ struct varobj
frozen. */
int not_fetched;

+ /* Sub-range of children which the MI consumer has requested. If
+ FROM < 0 or TO < 0, means that all children have been
+ requested. */
+ int from;
+ int to;
+
+ /* The pretty-printer constructor. If NULL, then the default
+ pretty-printer will be looked up. If None, then no
+ pretty-printer will be installed. */
+ PyObject *constructor;
+
/* The pretty-printer that has been constructed. If NULL, then a
new printer object is needed, and one will be constructed. */
PyObject *pretty_printer;
+
+ /* The iterator returned by the printer's 'children' method, or NULL
+ if not available. */
+ PyObject *child_iter;
+
+ /* We request one extra item from the iterator, so that we can
+ report to the caller whether there are more items than we have
+ already reported. However, we don't want to install this value
+ when we read it, because that will mess up future updates. So,
+ we stash it here instead. */
+ PyObject *saved_item;
};

struct cpstack
@@ -236,8 +268,6 @@ static char *cppop (struct cpstack **pstack);
static int install_new_value (struct varobj *var, struct value *value,
int initial);

-static void install_default_visualizer (struct varobj *var);
-
/* Language-specific routines. */

static enum varobj_languages variable_language (struct varobj *var);
@@ -623,7 +653,6 @@ varobj_create (char *objname,
}
}

- install_default_visualizer (var);
discard_cleanups (old_chain);
return var;
}
@@ -738,15 +767,8 @@ instantiate_pretty_printer (PyObject *constructor, struct value *value)
#if HAVE_PYTHON
PyObject *val_obj = NULL;
PyObject *printer;
- volatile struct gdb_exception except;

- TRY_CATCH (except, RETURN_MASK_ALL)
- {
- value = value_copy (value);
- }
- GDB_PY_HANDLE_EXCEPTION (except);
val_obj = value_to_value_object (value);
-
if (! val_obj)
return NULL;

@@ -810,6 +832,17 @@ varobj_get_display_hint (struct varobj *var)
return result;
}

+/* Return true if the varobj has items after TO, false otherwise. */
+
+int
+varobj_has_more (struct varobj *var, int to)
+{
+ if (VEC_length (varobj_p, var->children) > to)
+ return 1;
+ return ((to == -1 || VEC_length (varobj_p, var->children) == to)
+ && var->saved_item != NULL);
+}
+
/* If the variable object is bound to a specific thread, that
is its evaluation can always be done in context of a frame
inside that thread, returns GDB id of the thread -- which
@@ -842,22 +875,97 @@ varobj_get_frozen (struct varobj *var)
return var->frozen;
}

+/* A helper function that restricts a range to what is actually
+ available in a VEC. This follows the usual rules for the meaning
+ of FROM and TO -- if either is negative, the entire range is
+ used. */
+
+static void
+restrict_range (VEC (varobj_p) *children, int *from, int *to)
+{
+ if (*from < 0 || *to < 0)
+ {
+ *from = 0;
+ *to = VEC_length (varobj_p, children);
+ }
+ else
+ {
+ if (*from > VEC_length (varobj_p, children))
+ *from = VEC_length (varobj_p, children);
+ if (*to > VEC_length (varobj_p, children))
+ *to = VEC_length (varobj_p, children);
+ if (*from > *to)
+ *from = *to;
+ }
+}
+
+/* A helper for update_dynamic_varobj_children that installs a new
+ child when needed. */
+
+static void
+install_dynamic_child (struct varobj *var,
+ VEC (varobj_p) **changed,
+ VEC (varobj_p) **new,
+ VEC (varobj_p) **unchanged,
+ int *cchanged,
+ int index,
+ const char *name,
+ struct value *value)
+{
+ if (VEC_length (varobj_p, var->children) < index + 1)
+ {
+ /* There's no child yet. */
+ struct varobj *child = varobj_add_child (var, name, value);
+ if (new)
+ {
+ VEC_safe_push (varobj_p, *new, child);
+ *cchanged = 1;
+ }
+ }
+ else
+ {
+ varobj_p existing = VEC_index (varobj_p, var->children, index);
+ if (install_new_value (existing, value, 0))
+ {
+ if (changed)
+ VEC_safe_push (varobj_p, *changed, existing);
+ }
+ else if (unchanged)
+ VEC_safe_push (varobj_p, *unchanged, existing);
+ }
+}
+
+#if HAVE_PYTHON
+
+static int
+dynamic_varobj_has_child_method (struct varobj *var)
+{
+ struct cleanup *back_to;
+ PyObject *printer = var->pretty_printer;
+ int result;
+
+ back_to = varobj_ensure_python_env (var);
+ result = PyObject_HasAttr (printer, gdbpy_children_cst);
+ do_cleanups (back_to);
+ return result;
+}
+
+#endif
+
static int
update_dynamic_varobj_children (struct varobj *var,
VEC (varobj_p) **changed,
- VEC (varobj_p) **new_and_unchanged,
- int *cchanged)
-
+ VEC (varobj_p) **new,
+ VEC (varobj_p) **unchanged,
+ int *cchanged,
+ int update_children,
+ int from,
+ int to)
{
#if HAVE_PYTHON
- /* FIXME: we *might* want to provide this functionality as
- a standalone function, so that other interested parties
- than varobj code can benefit for this. */
struct cleanup *back_to;
PyObject *children;
- PyObject *iterator;
int i;
- int children_changed = 0;
PyObject *printer = var->pretty_printer;

back_to = varobj_ensure_python_env (var);
@@ -869,87 +977,106 @@ update_dynamic_varobj_children (struct varobj *var,
return 0;
}

- children = PyObject_CallMethodObjArgs (printer, gdbpy_children_cst,
- NULL);
-
- if (!children)
+ if (update_children || !var->child_iter)
{
- gdbpy_print_stack ();
- error (_("Null value returned for children"));
- }
+ children = PyObject_CallMethodObjArgs (printer, gdbpy_children_cst,
+ NULL);
+
+ if (!children)
+ {
+ gdbpy_print_stack ();
+ error (_("Null value returned for children"));
+ }

- make_cleanup_py_decref (children);
+ make_cleanup_py_decref (children);

- if (!PyIter_Check (children))
- error (_("Returned value is not iterable"));
+ if (!PyIter_Check (children))
+ error (_("Returned value is not iterable"));

- iterator = PyObject_GetIter (children);
- if (!iterator)
- {
- gdbpy_print_stack ();
- error (_("Could not get children iterator"));
+ Py_XDECREF (var->child_iter);
+ var->child_iter = PyObject_GetIter (children);
+ if (!var->child_iter)
+ {
+ gdbpy_print_stack ();
+ error (_("Could not get children iterator"));
+ }
+
+ Py_XDECREF (var->saved_item);
+ var->saved_item = NULL;
+
+ i = 0;
}
- make_cleanup_py_decref (iterator);
+ else
+ i = VEC_length (varobj_p, var->children);

- for (i = 0; ; ++i)
+ /* We ask for one extra child, so that MI can report whether there
+ are more children. */
+ for (; to < 0 || i < to + 1; ++i)
{
- PyObject *item = PyIter_Next (iterator);
- PyObject *py_v;
- struct value *v;
- char *name;
- struct cleanup *inner;
-
- if (!item)
- break;
- inner = make_cleanup_py_decref (item);
+ PyObject *item;

- if (!PyArg_ParseTuple (item, "sO", &name, &py_v))
- error (_("Invalid item from the child list"));
-
- v = convert_value_from_python (py_v);
+ /* See if there was a leftover from last time. */
+ if (var->saved_item)
+ {
+ item = var->saved_item;
+ var->saved_item = NULL;
+ }
+ else
+ item = PyIter_Next (var->child_iter);

- /* TODO: This assume the name of the i-th child never changes. */
+ if (!item)
+ break;

- /* Now see what to do here. */
- if (VEC_length (varobj_p, var->children) < i + 1)
+ /* We don't want to push the extra child on any report list. */
+ if (to < 0 || i < to)
{
- /* There's no child yet. */
- struct varobj *child = varobj_add_child (var, name, v);
- if (new_and_unchanged)
- VEC_safe_push (varobj_p, *new_and_unchanged, child);
- children_changed = 1;
+ PyObject *py_v;
+ char *name;
+ struct value *v;
+ struct cleanup *inner;
+ int can_mention = from < 0 || i >= from;
+
+ inner = make_cleanup_py_decref (item);
+
+ if (!PyArg_ParseTuple (item, "sO", &name, &py_v))
+ error (_("Invalid item from the child list"));
+
+ v = convert_value_from_python (py_v);
+ install_dynamic_child (var, can_mention ? changed : NULL,
+ can_mention ? new : NULL,
+ can_mention ? unchanged : NULL,
+ can_mention ? cchanged : NULL, i, name, v);
+ do_cleanups (inner);
}
- else
+ else
{
- varobj_p existing = VEC_index (varobj_p, var->children, i);
- if (install_new_value (existing, v, 0) && changed)
- {
- if (changed)
- VEC_safe_push (varobj_p, *changed, existing);
- }
- else
- {
- if (new_and_unchanged)
- VEC_safe_push (varobj_p, *new_and_unchanged, existing);
- }
- }
+ Py_XDECREF (var->saved_item);
+ var->saved_item = item;

- do_cleanups (inner);
+ /* We want to truncate the child list just before this
+ element. */
+ break;
+ }
}

if (i < VEC_length (varobj_p, var->children))
{
- int i;
- children_changed = 1;
- for (i = 0; i < VEC_length (varobj_p, var->children); ++i)
- varobj_delete (VEC_index (varobj_p, var->children, i), NULL, 0);
+ int j;
+ *cchanged = 1;
+ for (j = i; j < VEC_length (varobj_p, var->children); ++j)
+ varobj_delete (VEC_index (varobj_p, var->children, j), NULL, 0);
+ VEC_truncate (varobj_p, var->children, i);
}
- VEC_truncate (varobj_p, var->children, i);
+
+ /* If there are fewer children than requested, note that the list of
+ children changed. */
+ if (to >= 0 && VEC_length (varobj_p, var->children) < to)
+ *cchanged = 1;
+
var->num_children = VEC_length (varobj_p, var->children);

do_cleanups (back_to);

- *cchanged = children_changed;
return 1;
#else
gdb_assert (0 && "should never be called if Python is not enabled");
@@ -961,20 +1088,27 @@ varobj_get_num_children (struct varobj *var)
{
if (var->num_children == -1)
{
- int changed;
- if (!var->pretty_printer
- || !update_dynamic_varobj_children (var, NULL, NULL, &changed))
+ if (var->pretty_printer)
+ {
+ int dummy;
+
+ /* If we have a dynamic varobj, don't report -1 children.
+ So, try to fetch some children first. */
+ update_dynamic_varobj_children (var, NULL, NULL, NULL, &dummy,
+ 0, 0, 0);
+ }
+ else
var->num_children = number_of_children (var);
}

- return var->num_children;
+ return var->num_children >= 0 ? var->num_children : 0;
}

/* Creates a list of the immediate children of a variable object;
the return code is the number of such children or -1 on error */

VEC (varobj_p)*
-varobj_list_children (struct varobj *var)
+varobj_list_children (struct varobj *var, int *from, int *to)
{
struct varobj *child;
char *name;
@@ -982,12 +1116,16 @@ varobj_list_children (struct varobj *var)

var->children_requested = 1;

- if (var->pretty_printer
+ if (var->pretty_printer)
+ {
/* This, in theory, can result in the number of children changing without
frontend noticing. But well, calling -var-list-children on the same
varobj twice is not something a sane frontend would do. */
- && update_dynamic_varobj_children (var, NULL, NULL, &children_changed))
- return var->children;
+ update_dynamic_varobj_children (var, NULL, NULL, NULL, &children_changed,
+ 0, 0, *to);
+ restrict_range (var->children, from, to);
+ return var->children;
+ }

if (var->num_children == -1)
var->num_children = number_of_children (var);
@@ -1013,10 +1151,10 @@ varobj_list_children (struct varobj *var)
name = name_of_child (var, i);
existing = create_child (var, i, name);
VEC_replace (varobj_p, var->children, i, existing);
- install_default_visualizer (existing);
}
}

+ restrict_range (var->children, from, to);
return var->children;
}

@@ -1027,7 +1165,6 @@ varobj_add_child (struct varobj *var, const char *name, struct value *value)
VEC_length (varobj_p, var->children),
name, value);
VEC_safe_push (varobj_p, var->children, v);
- install_default_visualizer (v);
return v;
}

@@ -1089,6 +1226,12 @@ varobj_get_attributes (struct varobj *var)
return attributes;
}

+int
+varobj_pretty_printed_p (struct varobj *var)
+{
+ return var->pretty_printer != NULL;
+}
+
char *
varobj_get_formatted_value (struct varobj *var,
enum varobj_display_formats format)
@@ -1166,6 +1309,116 @@ varobj_set_value (struct varobj *var, char *expression)
return 1;
}

+#if HAVE_PYTHON
+
+/* A helper function to install a constructor function and visualizer
+ in a varobj. */
+
+static void
+install_visualizer (struct varobj *var, PyObject *constructor,
+ PyObject *visualizer)
+{
+ Py_XDECREF (var->constructor);
+ var->constructor = constructor;
+
+ Py_XDECREF (var->pretty_printer);
+ var->pretty_printer = visualizer;
+
+ Py_XDECREF (var->child_iter);
+ var->child_iter = NULL;
+}
+
+/* Install the default visualizer for VAR. */
+
+static void
+install_default_visualizer (struct varobj *var)
+{
+ if (pretty_printing)
+ {
+ PyObject *pretty_printer = NULL;
+
+ if (var->value)
+ {
+ pretty_printer = gdbpy_get_varobj_pretty_printer (var->value);
+ if (! pretty_printer)
+ {
+ gdbpy_print_stack ();
+ error (_("Cannot instantiate printer for default visualizer"));
+ }
+ }
+
+ if (pretty_printer == Py_None)
+ {
+ Py_DECREF (pretty_printer);
+ pretty_printer = NULL;
+ }
+
+ install_visualizer (var, NULL, pretty_printer);
+ }
+}
+
+/* Instantiate and install a visualizer for VAR using CONSTRUCTOR to
+ make a new object. */
+
+static void
+construct_visualizer (struct varobj *var, PyObject *constructor)
+{
+ PyObject *pretty_printer;
+
+ Py_INCREF (constructor);
+ if (constructor == Py_None)
+ pretty_printer = NULL;
+ else
+ {
+ pretty_printer = instantiate_pretty_printer (constructor, var->value);
+ if (! pretty_printer)
+ {
+ gdbpy_print_stack ();
+ Py_DECREF (constructor);
+ constructor = Py_None;
+ Py_INCREF (constructor);
+ }
+
+ if (pretty_printer == Py_None)
+ {
+ Py_DECREF (pretty_printer);
+ pretty_printer = NULL;
+ }
+ }
+
+ install_visualizer (var, constructor, pretty_printer);
+}
+
+#endif /* HAVE_PYTHON */
+
+/* A helper function for install_new_value. This creates and installs
+ a visualizer for VAR, if appropriate. */
+
+static void
+install_new_value_visualizer (struct varobj *var)
+{
+#if HAVE_PYTHON
+ /* If the constructor is None, then we want the raw value. If VAR
+ does not have a value, just skip this. */
+ if (var->constructor != Py_None && var->value)
+ {
+ struct cleanup *cleanup;
+ PyObject *pretty_printer = NULL;
+
+ cleanup = varobj_ensure_python_env (var);
+
+ if (!var->constructor)
+ install_default_visualizer (var);
+ else
+ construct_visualizer (var, var->constructor);
+
+ do_cleanups (cleanup);
+ }
+#else
+ /* Do nothing. */
+#endif
+}
+
/* Assign a new value to a variable object. If INITIAL is non-zero,
this is the first assignement after the variable object was just
created, or changed type. In that case, just assign the value
@@ -1206,10 +1459,7 @@ install_new_value (struct varobj *var, struct value *value, int initial)
that in C++ a reference is not rebindable, it cannot
meaningfully change. So, get hold of the real value. */
if (value)
- {
- value = coerce_ref (value);
- release_value (value);
- }
+ value = coerce_ref (value);

if (var->type && TYPE_CODE (var->type) == TYPE_CODE_UNION)
/* For unions, we need to fetch the value implicitly because
@@ -1256,7 +1506,7 @@ install_new_value (struct varobj *var, struct value *value, int initial)
values. Don't get string rendering if the value is
lazy -- if it is, the code above has decided that the value
should not be fetched. */
- if (value && !value_lazy (value))
+ if (value && !value_lazy (value) && !var->pretty_printer)
print_value = value_get_print_value (value, var->format, var);

/* If the type is changeable, compare the old and the new values.
@@ -1272,7 +1522,7 @@ install_new_value (struct varobj *var, struct value *value, int initial)
{
changed = 1;
}
- else
+ else if (! var->pretty_printer)
{
/* Try to compare the values. That requires that both
values are non-lazy. */
@@ -1317,74 +1567,53 @@ install_new_value (struct varobj *var, struct value *value, int initial)
if (var->value != NULL && var->value != value)
value_free (var->value);
var->value = value;
- if (var->print_value)
- xfree (var->print_value);
- var->print_value = print_value;
+ if (value != NULL)
+ value_incref (value);
if (value && value_lazy (value) && intentionally_not_fetched)
var->not_fetched = 1;
else
var->not_fetched = 0;
var->updated = 0;

+ install_new_value_visualizer (var);
+
+ /* If we installed a pretty-printer, re-compare the printed version
+ to see if the variable changed. */
+ if (var->pretty_printer)
+ {
+ xfree (print_value);
+ print_value = value_get_print_value (var->value, var->format, var);
+ if (!var->print_value || strcmp (var->print_value, print_value) != 0)
+ changed = 1;
+ }
+ if (var->print_value)
+ xfree (var->print_value);
+ var->print_value = print_value;
+
gdb_assert (!var->value || value_type (var->value));

return changed;
}

-static void
-install_visualizer (struct varobj *var, PyObject *visualizer)
+/* Return the requested range for a varobj. VAR is the varobj. FROM
+ and TO are out parameters; *FROM and *TO will be set to the
+ selected sub-range of VAR. If no range was selected using
+ -var-set-update-range, then both will be -1. */
+void
+varobj_get_child_range (struct varobj *var, int *from, int *to)
{
-#if HAVE_PYTHON
- /* If there are any children now, wipe them. */
- varobj_delete (var, NULL, 1 /* children only */);
- var->num_children = -1;
-
- Py_XDECREF (var->pretty_printer);
- var->pretty_printer = visualizer;
-
- install_new_value (var, var->value, 1);
-
- /* If we removed the visualizer, and the user ever requested the
- object's children, then we must compute the list of children.
- Note that we needn't do this when installing a visualizer,
- because updating will recompute dynamic children. */
- if (!visualizer && var->children_requested)
- varobj_list_children (var);
-#else
- error (_("Python support required"));
-#endif
+ *from = var->from;
+ *to = var->to;
}

-static void
-install_default_visualizer (struct varobj *var)
+/* Set the selected sub-range of children of VAR to start at index
+ FROM and end at index TO. If either FROM or TO is less than zero,
+ this is interpreted as a request for all children. */
+void
+varobj_set_child_range (struct varobj *var, int from, int to)
{
-#if HAVE_PYTHON
- struct cleanup *cleanup;
- PyObject *pretty_printer = NULL;
-
- cleanup = varobj_ensure_python_env (var);
-
- if (var->value)
- {
- pretty_printer = gdbpy_get_varobj_pretty_printer (var->value);
- if (! pretty_printer)
- {
- gdbpy_print_stack ();
- error (_("Cannot instantiate printer for default visualizer"));
- }
- }
-
- if (pretty_printer == Py_None)
- {
- Py_DECREF (pretty_printer);
- pretty_printer = NULL;
- }
-
- install_visualizer (var, pretty_printer);
- do_cleanups (cleanup);
-#else
- /* No error is right as this function is inserted just as a hook. */
-#endif
+ var->from = from;
+ var->to = to;
}

void
@@ -1402,31 +1631,19 @@ varobj_set_visualizer (struct varobj *var, const char *visualizer)
make_cleanup_py_decref (globals);

constructor = PyRun_String (visualizer, Py_eval_input, globals, globals);
-
- /* Do not instantiate NoneType. */
- if (constructor == Py_None)
- {
- pretty_printer = Py_None;
- Py_INCREF (pretty_printer);
- }
- else
- pretty_printer = instantiate_pretty_printer (constructor, var->value);
-
- Py_XDECREF (constructor);

- if (! pretty_printer)
+ if (! constructor)
{
gdbpy_print_stack ();
error (_("Could not evaluate visualizer expression: %s"), visualizer);
}

- if (pretty_printer == Py_None)
- {
- Py_DECREF (pretty_printer);
- pretty_printer = NULL;
- }
+ construct_visualizer (var, constructor);
+ Py_XDECREF (constructor);

- install_visualizer (var, pretty_printer);
+ /* If there are any children now, wipe them. */
+ varobj_delete (var, NULL, 1 /* children only */);
+ var->num_children = -1;

do_cleanups (back_to);
#else
@@ -1537,44 +1754,75 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit)

/* We probably should not get children of a varobj that has a
pretty-printer, but for which -var-list-children was never
- invoked. Presumably, such varobj is not yet expanded in the
- UI, so we need not bother getting it. */
+ invoked. */
if (v->pretty_printer)
{
- VEC (varobj_p) *changed = 0, *new_and_unchanged = 0;
+ VEC (varobj_p) *changed = 0, *new = 0, *unchanged = 0;
int i, children_changed;
varobj_p tmp;

- if (!v->children_requested)
- continue;
-
if (v->frozen)
continue;

+ if (!v->children_requested)
+ {
+ int dummy;
+
+ /* If we initially did not have potential children, but
+ now we do, consider the varobj as changed.
+ Otherwise, if children were never requested, consider
+ it as unchanged -- presumably, such varobj is not yet
+ expanded in the UI, so we need not bother getting
+ it. */
+ if (!varobj_has_more (v, 0))
+ {
+ update_dynamic_varobj_children (v, NULL, NULL, NULL,
+ &dummy, 0, 0, 0);
+ if (varobj_has_more (v, 0))
+ r.changed = 1;
+ }
+
+ if (r.changed)
+ VEC_safe_push (varobj_update_result, result, &r);
+
+ continue;
+ }
+
/* If update_dynamic_varobj_children returns 0, then we have
a non-conforming pretty-printer, so we skip it. */
- if (update_dynamic_varobj_children (v, &changed, &new_and_unchanged,
- &children_changed))
+ if (update_dynamic_varobj_children (v, &changed, &new, &unchanged,
+ &children_changed, 1,
+ v->from, v->to))
{
- if (children_changed)
- r.children_changed = 1;
- for (i = 0; VEC_iterate (varobj_p, changed, i, tmp); ++i)
+ if (children_changed || new)
{
- varobj_update_result r = {tmp};
- r.changed = 1;
- r.value_installed = 1;
- VEC_safe_push (varobj_update_result, stack, &r);
+ r.children_changed = 1;
+ r.new = new;
}
- for (i = 0;
- VEC_iterate (varobj_p, new_and_unchanged, i, tmp);
- ++i)
+ for (i = 0; VEC_iterate (varobj_p, changed, i, tmp); ++i)
{
varobj_update_result r = {tmp};
+ r.changed = 1;
r.value_installed = 1;
VEC_safe_push (varobj_update_result, stack, &r);
}
+ for (i = 0; VEC_iterate (varobj_p, unchanged, i, tmp); ++i)
+ {
+ if (!tmp->frozen)
+ {
+ varobj_update_result r = {tmp};
+ r.value_installed = 1;
+ VEC_safe_push (varobj_update_result, stack, &r);
+ }
+ }
if (r.changed || r.children_changed)
VEC_safe_push (varobj_update_result, result, &r);
+
+ /* Free CHANGED and UNCHANGED, but not NEW, because NEW
+ has been put into the result vector. */
+ VEC_free (varobj_p, changed);
+ VEC_free (varobj_p, unchanged);
+
continue;
}
}
@@ -1862,7 +2110,12 @@ new_variable (void)
var->frozen = 0;
var->not_fetched = 0;
var->children_requested = 0;
+ var->from = -1;
+ var->to = -1;
+ var->constructor = 0;
var->pretty_printer = 0;
+ var->child_iter = 0;
+ var->saved_item = 0;

return var;
}
@@ -1892,7 +2145,10 @@ free_variable (struct varobj *var)
if (var->pretty_printer)
{
struct cleanup *cleanup = varobj_ensure_python_env (var);
- Py_DECREF (var->pretty_printer);
+ Py_XDECREF (var->constructor);
+ Py_XDECREF (var->pretty_printer);
+ Py_XDECREF (var->child_iter);
+ Py_XDECREF (var->saved_item);
do_cleanups (cleanup);
}
#endif
@@ -2139,6 +2395,8 @@ value_of_root (struct varobj **var_handle, int *type_changed)
else
{
tmp_var->obj_name = xstrdup (var->obj_name);
+ tmp_var->from = var->from;
+ tmp_var->to = var->to;
varobj_delete (var, NULL, 0);

install_variable (tmp_var);
@@ -2173,7 +2431,11 @@ static char *
my_value_of_variable (struct varobj *var, enum varobj_display_formats format)
{
if (var->root->is_valid)
- return (*var->root->lang->value_of_variable) (var, format);
+ {
+ if (var->pretty_printer)
+ return value_get_print_value (var->value, var->format, var);
+ return (*var->root->lang->value_of_variable) (var, format);
+ }
else
return NULL;
}
@@ -2196,43 +2458,51 @@ value_get_print_value (struct value *value, enum varobj_display_formats format,
struct cleanup *back_to = varobj_ensure_python_env (var);
PyObject *value_formatter = var->pretty_printer;

- if (value_formatter && PyObject_HasAttr (value_formatter,
- gdbpy_to_string_cst))
+ if (value_formatter)
{
- char *hint;
- struct value *replacement;
- int string_print = 0;
- PyObject *output = NULL;
+ /* First check to see if we have any children at all. If so,
+ we simply return {...}. */
+ if (dynamic_varobj_has_child_method (var))
+ return xstrdup ("{...}");

- hint = gdbpy_get_display_hint (value_formatter);
- if (hint)
+ if (PyObject_HasAttr (value_formatter, gdbpy_to_string_cst))
{
- if (!strcmp (hint, "string"))
- string_print = 1;
- xfree (hint);
- }
+ char *hint;
+ struct value *replacement;
+ int string_print = 0;
+ PyObject *output = NULL;
+
+ hint = gdbpy_get_display_hint (value_formatter);
+ if (hint)
+ {
+ if (!strcmp (hint, "string"))
+ string_print = 1;
+ xfree (hint);
+ }

- output = apply_varobj_pretty_printer (value_formatter,
- &replacement);
- if (output)
- {
- PyObject *py_str = python_string_to_target_python_string (output);
- if (py_str)
- {
- char *s = PyString_AsString (py_str);
- len = PyString_Size (py_str);
- thevalue = xmemdup (s, len + 1, len + 1);
- Py_DECREF (py_str);
+ output = apply_varobj_pretty_printer (value_formatter,
+ &replacement);
+ if (output)
+ {
+ PyObject *py_str
+ = python_string_to_target_python_string (output);
+ if (py_str)
+ {
+ char *s = PyString_AsString (py_str);
+ len = PyString_Size (py_str);
+ thevalue = xmemdup (s, len + 1, len + 1);
+ Py_DECREF (py_str);
+ }
+ Py_DECREF (output);
}
- Py_DECREF (output);
- }
- if (thevalue && !string_print)
- {
- do_cleanups (back_to);
- return thevalue;
+ if (thevalue && !string_print)
+ {
+ do_cleanups (back_to);
+ return thevalue;
+ }
+ if (replacement)
+ value = replacement;
}
- if (replacement)
- value = replacement;
}
do_cleanups (back_to);
}
@@ -2961,10 +3231,7 @@ cplus_describe_child (struct varobj *parent, int index,
*cname = xstrdup (TYPE_FIELD_NAME (type, index));

if (cvalue && value)
- {
- *cvalue = value_cast (TYPE_FIELD_TYPE (type, index), value);
- release_value (*cvalue);
- }
+ *cvalue = value_cast (TYPE_FIELD_TYPE (type, index), value);

if (ctype)
{
diff --git a/gdb/varobj.h b/gdb/varobj.h
index 7297243..f43c593 100644
--- a/gdb/varobj.h
+++ b/gdb/varobj.h
@@ -78,6 +78,12 @@ typedef struct varobj_update_result_t
new value of varobj is already computed and installed, or has to
be yet installed. Don't use this outside varobj.c */
int value_installed;
+
+ /* This will be non-NULL when new children were added to the varobj.
+ It lists the new children (which must necessarily come at the end
+ of the child list) added during an update. The caller is
+ responsible for freeing this vector. */
+ VEC (varobj_p) *new;
} varobj_update_result;

DEF_VEC_O (varobj_update_result);
@@ -112,13 +118,24 @@ extern void varobj_set_frozen (struct varobj *var, int frozen);

extern int varobj_get_frozen (struct varobj *var);

+extern void varobj_get_child_range (struct varobj *var, int *from, int *to);
+
+extern void varobj_set_child_range (struct varobj *var, int from, int to);
+
extern char *varobj_get_display_hint (struct varobj *var);

extern int varobj_get_num_children (struct varobj *var);

-/* Return the list of children of VAR. The returned vector
- should not be modified in any way. */
-extern VEC (varobj_p)* varobj_list_children (struct varobj *var);
+/* Return the list of children of VAR. The returned vector should not
+ be modified in any way. FROM and TO are in/out parameters
+ indicating the range of children to return. If either *FROM or *TO
+ is less than zero on entry, then all children will be returned. On
+ return, *FROM and *TO will be updated to indicate the real range
+ that was returned. The resulting VEC will contain at least the
+ children from *FROM to just before *TO; it might contain more
+ children, depending on whether any more were available. */
+extern VEC (varobj_p)* varobj_list_children (struct varobj *var,
+ int *from, int *to);

extern char *varobj_get_type (struct varobj *var);

@@ -149,6 +166,13 @@ extern int varobj_editable_p (struct varobj *var);

extern int varobj_floating_p (struct varobj *var);

-extern void varobj_set_visualizer (struct varobj *var, const char *visualizer);
+extern void
+varobj_set_visualizer (struct varobj *var, const char *visualizer);
+
+extern void varobj_enable_pretty_printing (void);
+
+extern int varobj_has_more (struct varobj *var, int to);
+
+extern int varobj_pretty_printed_p (struct varobj *var);

#endif /* VAROBJ_H */