X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fvarobj.c;h=c4d02c96c5e1bdfe41c7f10bc06949e54af463b2;hb=8bf6485c1cee41f31564e1097199ff67a3615ebe;hp=c16e08819fe1cb80d01e3b95c0e0dac5cc9e31a1;hpb=01f0fe5e0450edf168c1f612feb93cf588e4e7ea;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/varobj.c b/gdb/varobj.c index c16e08819f..c4d02c96c5 100644 --- a/gdb/varobj.c +++ b/gdb/varobj.c @@ -1,11 +1,11 @@ /* Implementation of the GDB variable objects API. - Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 - Free Software Foundation, Inc. + Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, + 2009, 2010 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 - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -14,9 +14,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. */ + along with this program. If not, see . */ #include "defs.h" #include "exceptions.h" @@ -26,11 +24,24 @@ #include "language.h" #include "wrapper.h" #include "gdbcmd.h" +#include "block.h" +#include "valprint.h" #include "gdb_assert.h" #include "gdb_string.h" +#include "gdb_regex.h" #include "varobj.h" +#include "vec.h" +#include "gdbthread.h" +#include "inferior.h" + +#if HAVE_PYTHON +#include "python/python.h" +#include "python/python-internal.h" +#else +typedef int PyObject; +#endif /* Non-zero if we want to see trace of varobj level stuff. */ @@ -49,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 @@ -62,12 +82,25 @@ struct varobj_root /* Block for which this expression is valid */ struct block *valid_block; - /* The frame for this expression */ + /* The frame for this expression. This field is set iff valid_block is + not NULL. */ struct frame_id frame; - /* If 1, "update" always recomputes the frame & valid block - using the currently selected frame. */ - int use_selected_frame; + /* The thread ID that this varobj_root belong to. This field + is only valid if valid_block is not NULL. + When not 0, indicates which thread 'frame' belongs to. + When 0, indicates that the thread list was empty when the varobj_root + was created. */ + int thread_id; + + /* If 1, the -var-update always recomputes the value in the + current thread and frame. Otherwise, variable object is + always updated in the specific scope/thread/frame */ + int floating; + + /* Flag that indicates validity: set to 0 when this varobj_root refers + to symbols that do not exist anymore. */ + int is_valid; /* Language info for this variable and its children */ struct language_specific *lang; @@ -91,6 +124,10 @@ struct varobj /* NOTE: This is the "expression" */ char *name; + /* Alloc'd expression for this child. Can be used to create a + root variable corresponding to this child. */ + char *path_expr; + /* The alloc'd name for this variable's object. This is here for convenience when constructing this object's children. */ char *obj_name; @@ -98,23 +135,31 @@ struct varobj /* Index of this variable in its parent or -1 */ int index; - /* The type of this variable. This may NEVER be NULL. */ + /* The type of this variable. This can be NULL + for artifial variable objects -- currently, the "accessibility" + variable objects in C++. */ struct type *type; - /* The value of this expression or subexpression. This may be NULL. */ + /* 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; + + /* Whether the children of this varobj were requested. This field is + used to decide if dynamic varobj should recompute their children. + In the event that the frontend never asked for the children, we + can avoid that. */ + int children_requested; /* Description of the root variable. Points to root variable for children. */ struct varobj_root *root; @@ -124,29 +169,45 @@ struct varobj /* 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; + + /* Is this variable frozen. Frozen variables are never implicitly + updated by -var-update * + or -var-update . */ + 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; + + /* 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 @@ -176,13 +237,11 @@ static int install_variable (struct varobj *); 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 *); +static struct varobj * +create_child_with_value (struct varobj *parent, int index, const char *name, + struct value *value); /* Utility routines */ @@ -196,22 +255,19 @@ static struct cleanup *make_cleanup_free_variable (struct varobj *var); static struct type *get_type (struct varobj *var); -static struct type *get_type_deref (struct varobj *var); +static struct type *get_value_type (struct varobj *var); static struct type *get_target_type (struct type *); static enum varobj_display_formats variable_default_display (struct varobj *); -static int my_value_equal (struct value *, struct value *, int *); - -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 int install_new_value (struct varobj *var, struct value *value, + int initial); + /* Language-specific routines. */ static enum varobj_languages variable_language (struct varobj *var); @@ -226,13 +282,23 @@ static struct value *value_of_root (struct varobj **var_handle, int *); static struct value *value_of_child (struct varobj *parent, int index); -static struct type *type_of_child (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, + struct varobj *var); -static int variable_editable (struct varobj *var); +static int varobj_value_is_changeable_p (struct varobj *var); -static char *my_value_of_variable (struct varobj *var); +static int is_root_p (struct varobj *var); -static int type_changeable (struct varobj *var); +#if HAVE_PYTHON + +static struct varobj * +varobj_add_child (struct varobj *var, const char *name, struct value *value); + +#endif /* HAVE_PYTHON */ /* C implementation */ @@ -242,15 +308,16 @@ static char *c_name_of_variable (struct varobj *parent); static char *c_name_of_child (struct varobj *parent, int index); +static char *c_path_expr_of_child (struct varobj *child); + static struct value *c_value_of_root (struct varobj **var_handle); static struct value *c_value_of_child (struct varobj *parent, int index); static struct type *c_type_of_child (struct varobj *parent, int index); -static int c_variable_editable (struct varobj *var); - -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 */ @@ -262,15 +329,16 @@ static char *cplus_name_of_variable (struct varobj *parent); static char *cplus_name_of_child (struct varobj *parent, int index); +static char *cplus_path_expr_of_child (struct varobj *child); + static struct value *cplus_value_of_root (struct varobj **var_handle); static struct value *cplus_value_of_child (struct varobj *parent, int index); static struct type *cplus_type_of_child (struct varobj *parent, int index); -static int cplus_variable_editable (struct varobj *var); - -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 */ @@ -280,15 +348,16 @@ static char *java_name_of_variable (struct varobj *parent); static char *java_name_of_child (struct varobj *parent, int index); +static char *java_path_expr_of_child (struct varobj *child); + static struct value *java_value_of_root (struct varobj **var_handle); static struct value *java_value_of_child (struct varobj *parent, int index); static struct type *java_type_of_child (struct varobj *parent, int index); -static int java_variable_editable (struct varobj *var); - -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 */ @@ -307,6 +376,10 @@ struct language_specific /* The name of the INDEX'th child of PARENT. */ char *(*name_of_child) (struct varobj * parent, int index); + /* Returns the rooted expression of CHILD, which is a variable + obtain that has some parent. */ + char *(*path_expr_of_child) (struct varobj * child); + /* The ``struct value *'' of the root variable ROOT. */ struct value *(*value_of_root) (struct varobj ** root_handle); @@ -316,26 +389,23 @@ struct language_specific /* The type of the INDEX'th child of PARENT. */ struct type *(*type_of_child) (struct varobj * parent, int index); - /* Is VAR editable? */ - int (*variable_editable) (struct varobj * var); - /* 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. */ -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, c_number_of_children, c_name_of_variable, c_name_of_child, + c_path_expr_of_child, c_value_of_root, c_value_of_child, c_type_of_child, - c_variable_editable, c_value_of_variable} , /* C */ @@ -344,10 +414,10 @@ static struct language_specific c_number_of_children, c_name_of_variable, c_name_of_child, + c_path_expr_of_child, c_value_of_root, c_value_of_child, c_type_of_child, - c_variable_editable, c_value_of_variable} , /* C++ */ @@ -356,10 +426,10 @@ static struct language_specific cplus_number_of_children, cplus_name_of_variable, cplus_name_of_child, + cplus_path_expr_of_child, cplus_value_of_root, cplus_value_of_child, cplus_type_of_child, - cplus_variable_editable, cplus_value_of_variable} , /* Java */ @@ -368,10 +438,10 @@ static struct language_specific java_number_of_children, java_name_of_variable, java_name_of_child, + java_path_expr_of_child, java_value_of_root, java_value_of_child, java_type_of_child, - java_variable_editable, java_value_of_variable} }; @@ -388,7 +458,6 @@ static int format_code[] = { 0, 't', 'd', 'x', 'o' }; /* Header of the list of root variable objects */ static struct varobj_root *rootlist; -static int rootcount = 0; /* number of root varobjs in the list */ /* Prime number indicating the number of buckets in the hash table */ /* A prime large enough to avoid too many colisions */ @@ -403,6 +472,22 @@ static struct vlist **varobj_table; /* API Implementation */ +static int +is_root_p (struct varobj *var) +{ + return (var->root->rootvar == var); +} + +#ifdef HAVE_PYTHON +/* Helper function to install a Python environment suitable for + use during operations on VAR. */ +struct cleanup * +varobj_ensure_python_env (struct varobj *var) +{ + return ensure_python_env (var->root->exp->gdbarch, + var->root->exp->language_defn); +} +#endif /* Creates a varobj (not its children) */ @@ -417,14 +502,24 @@ find_frame_addr_in_frame_chain (CORE_ADDR frame_addr) 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) + /* The CORE_ADDR we get as argument was parsed from a string GDB + output as $fp. This output got truncated to gdbarch_addr_bit. + Truncate the frame base address in the same manner before + comparing it against our argument. */ + CORE_ADDR frame_base = get_frame_base_address (frame); + int addr_bit = gdbarch_addr_bit (get_frame_arch (frame)); + if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT)) + frame_base &= ((CORE_ADDR) 1 << addr_bit) - 1; + + if (frame_base == frame_addr) return frame; } + + return NULL; } struct varobj * @@ -445,25 +540,32 @@ varobj_create (char *objname, { char *p; enum varobj_languages lang; + struct value *value = NULL; - /* 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_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) - var->root->use_selected_frame = 1; + var->root->floating = 1; block = NULL; if (fi != NULL) @@ -489,43 +591,53 @@ varobj_create (char *objname, var->format = variable_default_display (var); var->root->valid_block = innermost_block; - var->name = savestring (expression, strlen (expression)); + var->name = xstrdup (expression); + /* For a root var, the name and the expr are the same. */ + var->path_expr = xstrdup (expression); /* When the frame is different from the current frame, we must select the appropriate frame before parsing the expression, otherwise the value will not be current. Since select_frame is so benign, just call it for all cases. */ - if (fi != NULL) + if (innermost_block) { + /* User could specify explicit FRAME-ADDR which was not found but + EXPRESSION is frame specific and we would not be able to evaluate + it correctly next time. With VALID_BLOCK set we must also set + FRAME and THREAD_ID. */ + if (fi == NULL) + error (_("Failed to find the specified frame")); + var->root->frame = get_frame_id (fi); - old_fi = deprecated_selected_frame; - select_frame (fi); + var->root->thread_id = pid_to_thread_id (inferior_ptid); + old_fi = get_selected_frame (NULL); + select_frame (fi); } - /* We definitively need to catch errors here. + /* We definitely need to catch errors here. If evaluate_expression succeeds we got the value we wanted. But if it fails, we still go on with a call to evaluate_type() */ - if (gdb_evaluate_expression (var->root->exp, &var->value)) + if (!gdb_evaluate_expression (var->root->exp, &value)) { - /* no error */ - release_value (var->value); - if (value_lazy (var->value)) - gdb_value_fetch_lazy (var->value); + /* Error getting the value. Try to at least get the + right type. */ + struct value *type_only_value = evaluate_type (var->root->exp); + var->type = value_type (type_only_value); } - else - var->value = evaluate_type (var->root->exp); + else + var->type = value_type (value); - var->type = value_type (var->value); + install_new_value (var, value, 1 /* Initial assignment */); /* 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; /* Reset the selected frame */ - if (fi != NULL) + if (old_fi != NULL) select_frame (old_fi); } @@ -534,7 +646,7 @@ varobj_create (char *objname, if ((var != NULL) && (objname != NULL)) { - var->obj_name = savestring (objname, strlen (objname)); + var->obj_name = xstrdup (objname); /* If a varobj name is duplicated, the install will fail so we must clenup */ @@ -564,8 +676,8 @@ varobj_gen_name (void) return obj_name; } -/* Given an "objname", returns the pointer to the corresponding varobj - or NULL if not found */ +/* Given an OBJNAME, returns the pointer to the corresponding varobj. Call + error if OBJNAME cannot be found. */ struct varobj * varobj_get_handle (char *objname) @@ -651,6 +763,28 @@ varobj_delete (struct varobj *var, char ***dellist, int only_children) return delcount; } +#if HAVE_PYTHON + +/* Convenience function for varobj_set_visualizer. Instantiate a + pretty-printer for a given value. */ +static PyObject * +instantiate_pretty_printer (PyObject *constructor, struct value *value) +{ + PyObject *val_obj = NULL; + PyObject *printer; + + val_obj = value_to_value_object (value); + if (! val_obj) + return NULL; + + printer = PyObject_CallFunctionObjArgs (constructor, val_obj, NULL); + Py_DECREF (val_obj); + return printer; + return NULL; +} + +#endif + /* Set/Get variable object display format */ enum varobj_display_formats @@ -671,6 +805,13 @@ varobj_set_display_format (struct varobj *var, var->format = variable_default_display (var); } + if (varobj_value_is_changeable_p (var) + && var->value && !value_lazy (var->value)) + { + xfree (var->print_value); + var->print_value = value_get_print_value (var->value, var->format, var); + } + return var->format; } @@ -680,85 +821,376 @@ varobj_get_display_format (struct varobj *var) return var->format; } +char * +varobj_get_display_hint (struct varobj *var) +{ + char *result = NULL; + +#if HAVE_PYTHON + struct cleanup *back_to = varobj_ensure_python_env (var); + + if (var->pretty_printer) + result = gdbpy_get_display_hint (var->pretty_printer); + + do_cleanups (back_to); +#endif + + 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 + is always positive. Otherwise, returns -1. */ +int +varobj_get_thread_id (struct varobj *var) +{ + if (var->root->valid_block && var->root->thread_id > 0) + return var->root->thread_id; + else + return -1; +} + +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; +} + +/* 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; + } +} + +#if HAVE_PYTHON + +/* 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); + } +} + +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, + VEC (varobj_p) **unchanged, + int *cchanged, + int update_children, + int from, + int to) +{ +#if HAVE_PYTHON + struct cleanup *back_to; + PyObject *children; + int i; + PyObject *printer = var->pretty_printer; + + back_to = varobj_ensure_python_env (var); + + *cchanged = 0; + if (!PyObject_HasAttr (printer, gdbpy_children_cst)) + { + do_cleanups (back_to); + return 0; + } + + if (update_children || !var->child_iter) + { + children = PyObject_CallMethodObjArgs (printer, gdbpy_children_cst, + NULL); + + if (!children) + { + gdbpy_print_stack (); + error (_("Null value returned for children")); + } + + make_cleanup_py_decref (children); + + 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; + } + else + i = VEC_length (varobj_p, var->children); + + /* 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; + + /* 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; + + /* 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; + int can_mention = from < 0 || i >= from; + + 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); + install_dynamic_child (var, can_mention ? changed : NULL, + can_mention ? new : NULL, + can_mention ? unchanged : NULL, + can_mention ? cchanged : NULL, i, name, v); + do_cleanups (inner); + } + else + { + Py_XDECREF (var->saved_item); + var->saved_item = item; + + /* We want to truncate the child list just before this + element. */ + break; + } + } + + if (i < VEC_length (varobj_p, var->children)) + { + 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); + } + + /* 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); + + return 1; +#else + gdb_assert (0 && "should never be called if Python is not enabled"); +#endif +} + int varobj_get_num_children (struct varobj *var) { if (var->num_children == -1) - var->num_children = number_of_children (var); + { + 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, 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 */ -int -varobj_list_children (struct varobj *var, struct varobj ***childlist) +VEC (varobj_p)* +varobj_list_children (struct varobj *var, int *from, int *to) { struct varobj *child; char *name; - int i; + int i, children_changed; - /* sanity check: have we been passed a pointer? */ - if (childlist == NULL) - return -1; + var->children_requested = 1; - *childlist = NULL; + 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, NULL, &children_changed, + 0, 0, *to); + restrict_range (var->children, from, to); + return var->children; + } if (var->num_children == -1) var->num_children = number_of_children (var); - /* List of children */ - *childlist = xmalloc ((var->num_children + 1) * sizeof (struct varobj *)); + /* If that failed, give up. */ + if (var->num_children == -1) + return var->children; + + /* 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); for (i = 0; i < var->num_children; i++) { - /* Mark as the end in case we bail out */ - *((*childlist) + i) = NULL; + varobj_p existing = VEC_index (varobj_p, var->children, i); - /* 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); - - *((*childlist) + i) = child; + 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); + } } - /* End of list is marked by a NULL pointer */ - *((*childlist) + i) = NULL; + restrict_range (var->children, from, to); + return var->children; +} + +#if HAVE_PYTHON - return var->num_children; +static struct varobj * +varobj_add_child (struct varobj *var, const char *name, struct value *value) +{ + varobj_p v = create_child_with_value (var, + VEC_length (varobj_p, var->children), + name, value); + VEC_safe_push (varobj_p, var->children, v); + return v; } +#endif /* HAVE_PYTHON */ + /* Obtain the type of an object Variable as a string similar to the one gdb prints on the console */ char * varobj_get_type (struct varobj *var) { - struct value *val; - struct cleanup *old_chain; - struct ui_file *stb; - char *thetype; - long length; - /* For the "fake" variables, do not return a type. (It's type is - NULL, too.) */ - if (CPLUS_FAKE_CHILD (var)) + NULL, too.) + Do not return a type for invalid variables as well. */ + if (CPLUS_FAKE_CHILD (var) || !var->root->is_valid) return NULL; - stb = mem_fileopen (); - old_chain = make_cleanup_ui_file_delete (stb); - - /* To print the type, we simply create a zero ``struct value *'' and - cast it to our type. We then typeprint this variable. */ - val = value_zero (var->type, not_lval); - type_print (value_type (val), "", stb, -1); - - thetype = ui_file_xstrdup (stb, &length); - do_cleanups (old_chain); - return thetype; + return type_to_string (var->type); } /* Obtain the type of an object variable. */ @@ -769,6 +1201,23 @@ varobj_get_gdb_type (struct varobj *var) return var->type; } +/* Return a pointer to the full rooted expression of varobj VAR. + If it has not been computed yet, compute it. */ +char * +varobj_get_path_expr (struct varobj *var) +{ + if (var->path_expr != NULL) + return var->path_expr; + else + { + /* For root varobjs, we initialize path_expr + when creating varobj, so here it should be + child varobj. */ + gdb_assert (!is_root_p (var)); + return (*var->root->lang->path_expr_of_child) (var); + } +} + enum varobj_languages varobj_get_language (struct varobj *var) { @@ -780,17 +1229,30 @@ varobj_get_attributes (struct varobj *var) { int attributes = 0; - if (variable_editable (var)) + if (varobj_editable_p (var)) /* FIXME: define masks for attributes */ attributes |= 0x00000001; /* Editable */ 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) +{ + 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 @@ -810,239 +1272,607 @@ varobj_set_value (struct varobj *var, char *expression) struct expression *exp; struct value *value; int saved_input_radix = input_radix; + char *s = expression; + int i; - if (var->value != NULL && variable_editable (var) && !var->error) - { - char *s = expression; - int i; - - input_radix = 10; /* ALWAYS reset to decimal temporarily */ - exp = parse_exp_1 (&s, 0, 0); - if (!gdb_evaluate_expression (exp, &value)) - { - /* We cannot proceed without a valid expression. */ - xfree (exp); - return 0; - } + gdb_assert (varobj_editable_p (var)); - if (!my_value_equal (var->value, value, &error)) - var->updated = 1; - if (!gdb_value_assign (var->value, value, &val)) - return 0; - value_free (var->value); - release_value (val); - var->value = val; - input_radix = saved_input_radix; - return 1; + input_radix = 10; /* ALWAYS reset to decimal temporarily */ + exp = parse_exp_1 (&s, 0, 0); + if (!gdb_evaluate_expression (exp, &value)) + { + /* We cannot proceed without a valid expression. */ + xfree (exp); + return 0; } - return 0; + /* All types that are editable must also be changeable. */ + 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)); + + /* Need to coerce the input. We want to check if the + value of the variable object will be different + after assignment, and the first thing value_assign + does is coerce the input. + For example, if we are assigning an array to a pointer variable we + should compare the pointer with the the array's address, not with the + array's content. */ + value = coerce_array (value); + + /* The new value may be lazy. gdb_value_assign, or + rather value_contents, will take care of this. + If fetching of the new value will fail, gdb_value_assign + with catch the exception. */ + if (!gdb_value_assign (var->value, value, &val)) + return 0; + + /* If the value has changed, record it, so that next -var-update can + report this change. If a variable had a value of '1', we've set it + to '333' and then set again to '1', when -var-update will report this + variable as changed -- because the first assignment has set the + 'updated' flag. There's no need to optimize that, because return value + of -var-update should be considered an approximation. */ + var->updated = install_new_value (var, val, 0 /* Compare values. */); + input_radix = saved_input_radix; + return 1; } -/* Returns a malloc'ed list with all root variable objects */ -int -varobj_list (struct varobj ***varlist) -{ - struct varobj **cv; - struct varobj_root *croot; - int mycount = rootcount; +#if HAVE_PYTHON - /* Alloc (rootcount + 1) entries for the result */ - *varlist = xmalloc ((rootcount + 1) * sizeof (struct varobj *)); +/* A helper function to install a constructor function and visualizer + in a varobj. */ - cv = *varlist; - croot = rootlist; - while ((croot != NULL) && (mycount > 0)) - { - *cv = croot->rootvar; - mycount--; - cv++; - croot = croot->next; - } - /* Mark the end of the list */ - *cv = NULL; +static void +install_visualizer (struct varobj *var, PyObject *constructor, + PyObject *visualizer) +{ + Py_XDECREF (var->constructor); + var->constructor = constructor; - if (mycount || (croot != NULL)) - warning - ("varobj_list: assertion failed - wrong tally of root vars (%d:%d)", - rootcount, mycount); + Py_XDECREF (var->pretty_printer); + var->pretty_printer = visualizer; - return rootcount; + Py_XDECREF (var->child_iter); + var->child_iter = NULL; } -/* Update the values for a variable and its children. This is a - two-pronged attack. First, re-parse the value for the root's - 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 +/* Install the default visualizer for VAR. */ - Only root variables can be updated... +static void +install_default_visualizer (struct varobj *var) +{ + if (pretty_printing) + { + PyObject *pretty_printer = NULL; - NOTE: This function may delete the caller's varobj. If it - returns -2, then it has done this and VARP will be modified - to point to the new varobj. */ + 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); + } +} -int -varobj_update (struct varobj **varp, struct varobj ***changelist) +/* Instantiate and install a visualizer for VAR using CONSTRUCTOR to + make a new object. */ + +static void +construct_visualizer (struct varobj *var, PyObject *constructor) { - int changed = 0; - int error = 0; - int type_changed; - int i; - int vleft; - struct varobj *v; - struct varobj **cv; - struct varobj **templist = NULL; - struct value *new; - struct vstack *stack = NULL; - struct vstack *result = NULL; - struct frame_id old_fid; - struct frame_info *fi; + PyObject *pretty_printer; - /* sanity check: have we been passed a pointer? */ - if (changelist == NULL) - return -1; + 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); + } - /* Only root variables can be updated... */ - if ((*varp)->root->rootvar != *varp) - /* Not a root var */ - return -1; + if (pretty_printer == Py_None) + { + Py_DECREF (pretty_printer); + pretty_printer = NULL; + } + } + + install_visualizer (var, constructor, pretty_printer); +} + +#endif /* HAVE_PYTHON */ - /* Save the selected stack frame, since we will need to change it - in order to evaluate expressions. */ - old_fid = get_frame_id (deprecated_selected_frame); +/* A helper function for install_new_value. This creates and installs + a visualizer for VAR, if appropriate. */ - /* 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) +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) { - (*varp)->error = 1; - return -1; + 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 +} - /* Initialize a stack for temporary results */ - vpush (&result, NULL); +/* 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 + and return 0. + Otherwise, assign the new value, and return 1 if the value is different + from the current one, 0 otherwise. The comparison is done on textual + representation of value. Therefore, some types need not be compared. E.g. + for structures the reported value is always "{...}", so no comparison is + necessary here. If the old value was NULL and new one is not, or vice versa, + we always return 1. + + The VALUE parameter should not be released -- the function will + take care of releasing it when needed. */ +static int +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; + char *print_value = NULL; + + /* 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 = varobj_value_is_changeable_p (var); + + /* If the type has custom visualizer, we consider it to be always + changeable. FIXME: need to make sure this behaviour will not + mess up read-sensitive values. */ + if (var->pretty_printer) + changeable = 1; + + need_to_fetch = changeable; + + /* We are not interested in the address of references, and given + 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); + + if (var->type && TYPE_CODE (var->type) == TYPE_CODE_UNION) + /* For unions, we need to fetch the value implicitly because + of implementation of union member fetch. When gdb + creates a value for a field and the value of the enclosing + structure is not lazy, it immediately copies the necessary + bytes from the enclosing values. If the enclosing value is + lazy, the call to value_fetch_lazy on the field will read + the data from memory. For unions, that means we'll read the + same memory more than once, which is not desirable. So + fetch now. */ + need_to_fetch = 1; + + /* The new value might be lazy. If the type is changeable, + that is we'll be comparing values of this type, fetch the + value now. Otherwise, on the next update the old value + will be lazy, which means we've lost that old value. */ + if (need_to_fetch && value && value_lazy (value)) + { + struct varobj *parent = var->parent; + int frozen = var->frozen; + for (; !frozen && parent; parent = parent->parent) + frozen |= parent->frozen; - /* If this is a "use_selected_frame" varobj, and its type has changed, - them note that it's changed. */ - if (type_changed) + 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, + that we couldn't even read. */ + value = NULL; + } + } + + + /* Below, we'll be comparing string rendering of old and new + 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) && !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. + If this is the initial assignment, we don't have any old value + to compare with. */ + if (!initial && changeable) { - vpush (&result, *varp); - changed++; + /* 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. */ + if (var->updated) + { + changed = 1; + } + else if (! var->pretty_printer) + { + /* Try to compare the values. That requires that both + values are non-lazy. */ + 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) + { + changed = 1; + } + else + { + gdb_assert (!value_lazy (var->value)); + gdb_assert (!value_lazy (value)); + + gdb_assert (var->print_value != NULL && print_value != NULL); + if (strcmp (var->print_value, print_value) != 0) + changed = 1; + } + } } - /* If values are not equal, note that it's changed. - There a couple of exceptions here, though. - We don't want some types to be reported as "changed". */ - else if (type_changeable (*varp) && - ((*varp)->updated || !my_value_equal ((*varp)->value, new, &error))) + + if (!initial && !changeable) { - vpush (&result, *varp); - (*varp)->updated = 0; - changed++; - /* Its value is going to be updated to NEW. */ - (*varp)->error = error; + /* For values that are not changeable, we don't compare the values. + However, we want to notice if a value was not NULL and now is NULL, + or vise versa, so that we report when top-level varobjs come in scope + and leave the scope. */ + changed = (var->value != NULL) != (value != NULL); } - /* We must always keep around the new value for this root - variable expression, or we lose the updated children! */ - value_free ((*varp)->value); - (*varp)->value = new; + /* We must always keep the new value, since children depend on it. */ + if (var->value != NULL && var->value != value) + value_free (var->value); + var->value = 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; - /* Initialize a stack */ - vpush (&stack, NULL); + install_new_value_visualizer (var); - /* Push the root's children */ - if ((*varp)->children != NULL) + /* If we installed a pretty-printer, re-compare the printed version + to see if the variable changed. */ + if (var->pretty_printer) { - struct varobj_child *c; - for (c = (*varp)->children; c != NULL; c = c->next) - vpush (&stack, c->child); + xfree (print_value); + print_value = value_get_print_value (var->value, var->format, var); + if ((var->print_value == NULL && print_value != NULL) + || (var->print_value != NULL && print_value == NULL) + || (var->print_value != NULL && print_value != NULL + && 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; +} + +/* 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) +{ + *from = var->from; + *to = var->to; +} + +/* 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) +{ + var->from = from; + var->to = to; +} + +void +varobj_set_visualizer (struct varobj *var, const char *visualizer) +{ +#if HAVE_PYTHON + PyObject *mainmod, *globals, *pretty_printer, *constructor; + struct cleanup *back_to, *value; + + back_to = varobj_ensure_python_env (var); + + mainmod = PyImport_AddModule ("__main__"); + globals = PyModule_GetDict (mainmod); + Py_INCREF (globals); + make_cleanup_py_decref (globals); + + constructor = PyRun_String (visualizer, Py_eval_input, globals, globals); - /* Walk through the children, reconstructing them all. */ - v = vpop (&stack); - while (v != NULL) + if (! constructor) { - /* Push any children */ - if (v->children != NULL) - { - struct varobj_child *c; - for (c = v->children; c != NULL; c = c->next) - vpush (&stack, c->child); - } + gdbpy_print_stack (); + error (_("Could not evaluate visualizer expression: %s"), visualizer); + } - /* Update this variable */ - new = value_of_child (v->parent, v->index); - if (type_changeable (v) && - (v->updated || !my_value_equal (v->value, new, &error))) - { - /* Note that it's changed */ - vpush (&result, v); - v->updated = 0; - changed++; - } - /* Its value is going to be updated to NEW. */ - v->error = error; + construct_visualizer (var, constructor); + Py_XDECREF (constructor); + + /* If there are any children now, wipe them. */ + varobj_delete (var, NULL, 1 /* children only */); + var->num_children = -1; + + do_cleanups (back_to); +#else + error (_("Python support required")); +#endif +} + +/* Update the values for a variable and its children. This is a + two-pronged attack. First, re-parse the value for the root's + expression to see if it's changed. Then go all the way + through its children, reconstructing them and noting if they've + changed. + + 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. */ + +VEC(varobj_update_result) *varobj_update (struct varobj **varp, int explicit) +{ + int changed = 0; + int type_changed = 0; + int i; + int vleft; + struct varobj *v; + struct varobj **cv; + struct varobj **templist = NULL; + struct value *new; + VEC (varobj_update_result) *stack = NULL; + VEC (varobj_update_result) *result = NULL; + struct frame_info *fi; - /* We must always keep new values, since children depend on it. */ - if (v->value != NULL) - value_free (v->value); - v->value = new; + /* 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 result; - /* Get next child */ - v = vpop (&stack); + if (!(*varp)->root->is_valid) + { + varobj_update_result r = {0}; + r.varobj = *varp; + r.status = VAROBJ_INVALID; + VEC_safe_push (varobj_update_result, result, &r); + return result; } - /* Alloc (changed + 1) list entries */ - /* FIXME: add a cleanup for the allocated list(s) - because one day the select_frame called below can longjump */ - *changelist = xmalloc ((changed + 1) * sizeof (struct varobj *)); - if (changed > 1) + if ((*varp)->root->rootvar == *varp) { - templist = xmalloc ((changed + 1) * sizeof (struct varobj *)); - cv = templist; + varobj_update_result r = {0}; + r.varobj = *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); + r.varobj = *varp; + + r.type_changed = type_changed; + if (install_new_value ((*varp), new, type_changed)) + r.changed = 1; + + if (new == NULL) + r.status = VAROBJ_NOT_IN_SCOPE; + r.value_installed = 1; + + if (r.status == VAROBJ_NOT_IN_SCOPE) + { + if (r.type_changed || r.changed) + VEC_safe_push (varobj_update_result, result, &r); + return result; + } + + VEC_safe_push (varobj_update_result, stack, &r); } else - cv = *changelist; - - /* Copy from result stack to list */ - vleft = changed; - *cv = vpop (&result); - while ((*cv != NULL) && (vleft > 0)) { - vleft--; - cv++; - *cv = vpop (&result); + varobj_update_result r = {0}; + r.varobj = *varp; + VEC_safe_push (varobj_update_result, stack, &r); } - if (vleft) - warning (_("varobj_update: assertion failed - vleft <> 0")); - if (changed > 1) + /* Walk through the children, reconstructing them all. */ + while (!VEC_empty (varobj_update_result, stack)) { - /* Now we revert the order. */ - for (i = 0; i < changed; i++) - *(*changelist + i) = *(templist + changed - 1 - i); - *(*changelist + changed) = NULL; + varobj_update_result r = *(VEC_last (varobj_update_result, stack)); + struct varobj *v = r.varobj; + + VEC_pop (varobj_update_result, stack); + + /* Update this variable, unless it's a root, which is already + updated. */ + if (!r.value_installed) + { + new = value_of_child (v->parent, v->index); + if (install_new_value (v, new, 0 /* type not changed */)) + { + r.changed = 1; + v->updated = 0; + } + } + + /* We probably should not get children of a varobj that has a + pretty-printer, but for which -var-list-children was never + invoked. */ + if (v->pretty_printer) + { + VEC (varobj_p) *changed = 0, *new = 0, *unchanged = 0; + int i, children_changed = 0; + + 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, 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, &unchanged, + &children_changed, 1, + v->from, v->to)) + { + if (children_changed || new) + { + r.children_changed = 1; + r.new = new; + } + /* Push in 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, changed) - 1; i >= 0; --i) + { + varobj_p tmp = VEC_index (varobj_p, changed, i); + varobj_update_result r = {0}; + r.varobj = tmp; + r.changed = 1; + r.value_installed = 1; + VEC_safe_push (varobj_update_result, stack, &r); + } + for (i = VEC_length (varobj_p, unchanged) - 1; i >= 0; --i) + { + varobj_p tmp = VEC_index (varobj_p, unchanged, i); + if (!tmp->frozen) + { + varobj_update_result r = {0}; + r.varobj = 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; + } + } + + /* 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) + { + varobj_p c = VEC_index (varobj_p, v->children, i); + /* Child may be NULL if explicitly deleted by -var-delete. */ + if (c != NULL && !c->frozen) + { + varobj_update_result r = {0}; + r.varobj = c; + VEC_safe_push (varobj_update_result, stack, &r); + } + } + + if (r.changed || r.type_changed) + VEC_safe_push (varobj_update_result, result, &r); } - /* Restore selected frame */ - fi = frame_find_by_id (old_fid); - if (fi) - select_frame (fi); + VEC_free (varobj_update_result, stack); - if (type_changed) - return -2; - else - return changed; + return result; } @@ -1073,18 +1903,19 @@ delete_variable_1 (struct cpstack **resultp, int *delcountp, 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 (!child) + continue; 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) @@ -1106,7 +1937,7 @@ delete_variable_1 (struct cpstack **resultp, int *delcountp, 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) @@ -1145,7 +1976,7 @@ install_variable (struct varobj *var) *(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) @@ -1153,7 +1984,6 @@ install_variable (struct varobj *var) else var->root->next = rootlist; rootlist = var->root; - rootcount++; } return 1; /* OK */ @@ -1204,7 +2034,7 @@ uninstall_variable (struct varobj *var) 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) @@ -1230,30 +2060,21 @@ uninstall_variable (struct varobj *var) else prer->next = cr->next; } - rootcount--; } } -/* Does a child with the name NAME exist in VAR? If so, return its data. - If not, return NULL. */ +/* Create and install a child of the parent of the given name */ static struct varobj * -child_exists (struct varobj *var, char *name) +create_child (struct varobj *parent, int index, 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; + return create_child_with_value (parent, index, name, + value_of_child (parent, index)); } -/* Create and install a child of the parent of the given name */ static struct varobj * -create_child (struct varobj *parent, int index, char *name) +create_child_with_value (struct varobj *parent, int index, const char *name, + struct value *value) { struct varobj *child; char *childs_name; @@ -1261,64 +2082,28 @@ create_child (struct varobj *parent, int index, char *name) child = new_variable (); /* name is allocated by name_of_child */ - child->name = name; + /* FIXME: xstrdup should not be here. */ + child->name = xstrdup (name); child->index = index; - child->value = value_of_child (parent, index); - if ((!CPLUS_FAKE_CHILD (child) && child->value == NULL) || parent->error) - child->error = 1; child->parent = parent; child->root = parent->root; childs_name = xstrprintf ("%s.%s", parent->obj_name, name); child->obj_name = childs_name; install_variable (child); - /* Save a pointer to this child in the parent */ - save_child_in_parent (parent, child); - - /* Note the type of this child */ - child->type = type_of_child (child); - - 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; + /* Compute the type of the child. Must do this before + calling install_new_value. */ + if (value != NULL) + /* If the child had no evaluation errors, var->value + will be non-NULL and contain a valid type. */ + child->type = value_type (value); else - prev->next = vc->next; + /* Otherwise, we must compute the type. */ + child->type = (*child->root->lang->type_of_child) (child->parent, + child->index); + install_new_value (child, value, 1); + return child; } @@ -1334,17 +2119,27 @@ new_variable (void) var = (struct varobj *) xmalloc (sizeof (struct varobj)); var->name = NULL; + var->path_expr = NULL; var->obj_name = NULL; 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; + 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; } @@ -1359,8 +2154,9 @@ new_root_variable (void) var->root->exp = NULL; var->root->valid_block = NULL; var->root->frame = null_frame_id; - var->root->use_selected_frame = 0; + var->root->floating = 0; var->root->rootvar = NULL; + var->root->is_valid = 1; return var; } @@ -1369,15 +2165,31 @@ new_root_variable (void) static void free_variable (struct varobj *var) { +#if HAVE_PYTHON + if (var->pretty_printer) + { + struct cleanup *cleanup = varobj_ensure_python_env (var); + Py_XDECREF (var->constructor); + Py_XDECREF (var->pretty_printer); + Py_XDECREF (var->child_iter); + Py_XDECREF (var->saved_item); + do_cleanups (cleanup); + } +#endif + + value_free (var->value); + /* 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->exp); xfree (var->root); } xfree (var->name); xfree (var->obj_name); + xfree (var->print_value); + xfree (var->path_expr); xfree (var); } @@ -1410,18 +2222,34 @@ get_type (struct varobj *var) return type; } -/* This returns the type of the variable, dereferencing pointers, too. */ +/* Return the type of the value that's stored in VAR, + or that would have being stored there if the + value were accessible. + + This differs from VAR->type in that VAR->type is always + the true type of the expession in the source language. + The return value of this function is the type we're + actually storing in varobj, and using for displaying + the values and for comparing previous and new values. + + For example, top-level references are always stripped. */ static struct type * -get_type_deref (struct varobj *var) +get_value_type (struct varobj *var) { struct type *type; - type = get_type (var); + if (var->value) + type = value_type (var->value); + else + type = var->type; + + type = check_typedef (type); - if (type != NULL && (TYPE_CODE (type) == TYPE_CODE_PTR - || TYPE_CODE (type) == TYPE_CODE_REF)) + if (TYPE_CODE (type) == TYPE_CODE_REF) type = get_target_type (type); + type = check_typedef (type); + return type; } @@ -1451,72 +2279,6 @@ variable_default_display (struct varobj *var) return FORMAT_NATURAL; } -/* This function is similar to GDB's value_contents_equal, except that - this one is "safe"; it never longjmps. It determines if the VAL1's - value is the same as VAL2. If for some reason the value of VAR2 - can't be established, *ERROR2 is set to non-zero. */ - -static int -my_value_equal (struct value *val1, struct value *volatile val2, int *error2) -{ - volatile struct gdb_exception except; - - /* As a special case, if both are null, we say they're equal. */ - if (val1 == NULL && val2 == NULL) - return 1; - else if (val1 == NULL || val2 == NULL) - return 0; - - /* The contents of VAL1 are supposed to be known. */ - gdb_assert (!value_lazy (val1)); - - /* Make sure we also know the contents of VAL2. */ - val2 = coerce_array (val2); - TRY_CATCH (except, RETURN_MASK_ERROR) - { - if (value_lazy (val2)) - value_fetch_lazy (val2); - } - if (except.reason < 0) - { - *error2 = 1; - return 0; - } - gdb_assert (!value_lazy (val2)); - - return value_contents_equal (val1, val2); -} - -/* 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) @@ -1601,16 +2363,15 @@ name_of_child (struct varobj *var, int index) return (*var->root->lang->name_of_child) (var, index); } -/* What is the ``struct value *'' 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. */ +/* What is the ``struct value *'' of the root variable VAR? + For floating variable object, evaluation can get us a value + of different type from what is stored in varobj already. In + that case: + - *type_changed will be set to 1 + - old varobj will be freed, and new one will be + created, with the same name. + - *var_handle will be set to the new varobj + Otherwise, *type_changed will be set to 0. */ static struct value * value_of_root (struct varobj **var_handle, int *type_changed) { @@ -1624,43 +2385,51 @@ value_of_root (struct varobj **var_handle, int *type_changed) /* 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) + if (var->root->floating) { 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; } + old_type = varobj_get_type (var); 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; } else { - if (*type_changed) - { - tmp_var->obj_name = - savestring (var->obj_name, strlen (var->obj_name)); - varobj_delete (var, NULL, 0); - } - else - { - tmp_var->obj_name = varobj_gen_name (); - } + 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); *var_handle = tmp_var; var = *var_handle; *type_changed = 1; } + xfree (old_type); + xfree (new_type); } else { @@ -1678,53 +2447,164 @@ value_of_child (struct varobj *parent, int index) value = (*parent->root->lang->value_of_child) (parent, index); - /* If we're being lazy, fetch the real value of the variable. */ - if (value != NULL && value_lazy (value)) - { - /* If we fail to fetch the value of the child, return - NULL so that callers notice that we're leaving an - error message. */ - if (!gdb_value_fetch_lazy (value)) - value = NULL; - } - return value; } -/* What is the type of VAR? */ -static struct type * -type_of_child (struct varobj *var) +/* GDB already has a command called "value_of_variable". Sigh. */ +static char * +my_value_of_variable (struct varobj *var, enum varobj_display_formats format) { - - /* If the child had no evaluation errors, var->value - will be non-NULL and contain a valid type. */ - if (var->value != NULL) - return value_type (var->value); - - /* Otherwise, we must compute the type. */ - return (*var->root->lang->type_of_child) (var->parent, var->index); -} - -/* Is this variable editable? Use the variable's type to make - this determination. */ -static int -variable_editable (struct varobj *var) -{ - return (*var->root->lang->variable_editable) (var); + if (var->root->is_valid) + { + 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; } -/* GDB already has a command called "value_of_variable". Sigh. */ static char * -my_value_of_variable (struct varobj *var) +value_get_print_value (struct value *value, enum varobj_display_formats format, + struct varobj *var) +{ + struct ui_file *stb; + struct cleanup *old_chain; + gdb_byte *thevalue = NULL; + struct value_print_options opts; + struct type *type = NULL; + long len = 0; + char *encoding = NULL; + struct gdbarch *gdbarch = NULL; + + if (value == NULL) + return NULL; + + gdbarch = get_type_arch (value_type (value)); +#if HAVE_PYTHON + { + struct cleanup *back_to = varobj_ensure_python_env (var); + PyObject *value_formatter = var->pretty_printer; + + if (value_formatter) + { + /* 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 ("{...}"); + + if (PyObject_HasAttr (value_formatter, gdbpy_to_string_cst)) + { + 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) + { + if (gdbpy_is_lazy_string (output)) + { + thevalue = gdbpy_extract_lazy_string (output, &type, + &len, &encoding); + string_print = 1; + } + else + { + 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); + type = builtin_type (gdbarch)->builtin_char; + Py_DECREF (py_str); + } + } + Py_DECREF (output); + } + if (thevalue && !string_print) + { + do_cleanups (back_to); + xfree (encoding); + return thevalue; + } + if (replacement) + value = replacement; + } + } + do_cleanups (back_to); + } +#endif + + stb = mem_fileopen (); + old_chain = make_cleanup_ui_file_delete (stb); + + get_formatted_print_options (&opts, format_code[(int) format]); + opts.deref_ref = 0; + opts.raw = 1; + if (thevalue) + { + make_cleanup (xfree, thevalue); + make_cleanup (xfree, encoding); + LA_PRINT_STRING (stb, type, thevalue, len, encoding, 0, &opts); + } + else + common_val_print (value, stb, 0, &opts, current_language); + thevalue = ui_file_xstrdup (stb, NULL); + + do_cleanups (old_chain); + return thevalue; +} + +int +varobj_editable_p (struct varobj *var) { - return (*var->root->lang->value_of_variable) (var); + struct type *type; + struct value *value; + + if (!(var->root->is_valid && var->value && VALUE_LVAL (var->value))) + return 0; + + type = get_value_type (var); + + switch (TYPE_CODE (type)) + { + case TYPE_CODE_STRUCT: + case TYPE_CODE_UNION: + case TYPE_CODE_ARRAY: + case TYPE_CODE_FUNC: + case TYPE_CODE_METHOD: + return 0; + break; + + default: + return 1; + break; + } } -/* Is VAR something that can change? Depending on language, - some variable's values never change. For example, - struct and unions never change values. */ +/* 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 + changes of such values. This makes sense for structures + (since the changes in children values will be reported separately), + or for artifical objects (like 'public' pseudo-field in C++). + + 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; @@ -1732,7 +2612,7 @@ type_changeable (struct varobj *var) if (CPLUS_FAKE_CHILD (var)) return 0; - type = get_type (var); + type = get_value_type (var); switch (TYPE_CODE (type)) { @@ -1749,26 +2629,95 @@ type_changeable (struct varobj *var) 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. + This includes dereferencing top-level references + to all types and dereferencing pointers to + structures. + + Both TYPE and *TYPE should be non-null. VALUE + can be null if we want to only translate type. + *VALUE can be null as well -- if the parent + value is not known. + + If WAS_PTR is not NULL, set *WAS_PTR to 0 or 1 + depending on whether pointer was dereferenced + in this function. */ +static void +adjust_value_for_child_access (struct value **value, + struct type **type, + int *was_ptr) +{ + gdb_assert (type && *type); + + if (was_ptr) + *was_ptr = 0; + + *type = check_typedef (*type); + + /* The type of value stored in varobj, that is passed + to us, is already supposed to be + reference-stripped. */ + + gdb_assert (TYPE_CODE (*type) != TYPE_CODE_REF); + + /* Pointers to structures are treated just like + structures when accessing children. Don't + dererences pointers to other types. */ + 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 && *value) + { + int success = gdb_value_ind (*value, value); + if (!success) + *value = NULL; + } + *type = target_type; + if (was_ptr) + *was_ptr = 1; + } + } + + /* The 'get_target_type' function calls check_typedef on + result, so we can immediately check type code. No + need to call check_typedef here. */ +} + /* C */ static int c_number_of_children (struct varobj *var) { - struct type *type; + struct type *type = get_value_type (var); + int children = 0; struct type *target; - int children; - type = get_type (var); + adjust_value_for_child_access (NULL, &type, NULL); target = get_target_type (type); - children = 0; switch (TYPE_CODE (type)) { 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 - children = -1; + /* If we don't know how many elements there are, don't display + any. */ + children = 0; break; case TYPE_CODE_STRUCT: @@ -1777,30 +2726,19 @@ c_number_of_children (struct varobj *var) break; case TYPE_CODE_PTR: - /* This is where things get compilcated. 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. - We also don't dereference void* as we don't know what to show. + /* The type here is a pointer to non-struct. Typically, pointers + have one child, except for function ptrs, which have no children, + and except for 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 properly identify it: char* has TYPE_CODE == TYPE_CODE_INT and TYPE_NAME == "char" */ - - switch (TYPE_CODE (target)) - { - case TYPE_CODE_STRUCT: - case TYPE_CODE_UNION: - children = TYPE_NFIELDS (target); - break; - - case TYPE_CODE_FUNC: - case TYPE_CODE_VOID: - children = 0; - break; - - default: - children = 1; - } + if (TYPE_CODE (target) == TYPE_CODE_FUNC + || TYPE_CODE (target) == TYPE_CODE_VOID) + children = 0; + else + children = 1; break; default: @@ -1814,250 +2752,282 @@ c_number_of_children (struct varobj *var) static char * c_name_of_variable (struct varobj *parent) { - return savestring (parent->name, strlen (parent->name)); + return xstrdup (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 (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); + } + 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, + char **cfull_expression) +{ + struct value *value = parent->value; + struct type *type = get_value_type (parent); + char *parent_expression = NULL; + int was_ptr; + + if (cname) + *cname = NULL; + if (cvalue) + *cvalue = NULL; + if (ctype) + *ctype = NULL; + if (cfull_expression) + { + *cfull_expression = NULL; + parent_expression = varobj_get_path_expr (parent); + } + adjust_value_for_child_access (&value, &type, &was_ptr); + switch (TYPE_CODE (type)) { case TYPE_CODE_ARRAY: - name = xstrprintf ("%d", index - + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type))); + if (cname) + *cname = xstrdup (int_string (index + + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)), + 10, 1, 0, 0)); + + if (cvalue && value) + { + int real_index = index + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)); + gdb_value_subscript (value, real_index, cvalue); + } + + if (ctype) + *ctype = get_target_type (type); + + if (cfull_expression) + *cfull_expression = + xstrprintf ("(%s)[%s]", parent_expression, + int_string (index + + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)), + 10, 1, 0, 0)); + + break; case TYPE_CODE_STRUCT: case TYPE_CODE_UNION: - string = TYPE_FIELD_NAME (type, index); - name = savestring (string, strlen (string)); + if (cname) + *cname = xstrdup (TYPE_FIELD_NAME (type, index)); + + 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); + + if (cfull_expression) + { + char *join = was_ptr ? "->" : "."; + *cfull_expression = xstrprintf ("(%s)%s%s", parent_expression, join, + TYPE_FIELD_NAME (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) + { + int success = gdb_value_ind (value, cvalue); + if (!success) + *cvalue = NULL; } + + /* Don't use get_target_type because it calls + check_typedef and here, we want to show the true + declared type of the variable. */ + if (ctype) + *ctype = TYPE_TARGET_TYPE (type); + + if (cfull_expression) + *cfull_expression = xstrprintf ("*(%s)", parent_expression); + break; default: /* This should not happen */ - name = xstrdup ("???"); + if (cname) + *cname = xstrdup ("???"); + if (cfull_expression) + *cfull_expression = 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, NULL); return name; } +static char * +c_path_expr_of_child (struct varobj *child) +{ + c_describe_child (child->parent, child->index, NULL, NULL, NULL, + &child->path_expr); + return child->path_expr; +} + +/* If frame associated with VAR can be found, switch + to it and return 1. Otherwise, return 0. */ +static int +check_scope (struct varobj *var) +{ + struct frame_info *fi; + int scope; + + fi = frame_find_by_id (var->root->frame); + scope = fi != NULL; + + if (fi) + { + CORE_ADDR pc = get_frame_pc (fi); + if (pc < BLOCK_START (var->root->valid_block) || + pc >= BLOCK_END (var->root->valid_block)) + scope = 0; + else + select_frame (fi); + } + return scope; +} + 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; - + int within_scope = 0; + struct cleanup *back_to; + /* Only root variables can be updated... */ - if (var->root->rootvar != var) + if (!is_root_p (var)) /* Not a root var */ return NULL; + back_to = make_cleanup_restore_current_thread (); /* Determine whether the variable is still around. */ - if (var->root->valid_block == NULL) + if (var->root->valid_block == NULL || var->root->floating) within_scope = 1; + else if (var->root->thread_id == 0) + { + /* The program was single-threaded when the variable object was + created. Technically, it's possible that the program became + multi-threaded since then, but we don't support such + scenario yet. */ + within_scope = check_scope (var); + } else { - reinit_frame_cache (); - fi = frame_find_by_id (var->root->frame); - within_scope = fi != NULL; - /* FIXME: select_frame could fail */ - if (within_scope) - select_frame (fi); + ptid_t ptid = thread_id_to_pid (var->root->thread_id); + if (in_thread_list (ptid)) + { + switch_to_thread (ptid); + within_scope = check_scope (var); + } } 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 */ - 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... */ - if (!gdb_value_fetch_lazy (new_val)) - var->error = 1; - else - var->error = 0; - } - } - else - var->error = 1; - - release_value (new_val); + expression fails we want to just return NULL. */ + gdb_evaluate_expression (var->root->exp, &new_val); return new_val; } + do_cleanups (back_to); + return NULL; } 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; + struct value *value = NULL; + c_describe_child (parent, index, NULL, &value, NULL, NULL); - 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; - } - } - - 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, NULL); return type; } -static int -c_variable_editable (struct varobj *var) -{ - switch (TYPE_CODE (get_type (var))) - { - case TYPE_CODE_STRUCT: - case TYPE_CODE_UNION: - case TYPE_CODE_ARRAY: - case TYPE_CODE_FUNC: - case TYPE_CODE_MEMBER: - case TYPE_CODE_METHOD: - return 0; - break; - - default: - return 1; - break; - } -} - static char * -c_value_of_variable (struct varobj *var) -{ - /* BOGUS: if val_print sees a struct/class, it will print out its - children instead of "{...}" */ +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 + catch that case explicitly. */ + struct type *type = get_type (var); + + /* If we have a custom formatter, return whatever string it has + produced. */ + if (var->pretty_printer && var->print_value) + return xstrdup (var->print_value); + + /* Strip top-level references. */ + while (TYPE_CODE (type) == TYPE_CODE_REF) + type = check_typedef (TYPE_TARGET_TYPE (type)); - switch (TYPE_CODE (get_type (var))) + switch (TYPE_CODE (type)) { case TYPE_CODE_STRUCT: case TYPE_CODE_UNION: @@ -2083,19 +3053,22 @@ c_value_of_variable (struct varobj *var) } else { - long dummy; - struct ui_file *stb = mem_fileopen (); - struct cleanup *old_chain = make_cleanup_ui_file_delete (stb); - char *thevalue; - - if (value_lazy (var->value)) - gdb_value_fetch_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; - } + 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)); + + /* 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, var); + } } } } @@ -2114,7 +3087,8 @@ cplus_number_of_children (struct varobj *var) if (!CPLUS_FAKE_CHILD (var)) { - type = get_type_deref (var); + type = get_value_type (var); + adjust_value_for_child_access (NULL, &type, NULL); if (((TYPE_CODE (type)) == TYPE_CODE_STRUCT) || ((TYPE_CODE (type)) == TYPE_CODE_UNION)) @@ -2140,7 +3114,8 @@ cplus_number_of_children (struct varobj *var) { int kids[3]; - type = get_type_deref (var->parent); + type = get_value_type (var->parent); + adjust_value_for_child_access (NULL, &type, NULL); cplus_class_num_children (type, kids); if (strcmp (var->name, "public") == 0) @@ -2164,16 +3139,21 @@ cplus_number_of_children (struct varobj *var) static void cplus_class_num_children (struct type *type, int children[3]) { - int i; + int i, vptr_fieldno; + struct type *basetype = NULL; children[v_public] = 0; children[v_private] = 0; children[v_protected] = 0; + vptr_fieldno = get_vptr_fieldno (type, &basetype); for (i = TYPE_N_BASECLASSES (type); i < TYPE_NFIELDS (type); i++) { - /* If we have a virtual table pointer, omit it. */ - if (TYPE_VPTR_BASETYPE (type) == type && TYPE_VPTR_FIELDNO (type) == i) + /* If we have a virtual table pointer, omit it. Even if virtual + table pointers are not specifically marked in the debug info, + they should be artificial. */ + if ((type == basetype && i == vptr_fieldno) + || TYPE_FIELD_ARTIFICIAL (type, i)) continue; if (TYPE_FIELD_PROTECTED (type, i)) @@ -2191,25 +3171,65 @@ cplus_name_of_variable (struct varobj *parent) return c_name_of_variable (parent); } -static char * -cplus_name_of_child (struct varobj *parent, int index) +enum accessibility { private_field, protected_field, public_field }; + +/* Check if field INDEX of TYPE has the specified accessibility. + Return 0 if so and 1 otherwise. */ +static int +match_accessibility (struct type *type, int index, enum accessibility acc) { - char *name; + if (acc == private_field && TYPE_FIELD_PRIVATE (type, index)) + return 1; + else if (acc == protected_field && TYPE_FIELD_PROTECTED (type, index)) + return 1; + else if (acc == public_field && !TYPE_FIELD_PRIVATE (type, index) + && !TYPE_FIELD_PROTECTED (type, index)) + return 1; + else + return 0; +} + +static void +cplus_describe_child (struct varobj *parent, int index, + char **cname, struct value **cvalue, struct type **ctype, + char **cfull_expression) +{ + char *name = NULL; + struct value *value; struct type *type; + int was_ptr; + char *parent_expression = NULL; + + if (cname) + *cname = NULL; + if (cvalue) + *cvalue = NULL; + if (ctype) + *ctype = NULL; + if (cfull_expression) + *cfull_expression = NULL; if (CPLUS_FAKE_CHILD (parent)) { - /* Looking for children of public, private, or protected. */ - type = get_type_deref (parent->parent); + value = parent->parent->value; + type = get_value_type (parent->parent); + if (cfull_expression) + parent_expression = varobj_get_path_expr (parent->parent); } else - type = get_type_deref (parent); + { + value = parent->value; + type = get_value_type (parent); + if (cfull_expression) + parent_expression = varobj_get_path_expr (parent); + } - name = NULL; - switch (TYPE_CODE (type)) + adjust_value_for_child_access (&value, &type, &was_ptr); + + if (TYPE_CODE (type) == TYPE_CODE_STRUCT + || TYPE_CODE (type) == TYPE_CODE_UNION) { - case TYPE_CODE_STRUCT: - case TYPE_CODE_UNION: + char *join = was_ptr ? "->" : "."; if (CPLUS_FAKE_CHILD (parent)) { /* The fields of the class type are ordered as they @@ -2219,56 +3239,77 @@ cplus_name_of_child (struct varobj *parent, int index) have the access control we are looking for to properly find the indexed field. */ int type_index = TYPE_N_BASECLASSES (type); + enum accessibility acc = public_field; + int vptr_fieldno; + struct type *basetype = NULL; + + vptr_fieldno = get_vptr_fieldno (type, &basetype); if (strcmp (parent->name, "private") == 0) - { - while (index >= 0) - { - if (TYPE_VPTR_BASETYPE (type) == type - && type_index == TYPE_VPTR_FIELDNO (type)) - ; /* ignore vptr */ - else if (TYPE_FIELD_PRIVATE (type, type_index)) - --index; - ++type_index; - } - --type_index; - } + acc = private_field; else if (strcmp (parent->name, "protected") == 0) + acc = protected_field; + + while (index >= 0) { - while (index >= 0) - { - if (TYPE_VPTR_BASETYPE (type) == type - && type_index == TYPE_VPTR_FIELDNO (type)) - ; /* ignore vptr */ - else if (TYPE_FIELD_PROTECTED (type, type_index)) + if ((type == basetype && type_index == vptr_fieldno) + || TYPE_FIELD_ARTIFICIAL (type, type_index)) + ; /* ignore vptr */ + else if (match_accessibility (type, type_index, acc)) --index; ++type_index; - } - --type_index; } - else + --type_index; + + if (cname) + *cname = xstrdup (TYPE_FIELD_NAME (type, type_index)); + + if (cvalue && value) + *cvalue = value_struct_element_index (value, type_index); + + if (ctype) + *ctype = TYPE_FIELD_TYPE (type, type_index); + + if (cfull_expression) + *cfull_expression = xstrprintf ("((%s)%s%s)", parent_expression, + join, + TYPE_FIELD_NAME (type, type_index)); + } + else if (index < TYPE_N_BASECLASSES (type)) + { + /* This is a baseclass. */ + if (cname) + *cname = xstrdup (TYPE_FIELD_NAME (type, index)); + + if (cvalue && value) + *cvalue = value_cast (TYPE_FIELD_TYPE (type, index), value); + + if (ctype) { - while (index >= 0) - { - if (TYPE_VPTR_BASETYPE (type) == type - && type_index == TYPE_VPTR_FIELDNO (type)) - ; /* ignore vptr */ - else if (!TYPE_FIELD_PRIVATE (type, type_index) && - !TYPE_FIELD_PROTECTED (type, type_index)) - --index; - ++type_index; - } - --type_index; + *ctype = TYPE_FIELD_TYPE (type, index); } - name = TYPE_FIELD_NAME (type, type_index); + if (cfull_expression) + { + char *ptr = was_ptr ? "*" : ""; + /* Cast the parent to the base' type. Note that in gdb, + expression like + (Base1)d + will create an lvalue, for all appearences, so we don't + need to use more fancy: + *(Base1*)(&d) + construct. */ + *cfull_expression = xstrprintf ("(%s(%s%s) %s)", + ptr, + TYPE_FIELD_NAME (type, index), + ptr, + parent_expression); + } } - else if (index < TYPE_N_BASECLASSES (type)) - /* We are looking up the name of a base class */ - name = TYPE_FIELD_NAME (type, index); else { + char *access = NULL; int children[3]; - cplus_class_num_children(type, children); + cplus_class_num_children (type, children); /* Everything beyond the baseclasses can only be "public", "private", or "protected" @@ -2280,49 +3321,61 @@ cplus_name_of_child (struct varobj *parent, int index) { case 0: if (children[v_public] > 0) - name = "public"; + access = "public"; else if (children[v_private] > 0) - name = "private"; + access = "private"; else - name = "protected"; + access = "protected"; break; case 1: if (children[v_public] > 0) { if (children[v_private] > 0) - name = "private"; + access = "private"; else - name = "protected"; + access = "protected"; } else if (children[v_private] > 0) - name = "protected"; + access = "protected"; break; case 2: /* Must be protected */ - name = "protected"; + access = "protected"; break; default: /* error! */ break; } - } - break; - default: - break; - } + gdb_assert (access); + if (cname) + *cname = xstrdup (access); - if (name == NULL) - return c_name_of_child (parent, index); + /* Value and type and full expression are null here. */ + } + } else { - if (name != NULL) - name = savestring (name, strlen (name)); - } + c_describe_child (parent, index, cname, cvalue, ctype, cfull_expression); + } +} +static char * +cplus_name_of_child (struct varobj *parent, int index) +{ + char *name = NULL; + cplus_describe_child (parent, index, &name, NULL, NULL, NULL); return name; } +static char * +cplus_path_expr_of_child (struct varobj *child) +{ + cplus_describe_child (child->parent, child->index, NULL, NULL, NULL, + &child->path_expr); + return child->path_expr; +} + static struct value * cplus_value_of_root (struct varobj **var_handle) { @@ -2332,131 +3385,21 @@ cplus_value_of_root (struct varobj **var_handle) static struct value * cplus_value_of_child (struct varobj *parent, int index) { - struct type *type; - struct value *value; - - if (CPLUS_FAKE_CHILD (parent)) - type = get_type_deref (parent->parent); - else - type = get_type_deref (parent); - - value = NULL; - - if (((TYPE_CODE (type)) == TYPE_CODE_STRUCT) || - ((TYPE_CODE (type)) == TYPE_CODE_UNION)) - { - if (CPLUS_FAKE_CHILD (parent)) - { - char *name; - struct value *temp = parent->parent->value; - - if (temp == NULL) - return NULL; - - name = name_of_child (parent, index); - gdb_value_struct_elt (NULL, &value, &temp, NULL, name, NULL, - "cplus_structure"); - if (value != NULL) - release_value (value); - - xfree (name); - } - else if (index >= TYPE_N_BASECLASSES (type)) - { - /* public, private, or protected */ - return NULL; - } - else - { - /* Baseclass */ - if (parent->value != NULL) - { - struct value *temp = NULL; - - if (TYPE_CODE (value_type (parent->value)) == TYPE_CODE_PTR - || TYPE_CODE (value_type (parent->value)) == TYPE_CODE_REF) - { - if (!gdb_value_ind (parent->value, &temp)) - return NULL; - } - else - temp = parent->value; - - if (temp != NULL) - { - value = value_cast (TYPE_FIELD_TYPE (type, index), temp); - release_value (value); - } - else - { - /* We failed to evaluate the parent's value, so don't even - bother trying to evaluate this child. */ - return NULL; - } - } - } - } - - if (value == NULL) - return c_value_of_child (parent, index); - + struct value *value = NULL; + cplus_describe_child (parent, index, NULL, &value, NULL, NULL); return value; } static struct type * cplus_type_of_child (struct varobj *parent, int index) { - struct type *type, *t; - - if (CPLUS_FAKE_CHILD (parent)) - { - /* Looking for the type of a child of public, private, or protected. */ - t = get_type_deref (parent->parent); - } - else - t = get_type_deref (parent); - - type = NULL; - switch (TYPE_CODE (t)) - { - case TYPE_CODE_STRUCT: - case TYPE_CODE_UNION: - if (CPLUS_FAKE_CHILD (parent)) - { - char *name = cplus_name_of_child (parent, index); - type = lookup_struct_elt_type (t, name, 0); - xfree (name); - } - else if (index < TYPE_N_BASECLASSES (t)) - type = TYPE_FIELD_TYPE (t, index); - else - { - /* special */ - return NULL; - } - break; - - default: - break; - } - - if (type == NULL) - return c_type_of_child (parent, index); - + struct type *type = NULL; + cplus_describe_child (parent, index, NULL, NULL, &type, NULL); return type; } -static int -cplus_variable_editable (struct varobj *var) -{ - if (CPLUS_FAKE_CHILD (var)) - return 0; - - return c_variable_editable (var); -} - 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 @@ -2464,7 +3407,7 @@ cplus_value_of_variable (struct varobj *var) if (CPLUS_FAKE_CHILD (var)) return xstrdup (""); - return c_value_of_variable (var); + return c_value_of_variable (var, format); } /* Java */ @@ -2514,6 +3457,12 @@ java_name_of_child (struct varobj *parent, int index) return name; } +static char * +java_path_expr_of_child (struct varobj *child) +{ + return NULL; +} + static struct value * java_value_of_root (struct varobj **var_handle) { @@ -2532,16 +3481,28 @@ java_type_of_child (struct varobj *parent, int index) return cplus_type_of_child (parent, index); } -static int -java_variable_editable (struct varobj *var) +static char * +java_value_of_variable (struct varobj *var, enum varobj_display_formats format) { - return cplus_variable_editable (var); + return cplus_value_of_variable (var, format); } -static char * -java_value_of_variable (struct varobj *var) +/* Iterate all the existing _root_ VAROBJs and call the FUNC callback for them + with an arbitrary caller supplied DATA pointer. */ + +void +all_root_varobjs (void (*func) (struct varobj *var, void *data), void *data) { - return cplus_value_of_variable (var); + struct varobj_root *var_root, *var_root_next; + + /* Iterate "safely" - handle if the callee deletes its passed VAROBJ. */ + + for (var_root = rootlist; var_root != NULL; var_root = var_root_next) + { + var_root_next = var_root->next; + + (*func) (var_root->rootvar, data); + } } extern void _initialize_varobj (void); @@ -2562,3 +3523,46 @@ When non-zero, varobj debugging is enabled."), show_varobjdebug, &setlist, &showlist); } + +/* Invalidate varobj VAR if it is tied to locals and re-create it if it is + defined on globals. It is a helper for varobj_invalidate. */ + +static void +varobj_invalidate_iter (struct varobj *var, void *unused) +{ + /* Floating varobjs are reparsed on each stop, so we don't care if the + presently parsed expression refers to something that's gone. */ + if (var->root->floating) + return; + + /* global var must be re-evaluated. */ + if (var->root->valid_block == NULL) + { + struct varobj *tmp_var; + + /* Try to create a varobj with same expression. If we succeed + replace the old varobj, otherwise invalidate it. */ + tmp_var = varobj_create (NULL, var->name, (CORE_ADDR) 0, + USE_CURRENT_FRAME); + if (tmp_var != NULL) + { + tmp_var->obj_name = xstrdup (var->obj_name); + varobj_delete (var, NULL, 0); + install_variable (tmp_var); + } + else + var->root->is_valid = 0; + } + else /* locals must be invalidated. */ + var->root->is_valid = 0; +} + +/* Invalidate the varobjs that are tied to locals and re-create the ones that + are defined on globals. + Invalidated varobjs will be always printed in_scope="invalid". */ + +void +varobj_invalidate (void) +{ + all_root_varobjs (varobj_invalidate_iter, NULL); +}