* varobj.h (varobj_set_frozen): New

(varobj_get_frozen): New.
        (varobj_update): New parameter explicit.
        * varobj.c (struct varobj): New fields frozen
        and not_fetched.
        (varobj_set_frozen, varobj_get_frozen): New.
        (install_new_value): Don't fetch values for
        frozen variable object, or children thereof.  Allow
        a frozen variable object to have non-fetched value.
        (varobj_update): Allow updating child variables.
        Don't traverse frozen children.
        (new_variable): Initialize the frozen field.
        (c_value_of_variable): Return NULL for frozen
        variable without any value yet.
        * mi/mi-cmd-var.c (varobj_update_one): New parameter
        'explicit'.
        (mi_cmd_var_create): Output the 'frozen' field,
        as soon as testsuite is adjusted to expect that field.
        (mi_cmd_var_set_frozen): New.
        (mi_cmd_var_update): Pass the 'explicit' parameter to
        varobj_update_one.
        * mi/mi-cmds.c (mi_cmds): Register '-var-set-frozen'.
        * mi/mi-cmds.h (mi_cmd_var_set_frozen): Declare.
This commit is contained in:
Vladimir Prus 2007-04-14 09:51:30 +00:00
parent 4d115fc687
commit 25d5ea921b
12 changed files with 363 additions and 58 deletions

View File

@ -1,3 +1,29 @@
2007-04-14 Vladimir Prus <vladimir@codesourcery.com>
* varobj.h (varobj_set_frozen): New
(varobj_get_frozen): New.
(varobj_update): New parameter explicit.
* varobj.c (struct varobj): New fields frozen
and not_fetched.
(varobj_set_frozen, varobj_get_frozen): New.
(install_new_value): Don't fetch values for
frozen variable object, or children thereof. Allow
a frozen variable object to have non-fetched value.
(varobj_update): Allow updating child variables.
Don't traverse frozen children.
(new_variable): Initialize the frozen field.
(c_value_of_variable): Return NULL for frozen
variable without any value yet.
* mi/mi-cmd-var.c (varobj_update_one): New parameter
'explicit'.
(mi_cmd_var_create): Output the 'frozen' field,
as soon as testsuite is adjusted to expect that field.
(mi_cmd_var_set_frozen): New.
(mi_cmd_var_update): Pass the 'explicit' parameter to
varobj_update_one.
* mi/mi-cmds.c (mi_cmds): Register '-var-set-frozen'.
* mi/mi-cmds.h (mi_cmd_var_set_frozen): Declare.
2007-04-13 Paul Brook <paul@codesourcery.com>
* target-descriptions.c (tdesc_named_type): Add ieee_single and

View File

@ -1,3 +1,8 @@
2007-04-14 Vladimir Prus <vladimir@codesourcery.com>
* gdb.texinfo (GDB/MI Variable Objects): Document
frozen variables objects.
2007-04-13 Daniel Jacobowitz <dan@codesourcery.com>
* gdb.texinfo (Memory): Reference Remote Debugging chapter.

View File

