aboutsummaryrefslogtreecommitdiff
path: root/gdb/varobj.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/varobj.c')
-rw-r--r--gdb/varobj.c195
1 files changed, 153 insertions, 42 deletions
diff --git a/gdb/varobj.c b/gdb/varobj.c
index f0740c6..e2a2419 100644
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -56,6 +56,10 @@ struct varobj_root
/* The frame for this expression */
CORE_ADDR frame;
+ /* If 1, "update" always recomputes the frame & valid block
+ using the currently selected frame. */
+ int use_selected_frame;
+
/* Language info for this variable and its children */
struct language_specific *lang;
@@ -204,7 +208,8 @@ static char *name_of_variable PARAMS ((struct varobj *));
static char *name_of_child PARAMS ((struct varobj *, int));
-static value_ptr value_of_root PARAMS ((struct varobj * var));
+static value_ptr value_of_root PARAMS ((struct varobj ** var_handle,
+ int *));
static value_ptr value_of_child PARAMS ((struct varobj * parent, int index));
@@ -224,7 +229,7 @@ static char *c_name_of_variable PARAMS ((struct varobj * parent));
static char *c_name_of_child PARAMS ((struct varobj * parent, int index));
-static value_ptr c_value_of_root PARAMS ((struct varobj * var));
+static value_ptr c_value_of_root PARAMS ((struct varobj ** var_handle));
static value_ptr c_value_of_child PARAMS ((struct varobj * parent, int index));
@@ -244,7 +249,7 @@ static char *cplus_name_of_variable PARAMS ((struct varobj * parent));
static char *cplus_name_of_child PARAMS ((struct varobj * parent, int index));
-static value_ptr cplus_value_of_root PARAMS ((struct varobj * var));
+static value_ptr cplus_value_of_root PARAMS ((struct varobj ** var_handle));
static value_ptr cplus_value_of_child PARAMS ((struct varobj * parent, int index));
@@ -262,7 +267,7 @@ static char *java_name_of_variable PARAMS ((struct varobj * parent));
static char *java_name_of_child PARAMS ((struct varobj * parent, int index));
-static value_ptr java_value_of_root PARAMS ((struct varobj * var));
+static value_ptr java_value_of_root PARAMS ((struct varobj ** var_handle));
static value_ptr java_value_of_child PARAMS ((struct varobj * parent, int index));
@@ -290,7 +295,7 @@ struct language_specific
char *(*name_of_child) PARAMS ((struct varobj * parent, int index));
/* The value_ptr of the root variable ROOT. */
- value_ptr (*value_of_root) PARAMS ((struct varobj * root));
+ value_ptr (*value_of_root) PARAMS ((struct varobj ** root_handle));
/* The value_ptr of the INDEX'th child of PARENT. */
value_ptr (*value_of_child) PARAMS ((struct varobj * parent, int index));
@@ -401,7 +406,8 @@ static struct vlist **varobj_table;
struct varobj *
varobj_create (char *objname,
- char *expression, CORE_ADDR frame)
+ char *expression, CORE_ADDR frame,
+ enum varobj_type type)
{
struct varobj *var;
struct frame_info *fi, *old_fi;
@@ -421,19 +427,28 @@ varobj_create (char *objname,
of the variable's data as possible */
/* Allow creator to specify context of variable */
- if (frame == (CORE_ADDR) -1)
+ if ((type == USE_CURRENT_FRAME)
+ || (type == USE_SELECTED_FRAME))
fi = selected_frame;
else
fi = find_frame_addr_in_frame_chain (frame);
+ /* frame = -2 means always use selected frame */
+ if (type == USE_SELECTED_FRAME)
+ var->root->use_selected_frame = 1;
+
block = NULL;
if (fi != NULL)
block = get_frame_block (fi);
p = expression;
innermost_block = NULL;
- /* Callee may longjump */
- var->root->exp = parse_exp_1 (&p, block, 0);
+ /* Wrap the call to parse expression, so we can
+ return a sensible error. */
+ if (!gdb_parse_exp_1 (&p, block, 0, &var->root->exp))
+ {
+ return NULL;
+ }
/* Don't allow variables to be created for types. */
if (var->root->exp->elts[0].opcode == OP_TYPE)
@@ -486,7 +501,10 @@ varobj_create (char *objname,
select_frame (old_fi, -1);
}
- if (var != NULL)
+ /* If the variable object name is null, that means this
+ is a temporary variable, so don't install it. */
+
+ if ((var != NULL) && (objname != NULL))
{
var->obj_name = savestring (objname, strlen (objname));
@@ -845,6 +863,10 @@ varobj_list (struct varobj ***varlist)
expression to see if it's changed. Then go all the way
through its children, reconstructing them and noting if they've
changed.
+ Return value:
+ -1 if there was an error updating the varobj
+ -2 if the type changed
+ Otherwise it is the number of children + parent changed
Only root variables can be updated... */
@@ -852,6 +874,7 @@ int
varobj_update (struct varobj *var, struct varobj ***changelist)
{
int changed = 0;
+ int type_changed;
int i;
int vleft;
int error2;
@@ -878,19 +901,27 @@ varobj_update (struct varobj *var, struct varobj ***changelist)
/* 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. */
- new = value_of_root (var);
+ 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 (&var, &type_changed);
if (new == NULL)
- return -1;
+ {
+ var->error = 1;
+ return -1;
+ }
/* Initialize a stack for temporary results */
vpush (&result, NULL);
- if (!my_value_equal (var->value, new, &error2))
+ if (type_changed || !my_value_equal (var->value, new, &error2))
{
/* Note that it's changed There a couple of exceptions here,
- though. We don't want some types to be reported as "changed". */
- if (type_changeable (var))
+ though. We don't want some types to be reported as
+ "changed". The exception to this is if this is a
+ "use_selected_frame" varobj, and its type has changed. */
+ if (type_changed || type_changeable (var))
{
vpush (&result, var);
changed++;
@@ -984,7 +1015,10 @@ varobj_update (struct varobj *var, struct varobj ***changelist)
/* Restore selected frame */
select_frame (old_fi, -1);
- return changed;
+ if (type_changed)
+ return -2;
+ else
+ return changed;
}
@@ -1039,9 +1073,9 @@ delete_variable_1 (resultp, delcountp, var,
return;
/* Otherwise, add it to the list of deleted ones and proceed to do so */
- if (var->obj_name == NULL)
- warning ("Assertion failed: NULL var->obj_name unexpectdly found");
- else
+ /* If the name is null, this is a temporary variable, that has not
+ yet been installed, don't report it, it belongs to the caller... */
+ if (var->obj_name != NULL)
{
cppush (resultp, strdup (var->obj_name));
*delcountp = *delcountp + 1;
@@ -1057,8 +1091,9 @@ delete_variable_1 (resultp, delcountp, var,
{
remove_child_from_parent (var->parent, var);
}
-
- uninstall_variable (var);
+
+ if (var->obj_name != NULL)
+ uninstall_variable (var);
/* Free memory associated with this variable */
free_variable (var);
@@ -1315,6 +1350,7 @@ new_root_variable (void)
var->root->exp = NULL;
var->root->valid_block = NULL;
var->root->frame = (CORE_ADDR) -1;
+ var->root->use_selected_frame = 0;
var->root->rootvar = NULL;
return var;
@@ -1578,12 +1614,74 @@ name_of_child (var, index)
return (*var->root->lang->name_of_child) (var, index);
}
-/* What is the value_ptr of the root variable VAR? */
+/* What is the value_ptr of the root variable VAR?
+ TYPE_CHANGED controls what to do if the type of a
+ use_selected_frame = 1 variable changes. On input,
+ TYPE_CHANGED = 1 means discard the old varobj, and replace
+ it with this one. TYPE_CHANGED = 0 means leave it around.
+ NB: In both cases, var_handle will point to the new varobj,
+ so if you use TYPE_CHANGED = 0, you will have to stash the
+ old varobj pointer away somewhere before calling this.
+ On return, TYPE_CHANGED will be 1 if the type has changed, and
+ 0 otherwise. */
static value_ptr
-value_of_root (var)
- struct varobj *var;
+value_of_root (var_handle, type_changed)
+ struct varobj ** var_handle;
+ int *type_changed;
{
- return (*var->root->lang->value_of_root) (var);
+ struct varobj *var;
+
+ if (var_handle == NULL)
+ return NULL;
+
+ var = *var_handle;
+
+ /* This should really be an exception, since this should
+ only get called with a root variable. */
+
+ if (var->root->rootvar != var)
+ return NULL;
+
+ if (var->root->use_selected_frame)
+ {
+ struct varobj *tmp_var;
+ char *old_type, *new_type;
+ old_type = varobj_get_type (var);
+ tmp_var = varobj_create (NULL, var->name, (CORE_ADDR) 0,
+ USE_SELECTED_FRAME);
+ if (tmp_var == NULL)
+ {
+ return NULL;
+ }
+ new_type = varobj_get_type (tmp_var);
+ if (strcmp(old_type, new_type) == 0)
+ {
+ varobj_delete (tmp_var, NULL, 0);
+ *type_changed = 0;
+ }
+ else
+ {
+ if (*type_changed)
+ {
+ tmp_var->obj_name =
+ savestring (var->obj_name, strlen (var->obj_name));
+ uninstall_variable (var);
+ }
+ else
+ {
+ tmp_var->obj_name = varobj_gen_name ();
+ }
+ install_variable (tmp_var);
+ *var_handle = tmp_var;
+ *type_changed = 1;
+ }
+ }
+ else
+ {
+ *type_changed = 0;
+ }
+
+ return (*var->root->lang->value_of_root) (var_handle);
}
/* What is the value_ptr for the INDEX'th child of PARENT? */
@@ -1790,38 +1888,51 @@ c_name_of_child (parent, index)
}
static value_ptr
-c_value_of_root (var)
- struct varobj *var;
+c_value_of_root (var_handle)
+ struct varobj **var_handle;
{
value_ptr new_val;
+ struct varobj *var = *var_handle;
struct frame_info *fi;
int within_scope;
+ /* Only root variables can be updated... */
+ if (var->root->rootvar != var)
+ /* Not a root var */
+ return NULL;
+
+
/* Determine whether the variable is still around. */
if (var->root->valid_block == NULL)
within_scope = 1;
else
{
reinit_frame_cache ();
+
+
fi = find_frame_addr_in_frame_chain (var->root->frame);
+
within_scope = fi != NULL;
/* FIXME: select_frame could fail */
if (within_scope)
select_frame (fi, -1);
}
-
+
if (within_scope)
{
- /* We need to catch errors here, because if evaluate expression fails
- we just want to make val->error = 1 and go on */
+ /* We need to catch errors here, because if evaluate
+ expression fails we just want to make val->error = 1 and
+ go on */
if (gdb_evaluate_expression (var->root->exp, &new_val))
{
if (VALUE_LAZY (new_val))
{
- /* We need to catch errors because if value_fetch_lazy fails we
- still want to continue (after making val->error = 1) */
- /* FIXME: Shouldn't be using VALUE_CONTENTS? The comment on
- value_fetch_lazy() says it is only called from the macro... */
+ /* We need to catch errors because if
+ value_fetch_lazy fails we still want to continue
+ (after making val->error = 1) */
+ /* FIXME: Shouldn't be using VALUE_CONTENTS? The
+ comment on value_fetch_lazy() says it is only
+ called from the macro... */
if (!gdb_value_fetch_lazy (new_val))
var->error = 1;
else
@@ -1830,7 +1941,7 @@ c_value_of_root (var)
}
else
var->error = 1;
-
+
release_value (new_val);
return new_val;
}
@@ -2194,10 +2305,10 @@ cplus_name_of_child (parent, index)
}
static value_ptr
-cplus_value_of_root (var)
- struct varobj *var;
+cplus_value_of_root (var_handle)
+ struct varobj **var_handle;
{
- return c_value_of_root (var);
+ return c_value_of_root (var_handle);
}
static value_ptr
@@ -2367,10 +2478,10 @@ java_name_of_child (parent, index)
}
static value_ptr
-java_value_of_root (var)
- struct varobj *var;
+java_value_of_root (var_handle)
+ struct varobj **var_handle;
{
- return cplus_value_of_root (var);
+ return cplus_value_of_root (var_handle);
}
static value_ptr