#include "defs.h"
#include "exceptions.h"
#include "value.h"
#include "cp-abi.h"
#include "expression.h"
#include "frame.h"
#include "language.h"
#include "wrapper.h"
#include "gdbcmd.h"
#include "gdb_assert.h"
#include "gdb_string.h"
#include "block.h"
#include "target.h"
#include "objfiles.h"
#include <math.h>
#include "varobj.h"
#include "parser-defs.h"
int varobjdebug = 0;
static int varobj_use_dynamic_type = 1;
static int varobj_get_type_index_from_fake_child (struct varobj *parent, int index);
static int varobj_value_struct_elt_by_index (struct varobj *parent, int index,
struct value **ret_val);
static struct type *varobj_lookup_struct_elt_type_by_index (struct varobj *parent, int index);
static void
show_varobjdebug (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
fprintf_filtered (file, _("Varobj debugging is %s.\n"), value);
}
char *varobj_format_string[] =
{ "natural", "binary", "decimal", "hexadecimal", "octal", "unsigned", "OSType", "floating point hex" };
char *varobj_language_string[] = { "unknown", "C", "C++", "Java" };
struct varobj_root
{
struct expression *exp;
struct block *valid_block;
struct frame_id frame;
int use_selected_frame;
int in_scope;
struct language_specific *lang;
struct varobj *rootvar;
struct varobj_root *next;
};
enum varobj_join_type
{
VAROBJ_AS_DUNNO,
VAROBJ_AS_STRUCT,
VAROBJ_AS_PTR_TO_SCALAR,
VAROBJ_AS_PTR_TO_STRUCT,
VAROBJ_AS_ARRAY,
};
struct varobj
{
char *name;
char *path_expr;
enum varobj_join_type join_in_expr;
int elide_in_expr;
char *obj_name;
int index;
struct type *type;
struct type *dynamic_type;
char *dynamic_type_name;
struct value *value;
int error;
int num_children;
struct varobj *parent;
struct varobj_child *children;
int fake_child;
struct varobj_root *root;
enum varobj_display_formats format;
int updated;
struct objfile_hitlist *hitlist;
};
struct varobj_child
{
struct varobj *child;
struct varobj_child *next;
};
struct vstack
{
struct varobj *var;
struct vstack *next;
};
struct cpstack
{
char *name;
struct cpstack *next;
};
struct vlist
{
struct varobj *var;
struct vlist *next;
};
struct varobj_changelist_elem {
struct varobj *var;
enum varobj_type_change type_changed;
struct varobj_changelist_elem *next;
};
struct varobj_changelist {
struct varobj_changelist_elem *tail;
struct varobj_changelist_elem *head;
};
static int delete_variable (struct cpstack **, struct varobj *, int);
static void delete_variable_1 (struct cpstack **, int *,
struct varobj *, int, int);
static int install_variable (struct varobj *);
static void uninstall_variable (struct varobj *);
static struct varobj *child_exists (struct varobj *, int index);
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 *new_variable (void);
static struct varobj *new_root_variable (void);
static void free_variable (struct varobj *var);
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, int *was_ptr);
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 struct varobj_changelist *varobj_changelist_init ();
static void varobj_add_to_changelist(struct varobj_changelist *changelist,
struct varobj *var,
enum varobj_type_change type_changed);
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 enum varobj_languages variable_language (struct varobj *var);
static int number_of_children (struct varobj *);
static char *name_of_variable (struct varobj *);
static char *path_expr_of_variable (struct varobj *);
static char *make_name_of_child (struct varobj *, int);
static char *path_expr_of_child (struct varobj *, int);
static struct value *value_of_root (struct varobj **var_handle, enum varobj_type_change *);
static struct value *value_of_child (struct varobj *parent, int index,
enum varobj_type_change *);
static struct type *type_of_child (struct varobj *var);
static int variable_editable (struct varobj *var);
static char *my_value_of_variable (struct varobj *var);
static int varobj_value_is_changeable_p (struct varobj *var);
static int is_root_p (struct varobj *var);
static enum varobj_join_type get_join_type (struct type *type);
static int c_number_of_children (struct varobj *var);
static char *c_make_name_of_child (struct varobj *parent, int index);
static char *c_path_expr_of_child (struct varobj *parent, int index);
static struct value *c_value_of_root (struct varobj **var_handle, enum varobj_type_change *type_changed);
static struct value *c_value_of_child (struct varobj *parent, int index, int *lookup_dynamic_type);
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 int cplus_number_of_children (struct varobj *var);
static void cplus_class_num_children (struct type *type, int children[3]);
static char *cplus_make_name_of_child (struct varobj *parent, int index);
static char *cplus_path_expr_of_child (struct varobj *parent, int index);
static struct value *cplus_value_of_root (struct varobj **var_handle, enum varobj_type_change *type_changed);
static struct value *cplus_value_of_child (struct varobj *parent, int index, int *lookup_dynamic_type);
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 int java_number_of_children (struct varobj *var);
static char *java_make_name_of_child (struct varobj *parent, int index);
static char *java_path_expr_of_child (struct varobj *parent, int index);
static struct value *java_value_of_root (struct varobj **var_handle, enum varobj_type_change *type_changed);
static struct value *java_value_of_child (struct varobj *parent, int index, int *lookup_dynamic_type);
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);
struct language_specific
{
enum varobj_languages language;
int (*number_of_children) (struct varobj * parent);
char *(*make_name_of_child) (struct varobj * parent, int index);
char *(*path_expr_of_child) (struct varobj * parent, int index);
struct value *(*value_of_root) (struct varobj ** root_handle,
enum varobj_type_change *type_changed);
struct value *(*value_of_child) (struct varobj * parent, int index, int *lookup_dynamic_type);
struct type *(*type_of_child) (struct varobj * parent, int index);
int (*variable_editable) (struct varobj * var);
char *(*value_of_variable) (struct varobj * var);
};
static struct language_specific
languages[vlang_end][sizeof (struct language_specific)] = {
{
vlang_unknown,
c_number_of_children,
c_make_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}
,
{
vlang_c,
c_number_of_children,
c_make_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}
,
{
vlang_cplus,
cplus_number_of_children,
cplus_make_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}
,
{
vlang_java,
java_number_of_children,
java_make_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}
};
enum vsections
{
v_public = 0, v_private, v_protected
};
static int cplus_real_type_index_for_fake_child_index (
struct type *type,
enum vsections prot,
int num);
static int format_code[] = { 0, 't', 'd', 'x', 'o', 'u', 'T' };
static struct varobj_root *rootlist;
static int rootcount = 0;
#define VAROBJ_TABLE_SIZE 227
static struct vlist **varobj_table;
int varobj_runs_all_threads = 0;
#define CPLUS_FAKE_CHILD(x) \
\
((x) != NULL && (x)->fake_child)
int
varobj_parse_exp_1 (char **stringptr, struct block *block, int comma,
struct expression **expression)
{
struct cleanup *print_closure_cleanup;
int ret_val;
print_closure_cleanup = make_cleanup_set_restore_print_closure (0);
ret_val = gdb_parse_exp_1 (stringptr, block, comma, expression);
do_cleanups (print_closure_cleanup);
return ret_val;
}
static int
varobj_evaluate_expression (struct expression *exp, struct value **value)
{
struct cleanup *print_closure_cleanup;
int ret_val;
print_closure_cleanup = make_cleanup_set_restore_print_closure (0);
ret_val = gdb_evaluate_expression (exp, value);
do_cleanups (print_closure_cleanup);
return ret_val;
}
int
varobj_evaluate_type (struct expression *exp, struct value **value)
{
struct cleanup *print_closure_cleanup;
int ret_val;
print_closure_cleanup = make_cleanup_set_restore_print_closure (0);
ret_val = gdb_evaluate_type (exp, value);
do_cleanups (print_closure_cleanup);
return ret_val;
}
static int
is_root_p (struct varobj *var)
{
return (var->root->rootvar == var);
}
static enum varobj_join_type
get_join_type (struct type *in_type)
{
if (in_type == NULL)
return VAROBJ_AS_DUNNO;
struct type *type = check_typedef (in_type);
switch (TYPE_CODE (type))
{
case TYPE_CODE_PTR:
case TYPE_CODE_REF:
{
struct type *target = get_target_type (type);
switch (TYPE_CODE (target))
{
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
return VAROBJ_AS_PTR_TO_STRUCT;
default:
return VAROBJ_AS_PTR_TO_SCALAR;
break;
}
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
return VAROBJ_AS_STRUCT;
break;
case TYPE_CODE_ARRAY:
return VAROBJ_AS_ARRAY;
break;
default:
return VAROBJ_AS_DUNNO;
}
}
}
static struct type *
safe_value_rtti_target_type (struct value *val, int *full, int *top, int *using_enc)
{
volatile struct gdb_exception except;
struct ui_file *saved_gdb_stderr;
static struct ui_file *null_stderr = NULL;
struct type *dynamic_type = NULL;
if (null_stderr == NULL)
null_stderr = ui_file_new ();
saved_gdb_stderr = gdb_stderr;
gdb_stderr = null_stderr;
TRY_CATCH (except, RETURN_MASK_ALL)
{
dynamic_type = value_rtti_target_type (val, full, top, using_enc);
}
gdb_stderr = saved_gdb_stderr;
if (except.reason < 0)
return NULL;
else
return dynamic_type;
}
static struct value *
varobj_fixup_value (struct value *in_value,
int use_dynamic_type,
struct block *block,
struct type **dynamic_type_handle,
char **dynamic_type_name)
{
struct value *full_value = in_value;
struct type *dynamic_type;
struct type *base_type;
dynamic_type = NULL;
if (dynamic_type_name != NULL)
*dynamic_type_name = NULL;
base_type = check_typedef (value_type (in_value));
if (TYPE_CODE(base_type) == TYPE_CODE_PTR)
{
int top, full, using_enc;
dynamic_type = safe_value_rtti_target_type (in_value, &full, &top,
&using_enc);
if (dynamic_type)
{
dynamic_type = lookup_pointer_type (dynamic_type);
}
else
{
dynamic_type = get_closure_dynamic_type (in_value);
if (dynamic_type == NULL)
{
int ret_val;
char *dynamic_class_name;
ret_val = safe_value_objc_target_type (in_value, block, &dynamic_type, &dynamic_class_name);
if (!ret_val
|| dynamic_type == 0)
{
if (dynamic_type != NULL)
*dynamic_type_name = NULL;
}
if (dynamic_type)
dynamic_type = lookup_pointer_type (dynamic_type);
else if (dynamic_class_name != NULL)
{
if (dynamic_type_name == NULL)
xfree (dynamic_class_name);
else
{
int namelen = strlen (dynamic_class_name);
char *typestr;
typestr = xmalloc (namelen + 3);
memmove (typestr, dynamic_class_name, namelen);
xfree (dynamic_class_name);
strcpy (typestr + namelen, " *");
*dynamic_type_name = typestr;
}
}
}
}
}
else if (TYPE_CODE (base_type) == TYPE_CODE_REF)
{
struct value *temp_val;
struct type *target_type;
temp_val = value_copy (in_value);
target_type = get_target_type (base_type);
if (target_type != NULL)
{
int full, top, using_enc;
deprecated_set_value_type (temp_val, lookup_pointer_type (target_type));
dynamic_type = safe_value_rtti_target_type (temp_val,
&full, &top,
&using_enc);
if (dynamic_type)
dynamic_type = lookup_reference_type (dynamic_type);
else
{
int ret_val;
char *dynamic_class_name;
ret_val = safe_value_objc_target_type (in_value, block, &dynamic_type, &dynamic_class_name);
if (!ret_val)
dynamic_type = NULL;
else if (dynamic_type)
dynamic_type = lookup_reference_type (dynamic_type);
else if (dynamic_class_name != NULL)
{
if (dynamic_type_name == NULL)
xfree (dynamic_class_name);
else
{
int namelen = strlen (dynamic_class_name);
char *typestr;
typestr = xmalloc (namelen + 3);
memmove (typestr, dynamic_class_name, namelen);
xfree (dynamic_class_name);
strcpy (typestr + namelen, " &");
*dynamic_type_name = typestr;
}
}
}
}
}
if (dynamic_type && use_dynamic_type)
{
int retval;
retval = gdb_value_cast (dynamic_type, in_value, &full_value);
if (retval == 0)
{
full_value = in_value;
dynamic_type = value_type (in_value);
}
}
if (dynamic_type_handle != NULL)
*dynamic_type_handle = dynamic_type;
return full_value;
}
static struct frame_info *
find_frame_addr_in_frame_chain (CORE_ADDR frame_addr)
{
struct frame_info *frame = NULL;
if (frame_addr == (CORE_ADDR) 0)
return NULL;
while (1)
{
frame = get_prev_frame (frame);
if (frame == NULL)
return NULL;
if (get_frame_base_address (frame) == frame_addr)
return frame;
}
}
struct varobj *
varobj_create (char *objname,
char *expression, CORE_ADDR frame,
struct block *block,
enum varobj_type type)
{
struct varobj *var;
struct frame_info *fi;
struct frame_id var_frame_id;
struct frame_id old_frame_id = null_frame_id;
struct cleanup *old_chain, *schedlock_chain;
int expr_len;
struct block *superblock;
var = new_root_variable ();
old_chain = make_cleanup_free_variable (var);
make_cleanup_objfile_init_clear_hitlist ();
if (!varobj_runs_all_threads)
schedlock_chain = make_cleanup_set_restore_scheduler_locking_mode (scheduler_locking_on);
else
schedlock_chain = make_cleanup (null_cleanup, NULL);
if (expression != NULL)
{
char *p;
enum varobj_languages lang;
if ((type == USE_CURRENT_FRAME) || (type == USE_SELECTED_FRAME)
|| (type == USE_BLOCK_IN_FRAME))
fi = deprecated_selected_frame;
else if (type == NO_FRAME_NEEDED)
fi = NULL;
else
fi = find_frame_addr_in_frame_chain (frame);
if (fi != NULL)
var_frame_id = get_frame_id (fi);
superblock = block;
if ((type == USE_BLOCK_IN_FRAME)
&& block)
{
while (!superblock->function
&& superblock->superblock)
superblock = superblock->superblock;
}
if (type == USE_BLOCK_IN_FRAME
&& block && fi
&& ((get_frame_pc (fi) < superblock->startaddr)
|| get_frame_pc (fi) > superblock->endaddr))
{
warning ("Attempting to create USE_BLOCK_IN_FRAME variable with block that isn't in the frame.");
goto error_cleanup;
}
if (type == USE_SELECTED_FRAME)
var->root->use_selected_frame = 1;
if (block == NULL)
{
if (type == USE_BLOCK_IN_FRAME)
{
warning ("Attempting to create USE_BLOCK_IN_FRAME variable with NULL block.");
goto error_cleanup;
}
else if (type == NO_FRAME_NEEDED)
{
warning ("Attempting to create NO_FRAME_NEEDED variable with NULL block.");
goto error_cleanup;
}
else if (fi != NULL)
block = get_frame_block (fi, 0);
}
p = expression;
innermost_block = NULL;
if (block)
block_found = block;
else
block_found = NULL;
if (varobj_parse_exp_1 (&p, block, 0, &var->root->exp))
{
if (var->root->exp->elts[0].opcode == OP_TYPE)
{
goto error_cleanup;
}
}
else if (var->root->use_selected_frame != 1)
goto error_cleanup;
var->format = variable_default_display (var);
var->root->valid_block = innermost_block;
expr_len = strlen (expression);
var->name = savestring (expression, expr_len);
var->path_expr = savestring (expression, expr_len);
if (var->root->exp != NULL)
{
if (fi != NULL)
{
fi = frame_find_by_id (var_frame_id);
var->root->frame = var_frame_id;
old_frame_id = get_frame_id (get_selected_frame (NULL));
select_frame (fi);
}
if ((var->root->use_selected_frame || varobj_pc_in_valid_block_p (var)
|| type == NO_FRAME_NEEDED)
&& varobj_evaluate_expression (var->root->exp, &var->value))
{
var->root->in_scope = 1;
var->type = value_type (var->value);
var->value = varobj_fixup_value (var->value,
varobj_use_dynamic_type, block,
&(var->dynamic_type),
&(var->dynamic_type_name));
if (value_lazy (var->value))
{
if (!gdb_value_fetch_lazy (var->value))
{
var->value = NULL;
var->error = 1;
}
else
var->error = 0;
}
}
else
{
int retval;
retval = varobj_evaluate_type (var->root->exp, &var->value);
if (retval != 0)
{
var->type = value_type (var->value);
var->root->in_scope = 0;
}
else
{
free_current_contents (&var->root->exp);
var->root->in_scope = 0;
var->type = NULL;
var->value = NULL;
}
}
if (var->value)
release_value (var->value);
lang = variable_language (var);
var->root->lang = languages[lang];
}
else
{
var->root->in_scope = 0;
}
var->root->rootvar = var;
if (frame_id_p (old_frame_id))
select_frame (frame_find_by_id (old_frame_id));
}
if ((var != NULL) && (objname != NULL))
{
var->obj_name = savestring (objname, strlen (objname));
if (!install_variable (var))
{
do_cleanups (old_chain);
return NULL;
}
}
if (var != NULL && var->type != NULL)
var->join_in_expr = get_join_type (var->type);
var->hitlist = objfile_detach_hitlist ();
do_cleanups (schedlock_chain);
discard_cleanups (old_chain);
return var;
error_cleanup:
do_cleanups (old_chain);
return NULL;
}
char *
varobj_gen_name (void)
{
static int id = 0;
char *obj_name;
id++;
obj_name = xstrprintf ("var%d", id);
return obj_name;
}
struct varobj *
varobj_get_handle (char *objname)
{
struct vlist *cv;
const char *chp;
unsigned int index = 0;
unsigned int i = 1;
for (chp = objname; *chp; chp++)
{
index = (index + (i++ * (unsigned int) *chp)) % VAROBJ_TABLE_SIZE;
}
cv = *(varobj_table + index);
while ((cv != NULL) && (strcmp (cv->var->obj_name, objname) != 0))
cv = cv->next;
if (cv == NULL)
error (_("Variable object not found"));
return cv->var;
}
char *
varobj_get_objname (struct varobj *var)
{
return var->obj_name;
}
char *
varobj_get_expression (struct varobj *var)
{
return name_of_variable (var);
}
int
varobj_delete (struct varobj *var, char ***dellist, int only_children)
{
int delcount;
int mycount;
struct cpstack *result = NULL;
char **cp;
cppush (&result, NULL);
if (only_children)
delcount = delete_variable (&result, var, 1 );
else
delcount = delete_variable (&result, var, 0 );
if (dellist != NULL)
{
*dellist = xmalloc ((delcount + 1) * sizeof (char *));
cp = *dellist;
mycount = delcount;
*cp = cppop (&result);
while ((*cp != NULL) && (mycount > 0))
{
mycount--;
cp++;
*cp = cppop (&result);
}
if (mycount || (*cp != NULL))
warning (_("varobj_delete: assertion failed - mycount(=%d) <> 0"),
mycount);
}
return delcount;
}
enum varobj_display_formats
varobj_set_display_format (struct varobj *var,
enum varobj_display_formats format)
{
switch (format)
{
case FORMAT_NATURAL:
case FORMAT_BINARY:
case FORMAT_DECIMAL:
case FORMAT_HEXADECIMAL:
case FORMAT_OCTAL:
case FORMAT_UNSIGNED:
case FORMAT_OSTYPE:
case FORMAT_HEXFLOAT:
var->format = format;
break;
default:
var->format = variable_default_display (var);
}
return var->format;
}
enum varobj_display_formats
varobj_get_display_format (struct varobj *var)
{
return var->format;
}
int
varobj_get_num_children (struct varobj *var)
{
if (var->root->exp == NULL)
return -1;
if (var->num_children == -1)
var->num_children = number_of_children (var);
return var->num_children;
}
int
varobj_list_children (struct varobj *var, struct varobj ***childlist)
{
struct varobj *child;
char *name;
int i;
if (childlist == NULL)
return -1;
*childlist = NULL;
if (var->num_children == -1)
var->num_children = number_of_children (var);
*childlist = xmalloc ((var->num_children + 1) * sizeof (struct varobj *));
for (i = 0; i < var->num_children; i++)
{
*((*childlist) + i) = NULL;
child = child_exists (var, i);
if (child == NULL)
{
name = make_name_of_child (var, i);
child = create_child (var, i, name);
}
*((*childlist) + i) = child;
}
*((*childlist) + i) = NULL;
return var->num_children;
}
int
varobj_is_fake_child (struct varobj *var)
{
return CPLUS_FAKE_CHILD (var);
}
char *
varobj_get_type_internal (struct varobj *var, int check_typedef_p)
{
struct value *val;
if (CPLUS_FAKE_CHILD (var))
return NULL;
if (var->type == NULL)
return savestring ("<error getting type>", strlen ("<error getting type>"));
if (check_typedef_p)
val = value_zero (remove_all_typedefs (var->type), not_lval);
else
val = value_zero (var->type, not_lval);
return (type_sprint (value_type (val), "", -1));
}
char *
varobj_get_type (struct varobj *var)
{
return varobj_get_type_internal (var, 0);
}
char *
varobj_get_resolved_type (struct varobj *var)
{
return varobj_get_type_internal (var, 1);
}
char *
varobj_get_dynamic_type (struct varobj *var)
{
struct value *val;
if (var->dynamic_type != NULL)
{
val = value_zero (var->dynamic_type, not_lval);
return (type_sprint (value_type (val), "", -1));
}
else if (var->dynamic_type_name != NULL)
return xstrdup (var->dynamic_type_name);
else
return xstrdup ("");
}
struct type *
varobj_get_type_struct (struct varobj *var)
{
return get_type (var);
}
char *
varobj_get_path_expr (struct varobj *var)
{
return path_expr_of_variable (var);
}
struct type *
varobj_get_gdb_type (struct varobj *var)
{
return var->type;
}
enum varobj_languages
varobj_get_language (struct varobj *var)
{
return variable_language (var);
}
int
varobj_in_scope_p (struct varobj *var)
{
return var->root->in_scope;
}
int
varobj_get_attributes (struct varobj *var)
{
int attributes = 0;
if (variable_editable (var))
attributes |= 0x00000001;
return attributes;
}
void
varobj_get_valid_block (struct varobj *var, CORE_ADDR *start,
CORE_ADDR *end)
{
if (var->root->valid_block == NULL)
{
*start = -1;
*end = -1;
return;
}
*start = var->root->valid_block->startaddr;
*end = var->root->valid_block->endaddr;
}
char *
varobj_get_value (struct varobj *var)
{
if (var->root->exp == NULL)
return NULL;
else if (var->value == NULL)
return NULL;
else
return my_value_of_variable (var);
}
int
varobj_set_value (struct varobj *var, char *expression)
{
struct value *val;
int error = 0;
struct expression *exp;
struct value *value;
int saved_input_radix = input_radix;
int ret_val = 1;
struct cleanup *schedlock_chain;
schedlock_chain = make_cleanup_set_restore_scheduler_locking_mode (scheduler_locking_on);
if (var->value != NULL && variable_editable (var) && !var->error)
{
char *s = expression;
input_radix = 10;
if (!varobj_parse_exp_1 (&s, 0, 0, &exp))
{
ret_val = 0;
goto cleanup;
}
if (!varobj_evaluate_expression (exp, &value))
{
xfree (exp);
ret_val = 0;
goto cleanup;
}
if (!my_value_equal (var->value, value, &error))
var->updated = 1;
if (!gdb_value_assign (var->value, value, &val))
{
ret_val = 0;
goto cleanup;
}
value_free (var->value);
release_value (val);
var->value = val;
input_radix = saved_input_radix;
ret_val = 1;
}
cleanup:
do_cleanups (schedlock_chain);
return ret_val;
}
int
varobj_list (struct varobj ***varlist)
{
struct varobj **cv;
struct varobj_root *croot;
int mycount = rootcount;
*varlist = xmalloc ((rootcount + 1) * sizeof (struct varobj *));
cv = *varlist;
croot = rootlist;
while ((croot != NULL) && (mycount > 0))
{
*cv = croot->rootvar;
mycount--;
cv++;
croot = croot->next;
}
*cv = NULL;
if (mycount || (croot != NULL))
warning
("varobj_list: assertion failed - wrong tally of root vars (%d:%d)",
rootcount, mycount);
return rootcount;
}
int
varobj_update (struct varobj **varp, struct varobj_changelist **changelist)
{
int changed = 0;
enum varobj_type_change child_type_changed;
int error2;
int error = 0;
enum varobj_type_change type_changed;
struct varobj *v;
struct value *new;
struct vstack *stack = NULL;
struct varobj_changelist *result = NULL;
struct frame_id old_fid;
struct frame_info *fi;
int came_in_scope = 0;
if (changelist == NULL)
return -1;
if ((*varp)->root->rootvar != *varp)
return -1;
old_fid = get_frame_id (deprecated_selected_frame);
if (varobjdebug)
fprintf_unfiltered (gdb_stdlog, "Updating variable: %s (%s).\n", (*varp)->name, (*varp)->obj_name);
type_changed = VAROBJ_TYPE_CHANGED;
new = value_of_root (varp, &type_changed);
if (varobjdebug)
{
if (new != NULL)
fprintf_unfiltered (gdb_stdlog, "Updating variable: %s (%s) got new value.\n", (*varp)->name, (*varp)->obj_name);
else
fprintf_unfiltered (gdb_stdlog, "Updating variable: %s (%s) got new value.\n", (*varp)->name, (*varp)->obj_name);
}
if (new != NULL && value_lazy (new))
{
if (!gdb_value_fetch_lazy (new))
new = NULL;
}
if (new == NULL)
{
int retval;
(*varp)->error = 1;
if ((*varp)->root->in_scope
&& type_changed != VAROBJ_TYPE_UNCHANGED)
{
retval = -3;
(*varp)->root->in_scope = 0;
}
else if (type_changed == VAROBJ_SCOPE_CHANGED)
{
retval = -4;
(*varp)->root->in_scope = 1;
}
else if (type_changed == VAROBJ_TYPE_UNCHANGED)
retval = 0;
else
{
retval = 0;
(*varp)->root->in_scope = 0;
}
return retval;
}
else
{
(*varp)->error = 0;
if ((*varp)->root->in_scope)
came_in_scope = 0;
else
came_in_scope = 1;
(*varp)->root->in_scope = 1;
}
result = varobj_changelist_init ();
if (type_changed != VAROBJ_TYPE_UNCHANGED)
{
varobj_add_to_changelist (result, *varp, type_changed);
changed++;
}
else if (came_in_scope
|| (varobj_value_is_changeable_p (*varp)
&& ((*varp)->updated || !my_value_equal ((*varp)->value, new, &error2))))
{
if (varobjdebug)
fprintf_unfiltered (gdb_stdlog, "Updating variable: %s (%s) has changed.\n", (*varp)->name, (*varp)->obj_name);
varobj_add_to_changelist (result, *varp, type_changed);
(*varp)->updated = 0;
changed++;
(*varp)->error = error;
}
value_free ((*varp)->value);
(*varp)->value = new;
vpush (&stack, NULL);
if ((*varp)->children != NULL)
{
struct varobj_child *c;
for (c = (*varp)->children; c != NULL; c = c->next)
vpush (&stack, c->child);
}
v = vpop (&stack);
while (v != NULL)
{
new = value_of_child (v->parent, v->index, &child_type_changed);
if (varobjdebug)
{
if (new != NULL)
fprintf_unfiltered (gdb_stdlog, "Updating child variable: %s (%s) found a value.\n", v->name, v->obj_name);
else
fprintf_unfiltered (gdb_stdlog, "Updating child variable: %s (%s) could not get a value.\n", v->name, v->obj_name);
}
if ((child_type_changed != VAROBJ_TYPE_UNCHANGED)
|| came_in_scope
|| (varobj_value_is_changeable_p (v)
&& (v->updated || !my_value_equal (v->value, new, &error2))))
{
if (varobjdebug)
fprintf_unfiltered (gdb_stdlog, "Updating variable: %s (%s) has changed.\n", v->name, v->obj_name);
varobj_add_to_changelist (result, v, child_type_changed);
v->updated = 0;
changed++;
}
v->error = error;
if (v->value != NULL)
value_free (v->value);
v->value = new;
if (child_type_changed == VAROBJ_TYPE_UNCHANGED)
{
if (v->children != NULL)
{
struct varobj_child *c;
for (c = v->children; c != NULL; c = c->next)
vpush (&stack, c->child);
}
}
else
{
varobj_delete (v, NULL, 1);
}
v = vpop (&stack);
}
fi = frame_find_by_id (old_fid);
if (fi)
select_frame (fi);
*changelist = result;
if (type_changed != VAROBJ_TYPE_UNCHANGED)
return -2;
else
return changed;
}
static int
delete_variable (struct cpstack **resultp, struct varobj *var,
int only_children_p)
{
int delcount = 0;
delete_variable_1 (resultp, &delcount, var,
only_children_p, 1 );
return delcount;
}
static void
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;
for (vc = var->children; vc != NULL; vc = next)
{
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);
}
if (only_children_p)
return;
if (var->obj_name != NULL)
{
cppush (resultp, xstrdup (var->obj_name));
*delcountp = *delcountp + 1;
}
if ((remove_from_parent_p) && (var->parent != NULL))
{
remove_child_from_parent (var->parent, var);
}
if (var->obj_name != NULL)
uninstall_variable (var);
free_variable (var);
}
static int
install_variable (struct varobj *var)
{
struct vlist *cv;
struct vlist *newvl;
const char *chp;
unsigned int index = 0;
unsigned int i = 1;
if (var->obj_name == NULL)
return 0;
for (chp = var->obj_name; *chp; chp++)
{
index = (index + (i++ * (unsigned int) *chp)) % VAROBJ_TABLE_SIZE;
}
cv = *(varobj_table + index);
while ((cv != NULL) && (strcmp (cv->var->obj_name, var->obj_name) != 0))
cv = cv->next;
if (cv != NULL)
error (_("Duplicate variable object name"));
newvl = xmalloc (sizeof (struct vlist));
newvl->next = *(varobj_table + index);
newvl->var = var;
*(varobj_table + index) = newvl;
if (is_root_p (var))
{
if (rootlist == NULL)
var->root->next = NULL;
else
var->root->next = rootlist;
rootlist = var->root;
rootcount++;
}
return 1;
}
static void
uninstall_variable (struct varobj *var)
{
struct vlist *cv;
struct vlist *prev;
struct varobj_root *cr;
struct varobj_root *prer;
const char *chp;
unsigned int index = 0;
unsigned int i = 1;
if (var->obj_name == NULL)
return;
for (chp = var->obj_name; *chp; chp++)
{
index = (index + (i++ * (unsigned int) *chp)) % VAROBJ_TABLE_SIZE;
}
cv = *(varobj_table + index);
prev = NULL;
while ((cv != NULL) && (strcmp (cv->var->obj_name, var->obj_name) != 0))
{
prev = cv;
cv = cv->next;
}
if (varobjdebug)
fprintf_unfiltered (gdb_stdlog, "Deleting %s\n", var->obj_name);
if (cv == NULL)
{
warning
("Assertion failed: Could not find variable object \"%s\" to delete",
var->obj_name);
return;
}
if (prev == NULL)
*(varobj_table + index) = cv->next;
else
prev->next = cv->next;
xfree (cv);
if (is_root_p (var))
{
if (rootlist == var->root)
rootlist = var->root->next;
else
{
prer = NULL;
cr = rootlist;
while ((cr != NULL) && (cr->rootvar != var))
{
prer = cr;
cr = cr->next;
}
if (cr == NULL)
{
warning
("Assertion failed: Could not find varobj \"%s\" in root list",
var->obj_name);
return;
}
if (prer == NULL)
rootlist = NULL;
else
prer->next = cr->next;
}
rootcount--;
}
}
static struct varobj *
child_exists (struct varobj *var, int index)
{
struct varobj_child *vc;
for (vc = var->children; vc != NULL; vc = vc->next)
{
if (vc->child->index == index)
return vc->child;
}
return NULL;
}
static struct varobj *
create_child (struct varobj *parent, int index, char *name)
{
struct varobj *child;
char *childs_name;
enum varobj_type_change type_changed;
struct type *target;
child = new_variable ();
child->name = name;
child->index = index;
child->parent = parent;
child->root = parent->root;
if (*name != '\0')
childs_name = xstrprintf ("%s.%s", parent->obj_name, name);
else
childs_name = xstrprintf ("%s.#anon#%d", parent->obj_name, index);
child->obj_name = childs_name;
if (variable_language (parent) == vlang_cplus
&& name[0] == 'p'
&& ( strcmp ("private", name) == 0
|| strcmp ("public", name) == 0
|| strcmp ("protected", name) == 0))
{
child->fake_child = 1;
}
else
{
child->fake_child = 0;
}
install_variable (child);
save_child_in_parent (parent, child);
child->type = type_of_child (child);
if (CPLUS_FAKE_CHILD (parent))
child->join_in_expr = parent->join_in_expr;
else
{
if (TYPE_CODE (parent->type) == TYPE_CODE_PTR)
{
target = get_target_type (parent->type);
}
else
target = parent->type;
if (target != NULL
&& TYPE_CODE (target) == TYPE_CODE_STRUCT
&& TYPE_RUNTIME (target) == OBJC_RUNTIME
&& index < TYPE_N_BASECLASSES (target))
{
child->elide_in_expr = 1;
child->join_in_expr = parent->join_in_expr;
}
else if (CPLUS_FAKE_CHILD (child))
child->join_in_expr = parent->join_in_expr;
else
child->join_in_expr = get_join_type (child->type);
}
child->value = value_of_child (parent, index, &type_changed);
if ((!CPLUS_FAKE_CHILD(child) && child->value == NULL) || parent->error)
child->error = 1;
return child;
}
static void
save_child_in_parent (struct varobj *parent, struct varobj *child)
{
struct varobj_child *vc;
vc = parent->children;
parent->children =
(struct varobj_child *) xmalloc (sizeof (struct varobj_child));
parent->children->next = vc;
parent->children->child = child;
}
static void
remove_child_from_parent (struct varobj *parent, struct varobj *child)
{
struct varobj_child *vc, *prev;
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;
else
prev->next = vc->next;
}
static struct varobj *
new_variable (void)
{
struct varobj *var;
var = (struct varobj *) xmalloc (sizeof (struct varobj));
var->name = NULL;
var->obj_name = NULL;
var->index = -1;
var->type = NULL;
var->dynamic_type = NULL;
var->dynamic_type_name = NULL;
var->path_expr = NULL;
var->elide_in_expr = 0;
var->join_in_expr = VAROBJ_AS_DUNNO;
var->value = NULL;
var->error = 0;
var->num_children = -1;
var->parent = NULL;
var->children = NULL;
var->fake_child = 0;
var->format = 0;
var->root = NULL;
var->updated = 0;
var->hitlist = NULL;
return var;
}
static struct varobj *
new_root_variable (void)
{
struct varobj *var = new_variable ();
var->root = (struct varobj_root *) xmalloc (sizeof (struct varobj_root));;
var->root->lang = NULL;
var->root->exp = NULL;
var->root->valid_block = NULL;
var->root->frame = null_frame_id;
var->root->use_selected_frame = 0;
var->root->in_scope = 0;
var->root->rootvar = NULL;
return var;
}
static void
free_variable (struct varobj *var)
{
if (is_root_p (var))
{
if (var->root->exp != NULL)
free_current_contents ((char **) &var->root->exp);
xfree (var->root);
}
xfree (var->name);
xfree (var->path_expr);
xfree (var->obj_name);
xfree (var->dynamic_type_name);
if (var->value != NULL)
value_free (var->value);
if (var->hitlist != NULL)
xfree (var->hitlist);
xfree (var);
}
static void
do_free_variable_cleanup (void *var)
{
free_variable (var);
}
static struct cleanup *
make_cleanup_free_variable (struct varobj *var)
{
return make_cleanup (do_free_variable_cleanup, var);
}
void
varobj_delete_objfiles_vars (struct objfile *ofile)
{
struct varobj **rootlist;
struct varobj **root;
int nroots;
nroots = varobj_list (&rootlist);
if (nroots <= 0)
return;
root = rootlist;
while (*root != NULL)
{
if (objfile_on_hitlist_p ((*root)->hitlist, ofile))
{
struct cleanup *notify_cleanup;
notify_cleanup =
make_cleanup_ui_out_notify_begin_end (uiout, "var-deleted");
ui_out_field_string (uiout, "var", (*root)->obj_name);
do_cleanups (notify_cleanup);
varobj_delete (*root, NULL, 0);
}
root++;
}
xfree (rootlist);
}
static struct type *
get_type (struct varobj *var)
{
struct type *type;
if (varobj_use_dynamic_type && var->dynamic_type != NULL)
type = var->dynamic_type;
else
type = var->type;
if (type != NULL)
type = check_typedef (type);
return type;
}
static struct type *
get_type_deref (struct varobj *var, int *was_ptr)
{
struct type *type;
enum type_code code;
if (was_ptr != NULL)
*was_ptr = 0;
type = get_type (var);
code = TYPE_CODE (type);
if (type != NULL && (code == TYPE_CODE_PTR
|| code == TYPE_CODE_REF))
{
type = get_target_type (type);
if (was_ptr != NULL)
{
if (code == TYPE_CODE_PTR)
*was_ptr = 1;
else if (code == TYPE_CODE_REF)
*was_ptr = 2;
}
}
return type;
}
static struct type *
get_target_type (struct type *type)
{
if (type != NULL)
{
type = TYPE_TARGET_TYPE (type);
if (type != NULL)
type = check_typedef (type);
}
return type;
}
static enum varobj_display_formats
variable_default_display (struct varobj *var)
{
return FORMAT_NATURAL;
}
static int
my_value_equal (struct value *val1, struct value *volatile val2, int *error2)
{
int r, err1, err2;
if (val1 == NULL && val2 == NULL)
return 1;
else if (val1 == NULL || val2 == NULL)
return 0;
gdb_assert (!value_lazy (val1));
err1 = 0;
err2 = 0;
if (!gdb_value_equal (val1, val1, &r))
err1 = 1;
if (!gdb_value_equal (val2, val2, &r))
*error2 = err2 = 1;
if (err1 != err2)
return 0;
if (!gdb_value_equal (val1, val2, &r))
{
if (err1 == err2)
{
return 1;
}
else
{
return 0;
}
}
return r;
}
static struct varobj_changelist *
varobj_changelist_init ()
{
struct varobj_changelist *result =
(struct varobj_changelist *) xmalloc (sizeof (struct varobj_changelist *));
result->tail = NULL;
result->head = NULL;
return result;
}
static void
varobj_add_to_changelist (struct varobj_changelist *changelist,
struct varobj *var,
enum varobj_type_change type_changed)
{
struct varobj_changelist_elem *s;
s = (struct varobj_changelist_elem *)
xmalloc (sizeof (struct varobj_changelist_elem));
s->var = var;
s->type_changed = type_changed;
s->next = NULL;
if (changelist->head == NULL)
{
changelist->head = s;
changelist->tail = s;
}
else
{
changelist->tail->next = s;
changelist->tail = s;
}
}
struct varobj *
varobj_changelist_pop (struct varobj_changelist *changelist,
enum varobj_type_change *type_changed)
{
struct varobj_changelist_elem *s;
struct varobj *v;
if (changelist->head == NULL)
{
xfree (changelist);
return NULL;
}
s = changelist->head;
changelist->head = s->next;
v = s->var;
if (type_changed != NULL)
*type_changed = s->type_changed;
xfree (s);
return v;
}
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;
}
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;
}
static void
cppush (struct cpstack **pstack, char *name)
{
struct cpstack *s;
s = (struct cpstack *) xmalloc (sizeof (struct cpstack));
s->name = name;
s->next = *pstack;
*pstack = s;
}
static char *
cppop (struct cpstack **pstack)
{
struct cpstack *s;
char *v;
if ((*pstack)->name == NULL && (*pstack)->next == NULL)
return NULL;
s = *pstack;
v = s->name;
*pstack = (*pstack)->next;
xfree (s);
return v;
}
static enum varobj_languages
variable_language (struct varobj *var)
{
enum varobj_languages lang;
if (var->root->exp == NULL)
return vlang_c;
switch (var->root->exp->language_defn->la_language)
{
default:
case language_c:
lang = vlang_c;
break;
case language_objcplus:
case language_cplus:
lang = vlang_cplus;
break;
case language_java:
lang = vlang_java;
break;
}
return lang;
}
static int
number_of_children (struct varobj *var)
{
return (*var->root->lang->number_of_children) (var);;
}
static char *
name_of_variable (struct varobj *var)
{
return var->name;
}
static char *
path_expr_of_root (struct varobj *var)
{
char *path_expr = var->name;
char *dynamic_expr;
int dynamic_expr_len;
int root_name_len;
if (var->root->lang->language != vlang_cplus
&& var->root->lang->language != vlang_c)
return path_expr;
if (varobj_use_dynamic_type != 0
&& var->dynamic_type != NULL
&& var->dynamic_type != var->type)
{
struct type *root_type = NULL;
int root_is_ptr;
root_type = get_type_deref (var, &root_is_ptr);
if (root_is_ptr)
{
const char *format = "(('%s' *) (%s))";
dynamic_expr = TYPE_NAME (root_type);
if (dynamic_expr)
{
dynamic_expr_len = strlen (dynamic_expr);
if (dynamic_expr_len > 0)
{
root_name_len = strlen (var->name);
path_expr = (char *) xmalloc (dynamic_expr_len + root_name_len +
strlen (format) - 3);
sprintf (path_expr, format, dynamic_expr, var->name);
}
}
}
}
return path_expr;
}
static char *
path_expr_of_variable (struct varobj *var)
{
if (var->path_expr != NULL
&& (! is_root_p (var)))
return var->path_expr;
else if (is_root_p (var))
return path_expr_of_root (var);
else if (var->elide_in_expr)
{
if (CPLUS_FAKE_CHILD (var->parent))
var->path_expr = xstrdup (path_expr_of_variable (var->parent->parent));
else
var->path_expr = xstrdup (path_expr_of_variable (var->parent));
return var->path_expr;
}
else
return path_expr_of_child (var->parent, var->index);
}
static char *
make_name_of_child (struct varobj *var, int index)
{
return (*var->root->lang->make_name_of_child) (var, index);
}
static char *
path_expr_of_child (struct varobj *var, int index)
{
return (*var->root->lang->path_expr_of_child) (var, index);
}
int
varobj_type_is_equal_p (struct varobj *old_var, struct varobj *new_var)
{
char *old_type, *new_type;
int result;
if (old_var->type == NULL || new_var->type == NULL)
return 0;
old_type = varobj_get_type (old_var);
new_type = varobj_get_type (new_var);
result = (strcmp (old_type, new_type) == 0);
xfree (old_type);
xfree (new_type);
return result;
}
static struct value *
value_of_root (struct varobj **var_handle, enum varobj_type_change *type_changed)
{
struct varobj *var;
if (var_handle == NULL)
return NULL;
var = *var_handle;
if (var->root->rootvar != var)
return NULL;
if (var->root->use_selected_frame || get_type (var) == NULL)
{
struct varobj *tmp_var;
tmp_var = varobj_create (NULL, name_of_variable (var), (CORE_ADDR) 0, NULL,
USE_SELECTED_FRAME);
if (tmp_var == NULL)
{
return NULL;
}
else if (tmp_var->root->exp == NULL || tmp_var->type == NULL)
{
free_variable (tmp_var);
return NULL;
}
if (varobj_type_is_equal_p (tmp_var, var))
{
if (!frame_id_eq (tmp_var->root->frame, var->root->frame))
{
*type_changed = VAROBJ_SCOPE_CHANGED;
}
else if ((var->root->valid_block != NULL
&& tmp_var->root->valid_block != NULL)
&& ((var->root->valid_block->startaddr
!= tmp_var->root->valid_block->startaddr)
|| (var->root->valid_block->endaddr
!= tmp_var->root->valid_block->endaddr)))
{
*type_changed = VAROBJ_SCOPE_CHANGED;
}
else if (tmp_var->root->in_scope
&& !var->root->in_scope)
{
*type_changed = VAROBJ_SCOPE_CHANGED;
}
else
{
varobj_delete (tmp_var, NULL, 0);
*type_changed = VAROBJ_TYPE_UNCHANGED;
}
}
else
*type_changed = VAROBJ_TYPE_CHANGED;
if (*type_changed != VAROBJ_TYPE_UNCHANGED)
{
tmp_var->obj_name =
savestring (var->obj_name, strlen (var->obj_name));
varobj_delete (var, NULL, 0);
install_variable (tmp_var);
*var_handle = tmp_var;
var = *var_handle;
}
}
else
{
*type_changed = VAROBJ_TYPE_UNCHANGED;
if (!varobj_pc_in_valid_block_p (var))
{
if (var->root->in_scope == 1)
*type_changed = VAROBJ_SCOPE_CHANGED;
return NULL;
}
}
return (*var->root->lang->value_of_root) (var_handle, type_changed);
}
int
varobj_pc_in_valid_block_p (struct varobj *var)
{
struct frame_info *fi;
CORE_ADDR cur_pc;
if (var->root->valid_block == NULL)
return 1;
fi = frame_find_by_id (var->root->frame);
if (fi != NULL)
{
cur_pc = get_frame_pc (fi);
if (frame_relative_level (fi) > 0)
cur_pc -= 1;
return (block_contains_pc (var->root->valid_block, cur_pc));
}
else
{
return 0;
}
return 1;
}
static struct value *
value_of_child (struct varobj *parent, int index,
enum varobj_type_change *type_changed)
{
struct value *value;
struct varobj *child;
int lookup_dynamic_type;
*type_changed = VAROBJ_TYPE_UNCHANGED;
value = (*parent->root->lang->value_of_child) (parent, index, &lookup_dynamic_type);
child = child_exists (parent, index);
if (child == NULL)
error ("value_of_child called with a NULL child");
if (value == NULL)
return value;
if (lookup_dynamic_type)
{
struct type *dynamic_type;
struct value *new_value;
char *dynamic_type_name;
new_value = varobj_fixup_value (value, varobj_use_dynamic_type,
child->root->valid_block,
&dynamic_type, &dynamic_type_name);
if (new_value != value)
{
value_free (value);
release_value (new_value);
value = new_value;
}
if (dynamic_type != child->dynamic_type)
{
child->dynamic_type = dynamic_type;
if (child->dynamic_type_name != NULL)
{
xfree (child->dynamic_type_name);
child->dynamic_type_name = NULL;
}
*type_changed = VAROBJ_DYNAMIC_TYPE_CHANGED;
}
if (child->dynamic_type == NULL)
{
if (child->dynamic_type_name == NULL)
{
if (dynamic_type_name != NULL)
{
child->dynamic_type_name = dynamic_type_name;
*type_changed = VAROBJ_DYNAMIC_TYPE_CHANGED;
}
}
else
{
if (dynamic_type_name == NULL
|| strcmp (child->dynamic_type_name, dynamic_type_name) != 0)
{
xfree (child->dynamic_type_name);
child->dynamic_type_name = dynamic_type_name;
*type_changed = VAROBJ_DYNAMIC_TYPE_CHANGED;
}
}
}
}
if (value != NULL && value_lazy (value))
{
if (!gdb_value_fetch_lazy (value))
value = NULL;
}
return value;
}
static struct type *
type_of_child (struct varobj *var)
{
if (var->value != NULL)
return value_type (var->value);
return (*var->root->lang->type_of_child) (var->parent, var->index);
}
static int
variable_editable (struct varobj *var)
{
return (*var->root->lang->variable_editable) (var);
}
static char *
my_value_of_variable (struct varobj *var)
{
return (*var->root->lang->value_of_variable) (var);
}
static int
varobj_value_is_changeable_p (struct varobj *var)
{
int r;
struct type *type;
if (CPLUS_FAKE_CHILD (var))
return 0;
type = get_type (var);
if (type == NULL)
return 0;
switch (TYPE_CODE (type))
{
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
case TYPE_CODE_ARRAY:
r = 0;
break;
default:
r = 1;
}
return r;
}
static int
c_number_of_children (struct varobj *var)
{
struct type *type;
struct type *target;
int children;
type = get_type (var);
if (type == NULL)
return -1;
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)
children = TYPE_LENGTH (type) / TYPE_LENGTH (target);
else
children = -1;
break;
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
children = TYPE_NFIELDS (type);
break;
case TYPE_CODE_PTR:
case TYPE_CODE_REF:
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;
}
break;
default:
break;
}
return children;
}
static char *
c_make_name_of_child (struct varobj *parent, int index)
{
struct type *type;
struct type *target;
char *name;
char *string;
type = get_type (parent);
target = get_target_type (type);
switch (TYPE_CODE (type))
{
case TYPE_CODE_ARRAY:
name = xstrprintf ("%d", index);
break;
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
string = TYPE_FIELD_NAME (type, index);
name = savestring (string, strlen (string));
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;
default:
name = xstrprintf ("*%s", parent->name);
break;
}
break;
case TYPE_CODE_REF:
switch (TYPE_CODE (target))
{
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
string = TYPE_FIELD_NAME (target, index);
name = savestring (string, strlen (string));
break;
default:
name = xstrprintf ("*%s", parent->name);
break;
}
break;
default:
name = xstrdup ("???");
}
return name;
}
static char *
c_path_expr_of_child (struct varobj *parent, int index)
{
char *path_expr = NULL;
struct varobj *child = child_exists (parent, index);
char *parent_expr;
char *name;
int parent_len, child_len, len;
if (child == NULL)
error ("c_path_expr_of_child: "
"Tried to get path expression for a null child.");
parent_expr = path_expr_of_variable (parent);
name = name_of_variable (child);
if (name == NULL || strlen (name) == 0)
return parent_expr;
parent_len = strlen (parent_expr);
child_len = strlen (name);
len = parent_len + child_len + 2 + 1;
switch (parent->join_in_expr)
{
case VAROBJ_AS_ARRAY:
{
len += 2;
path_expr = (char *) xmalloc (len);
sprintf (path_expr, "(%s)[%s]", parent_expr, name);
}
break;
case VAROBJ_AS_STRUCT:
len += 1;
path_expr = (char *) xmalloc (len);
sprintf (path_expr, "(%s).%s", parent_expr, name);
break;
case VAROBJ_AS_PTR_TO_STRUCT:
len += 2;
path_expr = (char *) xmalloc (len);
sprintf (path_expr, "(%s)->%s", parent_expr, name);
break;
case VAROBJ_AS_PTR_TO_SCALAR:
len += parent_len + 2 + 1 + 1;
path_expr = (char *) xmalloc (len);
sprintf (path_expr, "*(%s)", parent_expr);
break;
case VAROBJ_AS_DUNNO:
len = 5;
path_expr =
(char *) xmalloc (len);
sprintf (path_expr, "????");
}
child->path_expr = path_expr;
return path_expr;
}
static struct value *
c_value_of_root (struct varobj **var_handle, enum varobj_type_change *type_changed)
{
struct value *new_val;
struct varobj *var = *var_handle;
struct frame_info *fi;
int within_scope;
struct value *ret_value = NULL;
if (var->root->rootvar != var)
return NULL;
if (var->root->valid_block == NULL)
within_scope = 1;
else
{
reinit_frame_cache ();
fi = frame_find_by_id (var->root->frame);
within_scope = fi != NULL;
if (within_scope)
select_frame (fi);
}
if (within_scope)
{
struct cleanup *schedlock_chain;
schedlock_chain = make_cleanup_set_restore_scheduler_locking_mode (scheduler_locking_on);
if (varobj_evaluate_expression (var->root->exp, &new_val))
{
struct type *dynamic_type;
char *dynamic_type_name;
new_val = varobj_fixup_value (new_val, varobj_use_dynamic_type,
var->root->valid_block,
&dynamic_type, &dynamic_type_name);
if (varobj_use_dynamic_type)
{
if (var->dynamic_type != dynamic_type)
{
*type_changed = VAROBJ_DYNAMIC_TYPE_CHANGED;
var->dynamic_type = dynamic_type;
xfree (var->dynamic_type_name);
var->dynamic_type_name = NULL;
varobj_delete (var, NULL, 1);
var->num_children = number_of_children (var);
}
if (var->dynamic_type == NULL)
{
if (var->dynamic_type_name == NULL)
{
if (dynamic_type_name != NULL)
{
*type_changed = VAROBJ_DYNAMIC_TYPE_CHANGED;
var->dynamic_type_name = dynamic_type_name;
}
}
else
{
if (dynamic_type_name == NULL
|| strcmp (dynamic_type_name, var->dynamic_type_name) != 0)
{
*type_changed = VAROBJ_DYNAMIC_TYPE_CHANGED;
xfree (var->dynamic_type_name);
var->dynamic_type_name = dynamic_type_name;
}
}
}
}
if (value_lazy (new_val))
{
if (!gdb_value_fetch_lazy (new_val))
var->error = 1;
else
var->error = 0;
}
release_value (new_val);
ret_value = new_val;
}
else
{
var->error = 1;
}
do_cleanups (schedlock_chain);
}
return ret_value;
}
static struct type *
varobj_lookup_struct_elt_type_by_index (struct varobj *parent, int index)
{
struct type *type;
int type_index;
char *type_for_printing;
if (CPLUS_FAKE_CHILD (parent))
{
type_index = varobj_get_type_index_from_fake_child (parent, index);
type = get_type (parent->parent);
}
else
{
type = get_type (parent);
type_index = index;
}
for (;;)
{
CHECK_TYPEDEF (type);
if (TYPE_CODE (type) != TYPE_CODE_PTR
&& TYPE_CODE (type) != TYPE_CODE_REF)
break;
type = TYPE_TARGET_TYPE (type);
}
if (TYPE_CODE (type) != TYPE_CODE_STRUCT &&
TYPE_CODE (type) != TYPE_CODE_UNION)
{
target_terminal_ours ();
gdb_flush (gdb_stdout);
type_for_printing = type_sprint (type, "", -1);
make_cleanup (xfree, type_for_printing);
error ("Type %s is not a structure or union type.", type_for_printing);
}
return TYPE_FIELD_TYPE (type, type_index);
}
static int
varobj_value_struct_elt_by_index (struct varobj *parent, int index, struct value **ret_val)
{
struct type *t;
struct value *value;
struct value *parent_value;
int type_index;
volatile struct gdb_exception e;
if (CPLUS_FAKE_CHILD (parent))
parent_value = parent->parent->value;
else
parent_value = parent->value;
parent_value = coerce_array (parent_value);
t = check_typedef (value_type (parent_value));
while (TYPE_CODE (t) == TYPE_CODE_PTR || TYPE_CODE (t) == TYPE_CODE_REF)
{
parent_value = value_ind (parent_value);
if (TYPE_CODE (value_type (parent_value)) != TYPE_CODE_FUNC)
parent_value = coerce_array (parent_value);
t = check_typedef (value_type (parent_value));
}
if (TYPE_CODE (t) == TYPE_CODE_MEMBER)
error (_("not implemented: member type in varobj_value_struct_elt_by_index"));
if (TYPE_CODE (t) != TYPE_CODE_STRUCT
&& TYPE_CODE (t) != TYPE_CODE_UNION)
error (_("Attempt to extract a component of a value that is not a struct or union."));
type_index = varobj_get_type_index_from_fake_child (parent, index);
TRY_CATCH (e, RETURN_MASK_ERROR)
{
if (TYPE_FIELD_STATIC (t, type_index))
value = value_static_field (t, type_index);
else
value = value_primitive_field (parent_value, 0, type_index, t);
}
if (e.reason < 0)
{
*ret_val = NULL;
return 0;
}
else
{
*ret_val = value;
return 1;
}
}
static int
varobj_get_type_index_from_fake_child (struct varobj *parent, int index)
{
struct type* type;
int type_index = -1;
if (!CPLUS_FAKE_CHILD (parent))
{
return index;
}
else
{
type = get_type_deref (parent->parent, NULL);
}
if (TYPE_CODE (type) != TYPE_CODE_STRUCT
&& TYPE_CODE_UNION)
return index;
type_index = TYPE_N_BASECLASSES (type);
if (strcmp (parent->name, "private") == 0)
{
while (index >= 0)
{
if (TYPE_VPTR_BASETYPE (type) == type
&& type_index == TYPE_VPTR_FIELDNO (type))
;
else if (TYPE_FIELD_STATIC (type, type_index))
;
else if (TYPE_FIELD_PRIVATE (type, type_index))
--index;
++type_index;
}
--type_index;
}
else if (strcmp (parent->name, "protected") == 0)
{
while (index >= 0)
{
if (TYPE_VPTR_BASETYPE (type) == type
&& type_index == TYPE_VPTR_FIELDNO (type))
;
else if (TYPE_FIELD_STATIC (type, type_index))
;
else if (TYPE_FIELD_PROTECTED (type, type_index))
--index;
++type_index;
}
--type_index;
}
else
{
while (index >= 0)
{
if (TYPE_VPTR_BASETYPE (type) == type
&& type_index == TYPE_VPTR_FIELDNO (type))
;
else if (TYPE_FIELD_STATIC (type, type_index))
;
else if (!TYPE_FIELD_PRIVATE (type, type_index) &&
!TYPE_FIELD_PROTECTED (type, type_index))
--index;
++type_index;
}
--type_index;
}
return type_index;
}
static struct value *
c_value_of_child (struct varobj *parent, int index, int *lookup_dynamic_type)
{
struct value *value;
struct value *temp;
struct value *indval;
struct type *type, *target;
struct varobj *child;
char *name;
if (lookup_dynamic_type != NULL)
{
switch (parent->root->exp->language_defn->la_language)
{
case language_objc:
case language_objcplus:
case language_cplus:
case language_java:
*lookup_dynamic_type = 1;
break;
case language_c:
default:
*lookup_dynamic_type = 0;
break;
}
}
type = get_type (parent);
target = get_target_type (type);
child = child_exists (parent, index);
if (child == NULL)
error ("c_value_of_child: called with NULL child");
name = name_of_variable (child);
temp = parent->value;
value = NULL;
if (temp != NULL)
{
switch (TYPE_CODE (type))
{
case TYPE_CODE_ARRAY:
#if 0
value = value_slice (temp, index, 1);
temp = value_coerce_array (value);
gdb_value_ind (temp, &value);
#else
indval = value_from_longest (builtin_type_int, (LONGEST) index);
gdb_value_subscript (temp, indval, &value);
#endif
break;
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
varobj_value_struct_elt_by_index (parent, index, &value);
break;
case TYPE_CODE_PTR:
case TYPE_CODE_REF:
switch (TYPE_CODE (target))
{
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
varobj_value_struct_elt_by_index (parent, index, &value);
break;
default:
if (TYPE_CODE (type) == TYPE_CODE_PTR)
{
if (!gdb_value_ind (temp, &value))
{
if (value != NULL)
release_value (value);
return NULL;
}
}
else if (TYPE_CODE (type) == TYPE_CODE_REF)
{
value = value_copy (temp);
value = coerce_ref (value);
}
break;
}
break;
default:
break;
}
}
if (value != NULL)
release_value (value);
return value;
}
static struct type *
c_type_of_child (struct varobj *parent, int index)
{
struct type *type;
struct varobj *child;
struct type *parent_type = get_type (parent);
struct type *target_type;
char *name;
child = child_exists (parent, index);
if (child == NULL)
error ("c_type_of_child: called with a NULL child.");
name = name_of_variable (child);
switch (TYPE_CODE (parent_type))
{
case TYPE_CODE_ARRAY:
type = TYPE_TARGET_TYPE (check_typedef(parent->type));
break;
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
type = varobj_lookup_struct_elt_type_by_index (parent, index);
break;
case TYPE_CODE_PTR:
case TYPE_CODE_REF:
target_type = check_typedef (get_target_type (parent_type));
switch (TYPE_CODE (target_type))
{
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
type = varobj_lookup_struct_elt_type_by_index (parent, index);
break;
default:
type = target_type;
break;
}
break;
default:
warning (_("Child of parent whose type does not allow children"));
type = NULL;
error ("Child of parent: \"%s\" whose type: \"%d\" does not allow children",
name_of_variable (parent), TYPE_CODE (parent_type));
break;
}
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)
{
switch (TYPE_CODE (get_type (var)))
{
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
return xstrdup ("{...}");
case TYPE_CODE_ARRAY:
{
char *number;
number = xstrprintf ("[%d]", varobj_get_num_children (var));
return (number);
}
default:
{
if (var->value == NULL)
{
return NULL;
}
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], 0, 0, 0);
thevalue = ui_file_xstrdup (stb, &dummy);
do_cleanups (old_chain);
return thevalue;
}
}
}
}
static int
cplus_number_of_children (struct varobj *var)
{
struct type *type;
int children, dont_know;
dont_know = 1;
children = 0;
if (!CPLUS_FAKE_CHILD (var))
{
type = get_type_deref (var, NULL);
if (type == NULL)
{
return -1;
}
else 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++;
children += TYPE_N_BASECLASSES (type);
dont_know = 0;
}
}
else
{
int kids[3];
type = get_type_deref (var->parent, NULL);
cplus_class_num_children (type, kids);
if (strcmp (name_of_variable (var), "public") == 0)
children = kids[v_public];
else if (strcmp (name_of_variable (var), "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;
}
static void
cplus_class_num_children (struct type *type, int children[3])
{
int i;
children[v_public] = 0;
children[v_private] = 0;
children[v_protected] = 0;
for (i = TYPE_N_BASECLASSES (type); i < TYPE_NFIELDS (type); i++)
{
if (TYPE_VPTR_BASETYPE (type) == type && TYPE_VPTR_FIELDNO (type) == i)
continue;
if (TYPE_FIELD_STATIC (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 int
cplus_real_type_index_for_fake_child_index (struct type *type,
enum vsections prot,
int num)
{
int num_found = 0;
int foundit = 0;
int i = 0;
switch (prot)
{
case v_public:
for (i = TYPE_N_BASECLASSES (type); i < TYPE_NFIELDS (type); i++)
{
if (TYPE_VPTR_BASETYPE (type) == type
&& TYPE_VPTR_FIELDNO (type) == i)
continue;
if (TYPE_FIELD_STATIC (type, i))
continue;
if (!TYPE_FIELD_PROTECTED (type, i)
&& !TYPE_FIELD_PRIVATE (type, i))
{
if (num_found == num)
{
foundit = 1;
break;
}
else
num_found++;
}
}
break;
case v_protected:
for (i = TYPE_N_BASECLASSES (type); i < TYPE_NFIELDS (type); i++)
{
if (TYPE_VPTR_BASETYPE (type) == type
&& TYPE_VPTR_FIELDNO (type) == i)
continue;
if (TYPE_FIELD_STATIC (type, i))
continue;
if (TYPE_FIELD_PROTECTED (type, i))
{
if (num_found == num)
{
foundit = 1;
break;
}
else
num_found++;
}
}
break;
case v_private:
for (i = TYPE_N_BASECLASSES (type); i < TYPE_NFIELDS (type); i++)
{
if (TYPE_VPTR_BASETYPE (type) == type
&& TYPE_VPTR_FIELDNO (type) == i)
continue;
if (TYPE_FIELD_STATIC (type, i))
continue;
if (TYPE_FIELD_PRIVATE (type, i))
{
if (num_found == num)
{
foundit = 1;
break;
}
else
num_found++;
}
}
break;
}
if (!foundit)
return -1;
return i;
}
static char *
cplus_make_name_of_child (struct varobj *parent, int index)
{
char *name;
struct type *type;
if (CPLUS_FAKE_CHILD (parent))
{
type = get_type_deref (parent->parent, NULL);
}
else
type = get_type_deref (parent, NULL);
name = NULL;
switch (TYPE_CODE (type))
{
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
if (CPLUS_FAKE_CHILD (parent))
{
int type_index = varobj_get_type_index_from_fake_child (parent, index);
name = TYPE_FIELD_NAME (type, type_index);
}
else if (index < TYPE_N_BASECLASSES (type))
name = TYPE_FIELD_NAME (type, index);
else
{
int children[3];
cplus_class_num_children(type, children);
index -= TYPE_N_BASECLASSES (type);
switch (index)
{
case 0:
if (children[v_public] > 0)
name = "public";
else if (children[v_private] > 0)
name = "private";
else
name = "protected";
break;
case 1:
if (children[v_public] > 0)
{
if (children[v_private] > 0)
name = "private";
else
name = "protected";
}
else if (children[v_private] > 0)
name = "protected";
break;
case 2:
name = "protected";
break;
default:
break;
}
if (name == NULL)
return NULL;
}
break;
default:
break;
}
if (name == NULL)
return c_make_name_of_child (parent, index);
else
{
if (name != NULL)
name = savestring (name, strlen (name));
}
return name;
}
static char *
cplus_path_expr_of_child (struct varobj *parent, int index)
{
char *path_expr;
struct type *type;
int children[3];
struct varobj *child = child_exists (parent, index);
char *parent_expr = path_expr_of_variable (parent);
int parent_len = strlen (parent_expr);
int child_len;
char *child_name;
int is_ptr;
if (child == NULL)
error ("cplus_path_expr_of_child: "
"Tried to get path expression for a null child.");
if (name_of_variable (child) == NULL ||
strlen (name_of_variable (child)) == 0)
return parent_expr;
if (CPLUS_FAKE_CHILD (child))
return parent_expr;
if (CPLUS_FAKE_CHILD (parent))
{
type = get_type_deref (parent->parent, &is_ptr);
}
else
type = get_type_deref (parent, &is_ptr);
if (TYPE_RUNTIME (type) == OBJC_RUNTIME)
return c_path_expr_of_child (parent, index);
path_expr = NULL;
switch (TYPE_CODE (type))
{
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
cplus_class_num_children (type, children);
if (CPLUS_FAKE_CHILD (parent))
{
int index_in_type;
enum vsections prot;
char *parent_name = name_of_variable (parent);
int child_is_ptr;
int dynamic_expr_len, join_expr_len;
char *dynamic_expr, *join_expr;
if (strcmp (parent_name, "private") == 0)
prot = v_private;
else if (strcmp (parent_name, "protected") == 0)
prot = v_protected;
else if (strcmp (parent_name, "public") == 0)
prot = v_public;
else
{
error ("cplus_make_name_of_child got a parent with invalid "
"fake child name: \"%s\".", parent_name);
return NULL;
}
index_in_type =
cplus_real_type_index_for_fake_child_index (type, prot, index);
child_name = TYPE_FIELD_NAME (type, index_in_type);
child_len = strlen (child_name);
if (varobj_use_dynamic_type != 0
&& child->dynamic_type != NULL
&& child->dynamic_type != child->type)
{
struct type *child_type = NULL;
child_type = get_type_deref (child, &child_is_ptr);
if (!child_is_ptr)
dynamic_expr_len = 0;
else
{
dynamic_expr = TYPE_NAME (child_type);
dynamic_expr_len = strlen (dynamic_expr);
}
}
else
{
dynamic_expr_len = 0;
}
if (is_ptr)
{
join_expr = "->";
join_expr_len = 2;
}
else
{
join_expr = ".";
join_expr_len = 1;
}
if (dynamic_expr_len > 0)
{
const char *format = "(('%s' *) ((%s)%s%s))";
path_expr = (char *) xmalloc (dynamic_expr_len + parent_len
+ join_expr_len + child_len + strlen (format) - 6 + 1);
sprintf (path_expr, format, dynamic_expr, parent_expr, join_expr, child_name);
}
else
{
const char *format = "((%s)%s%s)";
path_expr = (char *) xmalloc (parent_len + join_expr_len
+ child_len + strlen (format) - 4 + 1);
sprintf (path_expr, format, parent_expr, join_expr, child_name);
}
}
else if (index < TYPE_N_BASECLASSES (type))
{
child_name = TYPE_FIELD_NAME (type, index);
child_len = strlen (child_name);
if (is_ptr)
{
path_expr = (char *) xmalloc (parent_len + child_len + 9 + 1);
sprintf (path_expr, "(('%s' *) %s)", child_name, parent_expr);
}
else
{
path_expr = (char *) xmalloc (parent_len + child_len + 5 + 1);
sprintf (path_expr, "(('%s') %s)", child_name, parent_expr);
}
}
else
{
index -= TYPE_N_BASECLASSES (type);
switch (index)
{
case 0:
if (children[v_public] != 0)
{
path_expr = "public";
break;
}
case 1:
if (children[v_private] != 0)
{
path_expr = "private";
break;
}
case 2:
if (children[v_protected] != 0)
{
path_expr = "protected";
break;
}
default:
break;
}
}
break;
default:
break;
}
if (path_expr == NULL)
return c_path_expr_of_child (parent, index);
else
{
child->path_expr = path_expr;
}
return path_expr;
}
static struct value *
cplus_value_of_root (struct varobj **var_handle, enum varobj_type_change *type_changed)
{
return c_value_of_root (var_handle, type_changed);
}
static struct value *
cplus_value_of_child (struct varobj *parent, int index, int *lookup_dynamic_type)
{
struct type *type;
struct value *value;
int is_ptr;
if (CPLUS_FAKE_CHILD (parent))
type = get_type_deref (parent->parent, &is_ptr);
else
type = get_type_deref (parent, &is_ptr);
if (lookup_dynamic_type != NULL)
*lookup_dynamic_type = 1;
value = NULL;
if (((TYPE_CODE (type)) == TYPE_CODE_STRUCT) ||
((TYPE_CODE (type)) == TYPE_CODE_UNION))
{
if (CPLUS_FAKE_CHILD (parent))
{
enum gdb_rc ret_val;
struct varobj *child;
struct value *temp = parent->parent->value;
if (temp == NULL)
return NULL;
child = child_exists (parent, index);
if (!child)
error ("cplus_value_of_child: "
"Tried to get the value of a null child.");
ret_val = varobj_value_struct_elt_by_index (parent, index, &value);
if (!ret_val)
return NULL;
if (value != NULL)
release_value (value);
}
else if (index >= TYPE_N_BASECLASSES (type))
{
if (lookup_dynamic_type != NULL)
*lookup_dynamic_type = 0;
return NULL;
}
else
{
if (lookup_dynamic_type != NULL)
*lookup_dynamic_type = 0;
if (parent->value != NULL)
{
struct type *cast_type;
enum type_code code;
cast_type = TYPE_FIELD_TYPE (type, index);
code = TYPE_CODE (value_type (parent->value));
if (code == TYPE_CODE_PTR)
{
cast_type = lookup_pointer_type (cast_type);
}
else if (code == TYPE_CODE_REF)
{
cast_type = lookup_reference_type (cast_type);
}
if (cast_type != NULL)
{
struct value *copy = value_copy (parent->value);
value = value_cast (cast_type, copy);
if (copy != value)
{
release_value (copy);
value_free (copy);
}
release_value (value);
}
else
{
return NULL;
}
}
}
}
if (value == NULL)
return c_value_of_child (parent, index, lookup_dynamic_type);
return value;
}
static struct type *
cplus_type_of_child (struct varobj *parent, int index)
{
struct type *type, *t;
int is_ptr;
if (CPLUS_FAKE_CHILD (parent))
t = get_type_deref (parent->parent, &is_ptr);
else
t = get_type_deref (parent, &is_ptr);
type = NULL;
switch (TYPE_CODE (t))
{
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
if (CPLUS_FAKE_CHILD (parent))
{
type = varobj_lookup_struct_elt_type_by_index (parent, index);
}
else if (index < TYPE_N_BASECLASSES (t))
{
type = TYPE_FIELD_TYPE (t, index);
if (is_ptr == 1)
{
type = lookup_pointer_type (type);
}
else if (is_ptr == 2)
{
type = lookup_reference_type (type);
}
}
else
{
return NULL;
}
break;
default:
break;
}
if (type == NULL)
return c_type_of_child (parent, index);
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)
{
if (CPLUS_FAKE_CHILD (var))
return xstrdup ("");
return c_value_of_variable (var);
}
static int
java_number_of_children (struct varobj *var)
{
return cplus_number_of_children (var);
}
static char *
java_make_name_of_child (struct varobj *parent, int index)
{
char *name, *p;
name = cplus_make_name_of_child (parent, index);
p = name;
while (*p != '\000')
{
if (*p == '.')
*p = '-';
p++;
}
return name;
}
static struct value *
java_value_of_root (struct varobj **var_handle, enum varobj_type_change *type_changed)
{
return cplus_value_of_root (var_handle, type_changed);
}
static struct value *
java_value_of_child (struct varobj *parent, int index, int *lookup_dynamic_type)
{
return cplus_value_of_child (parent, index, lookup_dynamic_type);
}
static struct type *
java_type_of_child (struct varobj *parent, int index)
{
return cplus_type_of_child (parent, index);
}
static int
java_variable_editable (struct varobj *var)
{
return cplus_variable_editable (var);
}
static char *
java_value_of_variable (struct varobj *var)
{
return cplus_value_of_variable (var);
}
static char *
java_path_expr_of_child (struct varobj *parent, int index)
{
return cplus_path_expr_of_child (parent, index);
}
extern void _initialize_varobj (void);
void
_initialize_varobj (void)
{
int sizeof_table = sizeof (struct vlist *) * VAROBJ_TABLE_SIZE;
varobj_table = xmalloc (sizeof_table);
memset (varobj_table, 0, sizeof_table);
add_setshow_boolean_cmd ("varobj-print-object", class_obscure,
&varobj_use_dynamic_type, _("\
Set varobj to construct children using the most specific class type."), _("\
abc"), NULL,
NULL, NULL,
&setlist, &showlist);
add_setshow_boolean_cmd ("varobj-runs-all-threads", class_obscure,
&varobj_runs_all_threads, _("\
Set to run all threads when evaluating varobjs."), _("\
Set to run all threads when evaluating varobjs."), NULL,
NULL, NULL,
&setlist, &showlist);
add_setshow_zinteger_cmd ("varobj", class_maintenance,
&varobjdebug, _("\
Set varobj debugging."), _("\
Show varobj debugging."), _("\
When non-zero, varobj debugging is enabled."),
NULL,
show_varobjdebug,
&setdebuglist, &showdebuglist);
}