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
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
{ "natural", "binary", "decimal", "hexadecimal", "octal", "zero-hexadecimal" };
/* True if we want to allow Python-based pretty-printing. */
{ "natural", "binary", "decimal", "hexadecimal", "octal", "zero-hexadecimal" };
/* True if we want to allow Python-based pretty-printing. */
current thread and frame. Otherwise, variable object is
always updated in the specific scope/thread/frame. */
current thread and frame. Otherwise, variable object is
always updated in the specific scope/thread/frame. */
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. */
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. */
/* The pretty-printer constructor. If NULL, then the default
pretty-printer will be looked up. If None, then no
/* The pretty-printer constructor. If NULL, then the default
pretty-printer will be looked up. If None, then no
-static void delete_variable_1 (int *, struct varobj *, int, int);
+static void delete_variable_1 (int *, struct varobj *, bool, bool);
-static int update_type_if_necessary (struct varobj *var,
- struct value *new_value);
+static bool update_type_if_necessary (struct varobj *var,
+ struct value *new_value);
static struct value *value_of_child (const struct varobj *parent, int index);
static std::string my_value_of_variable (struct varobj *var,
enum varobj_display_formats format);
static struct value *value_of_child (const struct varobj *parent, int index);
static std::string my_value_of_variable (struct varobj *var,
enum varobj_display_formats format);
static struct varobj *varobj_add_child (struct varobj *var,
struct varobj_item *item);
static struct varobj *varobj_add_child (struct varobj *var,
struct varobj_item *item);
/* Wrap the call to parse expression, so we can
return a sensible error. */
/* Wrap the call to parse expression, so we can
return a sensible error. */
- var->root->exp = parse_exp_1 (&p, pc, block, 0);
+ var->root->exp = parse_exp_1 (&p, pc, block, 0, &tracker);
var->name = expression;
/* For a root var, the name and the expr are the same. */
var->path_expr = expression;
var->name = expression;
/* For a root var, the name and the expr are the same. */
var->path_expr = expression;
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. */
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. */
{
/* User could specify explicit FRAME-ADDR which was not found but
EXPRESSION is frame specific and we would not be able to evaluate
{
/* User could specify explicit FRAME-ADDR which was not found but
EXPRESSION is frame specific and we would not be able to evaluate
/* 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(). */
/* 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(). */
varobj_has_more (const struct varobj *var, int to)
{
if (var->children.size () > to)
varobj_has_more (const struct varobj *var, int to)
{
if (var->children.size () > to)
{
/* When a variable is unfrozen, we don't fetch its value.
The 'not_fetched' flag remains set, so next -var-update
{
/* When a variable is unfrozen, we don't fetch its value.
The 'not_fetched' flag remains set, so next -var-update
-/* 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. */
+/* A helper function that updates the contents of FROM and TO based on the
+ size of the vector CHILDREN. If the contents of either FROM or TO are
+ negative the entire range is used. */
std::vector<varobj *> *type_changed,
std::vector<varobj *> *newobj,
std::vector<varobj *> *unchanged,
std::vector<varobj *> *type_changed,
std::vector<varobj *> *newobj,
std::vector<varobj *> *unchanged,
dynamic_varobj_has_child_method (const struct varobj *var)
{
PyObject *printer = var->dynamic->pretty_printer;
if (!gdb_python_initialized)
dynamic_varobj_has_child_method (const struct varobj *var)
{
PyObject *printer = var->dynamic->pretty_printer;
if (!gdb_python_initialized)
gdbpy_enter_varobj enter_py (var);
return PyObject_HasAttr (printer, gdbpy_children_cst);
gdbpy_enter_varobj enter_py (var);
return PyObject_HasAttr (printer, gdbpy_children_cst);
update_dynamic_varobj_children (struct varobj *var,
std::vector<varobj *> *changed,
std::vector<varobj *> *type_changed,
std::vector<varobj *> *newobj,
std::vector<varobj *> *unchanged,
update_dynamic_varobj_children (struct varobj *var,
std::vector<varobj *> *changed,
std::vector<varobj *> *type_changed,
std::vector<varobj *> *newobj,
std::vector<varobj *> *unchanged,
/* Release vitem->value so its lifetime is not bound to the
execution of a command. */
if (item != NULL && item->value != NULL)
/* Release vitem->value so its lifetime is not bound to the
execution of a command. */
if (item != NULL && item->value != NULL)
install_dynamic_child (var, can_mention ? changed : NULL,
can_mention ? type_changed : NULL,
install_dynamic_child (var, can_mention ? changed : NULL,
can_mention ? type_changed : NULL,
for (int j = i; j < var->children.size (); ++j)
varobj_delete (var->children[j], 0);
for (int j = i; j < var->children.size (); ++j)
varobj_delete (var->children[j], 0);
/* If there are fewer children than requested, note that the list of
children changed. */
if (to >= 0 && var->children.size () < to)
/* If there are fewer children than requested, note that the list of
children changed. */
if (to >= 0 && var->children.size () < to)
/* 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, NULL, &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, NULL, &dummy,
const std::vector<varobj *> &
varobj_list_children (struct varobj *var, int *from, int *to)
{
const std::vector<varobj *> &
varobj_list_children (struct varobj *var, int *from, int *to)
{
/* 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, NULL,
/* 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, NULL,
- &children_changed, 0, 0, *to);
+ &children_changed, false, 0, *to);
/* Is VAR a path expression parent, i.e., can it be used to construct
a valid path expression? */
/* Is VAR a path expression parent, i.e., can it be used to construct
a valid path expression? */
is_path_expr_parent (const struct varobj *var)
{
gdb_assert (var->root->lang_ops->is_path_expr_parent != NULL);
is_path_expr_parent (const struct varobj *var)
{
gdb_assert (var->root->lang_ops->is_path_expr_parent != NULL);
varobj_set_value (struct varobj *var, const char *expression)
{
struct value *val = NULL; /* Initialize to keep gcc happy. */
varobj_set_value (struct varobj *var, const char *expression)
{
struct value *val = NULL; /* Initialize to keep gcc happy. */
input_radix = 10; /* ALWAYS reset to decimal temporarily. */
expression_up exp = parse_exp_1 (&s, 0, 0, 0);
input_radix = 10; /* ALWAYS reset to decimal temporarily. */
expression_up exp = parse_exp_1 (&s, 0, 0, 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. */
/* 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. */
/* The new value may be lazy. value_assign, or
rather value_contents, will take care of this. */
/* The new value may be lazy. value_assign, or
rather value_contents, will take care of this. */
/* 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
/* 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
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. */
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. */
-/* Assign a new value to a variable object. If INITIAL is non-zero,
- this is the first assignement after the variable object was just
+/* Assign a new value to a variable object. If INITIAL is true,
+ this is the first assignment after the variable object was just
- 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
+ and return false.
+ Otherwise, assign the new value, and return true if the value is
+ different from the current one, false 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
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
The VALUE parameter should not be released -- the function will
take care of releasing it when needed. */
The VALUE parameter should not be released -- the function will
take care of releasing it when needed. */
/* We need to know the varobj's type to decide if the value should
be fetched or not. C++ fake children (public/protected/private)
/* We need to know the varobj's type to decide if the value should
be fetched or not. C++ fake children (public/protected/private)
changeable. FIXME: need to make sure this behaviour will not
mess up read-sensitive values. */
if (var->dynamic->pretty_printer != NULL)
changeable. FIXME: need to make sure this behaviour will not
mess up read-sensitive values. */
if (var->dynamic->pretty_printer != NULL)
the data from memory. For unions, that means we'll read the
same memory more than once, which is not desirable. So
fetch now. */
the data from memory. For unions, that means we'll read the
same memory more than once, which is not desirable. So
fetch now. */
/* The new value might be lazy. If the type is changeable,
that is we'll be comparing values of this type, fetch the
/* The new value might be lazy. If the type is changeable,
that is we'll be comparing values of this type, fetch the
{
/* For variables that are frozen, or are children of frozen
variables, we don't do fetch on initial assignment.
{
/* For variables that are frozen, or are children of frozen
variables, we don't do fetch on initial assignment.
{
/* 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;
}
{
/* 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;
}
}
}
/* Get a reference now, before possibly passing it to any Python
code that might release it. */
}
}
/* Get a reference now, before possibly passing it to any Python
code that might release it. */
/* Below, we'll be comparing string rendering of old and new
values. Don't get string rendering if the value is
/* Below, we'll be comparing string rendering of old and new
values. Don't get string rendering if the value is
{
/* 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. */
{
/* 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. */
gdb_assert (!value_lazy (value));
gdb_assert (!var->print_value.empty () && !print_value.empty ());
if (var->print_value != print_value)
gdb_assert (!value_lazy (value));
gdb_assert (!var->print_value.empty () && !print_value.empty ());
if (var->print_value != print_value)
if ((var->print_value.empty () && !print_value.empty ())
|| (!var->print_value.empty () && print_value.empty ())
|| (!var->print_value.empty () && !print_value.empty ()
&& var->print_value != print_value))
if ((var->print_value.empty () && !print_value.empty ())
|| (!var->print_value.empty () && print_value.empty ())
|| (!var->print_value.empty () && !print_value.empty ()
&& var->print_value != print_value))
gdbpy_ref<> constructor (PyRun_String (visualizer, Py_eval_input,
globals.get (), globals.get ()));
gdbpy_ref<> constructor (PyRun_String (visualizer, Py_eval_input,
globals.get (), globals.get ()));
the new value is different from the type of the varobj's old
value.
NEW_VALUE may be NULL, if the varobj is now out of scope. */
the new value is different from the type of the varobj's old
value.
NEW_VALUE may be NULL, if the varobj is now out of scope. */
the type has mutated or not. For all intents and purposes,
it has not mutated. */
if (var->num_children < 0)
the type has mutated or not. For all intents and purposes,
it has not mutated. */
if (var->num_children < 0)
{
/* The varobj module, when installing new values, explicitly strips
references, saying that we're not interested in those addresses.
{
/* The varobj module, when installing new values, explicitly strips
references, saying that we're not interested in those addresses.
of MI request to update this specific variable, or
result of implicit -var-update *. For implicit request, we don't
update frozen variables.
of MI request to update this specific variable, or
result of implicit -var-update *. For implicit request, we don't
update frozen variables.
value_of_root variable dispose of the varobj if the type
has changed. */
newobj = value_of_root (varp, &type_changed);
value_of_root variable dispose of the varobj if the type
has changed. */
newobj = value_of_root (varp, &type_changed);
r.varobj = *varp;
r.type_changed = type_changed;
if (install_new_value ((*varp), newobj, type_changed))
r.varobj = *varp;
r.type_changed = type_changed;
if (install_new_value ((*varp), newobj, type_changed))
- std::vector<varobj *> changed, type_changed, unchanged, newobj;
- int children_changed = 0;
+ std::vector<varobj *> changed, type_changed_vec, unchanged, newobj_vec;
+ bool children_changed = false;
/* If we initially did not have potential children, but
now we do, consider the varobj as changed.
/* If we initially did not have potential children, but
now we do, consider the varobj as changed.
if (!varobj_has_more (v, 0))
{
update_dynamic_varobj_children (v, NULL, NULL, NULL, NULL,
if (!varobj_has_more (v, 0))
{
update_dynamic_varobj_children (v, NULL, NULL, NULL, NULL,
- if (update_dynamic_varobj_children (v, &changed, &type_changed, &newobj,
- &unchanged, &children_changed, 1,
- v->from, v->to))
+ if (update_dynamic_varobj_children (v, &changed, &type_changed_vec,
+ &newobj_vec,
+ &unchanged, &children_changed,
+ true, v->from, v->to))
}
/* 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". */
}
/* 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". */
{
int delcount = 0;
delete_variable_1 (&delcount, var, only_children_p,
{
int delcount = 0;
delete_variable_1 (&delcount, var, only_children_p,
and the parent is not removed we dump core. It must be always
initially called with remove_from_parent_p set. */
static void
and the parent is not removed we dump core. It must be always
initially called with remove_from_parent_p set. */
static void
-delete_variable_1 (int *delcountp, struct varobj *var, int only_children_p,
- int remove_from_parent_p)
+delete_variable_1 (int *delcountp, struct varobj *var, bool only_children_p,
+ bool remove_from_parent_p)
{
/* Delete any children of this variable, too. */
for (varobj *child : var->children)
{
/* Delete any children of this variable, too. */
for (varobj *child : var->children)
- delete_variable_1 (delcountp, child, 0, only_children_p);
+ delete_variable_1 (delcountp, child, false, only_children_p);
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.
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.
/* Determine whether the variable is still around. */
if (var->root->valid_block == NULL || var->root->floating)
/* Determine whether the variable is still around. */
if (var->root->valid_block == NULL || var->root->floating)
/* We need to catch errors here, because if evaluate
expression fails we want to just return NULL. */
/* We need to catch errors here, because if evaluate
expression fails we want to just return NULL. */
- *var_handle will be set to the new varobj
Otherwise, *type_changed will be set to 0. */
static struct value *
- *var_handle will be set to the new varobj
Otherwise, *type_changed will be set to 0. */
static struct value *
varobj_value_is_changeable_p (const struct varobj *var)
{
return var->root->lang_ops->value_is_changeable_p (var);
}
varobj_value_is_changeable_p (const struct varobj *var)
{
return var->root->lang_ops->value_is_changeable_p (var);
}
selected frame, and not bound to thread/frame. Such variable objects
are created using '@' as frame specifier to -var-create. */
selected frame, and not bound to thread/frame. Such variable objects
are created using '@' as frame specifier to -var-create. */