#include "vec.h"
#include "gdbthread.h"
#include "inferior.h"
-#include "typeprint.h"
#if HAVE_PYTHON
#include "python/python.h"
static char *value_get_print_value (struct value *value,
enum varobj_display_formats format,
- PyObject *value_formatter);
+ struct varobj *var);
static int varobj_value_is_changeable_p (struct varobj *var);
/* 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 */
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) */
/* Return the full FRAME which corresponds to the given CORE_ADDR
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 (innermost_block && 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);
var->root->thread_id = pid_to_thread_id (inferior_ptid);
old_fi = get_selected_frame (NULL);
&& var->value && !value_lazy (var->value))
{
xfree (var->print_value);
- var->print_value = value_get_print_value (var->value, var->format,
- var->pretty_printer);
+ var->print_value = value_get_print_value (var->value, var->format, var);
}
return var->format;
char *result = NULL;
#if HAVE_PYTHON
- PyGILState_STATE state = PyGILState_Ensure ();
+ struct cleanup *back_to = varobj_ensure_python_env (var);
+
if (var->pretty_printer)
result = gdbpy_get_display_hint (var->pretty_printer);
- PyGILState_Release (state);
+
+ do_cleanups (back_to);
#endif
return result;
int i;
int children_changed = 0;
PyObject *printer = var->pretty_printer;
- PyGILState_STATE state;
- state = PyGILState_Ensure ();
- back_to = make_cleanup_py_restore_gil (&state);
+ back_to = varobj_ensure_python_env (var);
*cchanged = 0;
if (!PyObject_HasAttr (printer, gdbpy_children_cst))
if (!PyArg_ParseTuple (item, "sO", &name, &py_v))
error (_("Invalid item from the child list"));
- if (PyObject_TypeCheck (py_v, &value_object_type))
- {
- /* If we just call convert_value_from_python for this type,
- we won't know who owns the result. For this one case we
- need to copy the resulting value. */
- v = value_object_to_value (py_v);
- v = value_copy (v);
- }
- else
- v = convert_value_from_python (py_v);
+ v = convert_value_from_python (py_v);
/* TODO: This assume the name of the i-th child never changes. */
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;
-
- /* Alloc (rootcount + 1) entries for the result */
- *varlist = xmalloc ((rootcount + 1) * sizeof (struct 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;
-
- if (mycount || (croot != NULL))
- warning
- ("varobj_list: assertion failed - wrong tally of root vars (%d:%d)",
- rootcount, mycount);
-
- return rootcount;
-}
-
/* 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
lazy -- if it is, the code above has decided that the value
should not be fetched. */
if (value && !value_lazy (value))
- print_value = value_get_print_value (value, var->format,
- 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
{
#if HAVE_PYTHON
struct cleanup *cleanup;
- PyGILState_STATE state;
PyObject *pretty_printer = NULL;
- state = PyGILState_Ensure ();
- cleanup = make_cleanup_py_restore_gil (&state);
+ cleanup = varobj_ensure_python_env (var);
if (var->value)
{
#if HAVE_PYTHON
PyObject *mainmod, *globals, *pretty_printer, *constructor;
struct cleanup *back_to, *value;
- PyGILState_STATE state;
-
- state = PyGILState_Ensure ();
- back_to = make_cleanup_py_restore_gil (&state);
+ back_to = varobj_ensure_python_env (var);
mainmod = PyImport_AddModule ("__main__");
globals = PyModule_GetDict (mainmod);
else
var->root->next = rootlist;
rootlist = var->root;
- rootcount++;
}
return 1; /* OK */
else
prer->next = cr->next;
}
- rootcount--;
}
}
static void
free_variable (struct varobj *var)
{
+#if HAVE_PYTHON
+ if (var->pretty_printer)
+ {
+ struct cleanup *cleanup = varobj_ensure_python_env (var);
+ Py_DECREF (var->pretty_printer);
+ do_cleanups (cleanup);
+ }
+#endif
+
value_free (var->value);
/* Free the expression if this is a root variable. */
xfree (var->root);
}
-#if HAVE_PYTHON
- {
- PyGILState_STATE state = PyGILState_Ensure ();
- Py_XDECREF (var->pretty_printer);
- PyGILState_Release (state);
- }
-#endif
-
xfree (var->name);
xfree (var->obj_name);
xfree (var->print_value);
static char *
value_get_print_value (struct value *value, enum varobj_display_formats format,
- PyObject *value_formatter)
+ struct varobj *var)
{
- long dummy;
struct ui_file *stb;
struct cleanup *old_chain;
- char *thevalue = NULL;
+ gdb_byte *thevalue = NULL;
struct value_print_options opts;
+ int len = 0;
if (value == NULL)
return NULL;
#if HAVE_PYTHON
{
- PyGILState_STATE state = PyGILState_Ensure ();
+ struct cleanup *back_to = varobj_ensure_python_env (var);
+ PyObject *value_formatter = var->pretty_printer;
+
if (value_formatter && 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)
xfree (hint);
}
- thevalue = apply_varobj_pretty_printer (value_formatter,
- &replacement);
+ output = apply_varobj_pretty_printer (value_formatter,
+ &replacement);
+ if (output)
+ {
+ 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);
+ Py_DECREF (py_str);
+ }
+ Py_DECREF (output);
+ }
if (thevalue && !string_print)
{
- PyGILState_Release (state);
+ do_cleanups (back_to);
return thevalue;
}
if (replacement)
value = replacement;
}
- PyGILState_Release (state);
+ do_cleanups (back_to);
}
#endif
opts.raw = 1;
if (thevalue)
{
+ struct gdbarch *gdbarch = get_type_arch (value_type (value));
make_cleanup (xfree, thevalue);
- LA_PRINT_STRING (stb, builtin_type (current_gdbarch)->builtin_char,
- (gdb_byte *) thevalue, strlen (thevalue),
- 0, &opts);
+ LA_PRINT_STRING (stb, builtin_type (gdbarch)->builtin_char,
+ thevalue, len, 0, &opts);
}
else
common_val_print (value, stb, 0, &opts, current_language);
- thevalue = ui_file_xstrdup (stb, &dummy);
+ thevalue = ui_file_xstrdup (stb, NULL);
do_cleanups (old_chain);
return thevalue;
if (format == var->format)
return xstrdup (var->print_value);
else
- return value_get_print_value (var->value, format,
- var->pretty_printer);
+ return value_get_print_value (var->value, format, var);
}
}
}
{
return cplus_value_of_variable (var, format);
}
+
+/* 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)
+{
+ 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);
+ }
+}
\f
extern void _initialize_varobj (void);
void
&setlist, &showlist);
}
-/* 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". */
+/* 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. */
-void
-varobj_invalidate (void)
+static void
+varobj_invalidate_iter (struct varobj *var, void *unused)
{
- struct varobj **all_rootvarobj;
- struct varobj **varp;
+ /* 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;
- if (varobj_list (&all_rootvarobj) > 0)
+ /* global var must be re-evaluated. */
+ if (var->root->valid_block == NULL)
{
- varp = all_rootvarobj;
- while (*varp != NULL)
- {
- /* Floating varobjs are reparsed on each stop, so we don't care if
- the presently parsed expression refers to something that's gone.
- */
- if ((*varp)->root->floating)
- continue;
-
- /* global var must be re-evaluated. */
- if ((*varp)->root->valid_block == NULL)
- {
- 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, (*varp)->name, (CORE_ADDR) 0,
- USE_CURRENT_FRAME);
- if (tmp_var != NULL)
- {
- tmp_var->obj_name = xstrdup ((*varp)->obj_name);
- varobj_delete (*varp, NULL, 0);
- install_variable (tmp_var);
- }
- else
- (*varp)->root->is_valid = 0;
- }
- else /* locals must be invalidated. */
- (*varp)->root->is_valid = 0;
+ struct varobj *tmp_var;
- varp++;
+ /* 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;
}
- xfree (all_rootvarobj);
- return;
+ 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);
}