@ -17296,7 +17296,7 @@ New fields may be added to the output of any MI command.
@item
The range of values for fields with specified values, e.g.,
@code{in_scope} (@pxref{-var-update}) may be extended.
@code{in_scope} (@pxref{-var-update-fields}) may be extended.
@c The format of field's content e.g type prefix, may change so parse it
@c at your own risk. Yes, in general?
@ -19223,7 +19223,10 @@ that corresponds to a composite type, such as structure in C, has
a number of child variable objects, for example corresponding to each
element of a structure. A child variable object can itself have
children, recursively. Recursion ends when we reach
leaf variable objects, which always have built-in types.
leaf variable objects, which always have built-in types. Child variable
objects are created only by explicit request, so if a frontend
is not interested in the children of a particular variable object, no
child will be created.
For a leaf variable object it is possible to obtain its value as a
string, or set the value from a string. String value can be also
@ -19235,7 +19238,19 @@ A frontend does not need to read the values of all variable objects each time
the program stops. Instead, MI provides an update command that lists all
variable objects whose values has changed since the last update
operation. This considerably reduces the amount of data that must
be transferred to the frontend.
be transferred to the frontend. As noted above, children variable
objects are created on demand, and only leaf variable objects have a
real value. As result, gdb will read target memory only for leaf
variables that frontend has created.
The automatic update is not always desirable. For example, a frontend
might want to keep a value of some expression for future reference,
and never update it. For another example, fetching memory is
relatively slow for embedded targets, so a frontend might want
to disable automatic update for the variables that are either not
visible on the screen, or ``closed''. This is possible using so
called ``frozen variable objects''. Such variable objects are never
implicitly updated.
The following is the complete set of @sc{gdb/mi} operations defined to
access this functionality:
@ -19268,6 +19283,8 @@ access this functionality:
@tab set the value of this variable
@item @code{-var-update}
@tab update the variable and its children
@item @code{-var-set-frozen}
@tab set frozeness attribute
@end multitable
In the next subsection we describe each operation in detail and suggest
@ -19533,6 +19550,7 @@ subsequent @code{-var-update} list.
@subheading The @code{-var-update} Command
@findex -var-update
@anchor{-var-update}
@subsubheading Synopsis
@ -19567,7 +19585,7 @@ type_changed="false"@}]
(gdb)
@end smallexample
@anchor{-var-update}
@anchor{-var-update-fields}
The field in_scope may take three values:
@table @code
@ -19590,6 +19608,37 @@ objects.
In the future new values may be added to this list so the front should
be prepared for this possibility. @xref{GDB/MI Development and Front Ends, ,@sc{GDB/MI} Development and Front Ends}.
@subheading The @code{-var-set-frozen} Command
@findex -var-set-frozen
@subsubheading Synopsis
@smallexample
-var-set-frozen @var{name} @samp{flag}
@end smallexample
Set the frozeness flag on the variable object @var{name}. The
@var{flag} parameter should be either @samp{1} to make the variable
frozen or @samp{0} to make it unfozen. If a variable object is
frozen, then neither itself, nor any of its children, are
implicitly updated by @code{-var-update} (@pxref{-var-update}) of
a parent variable or by @code{-var-update *}. Only
@code{-var-update} of the variable itself will update its value and
values of its children. After a variable object is unfrozen, it is
implicitly updated by all subsequent @code{-var-update} operations.
Unfreezing a variable does not update it, only subsequent
@code{-var-update} does.
@subsubheading Example
@smallexample
(gdb)
-var-set-frozen V 1
^done
(gdb)
@end smallexample
@c %%%%%%%%%%%%%%%%%%%%%%%%%%%% SECTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@node GDB/MI Data Manipulation
@section @sc{gdb/mi} Data Manipulation

View File

