/* Implementation of the GDB variable objects API.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
- Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+ 2009 Free Software Foundation, Inc.
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
#include "wrapper.h"
#include "gdbcmd.h"
#include "block.h"
+#include "valprint.h"
#include "gdb_assert.h"
#include "gdb_string.h"
static struct value *value_of_child (struct varobj *parent, int index);
-static char *my_value_of_variable (struct varobj *var);
+static char *my_value_of_variable (struct varobj *var,
+ enum varobj_display_formats format);
static char *value_get_print_value (struct value *value,
enum varobj_display_formats format);
static struct type *c_type_of_child (struct varobj *parent, int index);
-static char *c_value_of_variable (struct varobj *var);
+static char *c_value_of_variable (struct varobj *var,
+ enum varobj_display_formats format);
/* C++ implementation */
static struct type *cplus_type_of_child (struct varobj *parent, int index);
-static char *cplus_value_of_variable (struct varobj *var);
+static char *cplus_value_of_variable (struct varobj *var,
+ enum varobj_display_formats format);
/* Java implementation */
static struct type *java_type_of_child (struct varobj *parent, int index);
-static char *java_value_of_variable (struct varobj *var);
+static char *java_value_of_variable (struct varobj *var,
+ enum varobj_display_formats format);
/* The language specific vector */
struct type *(*type_of_child) (struct varobj * parent, int index);
/* The current value of VAR. */
- char *(*value_of_variable) (struct varobj * var);
+ char *(*value_of_variable) (struct varobj * var,
+ enum varobj_display_formats format);
};
/* Array of known source language routines. */
if (frame_addr == (CORE_ADDR) 0)
return NULL;
- while (1)
+ for (frame = get_current_frame ();
+ frame != NULL;
+ frame = get_prev_frame (frame))
{
- frame = get_prev_frame (frame);
- if (frame == NULL)
- return NULL;
if (get_frame_base_address (frame) == frame_addr)
return frame;
}
+
+ return NULL;
}
struct varobj *
struct value *value = NULL;
int expr_len;
- /* Parse and evaluate the expression, filling in as much
- of the variable's data as possible */
+ /* Parse and evaluate the expression, filling in as much of the
+ variable's data as possible. */
- /* Allow creator to specify context of variable */
- if ((type == USE_CURRENT_FRAME) || (type == USE_SELECTED_FRAME))
- fi = deprecated_safe_get_selected_frame ();
+ if (has_stack_frames ())
+ {
+ /* Allow creator to specify context of variable */
+ if ((type == USE_CURRENT_FRAME) || (type == USE_SELECTED_FRAME))
+ fi = get_selected_frame (NULL);
+ else
+ /* FIXME: cagney/2002-11-23: This code should be doing a
+ lookup using the frame ID and not just the frame's
+ ``address''. This, of course, means an interface
+ change. However, with out that interface change ISAs,
+ such as the ia64 with its two stacks, won't work.
+ Similar goes for the case where there is a frameless
+ function. */
+ fi = find_frame_addr_in_frame_chain (frame);
+ }
else
- /* FIXME: cagney/2002-11-23: This code should be doing a
- lookup using the frame ID and not just the frame's
- ``address''. This, of course, means an interface change.
- However, with out that interface change ISAs, such as the
- ia64 with its two stacks, won't work. Similar goes for the
- case where there is a frameless function. */
- fi = find_frame_addr_in_frame_chain (frame);
+ fi = NULL;
/* frame = -2 means always use selected frame */
if (type == USE_SELECTED_FRAME)
if (varobj_value_is_changeable_p (var)
&& var->value && !value_lazy (var->value))
{
- free (var->print_value);
+ xfree (var->print_value);
var->print_value = value_get_print_value (var->value, var->format);
}
return attributes;
}
+char *
+varobj_get_formatted_value (struct varobj *var,
+ enum varobj_display_formats format)
+{
+ return my_value_of_variable (var, format);
+}
+
char *
varobj_get_value (struct varobj *var)
{
- return my_value_of_variable (var);
+ return my_value_of_variable (var, var->format);
}
/* Set the value of an object variable (if it is editable) to the
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:
- < 0 for error values, see varobj.h.
- Otherwise it is the number of children + parent changed.
The EXPLICIT parameter specifies if this call is result
of MI request to update this specific variable, or
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,
- int explicit)
+VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit)
{
int changed = 0;
int type_changed = 0;
struct varobj **templist = NULL;
struct value *new;
VEC (varobj_p) *stack = NULL;
- VEC (varobj_p) *result = NULL;
+ VEC (varobj_update_result) *result = NULL;
struct frame_info *fi;
- /* sanity check: have we been passed a pointer? */
- gdb_assert (changelist);
-
/* 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;
+ return result;
if (!(*varp)->root->is_valid)
- return INVALID;
+ {
+ varobj_update_result r = {*varp};
+ r.status = VAROBJ_INVALID;
+ VEC_safe_push (varobj_update_result, result, &r);
+ return result;
+ }
if ((*varp)->root->rootvar == *varp)
{
+ varobj_update_result r = {*varp};
+ r.status = VAROBJ_IN_SCOPE;
+
/* 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. */
new = value_of_root (varp, &type_changed);
-
- /* If this is a floating 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);
- }
+ r.varobj = *varp;
+ r.type_changed = type_changed;
+ if (install_new_value ((*varp), new, type_changed))
+ r.changed = 1;
+
if (new == NULL)
- {
- /* This means the varobj itself is out of scope.
- Report it. */
- VEC_free (varobj_p, result);
- return NOT_IN_SCOPE;
- }
+ r.status = VAROBJ_NOT_IN_SCOPE;
+
+ if (r.type_changed || r.changed)
+ VEC_safe_push (varobj_update_result, result, &r);
+
+ if (r.status == VAROBJ_NOT_IN_SCOPE)
+ return result;
}
VEC_safe_push (varobj_p, stack, *varp);
if (install_new_value (v, new, 0 /* type not changed */))
{
/* Note that it's changed */
- VEC_safe_push (varobj_p, result, v);
+ varobj_update_result r = {v};
+ r.changed = 1;
+ VEC_safe_push (varobj_update_result, result, &r);
v->updated = 0;
}
}
}
- /* Alloc (changed + 1) list entries. */
- changed = VEC_length (varobj_p, result);
- *changelist = xmalloc ((changed + 1) * sizeof (struct varobj *));
- cv = *changelist;
-
- for (i = 0; i < changed; ++i)
- {
- *cv = VEC_index (varobj_p, result, i);
- gdb_assert (*cv != NULL);
- ++cv;
- }
- *cv = 0;
-
VEC_free (varobj_p, stack);
- VEC_free (varobj_p, result);
-
- if (type_changed)
- return TYPE_CHANGED;
- else
- return changed;
+ return result;
}
\f
new_type = varobj_get_type (tmp_var);
if (strcmp (old_type, new_type) == 0)
{
+ /* The expression presently stored inside var->root->exp
+ remembers the locations of local variables relatively to
+ the frame where the expression was created (in DWARF location
+ button, for example). Naturally, those locations are not
+ correct in other frames, so update the expression. */
+
+ struct expression *tmp_exp = var->root->exp;
+ var->root->exp = tmp_var->root->exp;
+ tmp_var->root->exp = tmp_exp;
+
varobj_delete (tmp_var, NULL, 0);
*type_changed = 0;
}
/* GDB already has a command called "value_of_variable". Sigh. */
static char *
-my_value_of_variable (struct varobj *var)
+my_value_of_variable (struct varobj *var, enum varobj_display_formats format)
{
if (var->root->is_valid)
- return (*var->root->lang->value_of_variable) (var);
+ return (*var->root->lang->value_of_variable) (var, format);
else
return NULL;
}
struct ui_file *stb;
struct cleanup *old_chain;
char *thevalue;
+ struct value_print_options opts;
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);
+ get_formatted_print_options (&opts, format_code[(int) format]);
+ opts.deref_ref = 0;
+ common_val_print (value, stb, 0, &opts, current_language);
thevalue = ui_file_xstrdup (stb, &dummy);
do_cleanups (old_chain);
return r;
}
+/* Return 1 if that varobj is floating, that is is always evaluated in the
+ selected frame, and not bound to thread/frame. Such variable objects
+ are created using '@' as frame specifier to -var-create. */
+int
+varobj_floating_p (struct varobj *var)
+{
+ return var->root->floating;
+}
+
/* Given the value and the type of a variable object,
adjust the value and type to those necessary
for getting children of the variable object.
{
case TYPE_CODE_ARRAY:
if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (target) > 0
- && TYPE_ARRAY_UPPER_BOUND_TYPE (type) != BOUND_CANNOT_BE_DETERMINED)
+ && !TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type))
children = TYPE_LENGTH (type) / TYPE_LENGTH (target);
else
/* If we don't know how many elements there are, don't display
TRY_CATCH (e, RETURN_MASK_ERROR)
{
- if (TYPE_FIELD_STATIC (type, type_index))
+ if (field_is_static (&TYPE_FIELD (type, type_index)))
result = value_static_field (type, type_index);
else
result = value_primitive_field (value, 0, type_index, type);
{
int real_index = index + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type));
struct value *indval =
- value_from_longest (builtin_type_int, (LONGEST) real_index);
+ value_from_longest (builtin_type_int32, (LONGEST) real_index);
gdb_value_subscript (value, indval, cvalue);
}
/* Not a root var */
return NULL;
- back_to = make_cleanup_restore_current_thread (
- inferior_ptid, get_frame_id (deprecated_safe_get_selected_frame ()));
+ back_to = make_cleanup_restore_current_thread ();
/* Determine whether the variable is still around. */
if (var->root->valid_block == NULL || var->root->floating)
}
static char *
-c_value_of_variable (struct varobj *var)
+c_value_of_variable (struct varobj *var, enum varobj_display_formats format)
{
/* BOGUS: if val_print sees a struct/class, or a reference to one,
it will print out its children instead of "{...}". So we need to
gdb_assert (varobj_value_is_changeable_p (var));
gdb_assert (!value_lazy (var->value));
- return xstrdup (var->print_value);
+
+ /* If the specified format is the current one,
+ we can reuse print_value */
+ if (format == var->format)
+ return xstrdup (var->print_value);
+ else
+ return value_get_print_value (var->value, format);
}
}
}
}
static char *
-cplus_value_of_variable (struct varobj *var)
+cplus_value_of_variable (struct varobj *var, enum varobj_display_formats format)
{
/* If we have one of our special types, don't print out
if (CPLUS_FAKE_CHILD (var))
return xstrdup ("");
- return c_value_of_variable (var);
+ return c_value_of_variable (var, format);
}
\f
/* Java */
}
static char *
-java_value_of_variable (struct varobj *var)
+java_value_of_variable (struct varobj *var, enum varobj_display_formats format)
{
- return cplus_value_of_variable (var);
+ return cplus_value_of_variable (var, format);
}
\f
extern void _initialize_varobj (void);
varp = all_rootvarobj;
while (*varp != NULL)
{
+ /* Floating varobjs are reparsed on each stop, so we don't care if
+ the presently parsed expression refers to something that's gone. */
+ if ((*varp)->root->floating)
+ continue;
+
/* global var must be re-evaluated. */
if ((*varp)->root->valid_block == NULL)
{
varp++;
}
- xfree (all_rootvarobj);
}
+ xfree (all_rootvarobj);
return;
}