/* Implementation of the GDB variable objects API.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
#include "gdb_string.h"
#include "varobj.h"
+#include "vec.h"
/* Non-zero if we want to see trace of varobj level stuff. */
struct varobj_root *next;
};
+typedef struct varobj *varobj_p;
+
+DEF_VEC_P (varobj_p);
+
/* Every variable in the system has a structure of this type defined
for it. This structure holds all information necessary to manipulate
a particular object variable. Members which must be freed are noted. */
/* The type of this variable. This may NEVER be NULL. */
struct type *type;
- /* The value of this expression or subexpression. This may be NULL.
- Invariant: if type_changeable (this) is non-zero, the value is either
- NULL, or not lazy. */
+ /* The value of this expression or subexpression. A NULL value
+ indicates there was an error getting this value.
+ Invariant: if varobj_value_is_changeable_p (this) is non-zero,
+ the value is either NULL, or not lazy. */
struct value *value;
- /* Did an error occur evaluating the expression or getting its value? */
- int error;
-
/* The number of (immediate) children this variable has */
int num_children;
/* If this object is a child, this points to its immediate parent. */
struct varobj *parent;
- /* A list of this object's children */
- struct varobj_child *children;
+ /* Children of this object. */
+ VEC (varobj_p) *children;
/* Description of the root variable. Points to root variable for children. */
struct varobj_root *root;
/* Was this variable updated via a varobj_set_value operation */
int updated;
-};
-
-/* Every variable keeps a linked list of its children, described
- by the following structure. */
-/* FIXME: Deprecated. All should use vlist instead */
-
-struct varobj_child
-{
-
- /* Pointer to the child's data */
- struct varobj *child;
-
- /* Pointer to the next child */
- struct varobj_child *next;
-};
-
-/* A stack of varobjs */
-/* FIXME: Deprecated. All should use vlist instead */
-struct vstack
-{
- struct varobj *var;
- struct vstack *next;
+ /* Last print value. */
+ char *print_value;
};
struct cpstack
static void uninstall_variable (struct varobj *);
-static struct varobj *child_exists (struct varobj *, char *);
-
static struct varobj *create_child (struct varobj *, int, char *);
-static void save_child_in_parent (struct varobj *, struct varobj *);
-
-static void remove_child_from_parent (struct varobj *, struct varobj *);
-
/* Utility routines */
static struct varobj *new_variable (void);
static enum varobj_display_formats variable_default_display (struct varobj *);
-static void vpush (struct vstack **pstack, struct varobj *var);
-
-static struct varobj *vpop (struct vstack **pstack);
-
static void cppush (struct cpstack **pstack, char *name);
static char *cppop (struct cpstack **pstack);
static char *my_value_of_variable (struct varobj *var);
-static int type_changeable (struct varobj *var);
+static char *value_get_print_value (struct value *value,
+ enum varobj_display_formats format);
+
+static int varobj_value_is_changeable_p (struct varobj *var);
+
+static int is_root_p (struct varobj *var);
/* C implementation */
};
/* Array of known source language routines. */
-static struct language_specific
- languages[vlang_end][sizeof (struct language_specific)] = {
+static struct language_specific languages[vlang_end] = {
/* Unknown (try treating as C */
{
vlang_unknown,
\f
/* API Implementation */
+static int
+is_root_p (struct varobj *var)
+{
+ return (var->root->rootvar == var);
+}
/* Creates a varobj (not its children) */
/* Set language info */
lang = variable_language (var);
- var->root->lang = languages[lang];
+ var->root->lang = &languages[lang];
/* Set ourselves as our root */
var->root->rootvar = var;
if (var->num_children == -1)
var->num_children = number_of_children (var);
+ /* If that failed, give up. */
+ if (var->num_children == -1)
+ return -1;
+
+ /* If we're called when the list of children is not yet initialized,
+ allocate enough elements in it. */
+ while (VEC_length (varobj_p, var->children) < var->num_children)
+ VEC_safe_push (varobj_p, var->children, NULL);
+
/* List of children */
*childlist = xmalloc ((var->num_children + 1) * sizeof (struct varobj *));
for (i = 0; i < var->num_children; i++)
{
+ varobj_p existing;
+
/* Mark as the end in case we bail out */
*((*childlist) + i) = NULL;
- /* check if child exists, if not create */
- name = name_of_child (var, i);
- child = child_exists (var, name);
- if (child == NULL)
- child = create_child (var, i, name);
+ existing = VEC_index (varobj_p, var->children, i);
+
+ if (existing == NULL)
+ {
+ /* Either it's the first call to varobj_list_children for
+ this variable object, and the child was never created,
+ or it was explicitly deleted by the client. */
+ name = name_of_child (var, i);
+ existing = create_child (var, i, name);
+ VEC_replace (varobj_p, var->children, i, existing);
+ }
- *((*childlist) + i) = child;
+ *((*childlist) + i) = existing;
}
/* End of list is marked by a NULL pointer */
struct value *value;
int saved_input_radix = input_radix;
- if (var->value != NULL && variable_editable (var) && !var->error)
+ if (var->value != NULL && variable_editable (var))
{
char *s = expression;
int i;
}
/* All types that are editable must also be changeable. */
- gdb_assert (type_changeable (var));
+ gdb_assert (varobj_value_is_changeable_p (var));
/* The value of a changeable variable object must not be lazy. */
gdb_assert (!value_lazy (var->value));
int need_to_fetch;
int changed = 0;
- var->error = 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
a type. */
gdb_assert (var->type || CPLUS_FAKE_CHILD (var));
- changeable = type_changeable (var);
+ changeable = varobj_value_is_changeable_p (var);
need_to_fetch = changeable;
/* We are not interested in the address of references, and given
{
if (!gdb_value_fetch_lazy (value))
{
- var->error = 1;
/* Set the value to NULL, so that for the next -var-update,
we don't try to compare the new value with this value,
that we couldn't even read. */
value = NULL;
}
- else
- var->error = 0;
}
/* If the type is changeable, compare the old and the new values.
If this is the initial assignment, we don't have any old value
to compare with. */
- if (!initial && changeable)
+ if (initial)
+ var->print_value = value_get_print_value (value, var->format);
+ else if (changeable)
{
/* If the value of the varobj was changed by -var-set-value, then the
value in the varobj and in the target is the same. However, that value
is different from the value that the varobj had after the previous
- -var-update. So need to the varobj as changed. */
+ -var-update. So need to the varobj as changed. */
if (var->updated)
- changed = 1;
+ {
+ xfree (var->print_value);
+ var->print_value = value_get_print_value (value, var->format);
+ changed = 1;
+ }
else
{
/* Try to compare the values. That requires that both
/* Equal. */
;
else if (var->value == NULL || value == NULL)
- changed = 1;
+ {
+ xfree (var->print_value);
+ var->print_value = value_get_print_value (value, var->format);
+ changed = 1;
+ }
else
{
+ char *print_value;
gdb_assert (!value_lazy (var->value));
gdb_assert (!value_lazy (value));
-
- if (!value_contents_equal (var->value, value))
- changed = 1;
+ print_value = value_get_print_value (value, var->format);
+
+ gdb_assert (var->print_value != NULL && print_value != NULL);
+ if (strcmp (var->print_value, print_value) != 0)
+ {
+ xfree (var->print_value);
+ var->print_value = print_value;
+ changed = 1;
+ }
+ else
+ xfree (print_value);
}
}
}
-
+
/* We must always keep the new value, since children depend on it. */
if (var->value != NULL)
value_free (var->value);
var->value = value;
var->updated = 0;
-
+
gdb_assert (!var->value || value_type (var->value));
return changed;
}
-
/* Update the values for a variable and its children. This is a
two-pronged attack. First, re-parse the value for the root's
struct varobj **cv;
struct varobj **templist = NULL;
struct value *new;
- struct vstack *stack = NULL;
- struct vstack *result = NULL;
+ VEC (varobj_p) *stack = NULL;
+ VEC (varobj_p) *result = NULL;
struct frame_id old_fid;
struct frame_info *fi;
return -1;
/* Only root variables can be updated... */
- if ((*varp)->root->rootvar != *varp)
+ if (!is_root_p (*varp))
/* Not a root var */
return -1;
if (fi)
select_frame (fi);
- if (new == NULL)
- {
- (*varp)->error = 1;
- return -1;
- }
-
- /* Initialize a stack for temporary results */
- vpush (&result, NULL);
-
/* If this is a "use_selected_frame" varobj, and its type has changed,
them note that it's changed. */
if (type_changed)
- {
- vpush (&result, *varp);
- 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);
- vpush (&result, (*varp));
- changed++;
+ VEC_safe_push (varobj_p, result, *varp);
}
- /* Initialize a stack */
- vpush (&stack, NULL);
-
- /* Push the root's children */
- if ((*varp)->children != NULL)
+ if (new == NULL)
{
- struct varobj_child *c;
- for (c = (*varp)->children; c != NULL; c = c->next)
- vpush (&stack, c->child);
+ /* This means the varobj itself is out of scope.
+ Report it. */
+ VEC_free (varobj_p, result);
+ return -1;
}
+ VEC_safe_push (varobj_p, stack, *varp);
+
/* Walk through the children, reconstructing them all. */
- v = vpop (&stack);
- while (v != NULL)
+ while (!VEC_empty (varobj_p, stack))
{
- /* Push any children */
- if (v->children != NULL)
+ v = VEC_pop (varobj_p, stack);
+
+ /* Push any children. Use reverse order so that the first
+ child is popped from the work stack first, and so
+ will be added to result first. This does not
+ affect correctness, just "nicer". */
+ for (i = VEC_length (varobj_p, v->children)-1; i >= 0; --i)
{
- struct varobj_child *c;
- for (c = v->children; c != NULL; c = c->next)
- vpush (&stack, c->child);
+ varobj_p c = VEC_index (varobj_p, v->children, i);
+ /* Child may be NULL if explicitly deleted by -var-delete. */
+ if (c != NULL)
+ VEC_safe_push (varobj_p, stack, c);
}
- /* Update this variable */
- new = value_of_child (v->parent, v->index);
- if (install_new_value (v, new, 0 /* type not changed */))
- {
- /* Note that it's changed */
- vpush (&result, v);
- v->updated = 0;
- changed++;
+ /* Update this variable, unless it's a root, which is already
+ updated. */
+ if (v != *varp)
+ {
+ new = value_of_child (v->parent, v->index);
+ if (install_new_value (v, new, 0 /* type not changed */))
+ {
+ /* Note that it's changed */
+ VEC_safe_push (varobj_p, result, v);
+ v->updated = 0;
+ }
}
-
- /* Get next child */
- v = vpop (&stack);
}
/* Alloc (changed + 1) list entries */
- /* FIXME: add a cleanup for the allocated list(s)
- because one day the select_frame called below can longjump */
+ changed = VEC_length (varobj_p, result);
*changelist = xmalloc ((changed + 1) * sizeof (struct varobj *));
- if (changed > 1)
- {
- templist = xmalloc ((changed + 1) * sizeof (struct varobj *));
- cv = templist;
- }
- else
- cv = *changelist;
-
- /* Copy from result stack to list */
- vleft = changed;
- *cv = vpop (&result);
- while ((*cv != NULL) && (vleft > 0))
- {
- vleft--;
- cv++;
- *cv = vpop (&result);
- }
- if (vleft)
- warning (_("varobj_update: assertion failed - vleft <> 0"));
+ cv = *changelist;
- if (changed > 1)
+ for (i = 0; i < changed; ++i)
{
- /* Now we revert the order. */
- for (i = 0; i < changed; i++)
- *(*changelist + i) = *(templist + changed - 1 - i);
- *(*changelist + changed) = NULL;
+ *cv = VEC_index (varobj_p, result, i);
+ gdb_assert (*cv != NULL);
+ ++cv;
}
+ *cv = 0;
if (type_changed)
return -2;
struct varobj *var, int only_children_p,
int remove_from_parent_p)
{
- struct varobj_child *vc;
- struct varobj_child *next;
+ int i;
/* Delete any children of this variable, too. */
- for (vc = var->children; vc != NULL; vc = next)
- {
+ for (i = 0; i < VEC_length (varobj_p, var->children); ++i)
+ {
+ varobj_p child = VEC_index (varobj_p, var->children, i);
if (!remove_from_parent_p)
- vc->child->parent = NULL;
- delete_variable_1 (resultp, delcountp, vc->child, 0, only_children_p);
- next = vc->next;
- xfree (vc);
+ child->parent = NULL;
+ delete_variable_1 (resultp, delcountp, child, 0, only_children_p);
}
+ VEC_free (varobj_p, var->children);
/* if we were called to delete only the children we are done here */
if (only_children_p)
discarding the list afterwards */
if ((remove_from_parent_p) && (var->parent != NULL))
{
- remove_child_from_parent (var->parent, var);
+ VEC_replace (varobj_p, var->parent->children, var->index, NULL);
}
if (var->obj_name != NULL)
*(varobj_table + index) = newvl;
/* If root, add varobj to root list */
- if (var->root->rootvar == var)
+ if (is_root_p (var))
{
/* Add to list of root variables */
if (rootlist == NULL)
xfree (cv);
/* If root, remove varobj from root list */
- if (var->root->rootvar == var)
+ if (is_root_p (var))
{
/* Remove from list of root variables */
if (rootlist == var->root)
}
-/* Does a child with the name NAME exist in VAR? If so, return its data.
- If not, return NULL. */
-static struct varobj *
-child_exists (struct varobj *var, char *name)
-{
- struct varobj_child *vc;
-
- for (vc = var->children; vc != NULL; vc = vc->next)
- {
- if (strcmp (vc->child->name, name) == 0)
- return vc->child;
- }
-
- return NULL;
-}
-
/* Create and install a child of the parent of the given name */
static struct varobj *
create_child (struct varobj *parent, int index, char *name)
child->obj_name = childs_name;
install_variable (child);
- /* Save a pointer to this child in the parent */
- save_child_in_parent (parent, child);
-
/* Compute the type of the child. Must do this before
calling install_new_value. */
if (value != NULL)
child->index);
install_new_value (child, value, 1);
- if ((!CPLUS_FAKE_CHILD (child) && child->value == NULL) || parent->error)
- child->error = 1;
-
return child;
}
-
-/* FIXME: This should be a generic add to list */
-/* Save CHILD in the PARENT's data. */
-static void
-save_child_in_parent (struct varobj *parent, struct varobj *child)
-{
- struct varobj_child *vc;
-
- /* Insert the child at the top */
- vc = parent->children;
- parent->children =
- (struct varobj_child *) xmalloc (sizeof (struct varobj_child));
-
- parent->children->next = vc;
- parent->children->child = child;
-}
-
-/* FIXME: This should be a generic remove from list */
-/* Remove the CHILD from the PARENT's list of children. */
-static void
-remove_child_from_parent (struct varobj *parent, struct varobj *child)
-{
- struct varobj_child *vc, *prev;
-
- /* Find the child in the parent's list */
- prev = NULL;
- for (vc = parent->children; vc != NULL;)
- {
- if (vc->child == child)
- break;
- prev = vc;
- vc = vc->next;
- }
-
- if (prev == NULL)
- parent->children = vc->next;
- else
- prev->next = vc->next;
-
-}
\f
/*
var->index = -1;
var->type = NULL;
var->value = NULL;
- var->error = 0;
var->num_children = -1;
var->parent = NULL;
var->children = NULL;
var->format = 0;
var->root = NULL;
var->updated = 0;
+ var->print_value = NULL;
return var;
}
free_variable (struct varobj *var)
{
/* Free the expression if this is a root variable. */
- if (var->root->rootvar == var)
+ if (is_root_p (var))
{
free_current_contents (&var->root->exp);
xfree (var->root);
xfree (var->name);
xfree (var->obj_name);
+ xfree (var->print_value);
xfree (var);
}
return type;
}
-/* This returns the type of the variable, dereferencing pointers, too. */
+/* This returns the type of the variable, dereferencing references, pointers
+ and references to pointers, too. */
static struct type *
get_type_deref (struct varobj *var)
{
type = get_type (var);
- if (type != NULL && (TYPE_CODE (type) == TYPE_CODE_PTR
- || TYPE_CODE (type) == TYPE_CODE_REF))
- type = get_target_type (type);
+ if (type)
+ {
+ if (TYPE_CODE (type) == TYPE_CODE_REF)
+ type = get_target_type (type);
+ if (TYPE_CODE (type) == TYPE_CODE_PTR)
+ type = get_target_type (type);
+ }
return type;
}
return FORMAT_NATURAL;
}
-/* FIXME: The following should be generic for any pointer */
-static void
-vpush (struct vstack **pstack, struct varobj *var)
-{
- struct vstack *s;
-
- s = (struct vstack *) xmalloc (sizeof (struct vstack));
- s->var = var;
- s->next = *pstack;
- *pstack = s;
-}
-
-/* FIXME: The following should be generic for any pointer */
-static struct varobj *
-vpop (struct vstack **pstack)
-{
- struct vstack *s;
- struct varobj *v;
-
- if ((*pstack)->var == NULL && (*pstack)->next == NULL)
- return NULL;
-
- s = *pstack;
- v = s->var;
- *pstack = (*pstack)->next;
- xfree (s);
-
- return v;
-}
-
/* FIXME: The following should be generic for any pointer */
static void
cppush (struct cpstack **pstack, char *name)
/* This should really be an exception, since this should
only get called with a root variable. */
- if (var->root->rootvar != var)
+ if (!is_root_p (var))
return NULL;
if (var->root->use_selected_frame)
return (*var->root->lang->value_of_variable) (var);
}
+static char *
+value_get_print_value (struct value *value, enum varobj_display_formats format)
+{
+ long dummy;
+ struct ui_file *stb;
+ struct cleanup *old_chain;
+ char *thevalue;
+
+ if (value == NULL)
+ return NULL;
+
+ stb = mem_fileopen ();
+ old_chain = make_cleanup_ui_file_delete (stb);
+
+ common_val_print (value, stb, format_code[(int) format], 1, 0, 0);
+ thevalue = ui_file_xstrdup (stb, &dummy);
+
+ do_cleanups (old_chain);
+ return thevalue;
+}
+
/* Return non-zero if changes in value of VAR
must be detected and reported by -var-update.
Return zero is -var-update should never report
Return value of 0 means that gdb need not call value_fetch_lazy
for the value of this variable object. */
static int
-type_changeable (struct varobj *var)
+varobj_value_is_changeable_p (struct varobj *var)
{
int r;
struct type *type;
&& TYPE_ARRAY_UPPER_BOUND_TYPE (type) != BOUND_CANNOT_BE_DETERMINED)
children = TYPE_LENGTH (type) / TYPE_LENGTH (target);
else
- children = -1;
+ /* If we don't know how many elements there are, don't display
+ any. */
+ children = 0;
break;
case TYPE_CODE_STRUCT:
break;
case TYPE_CODE_PTR:
- /* This is where things get compilcated. All pointers have one child.
+ /* This is where things get complicated. All pointers have one child.
Except, of course, for struct and union ptr, which we automagically
- dereference for the user and function ptrs, which have no children.
+ dereference for the user, and function ptrs which have no children.
We also don't dereference void* as we don't know what to show.
We can show char* so we allow it to be dereferenced. If you decide
to test for it, please mind that a little magic is necessary to
return savestring (parent->name, strlen (parent->name));
}
-static char *
-c_name_of_child (struct varobj *parent, int index)
+/* Return the value of element TYPE_INDEX of a structure
+ value VALUE. VALUE's type should be a structure,
+ or union, or a typedef to struct/union.
+
+ Returns NULL if getting the value fails. Never throws. */
+static struct value *
+value_struct_element_index (struct value *value, int type_index)
{
- struct type *type;
- struct type *target;
- char *name;
- char *string;
+ struct value *result = NULL;
+ volatile struct gdb_exception e;
- type = get_type (parent);
- target = get_target_type (type);
+ struct type *type = value_type (value);
+ type = check_typedef (type);
+ gdb_assert (TYPE_CODE (type) == TYPE_CODE_STRUCT
+ || TYPE_CODE (type) == TYPE_CODE_UNION);
+
+ TRY_CATCH (e, RETURN_MASK_ERROR)
+ {
+ if (TYPE_FIELD_STATIC (type, type_index))
+ result = value_static_field (type, type_index);
+ else
+ result = value_primitive_field (value, 0, type_index, type);
+ }
+ if (e.reason < 0)
+ {
+ return NULL;
+ }
+ else
+ {
+ return result;
+ }
+}
+
+/* Obtain the information about child INDEX of the variable
+ object PARENT.
+ If CNAME is not null, sets *CNAME to the name of the child relative
+ to the parent.
+ If CVALUE is not null, sets *CVALUE to the value of the child.
+ If CTYPE is not null, sets *CTYPE to the type of the child.
+
+ If any of CNAME, CVALUE, or CTYPE is not null, but the corresponding
+ information cannot be determined, set *CNAME, *CVALUE, or *CTYPE
+ to NULL. */
+static void
+c_describe_child (struct varobj *parent, int index,
+ char **cname, struct value **cvalue, struct type **ctype)
+{
+ struct value *value = parent->value;
+ struct type *type = get_type (parent);
+
+ if (cname)
+ *cname = NULL;
+ if (cvalue)
+ *cvalue = NULL;
+ if (ctype)
+ *ctype = NULL;
+
+ /* Pointers to structures are treated just like
+ structures when accessing children. */
+ if (TYPE_CODE (type) == TYPE_CODE_PTR)
+ {
+ struct type *target_type = get_target_type (type);
+ if (TYPE_CODE (target_type) == TYPE_CODE_STRUCT
+ || TYPE_CODE (target_type) == TYPE_CODE_UNION)
+ {
+ if (value)
+ gdb_value_ind (value, &value);
+ type = target_type;
+ }
+ }
+
switch (TYPE_CODE (type))
{
case TYPE_CODE_ARRAY:
- name = xstrprintf ("%d", index
- + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)));
+ if (cname)
+ *cname = xstrprintf ("%d", index
+ + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)));
+
+ if (cvalue && value)
+ {
+ int real_index = index + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type));
+ struct value *indval =
+ value_from_longest (builtin_type_int, (LONGEST) real_index);
+ gdb_value_subscript (value, indval, cvalue);
+ }
+
+ if (ctype)
+ *ctype = get_target_type (type);
+
break;
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
- string = TYPE_FIELD_NAME (type, index);
- name = savestring (string, strlen (string));
+ if (cname)
+ {
+ char *string = TYPE_FIELD_NAME (type, index);
+ *cname = savestring (string, strlen (string));
+ }
+
+ if (cvalue && value)
+ {
+ /* For C, varobj index is the same as type index. */
+ *cvalue = value_struct_element_index (value, index);
+ }
+
+ if (ctype)
+ *ctype = TYPE_FIELD_TYPE (type, index);
+
break;
case TYPE_CODE_PTR:
- switch (TYPE_CODE (target))
- {
- case TYPE_CODE_STRUCT:
- case TYPE_CODE_UNION:
- string = TYPE_FIELD_NAME (target, index);
- name = savestring (string, strlen (string));
- break;
+ if (cname)
+ *cname = xstrprintf ("*%s", parent->name);
- default:
- name = xstrprintf ("*%s", parent->name);
- break;
- }
+ if (cvalue && value)
+ gdb_value_ind (value, cvalue);
+
+ if (ctype)
+ *ctype = get_target_type (type);
+
break;
default:
/* This should not happen */
- name = xstrdup ("???");
+ if (cname)
+ *cname = xstrdup ("???");
+ /* Don't set value and type, we don't know then. */
}
+}
+static char *
+c_name_of_child (struct varobj *parent, int index)
+{
+ char *name;
+ c_describe_child (parent, index, &name, NULL, NULL);
return name;
}
static struct value *
c_value_of_root (struct varobj **var_handle)
{
- struct value *new_val;
+ struct value *new_val = NULL;
struct varobj *var = *var_handle;
struct frame_info *fi;
int within_scope;
/* Only root variables can be updated... */
- if (var->root->rootvar != var)
+ if (!is_root_p (var))
/* Not a root var */
return NULL;
/* Determine whether the variable is still around. */
- if (var->root->valid_block == NULL)
+ if (var->root->valid_block == NULL || var->root->use_selected_frame)
within_scope = 1;
else
{
- reinit_frame_cache ();
fi = frame_find_by_id (var->root->frame);
within_scope = fi != NULL;
/* FIXME: select_frame could fail */
if (pc < BLOCK_START (var->root->valid_block) ||
pc >= BLOCK_END (var->root->valid_block))
within_scope = 0;
- select_frame (fi);
+ else
+ select_frame (fi);
}
}
go on */
if (gdb_evaluate_expression (var->root->exp, &new_val))
{
- var->error = 0;
release_value (new_val);
}
- else
- var->error = 1;
return new_val;
}
static struct value *
c_value_of_child (struct varobj *parent, int index)
{
- struct value *value;
- struct value *temp;
- struct value *indval;
- struct type *type, *target;
- char *name;
- int real_index;
-
- type = get_type (parent);
- target = get_target_type (type);
- name = name_of_child (parent, index);
- temp = parent->value;
- value = NULL;
-
- if (temp != NULL)
- {
- switch (TYPE_CODE (type))
- {
- case TYPE_CODE_ARRAY:
- real_index = index + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type));
-#if 0
- /* This breaks if the array lives in a (vector) register. */
- value = value_slice (temp, real_index, 1);
- temp = value_coerce_array (value);
- gdb_value_ind (temp, &value);
-#else
- indval = value_from_longest (builtin_type_int, (LONGEST) real_index);
- gdb_value_subscript (temp, indval, &value);
-#endif
- break;
-
- case TYPE_CODE_STRUCT:
- case TYPE_CODE_UNION:
- gdb_value_struct_elt (NULL, &value, &temp, NULL, name, NULL,
- "vstructure");
- break;
-
- case TYPE_CODE_PTR:
- switch (TYPE_CODE (target))
- {
- case TYPE_CODE_STRUCT:
- case TYPE_CODE_UNION:
- gdb_value_struct_elt (NULL, &value, &temp, NULL, name, NULL,
- "vstructure");
- break;
-
- default:
- gdb_value_ind (temp, &value);
- break;
- }
- break;
-
- default:
- break;
- }
- }
-
+ struct value *value = NULL;
+ c_describe_child (parent, index, NULL, &value, NULL);
if (value != NULL)
release_value (value);
- xfree (name);
return value;
}
static struct type *
c_type_of_child (struct varobj *parent, int index)
{
- struct type *type;
- char *name = name_of_child (parent, index);
-
- switch (TYPE_CODE (parent->type))
- {
- case TYPE_CODE_ARRAY:
- type = get_target_type (parent->type);
- break;
-
- case TYPE_CODE_STRUCT:
- case TYPE_CODE_UNION:
- type = lookup_struct_elt_type (parent->type, name, 0);
- break;
-
- case TYPE_CODE_PTR:
- switch (TYPE_CODE (get_target_type (parent->type)))
- {
- case TYPE_CODE_STRUCT:
- case TYPE_CODE_UNION:
- type = lookup_struct_elt_type (parent->type, name, 0);
- break;
-
- default:
- type = get_target_type (parent->type);
- break;
- }
- break;
-
- default:
- /* This should not happen as only the above types have children */
- warning (_("Child of parent whose type does not allow children"));
- /* FIXME: Can we still go on? */
- type = NULL;
- break;
- }
-
- xfree (name);
+ struct type *type = NULL;
+ c_describe_child (parent, index, NULL, NULL, &type);
return type;
}
}
else
{
- long dummy;
- struct ui_file *stb = mem_fileopen ();
- struct cleanup *old_chain = make_cleanup_ui_file_delete (stb);
- char *thevalue;
-
- gdb_assert (type_changeable (var));
+ gdb_assert (varobj_value_is_changeable_p (var));
gdb_assert (!value_lazy (var->value));
- common_val_print (var->value, stb,
- format_code[(int) var->format], 1, 0, 0);
- thevalue = ui_file_xstrdup (stb, &dummy);
- do_cleanups (old_chain);
- return thevalue;
- }
+ return value_get_print_value (var->value, var->format);
+ }
}
}
}