-
-/* 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 = NULL;
- struct varobj *var = *var_handle;
- int within_scope = 0;
- struct cleanup *back_to;
-
- /* Only root variables can be updated... */
- 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 || 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
- {
- 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)
- {
- volatile struct gdb_exception except;
-
- /* We need to catch errors here, because if evaluate
- expression fails we want to just return NULL. */
- TRY_CATCH (except, RETURN_MASK_ERROR)
- {
- new_val = evaluate_expression (var->root->exp);
- }
- }
-
- do_cleanups (back_to);
-
- return new_val;
-}
-
-static struct value *
-c_value_of_child (struct varobj *parent, int index)
-{
- struct value *value = NULL;
-
- c_describe_child (parent, index, NULL, &value, NULL, NULL);
- return value;
-}
-
-static struct type *
-c_type_of_child (struct varobj *parent, int index)
-{
- struct type *type = NULL;
-
- c_describe_child (parent, index, NULL, NULL, &type, NULL);
- return type;
-}
-
-static char *
-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);
-
- /* Strip top-level references. */
- while (TYPE_CODE (type) == TYPE_CODE_REF)
- type = check_typedef (TYPE_TARGET_TYPE (type));
-
- switch (TYPE_CODE (type))
- {
- case TYPE_CODE_STRUCT:
- case TYPE_CODE_UNION:
- return xstrdup ("{...}");
- /* break; */
-
- case TYPE_CODE_ARRAY:
- {
- char *number;
-
- number = xstrprintf ("[%d]", var->num_children);
- return (number);
- }
- /* break; */
-
- default:
- {
- if (var->value == NULL)
- {
- /* This can happen if we attempt to get the value of a struct
- member when the parent is an invalid pointer. This is an
- error condition, so we should tell the caller. */
- return NULL;
- }
- else
- {
- 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);
- }
- }
- }
-}
-\f
-
-/* C++ */
-
-static int
-cplus_number_of_children (struct varobj *var)
-{
- struct value *value = NULL;
- struct type *type;
- int children, dont_know;
- int lookup_actual_type = 0;
- struct value_print_options opts;
-
- dont_know = 1;
- children = 0;
-
- get_user_print_options (&opts);
-
- if (!CPLUS_FAKE_CHILD (var))
- {
- type = get_value_type (var);
-
- /* It is necessary to access a real type (via RTTI). */
- if (opts.objectprint)
- {
- value = var->value;
- lookup_actual_type = (TYPE_CODE (var->type) == TYPE_CODE_REF
- || TYPE_CODE (var->type) == TYPE_CODE_PTR);
- }
- adjust_value_for_child_access (&value, &type, NULL, lookup_actual_type);
-
- if (((TYPE_CODE (type)) == TYPE_CODE_STRUCT) ||
- ((TYPE_CODE (type)) == TYPE_CODE_UNION))
- {
- int kids[3];
-
- cplus_class_num_children (type, kids);
- if (kids[v_public] != 0)
- children++;
- if (kids[v_private] != 0)
- children++;
- if (kids[v_protected] != 0)
- children++;
-
- /* Add any baseclasses. */
- children += TYPE_N_BASECLASSES (type);
- dont_know = 0;
-
- /* FIXME: save children in var. */
- }
- }
- else
- {
- int kids[3];
-
- type = get_value_type (var->parent);
-
- /* It is necessary to access a real type (via RTTI). */
- if (opts.objectprint)
- {
- struct varobj *parent = var->parent;
-
- value = parent->value;
- lookup_actual_type = (TYPE_CODE (parent->type) == TYPE_CODE_REF
- || TYPE_CODE (parent->type) == TYPE_CODE_PTR);
- }
- adjust_value_for_child_access (&value, &type, NULL, lookup_actual_type);
-
- cplus_class_num_children (type, kids);
- if (strcmp (var->name, "public") == 0)
- children = kids[v_public];
- else if (strcmp (var->name, "private") == 0)
- children = kids[v_private];
- else
- children = kids[v_protected];
- dont_know = 0;
- }
-
- if (dont_know)
- children = c_number_of_children (var);
-
- return children;
-}
-
-/* Compute # of public, private, and protected variables in this class.
- That means we need to descend into all baseclasses and find out
- how many are there, too. */
-static void
-cplus_class_num_children (struct type *type, int children[3])
-{
- 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. 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))
- children[v_protected]++;
- else if (TYPE_FIELD_PRIVATE (type, i))
- children[v_private]++;
- else
- children[v_public]++;
- }
-}
-
-static char *
-cplus_name_of_variable (struct varobj *parent)
-{
- return c_name_of_variable (parent);
-}
-
-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)
-{
- 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)
-{
- struct value *value;
- struct type *type;
- int was_ptr;
- int lookup_actual_type = 0;
- char *parent_expression = NULL;
- struct varobj *var;
- struct value_print_options opts;
-
- if (cname)
- *cname = NULL;
- if (cvalue)
- *cvalue = NULL;
- if (ctype)
- *ctype = NULL;
- if (cfull_expression)
- *cfull_expression = NULL;
-
- get_user_print_options (&opts);
-
- var = (CPLUS_FAKE_CHILD (parent)) ? parent->parent : parent;
- if (opts.objectprint)
- lookup_actual_type = (TYPE_CODE (var->type) == TYPE_CODE_REF
- || TYPE_CODE (var->type) == TYPE_CODE_PTR);
- value = var->value;
- type = get_value_type (var);
- if (cfull_expression)
- parent_expression = varobj_get_path_expr (get_path_expr_parent (var));
-
- adjust_value_for_child_access (&value, &type, &was_ptr, lookup_actual_type);
-
- if (TYPE_CODE (type) == TYPE_CODE_STRUCT
- || TYPE_CODE (type) == TYPE_CODE_UNION)
- {
- char *join = was_ptr ? "->" : ".";
-
- if (CPLUS_FAKE_CHILD (parent))
- {
- /* The fields of the class type are ordered as they
- appear in the class. We are given an index for a
- particular access control type ("public","protected",
- or "private"). We must skip over fields that don't
- 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;
- const char *field_name;
-
- vptr_fieldno = get_vptr_fieldno (type, &basetype);
- if (strcmp (parent->name, "private") == 0)
- acc = private_field;
- else if (strcmp (parent->name, "protected") == 0)
- acc = protected_field;
-
- while (index >= 0)
- {
- 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;
-
- /* If the type is anonymous and the field has no name,
- set an appopriate name. */
- field_name = TYPE_FIELD_NAME (type, type_index);
- if (field_name == NULL || *field_name == '\0')
- {
- if (cname)
- {
- if (TYPE_CODE (TYPE_FIELD_TYPE (type, type_index))
- == TYPE_CODE_STRUCT)
- *cname = xstrdup (ANONYMOUS_STRUCT_NAME);
- else if (TYPE_CODE (TYPE_FIELD_TYPE (type, type_index))
- == TYPE_CODE_UNION)
- *cname = xstrdup (ANONYMOUS_UNION_NAME);
- }
-
- if (cfull_expression)
- *cfull_expression = xstrdup ("");
- }
- else
- {
- if (cname)
- *cname = xstrdup (TYPE_FIELD_NAME (type, type_index));
-
- if (cfull_expression)
- *cfull_expression
- = xstrprintf ("((%s)%s%s)", parent_expression, join,
- field_name);
- }
-
- if (cvalue && value)
- *cvalue = value_struct_element_index (value, type_index);
-
- if (ctype)
- *ctype = TYPE_FIELD_TYPE (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)
- {
- *ctype = TYPE_FIELD_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.
-
- When we are in the scope of the base class or of one
- of its children, the type field name will be interpreted
- as a constructor, if it exists. Therefore, we must
- indicate that the name is a class name by using the
- 'class' keyword. See PR mi/11912 */
- *cfull_expression = xstrprintf ("(%s(class %s%s) %s)",
- ptr,
- TYPE_FIELD_NAME (type, index),
- ptr,
- parent_expression);
- }
- }
- else
- {
- char *access = NULL;
- int children[3];
-
- cplus_class_num_children (type, children);
-
- /* Everything beyond the baseclasses can
- only be "public", "private", or "protected"
-
- The special "fake" children are always output by varobj in
- this order. So if INDEX == 2, it MUST be "protected". */
- index -= TYPE_N_BASECLASSES (type);
- switch (index)
- {
- case 0:
- if (children[v_public] > 0)
- access = "public";
- else if (children[v_private] > 0)
- access = "private";
- else
- access = "protected";
- break;
- case 1:
- if (children[v_public] > 0)
- {
- if (children[v_private] > 0)
- access = "private";
- else
- access = "protected";
- }
- else if (children[v_private] > 0)
- access = "protected";
- break;
- case 2:
- /* Must be protected. */
- access = "protected";
- break;
- default:
- /* error! */
- break;
- }
-
- gdb_assert (access);
- if (cname)
- *cname = xstrdup (access);
-
- /* Value and type and full expression are null here. */
- }
- }
- else
- {
- 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)
-{
- return c_value_of_root (var_handle);
-}
-
-static struct value *
-cplus_value_of_child (struct varobj *parent, int 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 = NULL;
-
- cplus_describe_child (parent, index, NULL, NULL, &type, NULL);
- return type;
-}
-
-static char *
-cplus_value_of_variable (struct varobj *var,
- enum varobj_display_formats format)
-{
-
- /* If we have one of our special types, don't print out
- any value. */
- if (CPLUS_FAKE_CHILD (var))
- return xstrdup ("");
-
- return c_value_of_variable (var, format);
-}
-\f
-/* Java */
-
-static int
-java_number_of_children (struct varobj *var)
-{
- return cplus_number_of_children (var);
-}
-
-static char *
-java_name_of_variable (struct varobj *parent)
-{
- char *p, *name;
-
- name = cplus_name_of_variable (parent);
- /* If the name has "-" in it, it is because we
- needed to escape periods in the name... */
- p = name;
-
- while (*p != '\000')
- {
- if (*p == '-')
- *p = '.';
- p++;
- }
-
- return name;
-}
-
-static char *
-java_name_of_child (struct varobj *parent, int index)
-{
- char *name, *p;
-
- name = cplus_name_of_child (parent, index);
- /* Escape any periods in the name... */
- p = name;
-
- while (*p != '\000')
- {
- if (*p == '.')
- *p = '-';
- p++;
- }
-
- 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)
-{
- return cplus_value_of_root (var_handle);
-}
-
-static struct value *
-java_value_of_child (struct varobj *parent, int index)
-{
- return cplus_value_of_child (parent, index);
-}
-
-static struct type *
-java_type_of_child (struct varobj *parent, int index)
-{
- return cplus_type_of_child (parent, index);
-}
-
-static char *
-java_value_of_variable (struct varobj *var, enum varobj_display_formats format)
-{
- return cplus_value_of_variable (var, format);
-}
-
-/* Ada specific callbacks for VAROBJs. */
-
-static int
-ada_number_of_children (struct varobj *var)
-{
- return ada_varobj_get_number_of_children (var->value, var->type);
-}
-
-static char *
-ada_name_of_variable (struct varobj *parent)
-{
- return c_name_of_variable (parent);
-}
-
-static char *
-ada_name_of_child (struct varobj *parent, int index)
-{
- return ada_varobj_get_name_of_child (parent->value, parent->type,
- parent->name, index);
-}
-
-static char*
-ada_path_expr_of_child (struct varobj *child)
-{
- struct varobj *parent = child->parent;
- const char *parent_path_expr = varobj_get_path_expr (parent);
-
- return ada_varobj_get_path_expr_of_child (parent->value,
- parent->type,
- parent->name,
- parent_path_expr,
- child->index);
-}
-
-static struct value *
-ada_value_of_root (struct varobj **var_handle)
-{
- return c_value_of_root (var_handle);
-}
-
-static struct value *
-ada_value_of_child (struct varobj *parent, int index)
-{
- return ada_varobj_get_value_of_child (parent->value, parent->type,
- parent->name, index);
-}
-
-static struct type *
-ada_type_of_child (struct varobj *parent, int index)
-{
- return ada_varobj_get_type_of_child (parent->value, parent->type,
- index);
-}
-
-static char *
-ada_value_of_variable (struct varobj *var, enum varobj_display_formats format)
-{
- struct value_print_options opts;
-
- get_formatted_print_options (&opts, format_code[(int) format]);
- opts.deref_ref = 0;
- opts.raw = 1;
-
- return ada_varobj_get_value_of_variable (var->value, var->type, &opts);
-}
-
-/* Implement the "value_is_changeable_p" routine for Ada. */
-
-static int
-ada_value_is_changeable_p (struct varobj *var)
-{
- struct type *type = var->value ? value_type (var->value) : var->type;
-
- if (ada_is_array_descriptor_type (type)
- && TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
- {
- /* This is in reality a pointer to an unconstrained array.
- its value is changeable. */
- return 1;
- }
-
- if (ada_is_string_type (type))
- {
- /* We display the contents of the string in the array's
- "value" field. The contents can change, so consider
- that the array is changeable. */
- return 1;
- }
-
- return default_value_is_changeable_p (var);
-}
-
-/* Implement the "value_has_mutated" routine for Ada. */
-
-static int
-ada_value_has_mutated (struct varobj *var, struct value *new_val,
- struct type *new_type)
-{
- int i;
- int from = -1;
- int to = -1;
-
- /* If the number of fields have changed, then for sure the type
- has mutated. */
- if (ada_varobj_get_number_of_children (new_val, new_type)
- != var->num_children)
- return 1;
-
- /* If the number of fields have remained the same, then we need
- to check the name of each field. If they remain the same,
- then chances are the type hasn't mutated. This is technically
- an incomplete test, as the child's type might have changed
- despite the fact that the name remains the same. But we'll
- handle this situation by saying that the child has mutated,
- not this value.
-
- If only part (or none!) of the children have been fetched,
- then only check the ones we fetched. It does not matter
- to the frontend whether a child that it has not fetched yet
- has mutated or not. So just assume it hasn't. */
-
- restrict_range (var->children, &from, &to);
- for (i = from; i < to; i++)
- if (strcmp (ada_varobj_get_name_of_child (new_val, new_type,
- var->name, i),
- VEC_index (varobj_p, var->children, i)->name) != 0)
- return 1;
-
- return 0;
-}
-
-/* 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
-_initialize_varobj (void)