@ -37,7 +37,8 @@ const char mi_all_values[] = "--all-values";
extern int varobjdebug; /* defined in varobj.c. */
static void varobj_update_one (struct varobj *var,
enum print_values print_values);
enum print_values print_values,
int explicit);
static int mi_print_value_p (struct type *type, enum print_values print_values);
@ -64,6 +65,9 @@ print_varobj (struct varobj *var, enum print_values print_values,
ui_out_field_string (uiout, "type", type);
xfree (type);
}
if (varobj_get_frozen (var))
ui_out_field_int (uiout, "frozen", 1);
}
/* VAROBJ operations */
@ -232,6 +236,35 @@ mi_cmd_var_set_format (char *command, char **argv, int argc)
return MI_CMD_DONE;
}
enum mi_cmd_result
mi_cmd_var_set_frozen (char *command, char **argv, int argc)
{
struct varobj *var;
int frozen;
if (argc != 2)
error (_("-var-set-format: Usage: NAME FROZEN_FLAG."));
var = varobj_get_handle (argv[0]);
if (var == NULL)
error (_("Variable object not found"));
if (strcmp (argv[1], "0") == 0)
frozen = 0;
else if (strcmp (argv[1], "1") == 0)
frozen = 1;
else
error (_("Invalid flag value"));
varobj_set_frozen (var, frozen);
/* We don't automatically return the new value, or what varobjs got new
values during unfreezing. If this information is required, client
should call -var-update explicitly. */
return MI_CMD_DONE;
}
enum mi_cmd_result
mi_cmd_var_show_format (char *command, char **argv, int argc)
{
@ -513,7 +546,7 @@ mi_cmd_var_update (char *command, char **argv, int argc)
cr = rootlist;
while (*cr != NULL)
{
varobj_update_one (*cr, print_values);
varobj_update_one (*cr, print_values, 0 /* implicit */);
cr++;
}
do_cleanups (cleanup);
@ -529,7 +562,7 @@ mi_cmd_var_update (char *command, char **argv, int argc)
cleanup = make_cleanup_ui_out_tuple_begin_end (uiout, "changelist");
else
cleanup = make_cleanup_ui_out_list_begin_end (uiout, "changelist");
varobj_update_one (var, print_values);
varobj_update_one (var, print_values, 1 /* explicit */);
do_cleanups (cleanup);
}
return MI_CMD_DONE;
@ -538,14 +571,15 @@ mi_cmd_var_update (char *command, char **argv, int argc)
/* Helper for mi_cmd_var_update(). */
static void
varobj_update_one (struct varobj *var, enum print_values print_values)
varobj_update_one (struct varobj *var, enum print_values print_values,
int explicit)
{
struct varobj **changelist;
struct varobj **cc;
struct cleanup *cleanup = NULL;
int nc;
nc = varobj_update (&var, &changelist);
nc = varobj_update (&var, &changelist, explicit);
/* nc >= 0 represents the number of changes reported into changelist.
nc < 0 means that an error occured or the the variable has

View File

@ -156,6 +156,7 @@ struct mi_cmd mi_cmds[] =
{ "var-info-type", { NULL, 0 }, 0, mi_cmd_var_info_type},
{ "var-list-children", { NULL, 0 }, 0, mi_cmd_var_list_children},
{ "var-set-format", { NULL, 0 }, 0, mi_cmd_var_set_format},
{ "var-set-frozen", { NULL, 0 }, 0, mi_cmd_var_set_frozen},
{ "var-show-attributes", { NULL, 0 }, 0, mi_cmd_var_show_attributes},
{ "var-show-format", { NULL, 0 }, 0, mi_cmd_var_show_format},
{ "var-update", { NULL, 0 }, 0, mi_cmd_var_update},

View File

@ -113,6 +113,7 @@ extern mi_cmd_argv_ftype mi_cmd_var_info_num_children;
extern mi_cmd_argv_ftype mi_cmd_var_info_type;
extern mi_cmd_argv_ftype mi_cmd_var_list_children;
extern mi_cmd_argv_ftype mi_cmd_var_set_format;
extern mi_cmd_argv_ftype mi_cmd_var_set_frozen;
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;

View File

@ -1,3 +1,10 @@
2007-04-14 Vladimir Prus <vladimir@codesourcery.com>
* gdb.mi/mi-var-cmd.exp: Delete varobjs left by previous
tests. Run the frozen varobjs test.
* gdb.mi/var-cmd.c (do_frozen_tests): New.
* lib/mi-support.exp (mi_varobj_update): Fix thinko.
2007-04-11 Jan Kratochvil <jan.kratochvil@redhat.com>
* gdb.base/type-opaque-lib.c, gdb.base/type-opaque-main.c,

View File

@ -596,6 +596,20 @@ mi_gdb_test "-var-update selected_a" \
"\\^done,changelist=\\\[\{name=\"selected_a\",in_scope=\"true\",new_type=\"int\",new_num_children=\"0\"\}\\\]" \
"update selected_a in do_special_tests"
mi_delete_varobj selected_a "delete selected_a"
mi_delete_varobj array_ptr "delete array_ptr"
proc set_frozen {varobjs flag} {
foreach v $varobjs {
mi_gdb_test "-var-set-frozen $v $flag" \
"\\^done" \
"-var-set-frozen $v $flag"
}
}
mi_prepare_inline_tests $srcfile
mi_run_inline_test frozen
# Test whether bad varobjs crash GDB.
# A varobj we fail to read during -var-update should be considered

View File

@ -315,6 +315,92 @@ do_special_tests (void)
incr_a(2);
}
void do_frozen_tests ()
{
/*: BEGIN: frozen :*/
struct {
int i;
struct {
int j;
int k;
} nested;
} v1 = {1, {2, 3}};
int v2 = 4;
/*:
mi_create_varobj V1 v1 "create varobj for v1"
mi_create_varobj V2 v2 "create varobj for v2"
mi_list_varobj_children "V1" {
{"V1.i" "i" "0" "int"}
{"V1.nested" "nested" "2" "struct {...}"}
} "list children of v1"
mi_list_varobj_children "V1.nested" {
{"V1.nested.j" "j" "0" "int"}
{"V1.nested.k" "k" "0" "int"}
} "list children of v1.nested"
mi_check_varobj_value V1.i 1 "check V1.i: 1"
mi_check_varobj_value V1.nested.j 2 "check V1.nested.j: 2"
mi_check_varobj_value V1.nested.k 3 "check V1.nested.k: 3"
mi_check_varobj_value V2 4 "check V2: 4"
:*/
v2 = 5;
/*:
mi_varobj_update * {V2} "update varobjs: V2 changed"
set_frozen V2 1
:*/
v2 = 6;
/*:
mi_varobj_update * {} "update varobjs: nothing changed"
mi_check_varobj_value V2 5 "check V2: 5"
mi_varobj_update V2 {V2} "update V2 explicitly"
mi_check_varobj_value V2 6 "check V2: 6"
:*/
v1.i = 7;
v1.nested.j = 8;
v1.nested.k = 9;
/*:
set_frozen V1 1
mi_varobj_update * {} "update varobjs: nothing changed"
mi_check_varobj_value V1.i 1 "check V1.i: 1"
mi_check_varobj_value V1.nested.j 2 "check V1.nested.j: 2"
mi_check_varobj_value V1.nested.k 3 "check V1.nested.k: 3"
# Check that explicit update for elements of structures
# works.
# Update v1.j
mi_varobj_update V1.nested.j {V1.nested.j} "update V1.nested.j"
mi_check_varobj_value V1.i 1 "check V1.i: 1"
mi_check_varobj_value V1.nested.j 8 "check V1.nested.j: 8"
mi_check_varobj_value V1.nested.k 3 "check V1.nested.k: 3"
# Update v1.nested, check that children is updated.
mi_varobj_update V1.nested {V1.nested.k} "update V1.nested"
mi_check_varobj_value V1.i 1 "check V1.i: 1"
mi_check_varobj_value V1.nested.j 8 "check V1.nested.j: 8"
mi_check_varobj_value V1.nested.k 9 "check V1.nested.k: 9"
# Update v1.i
mi_varobj_update V1.i {V1.i} "update V1.i"
mi_check_varobj_value V1.i 7 "check V1.i: 7"
:*/
v1.i = 10;
v1.nested.j = 11;
v1.nested.k = 12;
/*:
# Check that unfreeze itself does not updates the values.
set_frozen V1 0
mi_check_varobj_value V1.i 7 "check V1.i: 7"
mi_check_varobj_value V1.nested.j 8 "check V1.nested.j: 8"
mi_check_varobj_value V1.nested.k 9 "check V1.nested.k: 9"
mi_varobj_update V1 {V1.i V1.nested.j V1.nested.k} "update V1"
mi_check_varobj_value V1.i 10 "check V1.i: 10"
mi_check_varobj_value V1.nested.j 11 "check V1.nested.j: 11"
mi_check_varobj_value V1.nested.k 12 "check V1.nested.k: 12"
:*/
/*: END: frozen :*/
}
int
main (int argc, char *argv [])
{
@ -322,6 +408,7 @@ main (int argc, char *argv [])
do_block_tests ();
do_children_tests ();
do_special_tests ();
do_frozen_tests ();
exit (0);
}

