From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 24640 invoked by alias); 10 Sep 2009 20:58:38 -0000 Received: (qmail 24582 invoked by uid 22791); 10 Sep 2009 20:58:24 -0000 X-SWARE-Spam-Status: No, hits=0.9 required=5.0 tests=AWL,BAYES_20,J_CHICKENPOX_13,J_CHICKENPOX_17,J_CHICKENPOX_34,J_CHICKENPOX_37,J_CHICKENPOX_43,J_CHICKENPOX_44,J_CHICKENPOX_51,J_CHICKENPOX_93,SPF_HELO_PASS,SPF_PASS X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 10 Sep 2009 20:58:12 +0000 Received: from int-mx08.intmail.prod.int.phx2.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id n8AKwA4o000536 for ; Thu, 10 Sep 2009 16:58:10 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx08.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id n8AKw9qD013571; Thu, 10 Sep 2009 16:58:09 -0400 Received: from opsy.redhat.com (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id n8AKw7Rj026465; Thu, 10 Sep 2009 16:58:07 -0400 Received: by opsy.redhat.com (Postfix, from userid 500) id B6D2E378183; Thu, 10 Sep 2009 14:58:06 -0600 (MDT) From: Tom Tromey To: gdb-patches@sourceware.org Subject: Patch: implement new dynamic varobj spec Reply-To: Tom Tromey Date: Thu, 10 Sep 2009 20:58:00 -0000 Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2009-09/txt/msg00283.txt.bz2 This is the long-awaited dynamic varobj patch. It implements the spec as described by Vladimir: http://sourceware.org/ml/gdb/2009-07/msg00088.html .. with various minor changes we've discussed on that thread and elsewhere. I didn't give the follow-up URLs; I think that the doc patch ought to be sufficient, and if it isn't, I will fix it up. This has been in development for quite a while, including testing using two different MI consumers (Vladimir's and one by Noam Yorav-Raphael). There are three outstanding bugs. * A dynamic varobj bug that I couldn't reproduce http://sourceware.org/ml/archer/2009-q3/msg00169.html * Lazy string printing. http://sourceware.org/ml/archer/2009-q3/msg00189.html I'm not sure what we'll do about this in the 7.0 timeframe, maybe nothing. * -var-info-path-expression doesn't work http://sourceware.org/bugzilla/show_bug.cgi?id=10252 (I am not sure it can be made to work, I was planning to turn it into an error.) This patch needs a doc review. This patch doesn't apply directly due to the big python renaming. You can probably run sed on the patch if you care to try it. Tom 2009-09-10 Tom Tromey * varobj.h (varobj_update_result_t) : 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) : New fields. (varobj_create): Don't call install_default_visualizer. (instantiate_pretty_printer): Don't use value_copy. (varobj_has_more): New function. (restrict_range): New function. (install_dynamic_child): Likewise. (dynamic_varobj_has_child_method): Likewise. (update_dynamic_varobj_children): Remove 'new_and_unchanged' argument; add 'new', 'unchanged', and 'to' arguments. Rewrite. (varobj_get_num_children): Call update_dynamic_varobj_children. (varobj_list_children): Add 'from' and 'to' arguments. Ignore result of update_dynamic_varobj_children. Don't call install_default_visualizer. Restrict result range. (varobj_add_child): Don't call install_default_visualizer. (varobj_pretty_printed_p): New function. (install_visualizer): Rewrite. Move earlier in file. (install_default_visualizer): Likewise. (construct_visualizer): New function. (install_new_value_visualizer): Likewise. (install_new_value): Don't call release_value. Special case pretty-printed objects. Use value_incref. Rearrange "changed" logic. (varobj_get_child_range): New function. (varobj_set_child_range): Likewise. (varobj_set_visualizer): Rewrite. (varobj_update): Rewrite pretty-printing logic. (new_variable): Initialize new fields. (free_variable): Destroy new fields. (value_of_root): Copy 'from' and 'to'. (my_value_of_variable): Handle pretty-printers. (value_get_print_value): Rework pretty-printing logic. (cplus_describe_child): Don't use release_value. * mi/mi-cmds.h (mi_cmd_enable_pretty_printing) (mi_cmd_var_set_update_range): Declare. * mi/mi-cmds.c (mi_cmds): Add enable-pretty-printing and var-set-update-range. * mi/mi-cmd-var.c (print_varobj): Update. Emit "dynamic" attribute. (mi_cmd_var_create): Emit "has_more" attribute. (mi_cmd_var_set_format): Plug memory leak. (mi_print_value_p): Replace 'type' argument with 'var'. Handle pretty-printed varobjs. (mi_cmd_var_list_children): Accept 'from' and 'to' arguments. Emit "has_more" attribute. (mi_cmd_var_evaluate_expression): Plug memory leak. (mi_cmd_var_assign): Likewise. (varobj_update_one): Likewise. Emit "dynamic", "has_more", and "new_children" attributes. (mi_cmd_enable_pretty_printing): New function. (mi_cmd_var_set_update_range): Likewise. 2009-09-10 Tom Tromey * gdb.texinfo (GDB/MI Variable Objects): Document -enable-pretty-printing, -var-set-update-range, dynamic varobjs. Expand -var-update documentation. 2009-09-10 Tom Tromey * lib/mi-support.exp (mi_create_varobj): Update. (mi_create_floating_varobj): Likewise. (mi_create_dynamic_varobj): New proc. (mi_varobj_update): Update. (mi_varobj_update_with_type_change): Likewise. (mi_varobj_update_kv_helper): New proc. (mi_varobj_update_dynamic_helper): Rewrite. (mi_varobj_update_dynamic): New proc. (mi_list_varobj_children): Update. (mi_list_varobj_children_range): Add 'from' and 'to' arguments. * gdb.python/python-prettyprint.py (pp_outer): New class. (pp_nullstr): Likewise. (lookup_function): Register new printers. * gdb.python/python-prettyprint.c (struct substruct): New type. (struct outerstruct): Likewise. (substruct_test): New function. (struct nullstr): New type. (string_1, string_2): New globals. (main): Add new tests. * gdb.python/python-mi.exp: Added regression tests. * gdb.mi/mi2-var-display.exp: Update. * gdb.mi/mi2-var-cmd.exp: Update. * gdb.mi/mi2-var-child.exp: Update. * gdb.mi/mi2-var-block.exp: Update. * gdb.mi/mi-var-invalidate.exp: Update. * gdb.mi/mi-var-display.exp: Update. * gdb.mi/mi-var-cmd.exp: Update. * gdb.mi/mi-var-child.exp: Update. * gdb.mi/mi-var-block.exp: Update. * gdb.mi/mi-break.exp: Update. * gdb.mi/gdb701.exp: Update. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 52ead12..096b3d3 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -23337,6 +23337,8 @@ access this functionality: @item @strong{Operation} @tab @strong{Description} +@item @code{-enable-pretty-printing} +@tab enable Python-based pretty-printing @item @code{-var-create} @tab create a variable object @item @code{-var-delete} @@ -23365,6 +23367,8 @@ access this functionality: @tab update the variable and its children @item @code{-var-set-frozen} @tab set frozeness attribute +@item @code{-var-set-update-range} +@tab set range of children to display on update @end multitable In the next subsection we describe each operation in detail and suggest @@ -23372,6 +23376,23 @@ how it can be used. @subheading Description And Use of Operations on Variable Objects +@subheading The @code{-enable-pretty-printing} Command +@findex -enable-pretty-printing + +@smallexample +-enable-pretty-printing +@end smallexample + +@value{GDBN} allows Python-based visualizers to affect the output of the +MI variable object commands. However, because there was no way to +implement this in a fully backward-compatible way, a front end must +request that this functionality be enabled. + +Once sent, this command cannot be undone. + +Note that if Python support has not been compiled into @value{GDBN}, +this command will still succeed. + @subheading The @code{-var-create} Command @findex -var-create @@ -23411,15 +23432,55 @@ begin with a @samp{*}), or one of the following: @samp{$@var{regname}} --- a CPU register name @end itemize +A varobj's contents may be provided by a Python-based pretty-printer. In this +case the varobj is known as a @dfn{dynamic varobj}. Dynamic varobjs +have slightly different semantics in some cases. If the +@code{-enable-pretty-printing} command is not sent, then @value{GDBN} +will never create a dynamic varobj. This ensures backward +compatibility for existing clients. + @subsubheading Result -This operation returns the name, number of children and the type of the -object created. Type is returned as a string as the ones generated by -the @value{GDBN} CLI. If a fixed variable object is bound to a -specific thread, the thread is is also printed: +This operation returns attributes of the newly-created varobj. These +include, but are not limited to: + +@table @samp +@item name +The name of the varobj. + +@item numchild +The number of children of the varobj. This number is not necessarily +reliable for a dynamic varobj. Instead, you must examine the +@samp{has_more} attribute. + +@item value +The varobj's scalar value. For a varobj whose type is some sort of +aggregate (e.g., a @code{struct}), or for a dynamic varobj, this value +will not be interesting. + +@item type +The varobj's type. This is a string representation of the type, as +would be printed by the @value{GDBN} CLI. + +@item thread-id +If a fixed variable object is bound to a specific thread, then this is +the thread's identifier. + +@item has_more +For a dynamic varobj, this indicates whether there appear to be any +children available. For a non-dynamic varobj, this will be 0. + +@item dynamic +This attribute will be present and have the value @samp{1} if the +varobj is a dynamic varobj. If the varobj is not a dynamic varobj, +then this attribute will not be present. +@end table + +Typical output will look like this: @smallexample - name="@var{name}",numchild="@var{N}",type="@var{type}",thread-id="@var{M}" + name="@var{name}",numchild="@var{N}",type="@var{type}",thread-id="@var{M}", + has_more="@var{has_more}" @end smallexample @@ -23497,6 +23558,10 @@ Returns the number of children of a variable object @var{name}: numchild=@var{n} @end smallexample +Note that this number is not completely reliable for a dynamic varobj. +It will return the current number of children, but more children may +be available. + @subheading The @code{-var-list-children} Command @findex -var-list-children @@ -23504,7 +23569,7 @@ Returns the number of children of a variable object @var{name}: @subsubheading Synopsis @smallexample - -var-list-children [@var{print-values}] @var{name} + -var-list-children [@var{print-values}] @var{name} [@var{from} @var{to}] @end smallexample @anchor{-var-list-children} @@ -23517,6 +23582,22 @@ values; and if it is 2 or @code{--simple-values} print the name and value for simple data types and just the name for arrays, structures and unions. +@var{from} and @var{to}, if specified, indicate the range of children +to report. If @var{from} or @var{to} is less than zero, the range is +reset and all children will be reported. Otherwise, children starting +at @var{from} (zero-based) and ending just before @var{to} will be +reported. + +If a child range is requested, it will not affect the range of +children reported by a future call to @code{-var-update}. For this, +you must instead use @code{-var-set-update-range}. The intent of this +approach is to enable a front end to implement any update approach it +likes; for example, scrolling a view may cause the front end to +request more children with @code{-var-list-children}, and then the +front end could call @code{-var-set-update-range} with a different +range to ensure that future updates are restricted to just the visible +items. + For each child the following results are returned: @table @var @@ -23533,8 +23614,13 @@ designate access qualifiers. For these pseudo children @var{exp} is @samp{public}, @samp{private}, or @samp{protected}. In this case the type and value are not present. +For a dynamic varobj, this value cannot reliably be used to form an +expression. Also, a dynamic varobj will not report the access +qualifying pseudo-children, regardless of the language. + @item numchild -Number of children this child has. +Number of children this child has. For a dynamic varobj, this will be +0. @item type The type of the child. @@ -23550,6 +23636,19 @@ Otherwise this result is not present. If the variable object is frozen, this variable will be present with a value of 1. @end table +The result may have its own attributes: + +@table @samp +@item displayhint +A dynamic varobj can supply a display hint to the front end. The +comes directly from the Python pretty-printer object's +@code{display_hint} method. @xref{Pretty Printing}. + +@item has_more +This is an integer attribute which is nonzero if there are children +remaining after the end of the selected range. +@end table + @subsubheading Example @smallexample @@ -23626,6 +23725,9 @@ result can be used only for UI presentation. Typical use of the @code{-var-info-path-expression} command is creating a watchpoint from a variable object. +This command is currently not valid for children of a dynamic varobj, +and will give an error when invoked on one. + For example, suppose @code{C} is a C@t{++} class, derived from class @code{Base}, and that the @code{Base} class has a member called @code{m_size}. Assume a variable @code{c} is has the type of @@ -23731,6 +23833,68 @@ With the @samp{*} parameter, if a variable object is bound to a currently running thread, it will not be updated, without any diagnostic. +If @code{-var-set-update-range} was previously used on a varobj, then +only the selected range of children will be reported. + +@code{-var-update} reports all the changed varobjs in a tuple named +@samp{changelist}. + +Each item in the change list is itself a tuple holding: + +@table @samp +@item name +The name of the varobj. + +@item value +If values were requested for this update, then this field will be +present and will hold the value of the varobj. + +@item in_scope +This is a string, either @samp{false} if the varobj is not in scope, +or @samp{true} if it is in scope. + +@item type_changed +This is only present if the varobj is still valid. If the type +changed, then this will be the string @samp{true}; otherwise it will +be @samp{false}. + +@item new_type +If the varobj's type changed, then this field will be present and will +hold the new type. + +@item new_num_children +For a dynamic varobj, if the number of children changed, or if the +type changed, this will be the new number of children. + +The @samp{numchild} field in other varobj responses is generally not +valid for a dynamic varobj -- it will show the number of children that +@value{GDBN} knows about, but because dynamic varobjs lazily +instantiate their children, this will not reflect the number of +children which may be available. + +The @samp{new_num_children} attribute only reports changes to the +number of children known by @value{GDBN}. This is the only way to +detect whether an update has removed children (which necessarily can +only happen at the end of the update range). + +@item displayhint +The display hint, if any. + +@item has_more +This is an integer value, which will be 1 if there are more children +available outside the varobj's update range. + +@item dynamic +This attribute will be present and have the value @samp{1} if the +varobj is a dynamic varobj. If the varobj is not a dynamic varobj, +then this attribute will not be present. + +@item new_children +If new children were added to a dynamic varobj within the selected +update range (as set by @code{-var-set-update-range}), then they will +be listed in this attribute. +@end table + @subsubheading Example @smallexample @@ -23798,6 +23962,32 @@ Unfreezing a variable does not update it, only subsequent (gdb) @end smallexample +@subheading The @code{-var-set-update-range} command +@findex -var-set-update-range +@anchor{-var-set-update-range} + +@subsubheading Synopsis + +@smallexample + -var-set-update-range @var{name} @var{from} @var{to} +@end smallexample + +Set the range of children to be returned by future invocations of +@code{-var-update}. + +@var{from} and @var{to} indicate the range of children to report. If +@var{from} or @var{to} is less than zero, the range is reset and all +children will be reported. Otherwise, children starting at @var{from} +(zero-based) and ending just before @var{to} will be reported. + +@subsubheading Example + +@smallexample +(gdb) +-var-set-update-range V 1 2 +^done +@end smallexample + @subheading The @code{-var-set-visualizer} command @findex -var-set-visualizer @anchor{-var-set-visualizer} diff --git a/gdb/mi/mi-cmd-var.c b/gdb/mi/mi-cmd-var.c index 0cf03d9..ede928c 100644 --- a/gdb/mi/mi-cmd-var.c +++ b/gdb/mi/mi-cmd-var.c @@ -41,7 +41,7 @@ static void varobj_update_one (struct varobj *var, enum print_values print_values, int explicit); -static int mi_print_value_p (struct type *type, enum print_values print_values); +static int mi_print_value_p (struct varobj *var, enum print_values print_values); /* Print variable object VAR. The PRINT_VALUES parameter controls if the value should be printed. The PRINT_EXPRESSION parameter @@ -59,8 +59,12 @@ print_varobj (struct varobj *var, enum print_values print_values, ui_out_field_string (uiout, "exp", varobj_get_expression (var)); ui_out_field_int (uiout, "numchild", varobj_get_num_children (var)); - if (mi_print_value_p (varobj_get_gdb_type (var), print_values)) - ui_out_field_string (uiout, "value", varobj_get_value (var)); + if (mi_print_value_p (var, print_values)) + { + char *val = varobj_get_value (var); + ui_out_field_string (uiout, "value", val); + xfree (val); + } type = varobj_get_type (var); if (type != NULL) @@ -75,6 +79,9 @@ print_varobj (struct varobj *var, enum print_values print_values, if (varobj_get_frozen (var)) ui_out_field_int (uiout, "frozen", 1); + + if (varobj_pretty_printed_p (var)) + ui_out_field_int (uiout, "dynamic", 1); } /* VAROBJ operations */ @@ -138,6 +145,8 @@ mi_cmd_var_create (char *command, char **argv, int argc) print_varobj (var, PRINT_ALL_VALUES, 0 /* don't print expression */); + ui_out_field_int (uiout, "has_more", varobj_has_more (var, 0)); + do_cleanups (old_cleanups); } @@ -223,6 +232,7 @@ mi_cmd_var_set_format (char *command, char **argv, int argc) { enum varobj_display_formats format; struct varobj *var; + char *val; if (argc != 2) error (_("mi_cmd_var_set_format: Usage: NAME FORMAT.")); @@ -239,7 +249,9 @@ mi_cmd_var_set_format (char *command, char **argv, int argc) ui_out_field_string (uiout, "format", varobj_format_string[(int) format]); /* Report the value in the new format */ - ui_out_field_string (uiout, "value", varobj_get_value (var)); + val = varobj_get_value (var); + ui_out_field_string (uiout, "value", val); + xfree (val); } void @@ -337,11 +349,12 @@ Must be: 0 or \"%s\", 1 or \"%s\", 2 or \"%s\""), } /* Return 1 if given the argument PRINT_VALUES we should display - a value of type TYPE. */ + the varobj VAR. */ static int -mi_print_value_p (struct type *type, enum print_values print_values) +mi_print_value_p (struct varobj *var, enum print_values print_values) { + struct type *type; if (print_values == PRINT_NO_VALUES) return 0; @@ -349,6 +362,10 @@ mi_print_value_p (struct type *type, enum print_values print_values) if (print_values == PRINT_ALL_VALUES) return 1; + if (varobj_pretty_printed_p (var)) + return 1; + + type = varobj_get_gdb_type (var); if (type == NULL) return 1; else @@ -369,24 +386,35 @@ mi_cmd_var_list_children (char *command, char **argv, int argc) struct varobj *var; VEC(varobj_p) *children; struct varobj *child; - struct cleanup *cleanup_children; int numchild; enum print_values print_values; int ix; + int from, to; char *display_hint; - if (argc != 1 && argc != 2) - error (_("mi_cmd_var_list_children: Usage: [PRINT_VALUES] NAME")); + if (argc < 1 || argc > 4) + error (_("mi_cmd_var_list_children: Usage: [PRINT_VALUES] NAME [FROM TO]")); /* Get varobj handle, if a valid var obj name was specified */ - if (argc == 1) + if (argc == 1 || argc == 3) var = varobj_get_handle (argv[0]); else var = varobj_get_handle (argv[1]); - children = varobj_list_children (var); - ui_out_field_int (uiout, "numchild", VEC_length (varobj_p, children)); - if (argc == 2) + if (argc > 2) + { + from = atoi (argv[argc - 2]); + to = atoi (argv[argc - 1]); + } + else + { + from = -1; + to = -1; + } + + children = varobj_list_children (var, &from, &to); + ui_out_field_int (uiout, "numchild", to - from); + if (argc == 2 || argc == 4) print_values = mi_parse_values_option (argv[0]); else print_values = PRINT_NO_VALUES; @@ -398,21 +426,28 @@ mi_cmd_var_list_children (char *command, char **argv, int argc) xfree (display_hint); } - if (VEC_length (varobj_p, children) == 0) - return; - - if (mi_version (uiout) == 1) - cleanup_children = make_cleanup_ui_out_tuple_begin_end (uiout, "children"); - else - cleanup_children = make_cleanup_ui_out_list_begin_end (uiout, "children"); - for (ix = 0; VEC_iterate (varobj_p, children, ix, child); ++ix) + if (from < to) { - struct cleanup *cleanup_child; - cleanup_child = make_cleanup_ui_out_tuple_begin_end (uiout, "child"); - print_varobj (child, print_values, 1 /* print expression */); - do_cleanups (cleanup_child); + struct cleanup *cleanup_children; + if (mi_version (uiout) == 1) + cleanup_children + = make_cleanup_ui_out_tuple_begin_end (uiout, "children"); + else + cleanup_children + = make_cleanup_ui_out_list_begin_end (uiout, "children"); + for (ix = from; + ix < to && VEC_iterate (varobj_p, children, ix, child); + ++ix) + { + struct cleanup *cleanup_child; + cleanup_child = make_cleanup_ui_out_tuple_begin_end (uiout, "child"); + print_varobj (child, print_values, 1 /* print expression */); + do_cleanups (cleanup_child); + } + do_cleanups (cleanup_children); } - do_cleanups (cleanup_children); + + ui_out_field_int (uiout, "has_more", varobj_has_more (var, to)); } void @@ -538,16 +573,24 @@ mi_cmd_var_evaluate_expression (char *command, char **argv, int argc) var = varobj_get_handle (argv[optind]); if (formatFound) - ui_out_field_string (uiout, "value", varobj_get_formatted_value (var, format)); + { + char *val = varobj_get_formatted_value (var, format); + ui_out_field_string (uiout, "value", val); + xfree (val); + } else - ui_out_field_string (uiout, "value", varobj_get_value (var)); + { + char *val = varobj_get_value (var); + ui_out_field_string (uiout, "value", val); + xfree (val); + } } void mi_cmd_var_assign (char *command, char **argv, int argc) { struct varobj *var; - char *expression; + char *expression, *val; if (argc != 2) error (_("mi_cmd_var_assign: Usage: NAME EXPRESSION.")); @@ -563,7 +606,9 @@ mi_cmd_var_assign (char *command, char **argv, int argc) if (!varobj_set_value (var, expression)) error (_("mi_cmd_var_assign: Could not assign expression to variable object")); - ui_out_field_string (uiout, "value", varobj_get_value (var)); + val = varobj_get_value (var); + ui_out_field_string (uiout, "value", val); + xfree (val); } /* Type used for parameters passing to mi_cmd_var_update_iter. */ @@ -670,6 +715,7 @@ varobj_update_one (struct varobj *var, enum print_values print_values, for (i = 0; VEC_iterate (varobj_update_result, changes, i, r); ++i) { char *display_hint; + int from, to; if (mi_version (uiout) > 1) cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); @@ -678,8 +724,12 @@ varobj_update_one (struct varobj *var, enum print_values print_values, switch (r->status) { case VAROBJ_IN_SCOPE: - if (mi_print_value_p (varobj_get_gdb_type (r->varobj), print_values)) - ui_out_field_string (uiout, "value", varobj_get_value (r->varobj)); + if (mi_print_value_p (r->varobj, print_values)) + { + char *val = varobj_get_value (r->varobj); + ui_out_field_string (uiout, "value", val); + xfree (val); + } ui_out_field_string (uiout, "in_scope", "true"); break; case VAROBJ_NOT_IN_SCOPE: @@ -699,11 +749,11 @@ varobj_update_one (struct varobj *var, enum print_values print_values, } if (r->type_changed) - { - ui_out_field_string (uiout, "new_type", varobj_get_type (r->varobj)); - ui_out_field_int (uiout, "new_num_children", - varobj_get_num_children (r->varobj)); - } + ui_out_field_string (uiout, "new_type", varobj_get_type (r->varobj)); + + if (r->type_changed || r->children_changed) + ui_out_field_int (uiout, "new_num_children", + varobj_get_num_children (r->varobj)); display_hint = varobj_get_display_hint (var); if (display_hint) @@ -712,28 +762,59 @@ varobj_update_one (struct varobj *var, enum print_values print_values, xfree (display_hint); } - if (r->children_changed) - { - int ix; - struct varobj *child; - struct cleanup *cleanup = - make_cleanup_ui_out_list_begin_end (uiout, "children"); + if (varobj_pretty_printed_p (var)) + ui_out_field_int (uiout, "dynamic", 1); - VEC (varobj_p)* children = varobj_list_children (r->varobj); + varobj_get_child_range (r->varobj, &from, &to); + ui_out_field_int (uiout, "has_more", + varobj_has_more (r->varobj, to)); - for (ix = 0; VEC_iterate (varobj_p, children, ix, child); ++ix) + if (r->new) + { + int j; + varobj_p child; + struct cleanup *cleanup; + + cleanup = make_cleanup_ui_out_list_begin_end (uiout, "new_children"); + for (j = 0; VEC_iterate (varobj_p, r->new, j, child); ++j) { struct cleanup *cleanup_child; cleanup_child = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); - print_varobj (child, print_values, 1 /* print expression */); + print_varobj (child, print_values, 1 /* print_expression */); do_cleanups (cleanup_child); } do_cleanups (cleanup); + VEC_free (varobj_p, r->new); + r->new = NULL; /* Paranoia. */ } - + if (mi_version (uiout) > 1) do_cleanups (cleanup); } VEC_free (varobj_update_result, changes); } + +void +mi_cmd_enable_pretty_printing (char *command, char **argv, int argc) +{ + if (argc != 0) + error (_("mi_cmd_enable_pretty_printing: no arguments allowed")); + varobj_enable_pretty_printing (); +} + +void +mi_cmd_var_set_update_range (char *command, char **argv, int argc) +{ + struct varobj *var; + int from, to; + + if (argc != 3) + error (_("mi_cmd_var_set_update_range: Usage: VAROBJ FROM TO")); + + var = varobj_get_handle (argv[0]); + from = atoi (argv[1]); + to = atoi (argv[2]); + + varobj_set_child_range (var, from, to); +} diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c index dd3d803..8ba086c 100644 --- a/gdb/mi/mi-cmds.c +++ b/gdb/mi/mi-cmds.c @@ -52,6 +52,7 @@ struct mi_cmd mi_cmds[] = { "data-write-memory", { NULL, 0 }, mi_cmd_data_write_memory}, { "data-write-register-values", { NULL, 0 }, mi_cmd_data_write_register_values}, { "enable-timings", { NULL, 0 }, mi_cmd_enable_timings}, + { "enable-pretty-printing", { NULL, 0 }, mi_cmd_enable_pretty_printing}, { "environment-cd", { NULL, 0 }, mi_cmd_env_cd}, { "environment-directory", { NULL, 0 }, mi_cmd_env_dir}, { "environment-path", { NULL, 0 }, mi_cmd_env_path}, @@ -112,6 +113,7 @@ struct mi_cmd mi_cmds[] = { "var-list-children", { NULL, 0 }, mi_cmd_var_list_children}, { "var-set-format", { NULL, 0 }, mi_cmd_var_set_format}, { "var-set-frozen", { NULL, 0 }, mi_cmd_var_set_frozen}, + { "var-set-update-range", { NULL, 0 }, mi_cmd_var_set_update_range }, { "var-set-visualizer", { NULL, 0 }, mi_cmd_var_set_visualizer}, { "var-show-attributes", { NULL, 0 }, mi_cmd_var_show_attributes}, { "var-show-format", { NULL, 0 }, mi_cmd_var_show_format}, diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h index 85ad0c4..dfab411 100644 --- a/gdb/mi/mi-cmds.h +++ b/gdb/mi/mi-cmds.h @@ -99,6 +99,8 @@ extern mi_cmd_argv_ftype mi_cmd_var_set_visualizer; extern mi_cmd_argv_ftype mi_cmd_var_show_attributes; extern mi_cmd_argv_ftype mi_cmd_var_show_format; extern mi_cmd_argv_ftype mi_cmd_var_update; +extern mi_cmd_argv_ftype mi_cmd_enable_pretty_printing; +extern mi_cmd_argv_ftype mi_cmd_var_set_update_range; /* Description of a single command. */ diff --git a/gdb/testsuite/gdb.mi/gdb701.exp b/gdb/testsuite/gdb.mi/gdb701.exp index d4acdc2..244c731 100644 --- a/gdb/testsuite/gdb.mi/gdb701.exp +++ b/gdb/testsuite/gdb.mi/gdb701.exp @@ -54,7 +54,7 @@ mi_gdb_test "-var-list-children fooPtr" \ foreach i [list x y z] { mi_gdb_test "-var-list-children fooPtr.$i" \ - "(&\".*\"\r\n)*\\^done,numchild=\"0\"" \ + "(&\".*\"\r\n)*\\^done,numchild=\"0\",has_more=\"0\"" \ "list children of fooPtr.$i" } diff --git a/gdb/testsuite/gdb.mi/mi-break.exp b/gdb/testsuite/gdb.mi/mi-break.exp index 619727d..8d06c0e 100644 --- a/gdb/testsuite/gdb.mi/mi-break.exp +++ b/gdb/testsuite/gdb.mi/mi-break.exp @@ -175,7 +175,7 @@ proc test_error {} { # containing function call, the internal breakpoint created to handle # function call would be reported, messing up MI output. mi_gdb_test "-var-create V * return_1()" \ - "\\^done,name=\"V\",numchild=\"0\",value=\"1\",type=\"int\"" \ + "\\^done,name=\"V\",numchild=\"0\",value=\"1\",type=\"int\",has_more=\"0\"" \ "create varobj for function call" mi_gdb_test "-var-update *" \ diff --git a/gdb/testsuite/gdb.mi/mi-var-block.exp b/gdb/testsuite/gdb.mi/mi-var-block.exp index 8806848..93ded26 100644 --- a/gdb/testsuite/gdb.mi/mi-var-block.exp +++ b/gdb/testsuite/gdb.mi/mi-var-block.exp @@ -74,7 +74,7 @@ mi_step_to "do_block_tests" "" "var-cmd.c" \ # Test: c_variable-3.4 # Desc: check foo, cb changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"foo\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"cb\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"foo\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"cb\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars: cb foo changed" # step to "foo = 321;" diff --git a/gdb/testsuite/gdb.mi/mi-var-child.exp b/gdb/testsuite/gdb.mi/mi-var-child.exp index 1f4bdc6..eb6c456 100644 --- a/gdb/testsuite/gdb.mi/mi-var-child.exp +++ b/gdb/testsuite/gdb.mi/mi-var-child.exp @@ -680,7 +680,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \ # Test: c_variable-5.2 # Desc: check that integer changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"struct_declarations.integer\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"struct_declarations.integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars struct_declarations.integer" # Step over: @@ -693,7 +693,7 @@ mi_execute_to "exec-step 3" "end-stepping-range" do_children_tests {} ".*${srcfi # Test: c_variable-5.3 # Desc: check that char_ptr changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"struct_declarations.char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.char_ptr.\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"struct_declarations.char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.char_ptr.\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars struct_declarations.char_ptr" # Step over "struct_declarations.int_ptr_ptr = &foo;" @@ -703,7 +703,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \ # Test: c_variable-5.4 # Desc: check that int_ptr_ptr and children changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr.\\*\\*weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr.\\*\\*int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr.\\*\\*weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr.\\*\\*int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars int_ptr_ptr and children changed" # Step over "weird->long_array[0] = 1234;" @@ -713,7 +713,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \ # Test: c_variable-5.5 # Desc: check that long_array[0] changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.0\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.0\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars struct_declarations.long_array.0 changed" # Step over "struct_declarations.long_array[1] = 2345;" @@ -723,7 +723,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \ # Test: c_variable-5.6 # Desc: check that long_array[1] changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.1\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.1\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars struct_declarations.long_array.1 changed" # Step over "weird->long_array[2] = 3456;" @@ -733,7 +733,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \ # Test: c_variable-5.7 # Desc: check that long_array[2] changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.2\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.2\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars struct_declarations.long_array.2 changed" # Step over: @@ -752,7 +752,7 @@ mi_execute_to "exec-step 7" "end-stepping-range" do_children_tests {} ".*${srcfi # Test: c_variable-5.8 # Desc: check that long_array[3-9] changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.3\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.4\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.5\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.6\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.7\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.8\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.9\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.3\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.4\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.5\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.6\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.7\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.8\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.9\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars struct_declarations.long_array.3-9 changed" @@ -763,7 +763,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \ # Test: c_variable-5.9 # Desc: check that func_ptr changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"struct_declarations.func_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"struct_declarations.func_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars struct_declarations.func_ptr changed" # Step over "struct_declarations.long_array[10] = 3456"; @@ -771,7 +771,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \ [expr $line_dct_nothing + 2] "step \$line_dct_nothing + 2" mi_gdb_test "-var-update --no-values *" \ - "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.10\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.10\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars struct_declarations.long_array.10 changed, don't print values." # Step over "struct_declarations.long_array[11] = 5678"; @@ -780,7 +780,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \ $line_dct_a0_0 "step \$line_dct_a0_0" mi_gdb_test "-var-update --all-values *" \ - "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.11\",value=\"5678\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.11\",value=\"5678\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars struct_declarations.long_array.11 changed, print values." mi_list_varobj_children {struct_declarations.long_array --all-values} { @@ -1121,7 +1121,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \ # Test: c_variable-5.47 # Desc: check that psnp->char_ptr (and [0].char_ptr) changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr.\\*\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr.\\*\\*\\*psnp->char_ptr.\\*\\*\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr.\\*\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr.\\*\\*\\*psnp->char_ptr.\\*\\*\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars psnp->char_ptr (and 0.char_ptr) changed" # Step over "snp1.char_ptr = &c3;" @@ -1131,7 +1131,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \ # Test: c_variable-5.48 # Desc: check that psnp->next->char_ptr (and [1].char_ptr) changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr.\\*\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr.\\*\\*\\*char_ptr.\\*\\*\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr.\\*\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr.\\*\\*\\*char_ptr.\\*\\*\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars psnp->next->char_ptr (and 1.char_ptr) changed" @@ -1142,7 +1142,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \ # Test: c_variable-5.49 # Desc: check that psnp->next->next->char_ptr (and [2].char_ptr) changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.next.char_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.next.char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars psnp->next->next->char_ptr (and 2.char_ptr) changed" @@ -1153,7 +1153,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \ # Test: c_variable-5.50 # Desc: check that psnp->long_ptr (and [0].long_ptr) changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr.\\*\\*\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr.\\*\\*\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars psnp->long_ptr (and 0.long_ptr) changed" @@ -1181,7 +1181,7 @@ mi_step_to do_children_tests {} ".*${srcfile}" \ # Test: c_variable-5.52 # Desc: check that psnp->next->next->long_ptr (and [2].long_ptr) changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.next.long_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.next.long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars psnp->next->next->long_ptr (and 2.long_ptr) changed" mi_prepare_inline_tests $srcfile diff --git a/gdb/testsuite/gdb.mi/mi-var-cmd.exp b/gdb/testsuite/gdb.mi/mi-var-cmd.exp index ad2e55c..6efb333 100644 --- a/gdb/testsuite/gdb.mi/mi-var-cmd.exp +++ b/gdb/testsuite/gdb.mi/mi-var-cmd.exp @@ -146,7 +146,7 @@ mi_step_to "do_locals_tests" "" "var-cmd.c" $line_dlt_linteger "step at do_local # Test: c_variable-2.2 # Desc: check whether only linteger changed values mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars: linteger changed" # Step over "lpinteger = &linteger;" @@ -155,7 +155,7 @@ mi_step_to "do_locals_tests" "" "var-cmd.c" [expr $line_dlt_linteger + 1] "step # Test: c_variable-2.3 # Desc: check whether only lpinteger changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"lpinteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"lpinteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars: lpinteger changed" # Step over "lcharacter = 'a';" @@ -164,7 +164,7 @@ mi_step_to "do_locals_tests" "" "var-cmd.c" [expr $line_dlt_linteger + 2] "step # Test: c_variable-2.4 # Desc: check whether only lcharacter changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"lcharacter\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"lcharacter\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars: lcharacter changed" # Step over "lpcharacter = &lcharacter;" @@ -173,7 +173,7 @@ mi_step_to "do_locals_tests" "" "var-cmd.c" [expr $line_dlt_linteger + 3] "step # Test: c_variable-2.5 # Desc: check whether only lpcharacter changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars: lpcharacter changed" @@ -195,7 +195,7 @@ mi_execute_to "exec-step 9" "end-stepping-range" "do_locals_tests" "" \ # Desc: check whether llong, lplong, lfloat, lpfloat, ldouble, lpdouble, lsimple.integer, # lsimple.unsigned_character lsimple.integer lsimple.character changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"lsimple.integer\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lsimple->integer\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lsimple.character\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lpdouble\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"ldouble\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lpfloat\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lfloat\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lplong\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"llong\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"lsimple.integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lsimple->integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lsimple.character\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lpdouble\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"ldouble\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lpfloat\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lfloat\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lplong\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"llong\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars: many changed" # Step over: @@ -212,7 +212,7 @@ mi_execute_to "exec-step 4" "end-stepping-range" "do_locals_tests" "" \ # Test: c_variable-2.7 # Desc: check whether (lsimple.signed_character, lsimple.char_ptr) lpsimple, func changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"func\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lpsimple\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"func\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lpsimple\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars: func and lpsimple changed" # Step over @@ -234,7 +234,7 @@ mi_execute_to "exec-step 8" "end-stepping-range" "do_locals_tests" "" \ # Note: this test also checks that lpsimple->integer and lsimple.integer have # changed (they are the same) mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"lsimple.integer\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lsimple->integer\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lsimple.character\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"ldouble\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lfloat\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"llong\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lcharacter\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"lsimple.integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lsimple->integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lsimple.character\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"ldouble\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lfloat\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"llong\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lcharacter\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars: lsimple and others changed" @@ -257,7 +257,7 @@ mi_gdb_test "-var-assign linteger 3333" \ # change. set lpchar_update "\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\"\}," mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[($lpchar_update)?\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[($lpchar_update)?\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars: linteger changed after assign" mi_gdb_test "-var-assign linteger 3333" \ @@ -277,7 +277,7 @@ mi_gdb_test "-var-assign lpinteger \"&linteger + 3\"" \ "assign to lpinteger" mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"lpinteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"lpinteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars: lpinteger changed after assign" mi_gdb_test "-var-update *" \ @@ -377,7 +377,7 @@ mi_gdb_test "-var-update *" \ "assign same value to func (update)" mi_gdb_test "-var-create array_ptr * array_ptr" \ - "\\^done,name=\"array_ptr\",numchild=\"1\",value=\"$hex\",type=\"int \\*\"" \ + "\\^done,name=\"array_ptr\",numchild=\"1\",value=\"$hex\",type=\"int \\*\",has_more=\"0\"" \ "create global variable array_ptr" mi_gdb_test "-var-assign array_ptr array2" \ @@ -385,7 +385,7 @@ mi_gdb_test "-var-assign array_ptr array2" \ "assign array to pointer" mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"array_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"array_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "assign array to pointer (update)" mi_gdb_test "-var-assign array_ptr array2" \ @@ -439,7 +439,7 @@ mi_step_to "subroutine1" "\{name=\"i\",value=\".*\"\},\{name=\"l\",value=\".*\"\ # Test: c_variable-2.13 # Desc: change subroutine1 local i mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"i\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"i\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars: i changed" mi_step_to "subroutine1" "\{name=\"i\",value=\".*\"\},\{name=\"l\",value=\".*\"\}" \ @@ -448,7 +448,7 @@ mi_step_to "subroutine1" "\{name=\"i\",value=\".*\"\},\{name=\"l\",value=\".*\"\ # Test: c_variable-2.14 # Desc: change do_locals_tests local llong mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"llong\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"llong\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars: llong changed" set line_dlt_call_subroutine1 [gdb_get_line_number "subroutine1 (linteger, &llong);"] @@ -458,7 +458,7 @@ mi_next_to "do_locals_tests" "" "var-cmd.c" \ # Test: c_variable-2.15 # Desc: check for out of scope subroutine1 locals mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"l\",in_scope=\"false\"\,type_changed=\"false\"},\{name=\"i\",in_scope=\"false\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"l\",in_scope=\"false\"\,type_changed=\"false\",has_more=\"0\"},\{name=\"i\",in_scope=\"false\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars: all now out of scope" # Done with locals/globals tests. Erase all variables @@ -550,14 +550,14 @@ mi_gdb_test "-var-create selected_a @ a" \ mi_continue_to incr_a mi_gdb_test "-var-update selected_a" \ - "\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",type_changed=\"true\",new_type=\"char\",new_num_children=\"0\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",type_changed=\"true\",new_type=\"char\",new_num_children=\"0\",has_more=\"0\"\}\\\]" \ "update selected_a in incr_a" mi_next "step a line in incr_a" mi_next "return from incr_a to do_special_tests" mi_gdb_test "-var-update selected_a" \ - "\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",type_changed=\"true\",new_type=\"int\",new_num_children=\"0\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",type_changed=\"true\",new_type=\"int\",new_num_children=\"0\",has_more=\"0\"\}\\\]" \ "update selected_a in do_special_tests" mi_gdb_test "-file-exec-and-symbols ${binfile}" "\\^done" \ @@ -596,7 +596,7 @@ mi_check_varobj_value F 7 "check F inside callee" # A varobj we fail to read during -var-update should be considered # out of scope. mi_gdb_test "-var-create null_ptr * **0" \ - {\^done,name="null_ptr",numchild="0",value=".*",type="int"} \ + {\^done,name="null_ptr",numchild="0",value=".*",type="int",has_more="0"} \ "create null_ptr" # Allow this to succeed, if address zero is readable, although it @@ -644,7 +644,7 @@ mi_check_varobj_value "L" "{...}" "in-and-out-of-scope: check initial value" mi_runto main mi_gdb_test "-var-update L" \ - {\^done,changelist=\[{name="L",in_scope="false",type_changed="false"}\]} \ + {\^done,changelist=\[{name="L",in_scope="false",type_changed="false",has_more="0"}\]} \ "in-and-out-of-scope: out of scope now" mi_gdb_test "-var-update L" \ @@ -654,7 +654,7 @@ mi_gdb_test "-var-update L" \ mi_continue_to do_locals_tests mi_gdb_test "-var-update L" \ - {\^done,changelist=\[{name="L",in_scope="true",type_changed="false"}\]} \ + {\^done,changelist=\[{name="L",in_scope="true",type_changed="false",has_more="0"}\]} \ "in-and-out-of-scope: in scope now" mi_gdb_test "-var-update L" \ diff --git a/gdb/testsuite/gdb.mi/mi-var-display.exp b/gdb/testsuite/gdb.mi/mi-var-display.exp index 4b02e50..faa9172 100644 --- a/gdb/testsuite/gdb.mi/mi-var-display.exp +++ b/gdb/testsuite/gdb.mi/mi-var-display.exp @@ -558,7 +558,7 @@ mi_gdb_test "-var-info-num-children e" \ # Test: c_variable-7.55 # Desc: children of e mi_gdb_test "-var-list-children e" \ - "\\^done,numchild=\"0\"" \ + "\\^done,numchild=\"0\",has_more=\"0\"" \ "get children of e" # Test: c_variable-7.60 @@ -600,7 +600,7 @@ mi_gdb_test "-var-info-num-children anone" \ # Test: c_variable-7.75 # Desc: children of anone mi_gdb_test "-var-list-children anone" \ - "\\^done,numchild=\"0\"" \ + "\\^done,numchild=\"0\",has_more=\"0\"" \ "get children of anone" diff --git a/gdb/testsuite/gdb.mi/mi-var-invalidate.exp b/gdb/testsuite/gdb.mi/mi-var-invalidate.exp index 05d46fa..4b95674 100644 --- a/gdb/testsuite/gdb.mi/mi-var-invalidate.exp +++ b/gdb/testsuite/gdb.mi/mi-var-invalidate.exp @@ -72,7 +72,7 @@ mi_runto main # Check local variable is "invalid". mi_gdb_test "-var-update linteger" \ - "\\^done,changelist=\\\[\{name=\"linteger\",in_scope=\"invalid\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"linteger\",in_scope=\"invalid\",has_more=\"0\"\}\\\]" \ "linteger not anymore in scope due to binary changes" mi_gdb_test "-var-info-type linteger" \ @@ -97,7 +97,7 @@ mi_delete_breakpoints mi_gdb_load ${binfile2} # Check local variable are "invalid" mi_gdb_test "-var-update linteger" \ - "\\^done,changelist=\\\[\{name=\"linteger\",in_scope=\"invalid\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"linteger\",in_scope=\"invalid\",has_more=\"0\"\}\\\]" \ "linteger not valid anymore due to binary changes" mi_gdb_test "-var-info-type linteger" \ @@ -106,7 +106,7 @@ mi_gdb_test "-var-info-type linteger" \ # Check global variable are still correct. mi_gdb_test "-var-update global_simple" \ - "\\^done,changelist=\\\[\{name=\"global_simple\",in_scope=\"invalid\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"global_simple\",in_scope=\"invalid\",has_more=\"0\"\}\\\]" \ "global_simple not anymore in scope due to binary changes" mi_gdb_test "-var-info-type global_simple" \ diff --git a/gdb/testsuite/gdb.mi/mi2-var-block.exp b/gdb/testsuite/gdb.mi/mi2-var-block.exp index 6bcfea3..9b3d08f 100644 --- a/gdb/testsuite/gdb.mi/mi2-var-block.exp +++ b/gdb/testsuite/gdb.mi/mi2-var-block.exp @@ -74,7 +74,7 @@ mi_step_to "do_block_tests" "" "var-cmd.c" \ # Test: c_variable-3.4 # Desc: check foo, cb changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"foo\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"cb\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"foo\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"cb\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars: cb foo changed" # step to "foo = 321;" diff --git a/gdb/testsuite/gdb.mi/mi2-var-child.exp b/gdb/testsuite/gdb.mi/mi2-var-child.exp index 161b34f..0f9b4d4 100644 --- a/gdb/testsuite/gdb.mi/mi2-var-child.exp +++ b/gdb/testsuite/gdb.mi/mi2-var-child.exp @@ -1,4 +1,4 @@ -# Copyright 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation +# Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2009 Free Software Foundation # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -680,7 +680,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \ # Test: c_variable-5.2 # Desc: check that integer changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"struct_declarations.integer\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"struct_declarations.integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars struct_declarations.integer" # Step over: @@ -693,7 +693,7 @@ mi_execute_to "exec-step 3" "end-stepping-range" do_children_tests {} {.*var-cmd # Test: c_variable-5.3 # Desc: check that char_ptr changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"struct_declarations.char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.char_ptr.\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"struct_declarations.char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.char_ptr.\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars struct_declarations.char_ptr" # Step over "struct_declarations.int_ptr_ptr = &foo;" @@ -703,7 +703,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \ # Test: c_variable-5.4 # Desc: check that int_ptr_ptr and children changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr.\\*\\*weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr.\\*\\*int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"weird->int_ptr_ptr.\\*weird->int_ptr_ptr.\\*\\*weird->int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.int_ptr_ptr.\\*int_ptr_ptr.\\*\\*int_ptr_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars int_ptr_ptr and children changed" # Step over "weird->long_array[0] = 1234;" @@ -713,7 +713,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \ # Test: c_variable-5.5 # Desc: check that long_array[0] changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.0\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.0\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars struct_declarations.long_array.0 changed" # Step over "struct_declarations.long_array[1] = 2345;" @@ -723,7 +723,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \ # Test: c_variable-5.6 # Desc: check that long_array[1] changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.1\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.1\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars struct_declarations.long_array.1 changed" # Step over "weird->long_array[2] = 3456;" @@ -733,7 +733,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \ # Test: c_variable-5.7 # Desc: check that long_array[2] changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.2\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.2\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars struct_declarations.long_array.2 changed" # Step over: @@ -752,7 +752,7 @@ mi_execute_to "exec-step 7" "end-stepping-range" do_children_tests {} {.*var-cmd # Test: c_variable-5.8 # Desc: check that long_array[3-9] changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.3\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.4\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.5\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.6\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.7\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.8\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"struct_declarations.long_array.9\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"struct_declarations.long_array.3\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.4\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.5\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.6\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.7\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.8\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"struct_declarations.long_array.9\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars struct_declarations.long_array.3-9 changed" @@ -764,7 +764,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \ # Test: c_variable-5.9 # Desc: check that func_ptr changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"struct_declarations.func_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"struct_declarations.func_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars struct_declarations.func_ptr changed" # Delete all variables @@ -1075,7 +1075,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \ # Test: c_variable-5.47 # Desc: check that psnp->char_ptr (and [0].char_ptr) changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr.\\*\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr.\\*\\*\\*psnp->char_ptr.\\*\\*\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr.\\*\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->char_ptr.\\*psnp->char_ptr.\\*\\*psnp->char_ptr.\\*\\*\\*psnp->char_ptr.\\*\\*\\*\\*psnp->char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars psnp->char_ptr (and 0.char_ptr) changed" # Step over "snp1.char_ptr = &c3;" @@ -1085,7 +1085,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \ # Test: c_variable-5.48 # Desc: check that psnp->next->char_ptr (and [1].char_ptr) changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr.\\*\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr.\\*\\*\\*char_ptr.\\*\\*\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr.\\*\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->ptrs.0.next.char_ptr.\\*char_ptr.\\*\\*char_ptr.\\*\\*\\*char_ptr.\\*\\*\\*\\*char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars psnp->next->char_ptr (and 1.char_ptr) changed" @@ -1096,7 +1096,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \ # Test: c_variable-5.49 # Desc: check that psnp->next->next->char_ptr (and [2].char_ptr) changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.next.char_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.next.char_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars psnp->next->next->char_ptr (and 2.char_ptr) changed" @@ -1107,7 +1107,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \ # Test: c_variable-5.50 # Desc: check that psnp->long_ptr (and [0].long_ptr) changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr.\\*\\*\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"psnp->long_ptr.\\*psnp->long_ptr.\\*\\*psnp->long_ptr.\\*\\*\\*psnp->long_ptr.\\*\\*\\*\\*psnp->long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars psnp->long_ptr (and 0.long_ptr) changed" @@ -1120,7 +1120,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \ # Why does this have a FIXME? setup_xfail *-*-* mi_gdb_test "-var-update *" \ - "FIXME\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.long_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "FIXME\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars psnp->next->long_ptr (and 1.long_ptr) changed" clear_xfail *-*-* @@ -1135,7 +1135,7 @@ mi_step_to do_children_tests {} {.*var-cmd.c} \ # Test: c_variable-5.52 # Desc: check that psnp->next->next->long_ptr (and [2].long_ptr) changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.next.long_ptr\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"psnp->ptrs.0.next.next.long_ptr\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars psnp->next->next->long_ptr (and 2.long_ptr) changed" diff --git a/gdb/testsuite/gdb.mi/mi2-var-cmd.exp b/gdb/testsuite/gdb.mi/mi2-var-cmd.exp index dda77bb..e900d14 100644 --- a/gdb/testsuite/gdb.mi/mi2-var-cmd.exp +++ b/gdb/testsuite/gdb.mi/mi2-var-cmd.exp @@ -126,11 +126,6 @@ mi_gdb_test "-var-create int * int" \ "&\"Attempt to use a type name as an expression.\\\\n\".*\\^error,msg=\"mi_cmd_var_create: unable to create variable object\"" \ "create int" -# The number 0 must be an invalid frame address and linteger a local variable. -mi_gdb_test "-var-create invalidframe 0 linteger" \ - "\\^error,msg=\"Failed to find the specified frame\"" \ - "create variable with invalid FRAME-ADDR" - ##### ##### # # @@ -151,7 +146,7 @@ mi_step_to "do_locals_tests" "" "var-cmd.c" $line_dlt_linteger "step at do_local # Test: c_variable-2.2 # Desc: check whether only linteger changed values mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars: linteger changed" # Step over "lpinteger = &linteger;" @@ -160,7 +155,7 @@ mi_step_to "do_locals_tests" "" "var-cmd.c" [expr $line_dlt_linteger + 1] "step # Test: c_variable-2.3 # Desc: check whether only lpinteger changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"lpinteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"lpinteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars: lpinteger changed" # Step over "lcharacter = 'a';" @@ -169,7 +164,7 @@ mi_step_to "do_locals_tests" "" "var-cmd.c" [expr $line_dlt_linteger + 2] "step # Test: c_variable-2.4 # Desc: check whether only lcharacter changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"lcharacter\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"lcharacter\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars: lcharacter changed" # Step over "lpcharacter = &lcharacter;" @@ -178,7 +173,7 @@ mi_step_to "do_locals_tests" "" "var-cmd.c" [expr $line_dlt_linteger + 3] "step # Test: c_variable-2.5 # Desc: check whether only lpcharacter changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars: lpcharacter changed" @@ -200,7 +195,7 @@ mi_execute_to "exec-step 9" "end-stepping-range" "do_locals_tests" "" \ # Desc: check whether llong, lplong, lfloat, lpfloat, ldouble, lpdouble, lsimple.integer, # lsimple.unsigned_character lsimple.integer lsimple.character changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"lsimple.integer\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lsimple->integer\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lsimple.character\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lpdouble\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"ldouble\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lpfloat\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lfloat\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lplong\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"llong\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"lsimple.integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lsimple->integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lsimple.character\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lpdouble\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"ldouble\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lpfloat\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lfloat\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lplong\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"llong\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars: many changed" # Step over: @@ -217,7 +212,7 @@ mi_execute_to "exec-step 4" "end-stepping-range" "do_locals_tests" "" \ # Test: c_variable-2.7 # Desc: check whether (lsimple.signed_character, lsimple.char_ptr) lpsimple, func changed mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"func\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lpsimple\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"func\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lpsimple\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars: func and lpsimple changed" # Step over @@ -239,7 +234,7 @@ mi_execute_to "exec-step 8" "end-stepping-range" "do_locals_tests" "" \ # Note: this test also checks that lpsimple->integer and lsimple.integer have # changed (they are the same) mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"lsimple.integer\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lsimple->integer\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lsimple.character\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"ldouble\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lfloat\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"llong\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"lcharacter\",in_scope=\"true\",type_changed=\"false\"\},\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"lsimple.integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lsimple->integer\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lsimple.character\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"ldouble\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lfloat\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"llong\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"lcharacter\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\},\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars: lsimple and others changed" @@ -262,7 +257,7 @@ mi_gdb_test "-var-assign linteger 3333" \ # change. set lpchar_update "\{name=\"lpcharacter\",in_scope=\"true\",type_changed=\"false\"\}," mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[($lpchar_update)?\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[($lpchar_update)?\{name=\"linteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars: linteger changed after assign" mi_gdb_test "-var-assign linteger 3333" \ @@ -282,7 +277,7 @@ mi_gdb_test "-var-assign lpinteger \"&linteger + 3\"" \ "assign to lpinteger" mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"lpinteger\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"lpinteger\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars: lpinteger changed after assign" mi_gdb_test "-var-update *" \ @@ -407,7 +402,7 @@ mi_step_to "subroutine1" "\{name=\"i\",value=\".*\"\},\{name=\"l\",value=\".*\"\ # Test: c_variable-2.13 # Desc: change subroutine1 local i mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"i\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"i\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars: i changed" mi_step_to "subroutine1" "\{name=\"i\",value=\".*\"\},\{name=\"l\",value=\".*\"\}" \ @@ -416,7 +411,7 @@ mi_step_to "subroutine1" "\{name=\"i\",value=\".*\"\},\{name=\"l\",value=\".*\"\ # Test: c_variable-2.14 # Desc: change do_locals_tests local llong mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"llong\",in_scope=\"true\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"llong\",in_scope=\"true\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars: llong changed" set line_dlt_call_subroutine1 [gdb_get_line_number "subroutine1 (linteger, &llong);"] @@ -426,7 +421,7 @@ mi_next_to "do_locals_tests" "" "var-cmd.c" \ # Test: c_variable-2.15 # Desc: check for out of scope subroutine1 locals mi_gdb_test "-var-update *" \ - "\\^done,changelist=\\\[\{name=\"l\",in_scope=\"false\"\,type_changed=\"false\"},\{name=\"i\",in_scope=\"false\",type_changed=\"false\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"l\",in_scope=\"false\"\,type_changed=\"false\",has_more=\"0\"},\{name=\"i\",in_scope=\"false\",type_changed=\"false\",has_more=\"0\"\}\\\]" \ "update all vars: all now out of scope" # Done with locals/globals tests. Erase all variables @@ -518,14 +513,14 @@ mi_gdb_test "-var-create selected_a @ a" \ mi_continue_to incr_a mi_gdb_test "-var-update selected_a" \ - "\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",type_changed=\"true\",new_type=\"char\",new_num_children=\"0\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",type_changed=\"true\",new_type=\"char\",new_num_children=\"0\"\,has_more=\"0\"}\\\]" \ "update selected_a in incr_a" mi_next "step a line in incr_a" mi_next "return from incr_a to do_special_tests" mi_gdb_test "-var-update selected_a" \ - "\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",type_changed=\"true\",new_type=\"int\",new_num_children=\"0\"\}\\\]" \ + "\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",type_changed=\"true\",new_type=\"int\",new_num_children=\"0\",has_more=\"0\"\}\\\]" \ "update selected_a in do_special_tests" mi_gdb_test "-file-exec-and-symbols ${binfile}" "\\^done" \ diff --git a/gdb/testsuite/gdb.mi/mi2-var-display.exp b/gdb/testsuite/gdb.mi/mi2-var-display.exp index d6ce673..17e208a 100644 --- a/gdb/testsuite/gdb.mi/mi2-var-display.exp +++ b/gdb/testsuite/gdb.mi/mi2-var-display.exp @@ -557,7 +557,7 @@ mi_gdb_test "-var-info-num-children e" \ # Test: c_variable-7.55 # Desc: children of e mi_gdb_test "-var-list-children e" \ - "\\^done,numchild=\"0\"" \ + "\\^done,numchild=\"0\",has_more=\"0\"" \ "get children of e" # Test: c_variable-7.60 @@ -599,7 +599,7 @@ mi_gdb_test "-var-info-num-children anone" \ # Test: c_variable-7.75 # Desc: children of anone mi_gdb_test "-var-list-children anone" \ - "\\^done,numchild=\"0\"" \ + "\\^done,numchild=\"0\",has_more=\"0\"" \ "get children of anone" diff --git a/gdb/testsuite/gdb.python/python-mi.exp b/gdb/testsuite/gdb.python/python-mi.exp index 3258810..bfdb595 100644 --- a/gdb/testsuite/gdb.python/python-mi.exp +++ b/gdb/testsuite/gdb.python/python-mi.exp @@ -48,23 +48,53 @@ mi_gdb_test "python execfile ('${srcdir}/${subdir}/${testfile}.py')" "" mi_continue_to_line [gdb_get_line_number {MI breakpoint here} ${testfile}.c] \ "step to breakpoint" -mi_create_floating_varobj container c "create container varobj" +mi_create_dynamic_varobj container c \ + "create container varobj, no pretty-printing" + +mi_list_varobj_children container { + { container.name name 1 string } + { container.len len 0 int } + { container.elements elements 1 "int ." } +} "examine container children=0, no pretty-printing" + +mi_delete_varobj container "delete varobj" + +mi_gdb_test "-enable-pretty-printing" "" + +mi_create_varobj_checked string string_1 \ + "struct string_repr" \ + "create string_1 varobj" + +mi_gdb_test "-data-evaluate-expression \"string_1 = string_2\"" ".*" \ + "assign string_1 from string_2" + +mi_gdb_test "-var-update string" \ + "\\^done,changelist=\\\[{name=\"string\",in_scope=\"true\",type_changed=\"false\",dynamic=\"1\",has_more=\"0\"}\\\]" \ + "update string varobj after assignment" + +mi_create_dynamic_varobj container c \ + "create container varobj" mi_list_varobj_children container { } "examine container children=0" mi_next "next over update 1" -mi_varobj_update_dynamic container { - { {container.\[0\]} {\[0\]} 0 int } -} "varobj update 1" +mi_varobj_update_dynamic container "varobj update 1" { + type_changed false new_num_children 1 dynamic 1 has_more 0 +} { +} { + { name {container.\[0\]} exp {\[0\]} numchild 0 type int thread-id 1 } +} mi_next "next over update 2" -mi_varobj_update_dynamic container { - { {container.\[0\]} {\[0\]} 0 int } - { {container.\[1\]} {\[1\]} 0 int } -} "varobj update 2" +mi_varobj_update_dynamic container "varobj update 2" { + type_changed false new_num_children 2 dynamic 1 has_more 0 +} { +} { + { name {container.\[1\]} exp {\[1\]} numchild 0 type int thread-id 1 } +} mi_gdb_test "-var-set-visualizer container None" \ "\\^done" \ @@ -78,19 +108,111 @@ mi_gdb_test "-var-set-visualizer container gdb.default_visualizer" \ "\\^done" \ "choose default visualizer" -mi_varobj_update_dynamic container { - { {container.\[0\]} {\[0\]} 0 int } - { {container.\[1\]} {\[1\]} 0 int } -} "varobj update after choosing default" +mi_varobj_update_dynamic container "varobj update after choosing default" { + type_changed false new_num_children 2 dynamic 1 has_more 0 +} { +} { + { name {container.\[0\]} exp {\[0\]} numchild 0 type int thread-id 1 } + { name {container.\[1\]} exp {\[1\]} numchild 0 type int thread-id 1 } +} mi_gdb_test "-var-set-visualizer container ContainerPrinter" \ "\\^done" \ "choose visualizer using expression" -mi_varobj_update_dynamic container { +mi_varobj_update_dynamic container \ + "varobj update after choosing via expression" { + type_changed false new_num_children 2 dynamic 1 has_more 0 + } { + } { + { name {container.\[0\]} exp {\[0\]} numchild 0 type int thread-id 1 } + { name {container.\[1\]} exp {\[1\]} numchild 0 type int thread-id 1 } + } + +mi_list_varobj_children_range container 1 2 2 { + { {container.\[1\]} {\[1\]} 0 int } +} "list varobj children after selecting child range" + +mi_list_varobj_children_range container -1 -1 2 { + { {container.\[0\]} {\[0\]} 0 int } + { {container.\[1\]} {\[1\]} 0 int } +} "list varobj children after resetting child range" + +mi_next "next over update 3" + +mi_gdb_test "-var-set-update-range container 0 1" \ + "\\^done" \ + "set update range" + +# This should truncate the list. +mi_list_varobj_children container { { {container.\[0\]} {\[0\]} 0 int } +} "list children after setting update range" + +# This should return just the items in [1,2). +mi_list_varobj_children_range container 1 2 2 { { {container.\[1\]} {\[1\]} 0 int } -} "varobj update after choosing via expression" +} "list selected children after setting range" + +# This should not be affected by the previous list-children request. +mi_list_varobj_children container { + { {container.\[0\]} {\[0\]} 0 int } +} "list children after listing selected range" + +mi_next "next over update 4" + + +# Regression test: examine an object that has no children, then update +# it to ensure that we don't print the children. +mi_create_dynamic_varobj container2 c2 \ + "create second container varobj" + +mi_gdb_test "-var-update container2" \ + "\\^done,changelist=.." \ + "update varobj, no children requested" + +mi_next "next over update 5" + +# Now container2 has an element -- and an update should mention that +# it has_more. But, because we did not request children, we still +# should not actually see them. +mi_varobj_update_dynamic container2 \ + "update varobj 2, no children requested" { + type_changed false dynamic 1 has_more 1 + } {} {} + +# This should only show the first child, because the update range has +# been set. +mi_varobj_update_dynamic container \ + "update after next with restricted range" { + type_changed false new_num_children 1 dynamic 1 has_more 1 + } { + { name {container.\[0\]} in_scope true type_changed false dynamic 1 has_more 0 } + } { + } + +mi_continue_to_line \ + [gdb_get_line_number {MI outer breakpoint here} ${testfile}.c] \ + "step to outer breakpoint" + +mi_create_dynamic_varobj outer outer \ + "create outer varobj" + +mi_list_varobj_children outer { + { outer.s s 2 "struct substruct" } + { outer.x x 0 "int" } +} "list children of outer" + +mi_list_varobj_children outer.s { + { outer.s.a a 0 int } + { outer.s.b b 0 int } +} "list children of outer.s" + +mi_next "next over outer update" + +mi_gdb_test "-var-update outer" \ + ".done,changelist=.{name=\"outer.s.a\",in_scope=\"true\",type_changed=\"false\",dynamic=\"1\",has_more=\"0\"}." \ + "update after updating element of outer" mi_continue_to_line \ [gdb_get_line_number {Another MI breakpoint} ${testfile}.c] \ diff --git a/gdb/testsuite/gdb.python/python-prettyprint.c b/gdb/testsuite/gdb.python/python-prettyprint.c index 3cafc48..bf41ebc 100644 --- a/gdb/testsuite/gdb.python/python-prettyprint.c +++ b/gdb/testsuite/gdb.python/python-prettyprint.c @@ -15,6 +15,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +#include + struct s { int a; @@ -80,6 +82,29 @@ class Derived : public Vbase1, public Vbase2, public Vbase3 #endif +struct substruct { + int a; + int b; +}; + +struct outerstruct { + struct substruct s; + int x; +}; + +struct outerstruct +substruct_test (void) +{ + struct outerstruct outer; + outer.s.a = 0; + outer.s.b = 0; + outer.x = 0; + + outer.s.a = 3; /* MI outer breakpoint here */ + + return outer; +} + typedef struct string_repr { struct whybother @@ -148,6 +173,14 @@ void do_nothing(void) c = 23; /* Another MI breakpoint */ } +struct nullstr +{ + char *s; +}; + +struct string_repr string_1 = { { "one" } }; +struct string_repr string_2 = { { "two" } }; + int main () { @@ -155,11 +188,15 @@ main () struct ss ssa[2]; string x = make_string ("this is x"); zzz_type c = make_container ("container"); + zzz_type c2 = make_container ("container2"); const struct string_repr cstring = { { "const string" } }; + /* Clearing by being `static' could invoke an other GDB C++ bug. */ + struct nullstr nullstr; init_ss(&ss, 1, 2); init_ss(ssa+0, 3, 4); init_ss(ssa+1, 5, 6); + memset (&nullstr, 0, sizeof nullstr); struct ns ns; ns.null_str = "embedded\0null\0string"; @@ -193,6 +230,13 @@ main () add_item (&c, 72); #ifdef MI + add_item (&c, 1011); + c.elements[0] = 1023; + + add_item (&c2, 2222); + add_item (&c2, 3333); + + substruct_test (); do_nothing (); #endif diff --git a/gdb/testsuite/gdb.python/python-prettyprint.py b/gdb/testsuite/gdb.python/python-prettyprint.py index bf009a1..2f070d8 100644 --- a/gdb/testsuite/gdb.python/python-prettyprint.py +++ b/gdb/testsuite/gdb.python/python-prettyprint.py @@ -92,6 +92,13 @@ class pp_vbase1: def to_string (self): return "pp class name: " + self.val.type.tag +class pp_nullstr: + def __init__(self, val): + self.val = val + + def to_string(self): + return self.val['s'].string(gdb.parameter('target-charset')) + class pp_ns: "Print a std::basic_string of some kind" @@ -105,11 +112,24 @@ class pp_ns: def display_hint (self): return 'string' +class pp_outer: + "Print struct outer" + + def __init__ (self, val): + self.val = val + + def to_string (self): + return "x = %s" % self.val['x'] + + def children (self): + yield 's', self.val['s'] + yield 'x', self.val['x'] + def lookup_function (val): "Look-up and return a pretty-printer that can print val." # Get the type. - type = val.type; + type = val.type # If it points to a reference, get the reference. if type.code == gdb.TYPE_CODE_REF: @@ -148,6 +168,9 @@ def register_pretty_printers (): pretty_printers_dict[re.compile ('^VirtualTest$')] = pp_multiple_virtual pretty_printers_dict[re.compile ('^Vbase1$')] = pp_vbase1 + + pretty_printers_dict[re.compile ('^struct nullstr$')] = pp_nullstr + pretty_printers_dict[re.compile ('^nullstr$')] = pp_nullstr # Note that we purposely omit the typedef names here. # Printer lookup is based on canonical name. @@ -160,6 +183,10 @@ def register_pretty_printers (): pretty_printers_dict[re.compile ('^struct ns$')] = pp_ns pretty_printers_dict[re.compile ('^ns$')] = pp_ns + + pretty_printers_dict[re.compile ('^struct outerstruct$')] = pp_outer + pretty_printers_dict[re.compile ('^outerstruct$')] = pp_outer + pretty_printers_dict = {} register_pretty_printers () diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp index e691232..167a02c 100644 --- a/gdb/testsuite/lib/mi-support.exp +++ b/gdb/testsuite/lib/mi-support.exp @@ -1195,13 +1195,13 @@ proc mi_list_breakpoints { expected test } { # Name cannot be "-". proc mi_create_varobj { name expression testname } { mi_gdb_test "-var-create $name * $expression" \ - "\\^done,name=\"$name\",numchild=\"\[0-9\]+\",value=\".*\",type=.*" \ + "\\^done,name=\"$name\",numchild=\"\[0-9\]+\",value=\".*\",type=.*,has_more=\"0\"" \ $testname } proc mi_create_floating_varobj { name expression testname } { mi_gdb_test "-var-create $name @ $expression" \ - "\\^done,name=\"$name\",numchild=\"\[0-9\]+\",value=\".*\",type=.*" \ + "\\^done,name=\"$name\",numchild=\"\(-1\|\[0-9\]+\)\",value=\".*\",type=.*" \ $testname } @@ -1214,6 +1214,14 @@ proc mi_create_varobj_checked { name expression type testname } { $testname } +# Same as mi_create_floating_varobj, but assumes the test is creating +# a dynamic varobj that has children, so the value must be "{...}". +proc mi_create_dynamic_varobj {name expression testname} { + mi_gdb_test "-var-create $name @ $expression" \ + "\\^done,name=\"$name\",numchild=\"\(-1\|\[0-9\]+\)\",value=\"{\\.\\.\\.}\",type=.*" \ + $testname +} + # Deletes the specified NAME. proc mi_delete_varobj { name testname } { mi_gdb_test "-var-delete $name" \ @@ -1229,7 +1237,7 @@ proc mi_varobj_update { name expected testname } { set er "\\^done,changelist=\\\[" set first 1 foreach item $expected { - set v "{name=\"$item\",in_scope=\"true\",type_changed=\"false\"}" + set v "{name=\"$item\",in_scope=\"true\",type_changed=\"false\",has_more=\".\"}" if {$first == 1} { set er "$er$v" set first 0 @@ -1244,22 +1252,70 @@ proc mi_varobj_update { name expected testname } { } proc mi_varobj_update_with_type_change { name new_type new_children testname } { - set v "{name=\"$name\",in_scope=\"true\",type_changed=\"true\",new_type=\"$new_type\",new_num_children=\"$new_children\"}" + set v "{name=\"$name\",in_scope=\"true\",type_changed=\"true\",new_type=\"$new_type\",new_num_children=\"$new_children\",has_more=\".\"}" set er "\\^done,changelist=\\\[$v\\\]" verbose -log "Expecting: $er" mi_gdb_test "-var-update $name" $er $testname } -# Update a dynamic varobj named NAME. CHILDREN is a list of children, -# in the same form as mi_list_varobj_children. TESTNAME is the name -# of the test. -proc mi_varobj_update_dynamic {name children testname} { - set children_exp_j [mi_child_regexp $children 0] +# A helper that turns a key/value list into a regular expression +# matching some MI output. +proc mi_varobj_update_kv_helper {list} { + set first 1 + set rx "" + foreach {key value} $list { + if {!$first} { + append rx , + } + set first 0 + if {$key == "new_children"} { + append rx "$key=\\\[$value\\\]" + } else { + append rx "$key=\"$value\"" + } + } + return $rx +} - set er "\\^done,changelist=\\\[" +# A helper for mi_varobj_update_dynamic that computes a match +# expression given a child list. +proc mi_varobj_update_dynamic_helper {children} { + set crx "" - append er "{name=\"$name\",in_scope=\"true\",type_changed=\"false\"" - append er ",children=\\\[$children_exp_j.*\\\]}\\\]" + set first 1 + foreach child $children { + if {!$first} { + append crx , + } + set first 0 + append crx "{" + append crx [mi_varobj_update_kv_helper $child] + append crx "}" + } + + return $crx +} + +# Update a dynamic varobj named NAME. CHILDREN is a list of children +# that have been updated; NEW_CHILDREN is a list of children that were +# added to the primary varobj. Each child is a list of key/value +# pairs that are expected. SELF is a key/value list holding +# information about the varobj itself. TESTNAME is the name of the +# test. +proc mi_varobj_update_dynamic {name testname self children new_children} { + if {[llength $new_children]} { + set newrx [mi_varobj_update_dynamic_helper $new_children] + lappend self new_children $newrx + } + set selfrx [mi_varobj_update_kv_helper $self] + set crx [mi_varobj_update_dynamic_helper $children] + + set er "\\^done,changelist=\\\[\{name=\"$name\",in_scope=\"true\"" + append er ",$selfrx\}" + if {"$crx" != ""} { + append er ",$crx" + } + append er "\\\]" verbose -log "Expecting: $er" mi_gdb_test "-var-update $name" $er $testname @@ -1329,14 +1385,13 @@ proc mi_child_regexp {children add_child} { # have no value. # proc mi_list_varobj_children { varname children testname } { - mi_list_varobj_children_range $varname [llength $children] $children \ + mi_list_varobj_children_range $varname "" "" [llength $children] $children \ $testname } -# Like mi_list_varobj_children, but assumes that a subrange has been -# selected with -var-set-child-range. NUMCHILDREN is the total number -# of children. -proc mi_list_varobj_children_range {varname numchildren children testname} { +# Like mi_list_varobj_children, but sets a subrange. NUMCHILDREN is +# the total number of children. +proc mi_list_varobj_children_range {varname from to numchildren children testname} { set options "" if {[llength $varname] == 2} { set options [lindex $varname 1] @@ -1352,9 +1407,18 @@ proc mi_list_varobj_children_range {varname numchildren children testname} { set expected "\\^done,numchild=\"0\"" } + if {"$to" == ""} { + append expected ",has_more=\"0\"" + } elseif {$to >= 0 && $numchildren > $to} { + append expected ",has_more=\"1\"" + } else { + append expected ",has_more=\"0\"" + } + verbose -log "Expecting: $expected" - mi_gdb_test "-var-list-children $options $varname" $expected $testname + mi_gdb_test "-var-list-children $options $varname $from $to" \ + $expected $testname } # Verifies that variable object VARNAME has NUMBER children, diff --git a/gdb/varobj.c b/gdb/varobj.c index 603071f..e884e19 100644 --- a/gdb/varobj.c +++ b/gdb/varobj.c @@ -29,6 +29,7 @@ #include "gdb_assert.h" #include "gdb_string.h" +#include "gdb_regex.h" #include "varobj.h" #include "vec.h" @@ -59,6 +60,15 @@ char *varobj_format_string[] = /* String representations of gdb's known languages */ char *varobj_language_string[] = { "unknown", "C", "C++", "Java" }; +/* True if we want to allow Python-based pretty-printing. */ +static int pretty_printing = 0; + +void +varobj_enable_pretty_printing (void) +{ + pretty_printing = 1; +} + /* Data structures */ /* Every root variable has one of these structures saved in its @@ -173,9 +183,31 @@ struct varobj frozen. */ int not_fetched; + /* Sub-range of children which the MI consumer has requested. If + FROM < 0 or TO < 0, means that all children have been + requested. */ + int from; + int to; + + /* The pretty-printer constructor. If NULL, then the default + pretty-printer will be looked up. If None, then no + pretty-printer will be installed. */ + PyObject *constructor; + /* The pretty-printer that has been constructed. If NULL, then a new printer object is needed, and one will be constructed. */ PyObject *pretty_printer; + + /* The iterator returned by the printer's 'children' method, or NULL + if not available. */ + PyObject *child_iter; + + /* We request one extra item from the iterator, so that we can + report to the caller whether there are more items than we have + already reported. However, we don't want to install this value + when we read it, because that will mess up future updates. So, + we stash it here instead. */ + PyObject *saved_item; }; struct cpstack @@ -236,8 +268,6 @@ static char *cppop (struct cpstack **pstack); static int install_new_value (struct varobj *var, struct value *value, int initial); -static void install_default_visualizer (struct varobj *var); - /* Language-specific routines. */ static enum varobj_languages variable_language (struct varobj *var); @@ -623,7 +653,6 @@ varobj_create (char *objname, } } - install_default_visualizer (var); discard_cleanups (old_chain); return var; } @@ -738,15 +767,8 @@ instantiate_pretty_printer (PyObject *constructor, struct value *value) #if HAVE_PYTHON PyObject *val_obj = NULL; PyObject *printer; - volatile struct gdb_exception except; - TRY_CATCH (except, RETURN_MASK_ALL) - { - value = value_copy (value); - } - GDB_PY_HANDLE_EXCEPTION (except); val_obj = value_to_value_object (value); - if (! val_obj) return NULL; @@ -810,6 +832,17 @@ varobj_get_display_hint (struct varobj *var) return result; } +/* Return true if the varobj has items after TO, false otherwise. */ + +int +varobj_has_more (struct varobj *var, int to) +{ + if (VEC_length (varobj_p, var->children) > to) + return 1; + return ((to == -1 || VEC_length (varobj_p, var->children) == to) + && var->saved_item != NULL); +} + /* If the variable object is bound to a specific thread, that is its evaluation can always be done in context of a frame inside that thread, returns GDB id of the thread -- which @@ -842,22 +875,94 @@ varobj_get_frozen (struct varobj *var) return var->frozen; } +/* A helper function that restricts a range to what is actually + available in a VEC. This follows the usual rules for the meaning + of FROM and TO -- if either is negative, the entire range is + used. */ + +static void +restrict_range (VEC (varobj_p) *children, int *from, int *to) +{ + if (*from < 0 || *to < 0) + { + *from = 0; + *to = VEC_length (varobj_p, children); + } + else + { + if (*from > VEC_length (varobj_p, children)) + *from = VEC_length (varobj_p, children); + if (*to > VEC_length (varobj_p, children)) + *to = VEC_length (varobj_p, children); + if (*from > *to) + *from = *to; + } +} + +/* A helper for update_dynamic_varobj_children that installs a new + child when needed. */ + +static void +install_dynamic_child (struct varobj *var, + VEC (varobj_p) **changed, + VEC (varobj_p) **new, + VEC (varobj_p) **unchanged, + int *cchanged, + int index, + const char *name, + struct value *value) +{ + if (VEC_length (varobj_p, var->children) < index + 1) + { + /* There's no child yet. */ + struct varobj *child = varobj_add_child (var, name, value); + if (new) + VEC_safe_push (varobj_p, *new, child); + *cchanged = 1; + } + else + { + varobj_p existing = VEC_index (varobj_p, var->children, index); + if (install_new_value (existing, value, 0)) + { + if (changed) + VEC_safe_push (varobj_p, *changed, existing); + } + else if (unchanged) + VEC_safe_push (varobj_p, *unchanged, existing); + } +} + +#if HAVE_PYTHON + +static int +dynamic_varobj_has_child_method (struct varobj *var) +{ + struct cleanup *back_to; + PyObject *printer = var->pretty_printer; + int result; + + back_to = varobj_ensure_python_env (var); + result = PyObject_HasAttr (printer, gdbpy_children_cst); + do_cleanups (back_to); + return result; +} + +#endif + static int update_dynamic_varobj_children (struct varobj *var, VEC (varobj_p) **changed, - VEC (varobj_p) **new_and_unchanged, - int *cchanged) - + VEC (varobj_p) **new, + VEC (varobj_p) **unchanged, + int *cchanged, + int update_children, + int to) { #if HAVE_PYTHON - /* FIXME: we *might* want to provide this functionality as - a standalone function, so that other interested parties - than varobj code can benefit for this. */ struct cleanup *back_to; PyObject *children; - PyObject *iterator; int i; - int children_changed = 0; PyObject *printer = var->pretty_printer; back_to = varobj_ensure_python_env (var); @@ -869,87 +974,103 @@ update_dynamic_varobj_children (struct varobj *var, return 0; } - children = PyObject_CallMethodObjArgs (printer, gdbpy_children_cst, - NULL); - - if (!children) + if (update_children || !var->child_iter) { - gdbpy_print_stack (); - error (_("Null value returned for children")); - } + children = PyObject_CallMethodObjArgs (printer, gdbpy_children_cst, + NULL); - make_cleanup_py_decref (children); + if (!children) + { + gdbpy_print_stack (); + error (_("Null value returned for children")); + } - if (!PyIter_Check (children)) - error (_("Returned value is not iterable")); + make_cleanup_py_decref (children); - iterator = PyObject_GetIter (children); - if (!iterator) - { - gdbpy_print_stack (); - error (_("Could not get children iterator")); + if (!PyIter_Check (children)) + error (_("Returned value is not iterable")); + + Py_XDECREF (var->child_iter); + var->child_iter = PyObject_GetIter (children); + if (!var->child_iter) + { + gdbpy_print_stack (); + error (_("Could not get children iterator")); + } + + Py_XDECREF (var->saved_item); + var->saved_item = NULL; + + i = 0; } - make_cleanup_py_decref (iterator); + else + i = VEC_length (varobj_p, var->children); - for (i = 0; ; ++i) + /* We ask for one extra child, so that MI can report whether there + are more children. */ + for (; to < 0 || i < to + 1; ++i) { - PyObject *item = PyIter_Next (iterator); - PyObject *py_v; - struct value *v; - char *name; - struct cleanup *inner; - + PyObject *item; + + /* See if there was a leftover from last time. */ + if (var->saved_item) + { + item = var->saved_item; + var->saved_item = NULL; + } + else + item = PyIter_Next (var->child_iter); + if (!item) break; - inner = make_cleanup_py_decref (item); - if (!PyArg_ParseTuple (item, "sO", &name, &py_v)) - error (_("Invalid item from the child list")); - - v = convert_value_from_python (py_v); + /* We don't want to push the extra child on any report list. */ + if (to < 0 || i < to) + { + PyObject *py_v; + char *name; + struct value *v; + struct cleanup *inner; - /* TODO: This assume the name of the i-th child never changes. */ + inner = make_cleanup_py_decref (item); - /* Now see what to do here. */ - if (VEC_length (varobj_p, var->children) < i + 1) - { - /* There's no child yet. */ - struct varobj *child = varobj_add_child (var, name, v); - if (new_and_unchanged) - VEC_safe_push (varobj_p, *new_and_unchanged, child); - children_changed = 1; + if (!PyArg_ParseTuple (item, "sO", &name, &py_v)) + error (_("Invalid item from the child list")); + + v = convert_value_from_python (py_v); + install_dynamic_child (var, changed, new, unchanged, + cchanged, i, name, v); + do_cleanups (inner); } - else + else { - varobj_p existing = VEC_index (varobj_p, var->children, i); - if (install_new_value (existing, v, 0) && changed) - { - if (changed) - VEC_safe_push (varobj_p, *changed, existing); - } - else - { - if (new_and_unchanged) - VEC_safe_push (varobj_p, *new_and_unchanged, existing); - } - } + Py_XDECREF (var->saved_item); + var->saved_item = item; - do_cleanups (inner); + /* We want to truncate the child list just before this + element. */ + break; + } } if (i < VEC_length (varobj_p, var->children)) { - int i; - children_changed = 1; - for (i = 0; i < VEC_length (varobj_p, var->children); ++i) - varobj_delete (VEC_index (varobj_p, var->children, i), NULL, 0); + int j; + *cchanged = 1; + for (j = i; j < VEC_length (varobj_p, var->children); ++j) + varobj_delete (VEC_index (varobj_p, var->children, j), NULL, 0); + VEC_truncate (varobj_p, var->children, i); } - VEC_truncate (varobj_p, var->children, i); + + /* If there are fewer children than requested, note that the list of + children changed. */ + if (to >= 0 && VEC_length (varobj_p, var->children) < to) + *cchanged = 1; + var->num_children = VEC_length (varobj_p, var->children); do_cleanups (back_to); - *cchanged = children_changed; return 1; #else gdb_assert (0 && "should never be called if Python is not enabled"); @@ -961,20 +1082,26 @@ varobj_get_num_children (struct varobj *var) { if (var->num_children == -1) { - int changed; - if (!var->pretty_printer - || !update_dynamic_varobj_children (var, NULL, NULL, &changed)) + if (var->pretty_printer) + { + int dummy; + + /* If we have a dynamic varobj, don't report -1 children. + So, try to fetch some children first. */ + update_dynamic_varobj_children (var, NULL, NULL, NULL, &dummy, 0, 0); + } + else var->num_children = number_of_children (var); } - return var->num_children; + return var->num_children >= 0 ? var->num_children : 0; } /* Creates a list of the immediate children of a variable object; the return code is the number of such children or -1 on error */ VEC (varobj_p)* -varobj_list_children (struct varobj *var) +varobj_list_children (struct varobj *var, int *from, int *to) { struct varobj *child; char *name; @@ -982,12 +1109,16 @@ varobj_list_children (struct varobj *var) var->children_requested = 1; - if (var->pretty_printer + if (var->pretty_printer) + { /* This, in theory, can result in the number of children changing without frontend noticing. But well, calling -var-list-children on the same varobj twice is not something a sane frontend would do. */ - && update_dynamic_varobj_children (var, NULL, NULL, &children_changed)) - return var->children; + update_dynamic_varobj_children (var, NULL, NULL, NULL, &children_changed, + 0, *to); + restrict_range (var->children, from, to); + return var->children; + } if (var->num_children == -1) var->num_children = number_of_children (var); @@ -1013,10 +1144,10 @@ varobj_list_children (struct varobj *var) name = name_of_child (var, i); existing = create_child (var, i, name); VEC_replace (varobj_p, var->children, i, existing); - install_default_visualizer (existing); } } + restrict_range (var->children, from, to); return var->children; } @@ -1027,7 +1158,6 @@ varobj_add_child (struct varobj *var, const char *name, struct value *value) VEC_length (varobj_p, var->children), name, value); VEC_safe_push (varobj_p, var->children, v); - install_default_visualizer (v); return v; } @@ -1089,6 +1219,12 @@ varobj_get_attributes (struct varobj *var) return attributes; } +int +varobj_pretty_printed_p (struct varobj *var) +{ + return var->pretty_printer != NULL; +} + char * varobj_get_formatted_value (struct varobj *var, enum varobj_display_formats format) @@ -1166,6 +1302,116 @@ varobj_set_value (struct varobj *var, char *expression) return 1; } +#if HAVE_PYTHON + +/* A helper function to install a constructor function and visualizer + in a varobj. */ + +static void +install_visualizer (struct varobj *var, PyObject *constructor, + PyObject *visualizer) +{ + Py_XDECREF (var->constructor); + var->constructor = constructor; + + Py_XDECREF (var->pretty_printer); + var->pretty_printer = visualizer; + + Py_XDECREF (var->child_iter); + var->child_iter = NULL; +} + +/* Install the default visualizer for VAR. */ + +static void +install_default_visualizer (struct varobj *var) +{ + if (pretty_printing) + { + PyObject *pretty_printer = NULL; + + if (var->value) + { + pretty_printer = gdbpy_get_varobj_pretty_printer (var->value); + if (! pretty_printer) + { + gdbpy_print_stack (); + error (_("Cannot instantiate printer for default visualizer")); + } + } + + if (pretty_printer == Py_None) + { + Py_DECREF (pretty_printer); + pretty_printer = NULL; + } + + install_visualizer (var, NULL, pretty_printer); + } +} + +/* Instantiate and install a visualizer for VAR using CONSTRUCTOR to + make a new object. */ + +static void +construct_visualizer (struct varobj *var, PyObject *constructor) +{ + PyObject *pretty_printer; + + Py_INCREF (constructor); + if (constructor == Py_None) + pretty_printer = NULL; + else + { + pretty_printer = instantiate_pretty_printer (constructor, var->value); + if (! pretty_printer) + { + gdbpy_print_stack (); + Py_DECREF (constructor); + constructor = Py_None; + Py_INCREF (constructor); + } + + if (pretty_printer == Py_None) + { + Py_DECREF (pretty_printer); + pretty_printer = NULL; + } + } + + install_visualizer (var, constructor, pretty_printer); +} + +#endif /* HAVE_PYTHON */ + +/* A helper function for install_new_value. This creates and installs + a visualizer for VAR, if appropriate. */ + +static void +install_new_value_visualizer (struct varobj *var) +{ +#if HAVE_PYTHON + /* If the constructor is None, then we want the raw value. If VAR + does not have a value, just skip this. */ + if (var->constructor != Py_None && var->value) + { + struct cleanup *cleanup; + PyObject *pretty_printer = NULL; + + cleanup = varobj_ensure_python_env (var); + + if (!var->constructor) + install_default_visualizer (var); + else + construct_visualizer (var, var->constructor); + + do_cleanups (cleanup); + } +#else + /* Do nothing. */ +#endif +} + /* Assign a new value to a variable object. If INITIAL is non-zero, this is the first assignement after the variable object was just created, or changed type. In that case, just assign the value @@ -1206,10 +1452,7 @@ install_new_value (struct varobj *var, struct value *value, int initial) that in C++ a reference is not rebindable, it cannot meaningfully change. So, get hold of the real value. */ if (value) - { - value = coerce_ref (value); - release_value (value); - } + value = coerce_ref (value); if (var->type && TYPE_CODE (var->type) == TYPE_CODE_UNION) /* For unions, we need to fetch the value implicitly because @@ -1256,7 +1499,7 @@ install_new_value (struct varobj *var, struct value *value, int initial) values. Don't get string rendering if the value is lazy -- if it is, the code above has decided that the value should not be fetched. */ - if (value && !value_lazy (value)) + if (value && !value_lazy (value) && !var->pretty_printer) print_value = value_get_print_value (value, var->format, var); /* If the type is changeable, compare the old and the new values. @@ -1272,7 +1515,7 @@ install_new_value (struct varobj *var, struct value *value, int initial) { changed = 1; } - else + else if (! var->pretty_printer) { /* Try to compare the values. That requires that both values are non-lazy. */ @@ -1317,74 +1560,53 @@ install_new_value (struct varobj *var, struct value *value, int initial) if (var->value != NULL && var->value != value) value_free (var->value); var->value = value; - if (var->print_value) - xfree (var->print_value); - var->print_value = print_value; + if (value != NULL) + value_incref (value); if (value && value_lazy (value) && intentionally_not_fetched) var->not_fetched = 1; else var->not_fetched = 0; var->updated = 0; + install_new_value_visualizer (var); + + /* If we installed a pretty-printer, re-compare the printed version + to see if the variable changed. */ + if (var->pretty_printer) + { + xfree (print_value); + print_value = value_get_print_value (var->value, var->format, var); + if (!var->print_value || strcmp (var->print_value, print_value) != 0) + changed = 1; + } + if (var->print_value) + xfree (var->print_value); + var->print_value = print_value; + gdb_assert (!var->value || value_type (var->value)); return changed; } -static void -install_visualizer (struct varobj *var, PyObject *visualizer) +/* Return the requested range for a varobj. VAR is the varobj. FROM + and TO are out parameters; *FROM and *TO will be set to the + selected sub-range of VAR. If no range was selected using + -var-set-update-range, then both will be -1. */ +void +varobj_get_child_range (struct varobj *var, int *from, int *to) { -#if HAVE_PYTHON - /* If there are any children now, wipe them. */ - varobj_delete (var, NULL, 1 /* children only */); - var->num_children = -1; - - Py_XDECREF (var->pretty_printer); - var->pretty_printer = visualizer; - - install_new_value (var, var->value, 1); - - /* If we removed the visualizer, and the user ever requested the - object's children, then we must compute the list of children. - Note that we needn't do this when installing a visualizer, - because updating will recompute dynamic children. */ - if (!visualizer && var->children_requested) - varobj_list_children (var); -#else - error (_("Python support required")); -#endif + *from = var->from; + *to = var->to; } -static void -install_default_visualizer (struct varobj *var) +/* Set the selected sub-range of children of VAR to start at index + FROM and end at index TO. If either FROM or TO is less than zero, + this is interpreted as a request for all children. */ +void +varobj_set_child_range (struct varobj *var, int from, int to) { -#if HAVE_PYTHON - struct cleanup *cleanup; - PyObject *pretty_printer = NULL; - - cleanup = varobj_ensure_python_env (var); - - if (var->value) - { - pretty_printer = gdbpy_get_varobj_pretty_printer (var->value); - if (! pretty_printer) - { - gdbpy_print_stack (); - error (_("Cannot instantiate printer for default visualizer")); - } - } - - if (pretty_printer == Py_None) - { - Py_DECREF (pretty_printer); - pretty_printer = NULL; - } - - install_visualizer (var, pretty_printer); - do_cleanups (cleanup); -#else - /* No error is right as this function is inserted just as a hook. */ -#endif + var->from = from; + var->to = to; } void @@ -1402,31 +1624,19 @@ varobj_set_visualizer (struct varobj *var, const char *visualizer) make_cleanup_py_decref (globals); constructor = PyRun_String (visualizer, Py_eval_input, globals, globals); - - /* Do not instantiate NoneType. */ - if (constructor == Py_None) - { - pretty_printer = Py_None; - Py_INCREF (pretty_printer); - } - else - pretty_printer = instantiate_pretty_printer (constructor, var->value); - - Py_XDECREF (constructor); - if (! pretty_printer) + if (! constructor) { gdbpy_print_stack (); error (_("Could not evaluate visualizer expression: %s"), visualizer); } - if (pretty_printer == Py_None) - { - Py_DECREF (pretty_printer); - pretty_printer = NULL; - } + construct_visualizer (var, constructor); + Py_XDECREF (constructor); - install_visualizer (var, pretty_printer); + /* If there are any children now, wipe them. */ + varobj_delete (var, NULL, 1 /* children only */); + var->num_children = -1; do_cleanups (back_to); #else @@ -1537,44 +1747,74 @@ VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit) /* We probably should not get children of a varobj that has a pretty-printer, but for which -var-list-children was never - invoked. Presumably, such varobj is not yet expanded in the - UI, so we need not bother getting it. */ + invoked. */ if (v->pretty_printer) { - VEC (varobj_p) *changed = 0, *new_and_unchanged = 0; + VEC (varobj_p) *changed = 0, *new = 0, *unchanged = 0; int i, children_changed; varobj_p tmp; - if (!v->children_requested) - continue; - if (v->frozen) continue; + if (!v->children_requested) + { + int dummy; + + /* If we initially did not have potential children, but + now we do, consider the varobj as changed. + Otherwise, if children were never requested, consider + it as unchanged -- presumably, such varobj is not yet + expanded in the UI, so we need not bother getting + it. */ + if (!varobj_has_more (v, 0)) + { + update_dynamic_varobj_children (v, NULL, NULL, NULL, + &dummy, 0, 0); + if (varobj_has_more (v, 0)) + r.changed = 1; + } + + if (r.changed) + VEC_safe_push (varobj_update_result, result, &r); + + continue; + } + /* If update_dynamic_varobj_children returns 0, then we have a non-conforming pretty-printer, so we skip it. */ - if (update_dynamic_varobj_children (v, &changed, &new_and_unchanged, - &children_changed)) + if (update_dynamic_varobj_children (v, &changed, &new, &unchanged, + &children_changed, 1, v->to)) { - if (children_changed) - r.children_changed = 1; - for (i = 0; VEC_iterate (varobj_p, changed, i, tmp); ++i) + if (children_changed || new) { - varobj_update_result r = {tmp}; - r.changed = 1; - r.value_installed = 1; - VEC_safe_push (varobj_update_result, stack, &r); + r.children_changed = 1; + r.new = new; } - for (i = 0; - VEC_iterate (varobj_p, new_and_unchanged, i, tmp); - ++i) + for (i = 0; VEC_iterate (varobj_p, changed, i, tmp); ++i) { varobj_update_result r = {tmp}; + r.changed = 1; r.value_installed = 1; VEC_safe_push (varobj_update_result, stack, &r); } + for (i = 0; VEC_iterate (varobj_p, unchanged, i, tmp); ++i) + { + if (!tmp->frozen) + { + varobj_update_result r = {tmp}; + r.value_installed = 1; + VEC_safe_push (varobj_update_result, stack, &r); + } + } if (r.changed || r.children_changed) VEC_safe_push (varobj_update_result, result, &r); + + /* Free CHANGED and UNCHANGED, but not NEW, because NEW + has been put into the result vector. */ + VEC_free (varobj_p, changed); + VEC_free (varobj_p, unchanged); + continue; } } @@ -1862,7 +2102,12 @@ new_variable (void) var->frozen = 0; var->not_fetched = 0; var->children_requested = 0; + var->from = -1; + var->to = -1; + var->constructor = 0; var->pretty_printer = 0; + var->child_iter = 0; + var->saved_item = 0; return var; } @@ -1892,7 +2137,10 @@ free_variable (struct varobj *var) if (var->pretty_printer) { struct cleanup *cleanup = varobj_ensure_python_env (var); - Py_DECREF (var->pretty_printer); + Py_XDECREF (var->constructor); + Py_XDECREF (var->pretty_printer); + Py_XDECREF (var->child_iter); + Py_XDECREF (var->saved_item); do_cleanups (cleanup); } #endif @@ -2139,6 +2387,8 @@ value_of_root (struct varobj **var_handle, int *type_changed) else { tmp_var->obj_name = xstrdup (var->obj_name); + tmp_var->from = var->from; + tmp_var->to = var->to; varobj_delete (var, NULL, 0); install_variable (tmp_var); @@ -2173,7 +2423,11 @@ static char * my_value_of_variable (struct varobj *var, enum varobj_display_formats format) { if (var->root->is_valid) - return (*var->root->lang->value_of_variable) (var, format); + { + if (var->pretty_printer) + return value_get_print_value (var->value, var->format, var); + return (*var->root->lang->value_of_variable) (var, format); + } else return NULL; } @@ -2196,43 +2450,51 @@ value_get_print_value (struct value *value, enum varobj_display_formats format, struct cleanup *back_to = varobj_ensure_python_env (var); PyObject *value_formatter = var->pretty_printer; - if (value_formatter && PyObject_HasAttr (value_formatter, - gdbpy_to_string_cst)) + if (value_formatter) { - char *hint; - struct value *replacement; - int string_print = 0; - PyObject *output = NULL; + /* First check to see if we have any children at all. If so, + we simply return {...}. */ + if (dynamic_varobj_has_child_method (var)) + return xstrdup ("{...}"); - hint = gdbpy_get_display_hint (value_formatter); - if (hint) + if (PyObject_HasAttr (value_formatter, gdbpy_to_string_cst)) { - if (!strcmp (hint, "string")) - string_print = 1; - xfree (hint); - } + char *hint; + struct value *replacement; + int string_print = 0; + PyObject *output = NULL; + + hint = gdbpy_get_display_hint (value_formatter); + if (hint) + { + if (!strcmp (hint, "string")) + string_print = 1; + xfree (hint); + } - output = apply_varobj_pretty_printer (value_formatter, - &replacement); - if (output) - { - PyObject *py_str = python_string_to_target_python_string (output); - if (py_str) - { - char *s = PyString_AsString (py_str); - len = PyString_Size (py_str); - thevalue = xmemdup (s, len + 1, len + 1); - Py_DECREF (py_str); + output = apply_varobj_pretty_printer (value_formatter, + &replacement); + if (output) + { + PyObject *py_str + = python_string_to_target_python_string (output); + if (py_str) + { + char *s = PyString_AsString (py_str); + len = PyString_Size (py_str); + thevalue = xmemdup (s, len + 1, len + 1); + Py_DECREF (py_str); + } + Py_DECREF (output); } - Py_DECREF (output); - } - if (thevalue && !string_print) - { - do_cleanups (back_to); - return thevalue; + if (thevalue && !string_print) + { + do_cleanups (back_to); + return thevalue; + } + if (replacement) + value = replacement; } - if (replacement) - value = replacement; } do_cleanups (back_to); } @@ -2961,10 +3223,7 @@ cplus_describe_child (struct varobj *parent, int index, *cname = xstrdup (TYPE_FIELD_NAME (type, index)); if (cvalue && value) - { - *cvalue = value_cast (TYPE_FIELD_TYPE (type, index), value); - release_value (*cvalue); - } + *cvalue = value_cast (TYPE_FIELD_TYPE (type, index), value); if (ctype) { diff --git a/gdb/varobj.h b/gdb/varobj.h index 7297243..f43c593 100644 --- a/gdb/varobj.h +++ b/gdb/varobj.h @@ -78,6 +78,12 @@ typedef struct varobj_update_result_t new value of varobj is already computed and installed, or has to be yet installed. Don't use this outside varobj.c */ int value_installed; + + /* This will be non-NULL when new children were added to the varobj. + It lists the new children (which must necessarily come at the end + of the child list) added during an update. The caller is + responsible for freeing this vector. */ + VEC (varobj_p) *new; } varobj_update_result; DEF_VEC_O (varobj_update_result); @@ -112,13 +118,24 @@ extern void varobj_set_frozen (struct varobj *var, int frozen); extern int varobj_get_frozen (struct varobj *var); +extern void varobj_get_child_range (struct varobj *var, int *from, int *to); + +extern void varobj_set_child_range (struct varobj *var, int from, int to); + extern char *varobj_get_display_hint (struct varobj *var); extern int varobj_get_num_children (struct varobj *var); -/* Return the list of children of VAR. The returned vector - should not be modified in any way. */ -extern VEC (varobj_p)* varobj_list_children (struct varobj *var); +/* Return the list of children of VAR. The returned vector should not + be modified in any way. FROM and TO are in/out parameters + indicating the range of children to return. If either *FROM or *TO + is less than zero on entry, then all children will be returned. On + return, *FROM and *TO will be updated to indicate the real range + that was returned. The resulting VEC will contain at least the + children from *FROM to just before *TO; it might contain more + children, depending on whether any more were available. */ +extern VEC (varobj_p)* varobj_list_children (struct varobj *var, + int *from, int *to); extern char *varobj_get_type (struct varobj *var); @@ -149,6 +166,13 @@ extern int varobj_editable_p (struct varobj *var); extern int varobj_floating_p (struct varobj *var); -extern void varobj_set_visualizer (struct varobj *var, const char *visualizer); +extern void +varobj_set_visualizer (struct varobj *var, const char *visualizer); + +extern void varobj_enable_pretty_printing (void); + +extern int varobj_has_more (struct varobj *var, int to); + +extern int varobj_pretty_printed_p (struct varobj *var); #endif /* VAROBJ_H */