Patch: implement new dynamic varobj spec

Tom Tromey
2009-09-10T20:58:38Z

This is the long-awaited dynamic varobj patch.
It implements the spec as described by Vladimir:

http://sourceware.org/ml/gdb/2009-07/msg00088.html

.. with various minor changes we've discussed on that thread and
elsewhere. I didn't give the follow-up URLs; I think that the doc patch
ought to be sufficient, and if it isn't, I will fix it up.

This has been in development for quite a while, including testing using
two different MI consumers (Vladimir's and one by Noam Yorav-Raphael).

There are three outstanding bugs.

* A dynamic varobj bug that I couldn't reproduce
http://sourceware.org/ml/archer/2009-q3/msg00169.html

* Lazy string printing.
http://sourceware.org/ml/archer/2009-q3/msg00189.html
I'm not sure what we'll do about this in the 7.0 timeframe, maybe
nothing.

* -var-info-path-expression doesn't work
http://sourceware.org/bugzilla/show_bug.cgi?id=10252
(I am not sure it can be made to work, I was planning to turn it into
an error.)

This patch needs a doc review.

This patch doesn't apply directly due to the big python renaming.
You can probably run sed on the patch if you care to try it.

Tom

2009-09-10 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', 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-10 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-10 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 52ead12..096b3d3 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -23337,6 +23337,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}
@@ -23365,6 +23367,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
@@ -23372,6 +23376,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 sent, this command cannot be undone.
+
+Note that if Python support has not been compiled into @value{GDBN},
+this command will still succeed.
+
@subheading The @code{-var-create} Command
@findex -var-create

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

+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
+include, but are not limited to:
+
+@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 fixed 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

@@ -23497,6 +23558,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
@@ -23504,7 +23569,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}

@@ -23517,6 +23582,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 ending just before @var{to} will be
+reported.
+
+If a child range is requested, it will not affect the range of
+children reported by a future call 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
@@ -23533,8 +23614,13 @@ 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.

+For a dynamic varobj, this value cannot reliably be used to form an
+expression. Also, a dynamic varobj will not report the access
+qualifying pseudo-children, regardless of the language.
+
@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.
@@ -23550,6 +23636,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
+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
@@ -23626,6 +23725,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
@@ -23731,6 +23833,68 @@ With the @samp{*} parameter, if a variable object is bound to a
currently running thread, it will not be updated, without any
diagnostic.

+If @code{-var-set-update-range} was previously used on a varobj, then
+only the selected range of children will be reported.
+
+@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
+This is a string, either @samp{false} if the varobj is not in scope,
+or @samp{true} if it is in scope.
+
+@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
@@ -23798,6 +23962,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 ending just before @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/python-mi.exp b/gdb/testsuite/gdb.python/python-mi.exp
index 3258810..bfdb595 100644
--- a/gdb/testsuite/gdb.python/python-mi.exp
+++ b/gdb/testsuite/gdb.python/python-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,111 @@ 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 }
+} "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 }
-} "varobj update after choosing via expression"
+} "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"
+
+
+# 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 5"
+
+# 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
+ } {} {}
+
+# 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_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/python-prettyprint.c b/gdb/testsuite/gdb.python/python-prettyprint.c
index 3cafc48..bf41ebc 100644
--- a/gdb/testsuite/gdb.python/python-prettyprint.c
+++ b/gdb/testsuite/gdb.python/python-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,13 @@ main ()
add_item (&c, 72);

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

diff --git a/gdb/testsuite/gdb.python/python-prettyprint.py b/gdb/testsuite/gdb.python/python-prettyprint.py
index bf009a1..2f070d8 100644
--- a/gdb/testsuite/gdb.python/python-prettyprint.py
+++ b/gdb/testsuite/gdb.python/python-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..e884e19 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,94 @@ 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 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 +974,103 @@ 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);

- make_cleanup_py_decref (children);
+ if (!children)
+ {
+ gdbpy_print_stack ();
+ error (_("Null value returned for children"));
+ }

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

- iterator = PyObject_GetIter (children);
- if (!iterator)
- {
- gdbpy_print_stack ();
- error (_("Could not get children iterator"));
+ if (!PyIter_Check (children))
+ error (_("Returned value is not iterable"));
+
+ 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;
-
+ PyObject *item;
+
+ /* 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);
+
if (!item)
break;
- 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);
+ /* We don't want to push the extra child on any report list. */
+ if (to < 0 || i < to)
+ {
+ PyObject *py_v;
+ char *name;
+ struct value *v;
+ struct cleanup *inner;

- /* TODO: This assume the name of the i-th child never changes. */
+ inner = make_cleanup_py_decref (item);

- /* Now see what to do here. */
- if (VEC_length (varobj_p, var->children) < i + 1)
- {
- /* 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;
+ 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, changed, new, unchanged,
+ cchanged, 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 +1082,26 @@ 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);
+ }
+ 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 +1109,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, *to);
+ restrict_range (var->children, from, to);
+ return var->children;
+ }

if (var->num_children == -1)
var->num_children = number_of_children (var);
@@ -1013,10 +1144,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 +1158,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 +1219,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 +1302,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 +1452,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 +1499,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 +1515,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 +1560,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 +1624,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 +1747,74 @@ 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);
+ 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->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 +2102,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 +2137,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 +2387,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 +2423,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 +2450,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 +3223,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 */