* varobj.h (varobj_update_result_t) <new>: New field.
(varobj_get_child_range, varobj_set_child_range): Declare.
(varobj_list_children): Update.
(varobj_enable_pretty_printing, varobj_has_more)
(varobj_pretty_printed_p): Declare.
* varobj.c (pretty_printing): New global.
(varobj_enable_pretty_printing): New function.
(struct varobj_root) <from, to, constructor, child_iter,
saved_item>: New fields.
(varobj_create): Don't call install_default_visualizer.
(instantiate_pretty_printer): Don't use value_copy.
(varobj_has_more): New function.
(restrict_range): New function.
(install_dynamic_child): Likewise.
(dynamic_varobj_has_child_method): Likewise.
(update_dynamic_varobj_children): Remove 'new_and_unchanged'
argument; add 'new', 'unchanged', 'from', and 'to' arguments.
Rewrite.
(varobj_get_num_children): Call update_dynamic_varobj_children.
(varobj_list_children): Add 'from' and 'to' arguments. Ignore
result of update_dynamic_varobj_children. Don't call
install_default_visualizer. Restrict result range.
(varobj_add_child): Don't call install_default_visualizer.
(varobj_pretty_printed_p): New function.
(install_visualizer): Rewrite. Move earlier in file.
(install_default_visualizer): Likewise.
(construct_visualizer): New function.
(install_new_value_visualizer): Likewise.
(install_new_value): Don't call release_value. Special case
pretty-printed objects. Use value_incref. Rearrange "changed"
logic.
(varobj_get_child_range): New function.
(varobj_set_child_range): Likewise.
(varobj_set_visualizer): Rewrite.
(varobj_update): Rewrite pretty-printing logic.
(new_variable): Initialize new fields.
(free_variable): Destroy new fields.
(value_of_root): Copy 'from' and 'to'.
(my_value_of_variable): Handle pretty-printers.
(value_get_print_value): Rework pretty-printing logic.
(cplus_describe_child): Don't use release_value.
* mi/mi-cmds.h (mi_cmd_enable_pretty_printing)
(mi_cmd_var_set_update_range): Declare.
* mi/mi-cmds.c (mi_cmds): Add enable-pretty-printing and
var-set-update-range.
* mi/mi-cmd-var.c (print_varobj): Update. Emit "dynamic"
attribute.
(mi_cmd_var_create): Emit "has_more" attribute.
(mi_cmd_var_set_format): Plug memory leak.
(mi_print_value_p): Replace 'type' argument with 'var'. Handle
pretty-printed varobjs.
(mi_cmd_var_list_children): Accept 'from' and 'to' arguments.
Emit "has_more" attribute.
(mi_cmd_var_evaluate_expression): Plug memory leak.
(mi_cmd_var_assign): Likewise.
(varobj_update_one): Likewise. Emit "dynamic", "has_more", and
"new_children" attributes.
(mi_cmd_enable_pretty_printing): New function.
(mi_cmd_var_set_update_range): Likewise.
gdb/doc
* gdb.texinfo (GDB/MI Variable Objects): Document
-enable-pretty-printing, -var-set-update-range, dynamic varobjs.
Expand -var-update documentation.
gdb/testsuite
* 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.
+2009-09-15 Tom Tromey <tromey@redhat.com>
+
+ * varobj.h (varobj_update_result_t) <new>: New field.
+ (varobj_get_child_range, varobj_set_child_range): Declare.
+ (varobj_list_children): Update.
+ (varobj_enable_pretty_printing, varobj_has_more)
+ (varobj_pretty_printed_p): Declare.
+ * varobj.c (pretty_printing): New global.
+ (varobj_enable_pretty_printing): New function.
+ (struct varobj_root) <from, to, constructor, child_iter,
+ saved_item>: New fields.
+ (varobj_create): Don't call install_default_visualizer.
+ (instantiate_pretty_printer): Don't use value_copy.
+ (varobj_has_more): New function.
+ (restrict_range): New function.
+ (install_dynamic_child): Likewise.
+ (dynamic_varobj_has_child_method): Likewise.
+ (update_dynamic_varobj_children): Remove 'new_and_unchanged'
+ argument; add 'new', 'unchanged', 'from', and 'to' arguments.
+ Rewrite.
+ (varobj_get_num_children): Call update_dynamic_varobj_children.
+ (varobj_list_children): Add 'from' and 'to' arguments. Ignore
+ result of update_dynamic_varobj_children. Don't call
+ install_default_visualizer. Restrict result range.
+ (varobj_add_child): Don't call install_default_visualizer.
+ (varobj_pretty_printed_p): New function.
+ (install_visualizer): Rewrite. Move earlier in file.
+ (install_default_visualizer): Likewise.
+ (construct_visualizer): New function.
+ (install_new_value_visualizer): Likewise.
+ (install_new_value): Don't call release_value. Special case
+ pretty-printed objects. Use value_incref. Rearrange "changed"
+ logic.
+ (varobj_get_child_range): New function.
+ (varobj_set_child_range): Likewise.
+ (varobj_set_visualizer): Rewrite.
+ (varobj_update): Rewrite pretty-printing logic.
+ (new_variable): Initialize new fields.
+ (free_variable): Destroy new fields.
+ (value_of_root): Copy 'from' and 'to'.
+ (my_value_of_variable): Handle pretty-printers.
+ (value_get_print_value): Rework pretty-printing logic.
+ (cplus_describe_child): Don't use release_value.
+ * mi/mi-cmds.h (mi_cmd_enable_pretty_printing)
+ (mi_cmd_var_set_update_range): Declare.
+ * mi/mi-cmds.c (mi_cmds): Add enable-pretty-printing and
+ var-set-update-range.
+ * mi/mi-cmd-var.c (print_varobj): Update. Emit "dynamic"
+ attribute.
+ (mi_cmd_var_create): Emit "has_more" attribute.
+ (mi_cmd_var_set_format): Plug memory leak.
+ (mi_print_value_p): Replace 'type' argument with 'var'. Handle
+ pretty-printed varobjs.
+ (mi_cmd_var_list_children): Accept 'from' and 'to' arguments.
+ Emit "has_more" attribute.
+ (mi_cmd_var_evaluate_expression): Plug memory leak.
+ (mi_cmd_var_assign): Likewise.
+ (varobj_update_one): Likewise. Emit "dynamic", "has_more", and
+ "new_children" attributes.
+ (mi_cmd_enable_pretty_printing): New function.
+ (mi_cmd_var_set_update_range): Likewise.
+
2009-09-15 Doug Evans <dje@google.com>
* dwarf2expr.h (dwarf_value_location): Add more comments describing
+2009-09-15 Tom Tromey <tromey@redhat.com>
+
+ * gdb.texinfo (GDB/MI Variable Objects): Document
+ -enable-pretty-printing, -var-set-update-range, dynamic varobjs.
+ Expand -var-update documentation.
+
2009-09-14 Sergio Durigan Junior <sergiodj@linux.vnet.ibm.com>
* gdb.texinfo (Set Catchpoints): Documentation about the catch syscall
@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}
@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
@subheading Description And Use of Operations on Variable Objects
+@subheading The @code{-enable-pretty-printing} Command
+@findex -enable-pretty-printing
+
+@smallexample
+-enable-pretty-printing
+@end smallexample
+
+@value{GDBN} allows Python-based visualizers to affect the output of the
+MI variable object commands. However, because there was no way to
+implement this in a fully backward-compatible way, a front end must
+request that this functionality be enabled.
+
+Once enabled, this feature cannot be disabled.
+
+Note that if Python support has not been compiled into @value{GDBN},
+this command will still succeed (and do nothing).
+
@subheading The @code{-var-create} Command
@findex -var-create
@samp{$@var{regname}} --- a CPU register name
@end itemize
+@cindex dynamic varobj
+A varobj's contents may be provided by a Python-based pretty-printer. In this
+case the varobj is known as a @dfn{dynamic varobj}. Dynamic varobjs
+have slightly different semantics in some cases. If the
+@code{-enable-pretty-printing} command is not sent, then @value{GDBN}
+will never create a dynamic varobj. This ensures backward
+compatibility for existing clients.
+
@subsubheading Result
-This operation returns the name, number of children and the type of the
-object created. Type is returned as a string as the ones generated by
-the @value{GDBN} CLI. If a fixed variable object is bound to a
-specific thread, the thread is is also printed:
+This operation returns attributes of the newly-created varobj. These
+are:
+
+@table @samp
+@item name
+The name of the varobj.
+
+@item numchild
+The number of children of the varobj. This number is not necessarily
+reliable for a dynamic varobj. Instead, you must examine the
+@samp{has_more} attribute.
+
+@item value
+The varobj's scalar value. For a varobj whose type is some sort of
+aggregate (e.g., a @code{struct}), or for a dynamic varobj, this value
+will not be interesting.
+
+@item type
+The varobj's type. This is a string representation of the type, as
+would be printed by the @value{GDBN} CLI.
+
+@item thread-id
+If a variable object is bound to a specific thread, then this is the
+thread's identifier.
+
+@item has_more
+For a dynamic varobj, this indicates whether there appear to be any
+children available. For a non-dynamic varobj, this will be 0.
+
+@item dynamic
+This attribute will be present and have the value @samp{1} if the
+varobj is a dynamic varobj. If the varobj is not a dynamic varobj,
+then this attribute will not be present.
+
+@item displayhint
+A dynamic varobj can supply a display hint to the front end. The
+value comes directly from the Python pretty-printer object's
+@code{display_hint} method. @xref{Pretty Printing}.
+@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
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
@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}
value for simple data types and just the name for arrays, structures
and unions.
+@var{from} and @var{to}, if specified, indicate the range of children
+to report. If @var{from} or @var{to} is less than zero, the range is
+reset and all children will be reported. Otherwise, children starting
+at @var{from} (zero-based) and up to and excluding @var{to} will be
+reported.
+
+If a child range is requested, it will only affect the current call to
+@code{-var-list-children}, but not future calls to @code{-var-update}.
+For this, you must instead use @code{-var-set-update-range}. The
+intent of this approach is to enable a front end to implement any
+update approach it likes; for example, scrolling a view may cause the
+front end to request more children with @code{-var-list-children}, and
+then the front end could call @code{-var-set-update-range} with a
+different range to ensure that future updates are restricted to just
+the visible items.
+
For each child the following results are returned:
@table @var
The expression to be shown to the user by the front end to designate this child.
For example this may be the name of a structure member.
+For a dynamic varobj, this value cannot be used to form an
+expression. There is no way to do this at all with a dynamic varobj.
+
For C/C@t{++} structures there are several pseudo children returned to
designate access qualifiers. For these pseudo children @var{exp} is
@samp{public}, @samp{private}, or @samp{protected}. In this case the
type and value are not present.
+A dynamic varobj will not report the access qualifying
+pseudo-children, regardless of the language. This information is not
+available at all with a dynamic varobj.
+
@item numchild
-Number of children this child has.
+Number of children this child has. For a dynamic varobj, this will be
+0.
@item type
The type of the child.
If the variable object is frozen, this variable will be present with a value of 1.
@end table
+The result may have its own attributes:
+
+@table @samp
+@item displayhint
+A dynamic varobj can supply a display hint to the front end. The
+value comes directly from the Python pretty-printer object's
+@code{display_hint} method. @xref{Pretty Printing}.
+
+@item has_more
+This is an integer attribute which is nonzero if there are children
+remaining after the end of the selected range.
+@end table
+
@subsubheading Example
@smallexample
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
currently running thread, it will not be updated, without any
diagnostic.
-@subsubheading Example
+If @code{-var-set-update-range} was previously used on a varobj, then
+only the selected range of children will be reported.
-@smallexample
-(gdb)
--var-assign var1 3
-^done,value="3"
-(gdb)
--var-update --all-values var1
-^done,changelist=[@{name="var1",value="3",in_scope="true",
-type_changed="false"@}]
-(gdb)
-@end smallexample
+@code{-var-update} reports all the changed varobjs in a tuple named
+@samp{changelist}.
+
+Each item in the change list is itself a tuple holding:
+
+@table @samp
+@item name
+The name of the varobj.
+
+@item value
+If values were requested for this update, then this field will be
+present and will hold the value of the varobj.
+@item in_scope
@anchor{-var-update}
-The field in_scope may take three values:
+This field is a string which may take one of three values:
@table @code
@item "true"
In the future new values may be added to this list so the front should
be prepared for this possibility. @xref{GDB/MI Development and Front Ends, ,@sc{GDB/MI} Development and Front Ends}.
+@item type_changed
+This is only present if the varobj is still valid. If the type
+changed, then this will be the string @samp{true}; otherwise it will
+be @samp{false}.
+
+@item new_type
+If the varobj's type changed, then this field will be present and will
+hold the new type.
+
+@item new_num_children
+For a dynamic varobj, if the number of children changed, or if the
+type changed, this will be the new number of children.
+
+The @samp{numchild} field in other varobj responses is generally not
+valid for a dynamic varobj -- it will show the number of children that
+@value{GDBN} knows about, but because dynamic varobjs lazily
+instantiate their children, this will not reflect the number of
+children which may be available.
+
+The @samp{new_num_children} attribute only reports changes to the
+number of children known by @value{GDBN}. This is the only way to
+detect whether an update has removed children (which necessarily can
+only happen at the end of the update range).
+
+@item displayhint
+The display hint, if any.
+
+@item has_more
+This is an integer value, which will be 1 if there are more children
+available outside the varobj's update range.
+
+@item dynamic
+This attribute will be present and have the value @samp{1} if the
+varobj is a dynamic varobj. If the varobj is not a dynamic varobj,
+then this attribute will not be present.
+
+@item new_children
+If new children were added to a dynamic varobj within the selected
+update range (as set by @code{-var-set-update-range}), then they will
+be listed in this attribute.
+@end table
+
+@subsubheading Example
+
+@smallexample
+(gdb)
+-var-assign var1 3
+^done,value="3"
+(gdb)
+-var-update --all-values var1
+^done,changelist=[@{name="var1",value="3",in_scope="true",
+type_changed="false"@}]
+(gdb)
+@end smallexample
+
@subheading The @code{-var-set-frozen} Command
@findex -var-set-frozen
@anchor{-var-set-frozen}
(gdb)
@end smallexample
+@subheading The @code{-var-set-update-range} command
+@findex -var-set-update-range
+@anchor{-var-set-update-range}
+
+@subsubheading Synopsis
+
+@smallexample
+ -var-set-update-range @var{name} @var{from} @var{to}
+@end smallexample
+
+Set the range of children to be returned by future invocations of
+@code{-var-update}.
+
+@var{from} and @var{to} indicate the range of children to report. If
+@var{from} or @var{to} is less than zero, the range is reset and all
+children will be reported. Otherwise, children starting at @var{from}
+(zero-based) and up to and excluding @var{to} will be reported.
+
+@subsubheading Example
+
+@smallexample
+(gdb)
+-var-set-update-range V 1 2
+^done
+@end smallexample
+
@subheading The @code{-var-set-visualizer} command
@findex -var-set-visualizer
@anchor{-var-set-visualizer}
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
struct type *gdb_type;
char *type;
int thread_id;
+ char *display_hint;
ui_out_field_string (uiout, "name", varobj_get_objname (var));
if (print_expression)
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)
if (varobj_get_frozen (var))
ui_out_field_int (uiout, "frozen", 1);
+
+ display_hint = varobj_get_display_hint (var);
+ if (display_hint)
+ {
+ ui_out_field_string (uiout, "displayhint", display_hint);
+ xfree (display_hint);
+ }
+
+ if (varobj_pretty_printed_p (var))
+ ui_out_field_int (uiout, "dynamic", 1);
}
/* VAROBJ operations */
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);
}
{
enum varobj_display_formats format;
struct varobj *var;
+ char *val;
if (argc != 2)
error (_("mi_cmd_var_set_format: Usage: NAME FORMAT."));
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
}
/* 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;
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
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;
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
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."));
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. */
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);
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:
}
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)
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);
+}
{ "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},
{ "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},
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. */
+2009-09-15 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.
+
2009-09-14 Sergio Durigan Junior <sergiodj@linux.vnet.ibm.com>
* Makefile.in: Inclusion of catch-syscall object.
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"
}
# 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 *" \
# 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;"
# 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:
# 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;"
# 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;"
# 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;"
# 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;"
# 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:
# 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"
# 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";
[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";
$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} {
# 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;"
# 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"
# 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"
# 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"
# 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
# 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;"
# 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';"
# 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;"
# 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"
# 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:
# 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
# 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"
# 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" \
"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 *" \
"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" \
"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" \
# 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=\".*\"\}" \
# 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);"]
# 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
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" \
# 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
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" \
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" \
# 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
# 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"
# 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" \
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" \
# 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" \
# 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;"
-# 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
# 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:
# 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;"
# 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;"
# 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;"
# 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;"
# 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:
# 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"
# 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
# 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;"
# 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"
# 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"
# 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"
# 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 *-*-*
# 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"
"&\"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"
-
##### #####
# #
# 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;"
# 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';"
# 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;"
# 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"
# 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:
# 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
# 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"
# 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" \
"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 *" \
# 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=\".*\"\}" \
# 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);"]
# 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
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" \
# 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
# 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"
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" \
"\\^done" \
"choose default visualizer"
-mi_varobj_update_dynamic container {
- { {container.\[0\]} {\[0\]} 0 int }
- { {container.\[1\]} {\[1\]} 0 int }
-} "varobj update after choosing default"
+mi_varobj_update_dynamic container "varobj update after choosing default" {
+ type_changed false new_num_children 2 dynamic 1 has_more 0
+} {
+} {
+ { name {container.\[0\]} exp {\[0\]} numchild 0 type int thread-id 1 }
+ { name {container.\[1\]} exp {\[1\]} numchild 0 type int thread-id 1 }
+}
mi_gdb_test "-var-set-visualizer container ContainerPrinter" \
"\\^done" \
"choose visualizer using expression"
-mi_varobj_update_dynamic container {
+mi_varobj_update_dynamic container \
+ "varobj update after choosing via expression" {
+ type_changed false new_num_children 2 dynamic 1 has_more 0
+ } {
+ } {
+ { name {container.\[0\]} exp {\[0\]} numchild 0 type int thread-id 1 }
+ { name {container.\[1\]} exp {\[1\]} numchild 0 type int thread-id 1 }
+ }
+
+mi_list_varobj_children_range container 1 2 2 {
+ { {container.\[1\]} {\[1\]} 0 int }
+} "list varobj children after selecting child range"
+
+mi_list_varobj_children_range container -1 -1 2 {
{ {container.\[0\]} {\[0\]} 0 int }
{ {container.\[1\]} {\[1\]} 0 int }
-} "varobj update after choosing via expression"
+} "list varobj children after resetting child range"
+
+mi_next "next over update 3"
+
+mi_gdb_test "-var-set-update-range container 0 1" \
+ "\\^done" \
+ "set update range"
+
+# This should truncate the list.
+mi_list_varobj_children container {
+ { {container.\[0\]} {\[0\]} 0 int }
+} "list children after setting update range"
+
+# This should return just the items in [1,2).
+mi_list_varobj_children_range container 1 2 2 {
+ { {container.\[1\]} {\[1\]} 0 int }
+} "list selected children after setting range"
+
+# This should not be affected by the previous list-children request.
+mi_list_varobj_children container {
+ { {container.\[0\]} {\[0\]} 0 int }
+} "list children after listing selected range"
+
+mi_next "next over update 4"
+
+# This should only show the first child, because the update range has
+# been set.
+mi_varobj_update_dynamic container \
+ "update after next with restricted range" {
+ type_changed false new_num_children 1 dynamic 1 has_more 1
+ } {
+ { name {container.\[0\]} in_scope true type_changed false dynamic 1 has_more 0 }
+ } {
+ }
+
+mi_gdb_test "-var-set-update-range container 3 4" \
+ "\\^done" \
+ "set update range with non-zero start"
+
+# Elements were updated but should not be reported.
+mi_varobj_update_dynamic container \
+ "update varobj with change outside selected range" {
+ type_changed false new_num_children 3 dynamic 1 has_more 0
+ } {
+ } {
+ }
+
+mi_next "next over update 5"
+
+# Regression test: examine an object that has no children, then update
+# it to ensure that we don't print the children.
+mi_create_dynamic_varobj container2 c2 \
+ "create second container varobj"
+
+mi_gdb_test "-var-update container2" \
+ "\\^done,changelist=.." \
+ "update varobj, no children requested"
+
+mi_next "next over update 6"
+
+# Now container2 has an element -- and an update should mention that
+# it has_more. But, because we did not request children, we still
+# should not actually see them.
+mi_varobj_update_dynamic container2 \
+ "update varobj 2, no children requested" {
+ type_changed false dynamic 1 has_more 1
+ } {} {}
+
+mi_continue_to_line \
+ [gdb_get_line_number {MI outer breakpoint here} ${testfile}.c] \
+ "step to outer breakpoint"
+
+mi_create_dynamic_varobj outer outer \
+ "create outer varobj"
+
+mi_list_varobj_children outer {
+ { outer.s s 2 "struct substruct" }
+ { outer.x x 0 "int" }
+} "list children of outer"
+
+mi_list_varobj_children outer.s {
+ { outer.s.a a 0 int }
+ { outer.s.b b 0 int }
+} "list children of outer.s"
+
+mi_next "next over outer update"
+
+mi_gdb_test "-var-update outer" \
+ ".done,changelist=.{name=\"outer.s.a\",in_scope=\"true\",type_changed=\"false\",dynamic=\"1\",has_more=\"0\"}." \
+ "update after updating element of outer"
mi_continue_to_line \
[gdb_get_line_number {Another MI breakpoint} ${testfile}.c] \
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;
#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
c = 23; /* Another MI breakpoint */
}
+struct nullstr
+{
+ char *s;
+};
+
+struct string_repr string_1 = { { "one" } };
+struct string_repr string_2 = { { "two" } };
+
int
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";
add_item (&c, 72);
#ifdef MI
+ add_item (&c, 1011);
+ c.elements[0] = 1023;
+ c.elements[0] = 2323;
+
+ add_item (&c2, 2222);
+ add_item (&c2, 3333);
+
+ substruct_test ();
do_nothing ();
#endif
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"
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:
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.
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 ()
# 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
}
$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" \
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
}
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
# 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]
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,
#include "gdb_assert.h"
#include "gdb_string.h"
+#include "gdb_regex.h"
#include "varobj.h"
#include "vec.h"
/* 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
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
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);
}
}
- install_default_visualizer (var);
discard_cleanups (old_chain);
return var;
}
#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;
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
return var->frozen;
}
+/* A helper function that restricts a range to what is actually
+ available in a VEC. This follows the usual rules for the meaning
+ of FROM and TO -- if either is negative, the entire range is
+ used. */
+
+static void
+restrict_range (VEC (varobj_p) *children, int *from, int *to)
+{
+ if (*from < 0 || *to < 0)
+ {
+ *from = 0;
+ *to = VEC_length (varobj_p, children);
+ }
+ else
+ {
+ if (*from > VEC_length (varobj_p, children))
+ *from = VEC_length (varobj_p, children);
+ if (*to > VEC_length (varobj_p, children))
+ *to = VEC_length (varobj_p, children);
+ if (*from > *to)
+ *from = *to;
+ }
+}
+
+/* A helper for update_dynamic_varobj_children that installs a new
+ child when needed. */
+
+static void
+install_dynamic_child (struct varobj *var,
+ VEC (varobj_p) **changed,
+ VEC (varobj_p) **new,
+ VEC (varobj_p) **unchanged,
+ int *cchanged,
+ int index,
+ const char *name,
+ struct value *value)
+{
+ if (VEC_length (varobj_p, var->children) < index + 1)
+ {
+ /* There's no child yet. */
+ struct varobj *child = varobj_add_child (var, name, value);
+ if (new)
+ {
+ VEC_safe_push (varobj_p, *new, child);
+ *cchanged = 1;
+ }
+ }
+ else
+ {
+ varobj_p existing = VEC_index (varobj_p, var->children, index);
+ if (install_new_value (existing, value, 0))
+ {
+ if (changed)
+ VEC_safe_push (varobj_p, *changed, existing);
+ }
+ else if (unchanged)
+ VEC_safe_push (varobj_p, *unchanged, existing);
+ }
+}
+
+#if HAVE_PYTHON
+
+static int
+dynamic_varobj_has_child_method (struct varobj *var)
+{
+ struct cleanup *back_to;
+ PyObject *printer = var->pretty_printer;
+ int result;
+
+ back_to = varobj_ensure_python_env (var);
+ result = PyObject_HasAttr (printer, gdbpy_children_cst);
+ do_cleanups (back_to);
+ return result;
+}
+
+#endif
+
static int
update_dynamic_varobj_children (struct varobj *var,
VEC (varobj_p) **changed,
- VEC (varobj_p) **new_and_unchanged,
- int *cchanged)
-
+ VEC (varobj_p) **new,
+ VEC (varobj_p) **unchanged,
+ int *cchanged,
+ int update_children,
+ int from,
+ int to)
{
#if HAVE_PYTHON
- /* FIXME: we *might* want to provide this functionality as
- a standalone function, so that other interested parties
- than varobj code can benefit for this. */
struct cleanup *back_to;
PyObject *children;
- PyObject *iterator;
int i;
- int children_changed = 0;
PyObject *printer = var->pretty_printer;
back_to = varobj_ensure_python_env (var);
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;
-
- if (!item)
- break;
- inner = make_cleanup_py_decref (item);
+ PyObject *item;
- if (!PyArg_ParseTuple (item, "sO", &name, &py_v))
- error (_("Invalid item from the child list"));
-
- v = convert_value_from_python (py_v);
+ /* See if there was a leftover from last time. */
+ if (var->saved_item)
+ {
+ item = var->saved_item;
+ var->saved_item = NULL;
+ }
+ else
+ item = PyIter_Next (var->child_iter);
- /* TODO: This assume the name of the i-th child never changes. */
+ if (!item)
+ break;
- /* Now see what to do here. */
- if (VEC_length (varobj_p, var->children) < i + 1)
+ /* We don't want to push the extra child on any report list. */
+ if (to < 0 || i < to)
{
- /* There's no child yet. */
- struct varobj *child = varobj_add_child (var, name, v);
- if (new_and_unchanged)
- VEC_safe_push (varobj_p, *new_and_unchanged, child);
- children_changed = 1;
+ PyObject *py_v;
+ char *name;
+ struct value *v;
+ struct cleanup *inner;
+ int can_mention = from < 0 || i >= from;
+
+ inner = make_cleanup_py_decref (item);
+
+ if (!PyArg_ParseTuple (item, "sO", &name, &py_v))
+ error (_("Invalid item from the child list"));
+
+ v = convert_value_from_python (py_v);
+ install_dynamic_child (var, can_mention ? changed : NULL,
+ can_mention ? new : NULL,
+ can_mention ? unchanged : NULL,
+ can_mention ? cchanged : NULL, i, name, v);
+ do_cleanups (inner);
}
- else
+ else
{
- varobj_p existing = VEC_index (varobj_p, var->children, i);
- if (install_new_value (existing, v, 0) && changed)
- {
- if (changed)
- VEC_safe_push (varobj_p, *changed, existing);
- }
- else
- {
- if (new_and_unchanged)
- VEC_safe_push (varobj_p, *new_and_unchanged, existing);
- }
- }
+ Py_XDECREF (var->saved_item);
+ var->saved_item = item;
- do_cleanups (inner);
+ /* We want to truncate the child list just before this
+ element. */
+ break;
+ }
}
if (i < VEC_length (varobj_p, var->children))
{
- int i;
- children_changed = 1;
- for (i = 0; i < VEC_length (varobj_p, var->children); ++i)
- varobj_delete (VEC_index (varobj_p, var->children, i), NULL, 0);
+ int j;
+ *cchanged = 1;
+ for (j = i; j < VEC_length (varobj_p, var->children); ++j)
+ varobj_delete (VEC_index (varobj_p, var->children, j), NULL, 0);
+ VEC_truncate (varobj_p, var->children, i);
}
- VEC_truncate (varobj_p, var->children, i);
+
+ /* If there are fewer children than requested, note that the list of
+ children changed. */
+ if (to >= 0 && VEC_length (varobj_p, var->children) < to)
+ *cchanged = 1;
+
var->num_children = VEC_length (varobj_p, var->children);
do_cleanups (back_to);
- *cchanged = children_changed;
return 1;
#else
gdb_assert (0 && "should never be called if Python is not enabled");
{
if (var->num_children == -1)
{
- int changed;
- if (!var->pretty_printer
- || !update_dynamic_varobj_children (var, NULL, NULL, &changed))
+ if (var->pretty_printer)
+ {
+ int dummy;
+
+ /* If we have a dynamic varobj, don't report -1 children.
+ So, try to fetch some children first. */
+ update_dynamic_varobj_children (var, NULL, NULL, NULL, &dummy,
+ 0, 0, 0);
+ }
+ else
var->num_children = number_of_children (var);
}
- return var->num_children;
+ return var->num_children >= 0 ? var->num_children : 0;
}
/* Creates a list of the immediate children of a variable object;
the return code is the number of such children or -1 on error */
VEC (varobj_p)*
-varobj_list_children (struct varobj *var)
+varobj_list_children (struct varobj *var, int *from, int *to)
{
struct varobj *child;
char *name;
var->children_requested = 1;
- if (var->pretty_printer
+ if (var->pretty_printer)
+ {
/* This, in theory, can result in the number of children changing without
frontend noticing. But well, calling -var-list-children on the same
varobj twice is not something a sane frontend would do. */
- && update_dynamic_varobj_children (var, NULL, NULL, &children_changed))
- return var->children;
+ update_dynamic_varobj_children (var, NULL, NULL, NULL, &children_changed,
+ 0, 0, *to);
+ restrict_range (var->children, from, to);
+ return var->children;
+ }
if (var->num_children == -1)
var->num_children = number_of_children (var);
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;
}
VEC_length (varobj_p, var->children),
name, value);
VEC_safe_push (varobj_p, var->children, v);
- install_default_visualizer (v);
return v;
}
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)
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
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
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.
{
changed = 1;
}
- else
+ else if (! var->pretty_printer)
{
/* Try to compare the values. That requires that both
values are non-lazy. */
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
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
/* We probably should not get children of a varobj that has a
pretty-printer, but for which -var-list-children was never
- invoked. Presumably, such varobj is not yet expanded in the
- UI, so we need not bother getting it. */
+ invoked. */
if (v->pretty_printer)
{
- VEC (varobj_p) *changed = 0, *new_and_unchanged = 0;
+ VEC (varobj_p) *changed = 0, *new = 0, *unchanged = 0;
int i, children_changed;
- varobj_p tmp;
-
- if (!v->children_requested)
- continue;
if (v->frozen)
continue;
+ if (!v->children_requested)
+ {
+ int dummy;
+
+ /* If we initially did not have potential children, but
+ now we do, consider the varobj as changed.
+ Otherwise, if children were never requested, consider
+ it as unchanged -- presumably, such varobj is not yet
+ expanded in the UI, so we need not bother getting
+ it. */
+ if (!varobj_has_more (v, 0))
+ {
+ update_dynamic_varobj_children (v, NULL, NULL, NULL,
+ &dummy, 0, 0, 0);
+ if (varobj_has_more (v, 0))
+ r.changed = 1;
+ }
+
+ if (r.changed)
+ VEC_safe_push (varobj_update_result, result, &r);
+
+ continue;
+ }
+
/* If update_dynamic_varobj_children returns 0, then we have
a non-conforming pretty-printer, so we skip it. */
- if (update_dynamic_varobj_children (v, &changed, &new_and_unchanged,
- &children_changed))
+ if (update_dynamic_varobj_children (v, &changed, &new, &unchanged,
+ &children_changed, 1,
+ v->from, v->to))
{
- if (children_changed)
- r.children_changed = 1;
- for (i = 0; VEC_iterate (varobj_p, changed, i, tmp); ++i)
+ if (children_changed || new)
{
- varobj_update_result r = {tmp};
- r.changed = 1;
- r.value_installed = 1;
- VEC_safe_push (varobj_update_result, stack, &r);
+ r.children_changed = 1;
+ r.new = new;
}
- for (i = 0;
- VEC_iterate (varobj_p, new_and_unchanged, i, tmp);
- ++i)
+ /* Push in reverse order so that the first child is
+ popped from the work stack first, and so will be
+ added to result first. This does not affect
+ correctness, just "nicer". */
+ for (i = VEC_length (varobj_p, changed) - 1; i >= 0; --i)
{
+ varobj_p tmp = VEC_index (varobj_p, changed, i);
varobj_update_result r = {tmp};
+ r.changed = 1;
r.value_installed = 1;
VEC_safe_push (varobj_update_result, stack, &r);
}
+ for (i = VEC_length (varobj_p, unchanged) - 1; i >= 0; --i)
+ {
+ varobj_p tmp = VEC_index (varobj_p, unchanged, 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;
}
}
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;
}
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
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);
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;
}
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);
}
*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)
{
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);
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);
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 */