This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Patch: implement new dynamic varobj spec


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 */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]