View File

@ -1024,8 +1024,9 @@ proc mi_varobj_update { name expected testname } {
set first 1
foreach item $expected {
set v "{name=\"$item\",in_scope=\"true\",type_changed=\"false\"}"
if {$first} {
if {$first == 1} {
set er "$er$v"
set first 0
} else {
set er "$er,$v"
}
@ -1312,7 +1313,7 @@ proc mi_run_inline_test { testcase } {
set line_now [mi_wait_for_stop "$testcase: step to $line"]
set first 0
} elseif {$line_now!=$line} {
set line_now [mi_continue_to_line "$mi_autotest_source:$line"]
set line_now [mi_continue_to_line "$mi_autotest_source:$line" "continue to $line"]
}
if {$line_now!=$line} {

View File

@ -137,6 +137,16 @@ struct varobj
/* Last print value. */
char *print_value;
/* Is this variable frozen. Frozen variables are never implicitly
updated by -var-update *
or -var-update <direct-or-indirect-parent>. */
int frozen;
/* Is the value of this variable intentionally not fetched? It is
not fetched if either the variable is frozen, or any parents is
frozen. */
int not_fetched;
};
struct cpstack
@ -669,6 +679,26 @@ varobj_get_display_format (struct varobj *var)
return var->format;
}
void
varobj_set_frozen (struct varobj *var, int frozen)
{
/* When a variable is unfrozen, we don't fetch its value.
The 'not_fetched' flag remains set, so next -var-update
won't complain.
We don't fetch the value, because for structures the client
should do -var-update anyway. It would be bad to have different
client-size logic for structure and other types. */
var->frozen = frozen;
}
int
varobj_get_frozen (struct varobj *var)
{
return var->frozen;
}
int
varobj_get_num_children (struct varobj *var)
{
@ -915,6 +945,7 @@ install_new_value (struct varobj *var, struct value *value, int initial)
int changeable;
int need_to_fetch;
int changed = 0;
int intentionally_not_fetched = 0;
/* We need to know the varobj's type to decide if the value should
be fetched or not. C++ fake children (public/protected/private) don't have
@ -950,7 +981,20 @@ install_new_value (struct varobj *var, struct value *value, int initial)
will be lazy, which means we've lost that old value. */
if (need_to_fetch && value && value_lazy (value))
{
if (!gdb_value_fetch_lazy (value))
struct varobj *parent = var->parent;
int frozen = var->frozen;
for (; !frozen && parent; parent = parent->parent)
frozen |= parent->frozen;
if (frozen && initial)
{
/* For variables that are frozen, or are children of frozen
variables, we don't do fetch on initial assignment.
For non-initial assignemnt we do the fetch, since it means we're
explicitly asked to compare the new value with the old one. */
intentionally_not_fetched = 1;
}
else if (!gdb_value_fetch_lazy (value))
{
/* Set the value to NULL, so that for the next -var-update,
we don't try to compare the new value with this value,
@ -980,9 +1024,16 @@ install_new_value (struct varobj *var, struct value *value, int initial)
{
/* Try to compare the values. That requires that both
values are non-lazy. */
/* Quick comparison of NULL values. */
if (var->value == NULL && value == NULL)
if (var->not_fetched && value_lazy (var->value))
{
/* This is a frozen varobj and the value was never read.
Presumably, UI shows some "never read" indicator.
Now that we've fetched the real value, we need to report
this varobj as changed so that UI can show the real
value. */
changed = 1;
}
else if (var->value == NULL && value == NULL)
/* Equal. */
;
else if (var->value == NULL || value == NULL)
@ -1012,9 +1063,13 @@ install_new_value (struct varobj *var, struct value *value, int initial)
}
/* We must always keep the new value, since children depend on it. */
if (var->value != NULL)
if (var->value != NULL && var->value != value)
value_free (var->value);
var->value = value;
if (value && value_lazy (value) && intentionally_not_fetched)
var->not_fetched = 1;
else
var->not_fetched = 0;
var->updated = 0;
gdb_assert (!var->value || value_type (var->value));
@ -1031,17 +1086,21 @@ install_new_value (struct varobj *var, struct value *value, int initial)
< 0 for error values, see varobj.h.
Otherwise it is the number of children + parent changed.
Only root variables can be updated...
The EXPLICIT parameter specifies if this call is result
of MI request to update this specific variable, or
result of implicit -var-update *. For implicit request, we don't
update frozen variables.
NOTE: This function may delete the caller's varobj. If it
returns TYPE_CHANGED, then it has done this and VARP will be modified
to point to the new varobj. */
int
varobj_update (struct varobj **varp, struct varobj ***changelist)
varobj_update (struct varobj **varp, struct varobj ***changelist,
int explicit)
{
int changed = 0;
int type_changed;
int type_changed = 0;
int i;
int vleft;
struct varobj *v;
@ -1056,48 +1115,56 @@ varobj_update (struct varobj **varp, struct varobj ***changelist)
/* sanity check: have we been passed a pointer? */
gdb_assert (changelist);
if (!is_root_p (*varp))
error (_("Only root variables can be updated"));
/* Frozen means frozen -- we don't check for any change in
this varobj, including its going out of scope, or
changing type. One use case for frozen varobjs is
retaining previously evaluated expressions, and we don't
want them to be reevaluated at all. */
if (!explicit && (*varp)->frozen)
return 0;
if (!(*varp)->root->is_valid)
return INVALID;
/* Save the selected stack frame, since we will need to change it
in order to evaluate expressions. */
old_fid = get_frame_id (deprecated_safe_get_selected_frame ());
/* Update the root variable. value_of_root can return NULL
if the variable is no longer around, i.e. we stepped out of
the frame in which a local existed. We are letting the
value_of_root variable dispose of the varobj if the type
has changed. */
type_changed = 1;
new = value_of_root (varp, &type_changed);
/* Restore selected frame. */
fi = frame_find_by_id (old_fid);
if (fi)
select_frame (fi);
/* If this is a "use_selected_frame" varobj, and its type has changed,
them note that it's changed. */
if (type_changed)
VEC_safe_push (varobj_p, result, *varp);
if (install_new_value ((*varp), new, type_changed))
if ((*varp)->root->rootvar == *varp)
{
/* If type_changed is 1, install_new_value will never return
non-zero, so we'll never report the same variable twice. */
gdb_assert (!type_changed);
VEC_safe_push (varobj_p, result, *varp);
}
/* Save the selected stack frame, since we will need to change it
in order to evaluate expressions. */
old_fid = get_frame_id (deprecated_safe_get_selected_frame ());
/* Update the root variable. value_of_root can return NULL
if the variable is no longer around, i.e. we stepped out of
the frame in which a local existed. We are letting the
value_of_root variable dispose of the varobj if the type
has changed. */
type_changed = 1;
new = value_of_root (varp, &type_changed);
if (new == NULL)
{
/* This means the varobj itself is out of scope.
Report it. */
VEC_free (varobj_p, result);
return NOT_IN_SCOPE;
/* Restore selected frame. */
fi = frame_find_by_id (old_fid);
if (fi)
select_frame (fi);
/* If this is a "use_selected_frame" varobj, and its type has changed,
them note that it's changed. */
if (type_changed)
VEC_safe_push (varobj_p, result, *varp);
if (install_new_value ((*varp), new, type_changed))
{
/* If type_changed is 1, install_new_value will never return
non-zero, so we'll never report the same variable twice. */
gdb_assert (!type_changed);
VEC_safe_push (varobj_p, result, *varp);
}
if (new == NULL)
{
/* This means the varobj itself is out of scope.
Report it. */
VEC_free (varobj_p, result);
return NOT_IN_SCOPE;
}
}
VEC_safe_push (varobj_p, stack, *varp);
@ -1115,13 +1182,13 @@ varobj_update (struct varobj **varp, struct varobj ***changelist)
{
varobj_p c = VEC_index (varobj_p, v->children, i);
/* Child may be NULL if explicitly deleted by -var-delete. */
if (c != NULL)
if (c != NULL && !c->frozen)
VEC_safe_push (varobj_p, stack, c);
}
/* Update this variable, unless it's a root, which is already
updated. */
if (v != *varp)
if (v->root->rootvar != v)
{
new = value_of_child (v->parent, v->index);
if (install_new_value (v, new, 0 /* type not changed */))
@ -1403,6 +1470,8 @@ new_variable (void)
var->root = NULL;
var->updated = 0;
var->print_value = NULL;
var->frozen = 0;
var->not_fetched = 0;
return var;
}
@ -2116,6 +2185,12 @@ c_value_of_variable (struct varobj *var)
}
else
{
if (var->not_fetched && value_lazy (var->value))
/* Frozen variable and no value yet. We don't
implicitly fetch the value. MI response will
use empty string for the value, which is OK. */
return NULL;
gdb_assert (varobj_value_is_changeable_p (var));
gdb_assert (!value_lazy (var->value));
return value_get_print_value (var->value, var->format);

View File

@ -86,6 +86,10 @@ extern enum varobj_display_formats varobj_set_display_format (
extern enum varobj_display_formats varobj_get_display_format (
struct varobj *var);
extern void varobj_set_frozen (struct varobj *var, int frozen);
extern int varobj_get_frozen (struct varobj *var);
extern int varobj_get_num_children (struct varobj *var);
extern int varobj_list_children (struct varobj *var,
@ -105,7 +109,8 @@ extern int varobj_set_value (struct varobj *var, char *expression);
extern int varobj_list (struct varobj ***rootlist);
extern int varobj_update (struct varobj **varp, struct varobj ***changelist);
extern int varobj_update (struct varobj **varp, struct varobj ***changelist,
int explicit);
extern void varobj_invalidate (void);