gdb/
* Makefile.in (SFILES): Add c-varobj.c and jv-varobj.c. (COMMON_OBS): Add c-varobj.o and jv-varobj.o. * ada-varobj.c: Include "varobj.h". (ada_number_of_children): New. Moved from varobj.c. (ada_name_of_variable, ada_name_of_child): Likewise. (ada_path_expr_of_child, ada_value_of_child): Likewise. (ada_type_of_child, ada_value_of_variable): Likewise. (ada_value_is_changeable_p, ada_value_has_mutated): Likewise. (ada_varobj_ops): New. * c-varobj.c, jv-varobj.c: New file. Moved from varobj.c. * gdbtypes.c (get_target_type): New. Moved from varobj.c. * gdbtypes.h (get_target_type): Declare. * varobj.c: Remove the inclusion of "ada-varobj.h" and "ada-lang.h". (ANONYMOUS_STRUCT_NAME): Move it to c-varobj.c. (ANONYMOUS_UNION_NAME): Likewise. (get_type, get_value_type, get_target_type): Remove declarations. (value_get_print_value, varobj_value_get_print_value): Likewise. (c_number_of_children, c_name_of_variable): Likewise. (c_name_of_child, c_path_expr_of_child): Likewise. (c_value_of_child, c_type_of_child): Likewise. (c_value_of_variable, cplus_number_of_children): Likewise. (cplus_class_num_children, cplus_name_of_variable): Likewise. (cplus_name_of_child, cplus_path_expr_of_child): Likewise. (cplus_value_of_child, cplus_type_of_child): Likewise. (cplus_value_of_variable, java_number_of_children): Likewise. (java_name_of_variable, java_name_of_child): Likewise. (java_path_expr_of_child, java_value_of_child): Likewise. (java_type_of_child, java_value_of_variable): Likewise. (ada_number_of_children, ada_name_of_variable): Likewise. (ada_name_of_child, ada_path_expr_of_child): Likewise. (ada_value_of_child, ada_type_of_child): Likewise. (ada_value_of_variable, ada_value_is_changeable_p): Likewise. (ada_value_has_mutated): Likewise. (struct language_specific): Move it to varobj.h. (CPLUS_FAKE_CHILD): Move it to varobj.h. (restrict_range): Rename it varobj_restrict_range. Make it extern. Callers update. (get_path_expr_parent): Rename it to varobj_get_path_expr_parent. Make it extern. (is_anonymous_child): Move it to c-varobj.c and rename to varobj_is_anonymous_child. Caller update. (get_type): Move it to c-varobj.c. (get_value_type): Rename it varobj_get_value_type. Make it extern. (get_target_type): Move it gdbtypes.c. (varobj_formatted_print_options): New function. (value_get_print_value): Rename it to varobj_value_get_print_value and make it extern. (varobj_value_is_changeable_p): Make it extern. (adjust_value_for_child_access): Move it to c-varobj.c. (default_value_is_changeable_p): Rename it to varobj_default_value_is_changeable_p. Make it extern. (c_number_of_children, c_name_of_variable): Move it to c-varobj.c (c_name_of_child, c_path_expr_of_child): Likewise. (c_value_of_child, c_type_of_child): Likewise. (c_value_of_variable, cplus_number_of_children): Likewise. (cplus_class_num_children, cplus_name_of_variable): Likewise. (cplus_name_of_child, cplus_path_expr_of_child): Likewise. (cplus_value_of_child, cplus_type_of_child): Likewise. (cplus_value_of_variable): Likewise. (java_number_of_children, java_name_of_variable): Move it to jv-varobj.c. (java_name_of_child, java_path_expr_of_child): Likewise. (java_value_of_child, java_type_of_child): Likewise. (java_value_of_variable): Likewise. (ada_number_of_children, ada_name_of_variable): Move it to ada-varobj.c. (ada_name_of_child, ada_path_expr_of_child): Likewise. (ada_value_of_child, ada_type_of_child): Likewise. (ada_value_of_variable, ada_value_is_changeable_p): Likewise. (ada_value_has_mutated): Likewise. * varobj.h (CPLUS_FAKE_CHILD): New macro, moved from varobj.c. (struct lang_varobj_ops): New. Renamed by 'struct language_specific'. (c_varobj_ops, cplus_varobj_ops): Declare. (java_varobj_ops, ada_varobj_ops): Declare. (varobj_default_value_is_changeable_p): Declare. (varobj_value_is_changeable_p): Declare. (varobj_get_value_type, varobj_is_anonymous_child): Declare. (varobj_get_path_expr_parent): Declare. (varobj_value_get_print_value): Declare. (varobj_formatted_print_options): Declare. (varobj_restrict_range): Declare.
This commit is contained in:
parent
c8a62302a5
commit
99ad94278d
|
@ -1,3 +1,87 @@
|
|||
2013-10-17 Yao Qi <yao@codesourcery.com>
|
||||
|
||||
* Makefile.in (SFILES): Add c-varobj.c and jv-varobj.c.
|
||||
(COMMON_OBS): Add c-varobj.o and jv-varobj.o.
|
||||
* ada-varobj.c: Include "varobj.h".
|
||||
(ada_number_of_children): New. Moved from varobj.c.
|
||||
(ada_name_of_variable, ada_name_of_child): Likewise.
|
||||
(ada_path_expr_of_child, ada_value_of_child): Likewise.
|
||||
(ada_type_of_child, ada_value_of_variable): Likewise.
|
||||
(ada_value_is_changeable_p, ada_value_has_mutated): Likewise.
|
||||
(ada_varobj_ops): New.
|
||||
* c-varobj.c, jv-varobj.c: New file. Moved from varobj.c.
|
||||
* gdbtypes.c (get_target_type): New. Moved from varobj.c.
|
||||
* gdbtypes.h (get_target_type): Declare.
|
||||
* varobj.c: Remove the inclusion of "ada-varobj.h" and
|
||||
"ada-lang.h".
|
||||
(ANONYMOUS_STRUCT_NAME): Move it to c-varobj.c.
|
||||
(ANONYMOUS_UNION_NAME): Likewise.
|
||||
(get_type, get_value_type, get_target_type): Remove declarations.
|
||||
(value_get_print_value, varobj_value_get_print_value): Likewise.
|
||||
(c_number_of_children, c_name_of_variable): Likewise.
|
||||
(c_name_of_child, c_path_expr_of_child): Likewise.
|
||||
(c_value_of_child, c_type_of_child): Likewise.
|
||||
(c_value_of_variable, cplus_number_of_children): Likewise.
|
||||
(cplus_class_num_children, cplus_name_of_variable): Likewise.
|
||||
(cplus_name_of_child, cplus_path_expr_of_child): Likewise.
|
||||
(cplus_value_of_child, cplus_type_of_child): Likewise.
|
||||
(cplus_value_of_variable, java_number_of_children): Likewise.
|
||||
(java_name_of_variable, java_name_of_child): Likewise.
|
||||
(java_path_expr_of_child, java_value_of_child): Likewise.
|
||||
(java_type_of_child, java_value_of_variable): Likewise.
|
||||
(ada_number_of_children, ada_name_of_variable): Likewise.
|
||||
(ada_name_of_child, ada_path_expr_of_child): Likewise.
|
||||
(ada_value_of_child, ada_type_of_child): Likewise.
|
||||
(ada_value_of_variable, ada_value_is_changeable_p): Likewise.
|
||||
(ada_value_has_mutated): Likewise.
|
||||
(struct language_specific): Move it to varobj.h.
|
||||
(CPLUS_FAKE_CHILD): Move it to varobj.h.
|
||||
(restrict_range): Rename it varobj_restrict_range. Make it extern.
|
||||
Callers update.
|
||||
(get_path_expr_parent): Rename it to varobj_get_path_expr_parent.
|
||||
Make it extern.
|
||||
(is_anonymous_child): Move it to c-varobj.c and rename to
|
||||
varobj_is_anonymous_child. Caller update.
|
||||
(get_type): Move it to c-varobj.c.
|
||||
(get_value_type): Rename it varobj_get_value_type. Make it
|
||||
extern.
|
||||
(get_target_type): Move it gdbtypes.c.
|
||||
(varobj_formatted_print_options): New function.
|
||||
(value_get_print_value): Rename it to
|
||||
varobj_value_get_print_value and make it extern.
|
||||
(varobj_value_is_changeable_p): Make it extern.
|
||||
(adjust_value_for_child_access): Move it to c-varobj.c.
|
||||
(default_value_is_changeable_p): Rename it to
|
||||
varobj_default_value_is_changeable_p. Make it extern.
|
||||
(c_number_of_children, c_name_of_variable): Move it to c-varobj.c
|
||||
(c_name_of_child, c_path_expr_of_child): Likewise.
|
||||
(c_value_of_child, c_type_of_child): Likewise.
|
||||
(c_value_of_variable, cplus_number_of_children): Likewise.
|
||||
(cplus_class_num_children, cplus_name_of_variable): Likewise.
|
||||
(cplus_name_of_child, cplus_path_expr_of_child): Likewise.
|
||||
(cplus_value_of_child, cplus_type_of_child): Likewise.
|
||||
(cplus_value_of_variable): Likewise.
|
||||
(java_number_of_children, java_name_of_variable): Move it to jv-varobj.c.
|
||||
(java_name_of_child, java_path_expr_of_child): Likewise.
|
||||
(java_value_of_child, java_type_of_child): Likewise.
|
||||
(java_value_of_variable): Likewise.
|
||||
(ada_number_of_children, ada_name_of_variable): Move it to ada-varobj.c.
|
||||
(ada_name_of_child, ada_path_expr_of_child): Likewise.
|
||||
(ada_value_of_child, ada_type_of_child): Likewise.
|
||||
(ada_value_of_variable, ada_value_is_changeable_p): Likewise.
|
||||
(ada_value_has_mutated): Likewise.
|
||||
* varobj.h (CPLUS_FAKE_CHILD): New macro, moved from varobj.c.
|
||||
(struct lang_varobj_ops): New. Renamed by 'struct language_specific'.
|
||||
(c_varobj_ops, cplus_varobj_ops): Declare.
|
||||
(java_varobj_ops, ada_varobj_ops): Declare.
|
||||
(varobj_default_value_is_changeable_p): Declare.
|
||||
(varobj_value_is_changeable_p): Declare.
|
||||
(varobj_get_value_type, varobj_is_anonymous_child): Declare.
|
||||
(varobj_get_path_expr_parent): Declare.
|
||||
(varobj_value_get_print_value): Declare.
|
||||
(varobj_formatted_print_options): Declare.
|
||||
(varobj_restrict_range): Declare.
|
||||
|
||||
2013-10-17 Luis Machado <lgustavo@codesourcery.com>
|
||||
|
||||
* target/waitstatus.h (target_waitkind): Remove spurious
|
||||
|
|
|
@ -721,7 +721,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
|
|||
block.c blockframe.c \
|
||||
breakpoint.c break-catch-sig.c break-catch-throw.c \
|
||||
build-id.c buildsym.c \
|
||||
c-exp.y c-lang.c c-typeprint.c c-valprint.c \
|
||||
c-exp.y c-lang.c c-typeprint.c c-valprint.c c-varobj.c \
|
||||
charset.c cleanups.c cli-out.c coffread.c coff-pe-read.c \
|
||||
complaints.c completer.c continuations.c corefile.c corelow.c \
|
||||
cp-abi.c cp-support.c cp-namespace.c cp-valprint.c \
|
||||
|
@ -742,7 +742,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
|
|||
infcmd.c inflow.c infrun.c \
|
||||
inline-frame.c \
|
||||
interps.c \
|
||||
jv-exp.y jv-lang.c jv-valprint.c jv-typeprint.c \
|
||||
jv-exp.y jv-lang.c jv-valprint.c jv-typeprint.c jv-varobj.c \
|
||||
language.c linespec.c minidebug.c \
|
||||
m2-exp.y m2-lang.c m2-typeprint.c m2-valprint.c \
|
||||
macrotab.c macroexp.c macrocmd.c macroscope.c main.c maint.c \
|
||||
|
@ -926,11 +926,11 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
|
|||
dwarf2read.o mipsread.o stabsread.o corefile.o \
|
||||
dwarf2expr.o dwarf2loc.o dwarf2-frame.o dwarf2-frame-tailcall.o \
|
||||
ada-lang.o c-lang.o d-lang.o f-lang.o objc-lang.o \
|
||||
ada-tasks.o ada-varobj.o \
|
||||
ada-tasks.o ada-varobj.o c-varobj.o \
|
||||
ui-out.o cli-out.o \
|
||||
varobj.o vec.o \
|
||||
go-lang.o go-valprint.o go-typeprint.o \
|
||||
jv-lang.o jv-valprint.o jv-typeprint.o \
|
||||
jv-lang.o jv-valprint.o jv-typeprint.o jv-varobj.o \
|
||||
m2-lang.o opencl-lang.o p-lang.o p-typeprint.o p-valprint.o \
|
||||
sentinel-frame.o \
|
||||
complaints.o typeprint.o \
|
||||
|
|
137
gdb/ada-varobj.c
137
gdb/ada-varobj.c
|
@ -20,6 +20,7 @@
|
|||
#include "defs.h"
|
||||
#include "ada-varobj.h"
|
||||
#include "ada-lang.h"
|
||||
#include "varobj.h"
|
||||
#include "language.h"
|
||||
#include "valprint.h"
|
||||
|
||||
|
@ -885,4 +886,140 @@ ada_varobj_get_value_of_variable (struct value *value,
|
|||
return result;
|
||||
}
|
||||
|
||||
/* 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_varobj_ops.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_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;
|
||||
|
||||
varobj_formatted_print_options (&opts, format);
|
||||
|
||||
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 varobj_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. */
|
||||
|
||||
varobj_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;
|
||||
}
|
||||
|
||||
/* varobj operations for ada. */
|
||||
|
||||
const struct lang_varobj_ops ada_varobj_ops =
|
||||
{
|
||||
ada_number_of_children,
|
||||
ada_name_of_variable,
|
||||
ada_name_of_child,
|
||||
ada_path_expr_of_child,
|
||||
ada_value_of_child,
|
||||
ada_type_of_child,
|
||||
ada_value_of_variable,
|
||||
ada_value_is_changeable_p,
|
||||
ada_value_has_mutated
|
||||
};
|
||||
|
|
|
@ -0,0 +1,910 @@
|
|||
/* varobj support for C and C++.
|
||||
|
||||
Copyright (C) 1999-2013 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "value.h"
|
||||
#include "varobj.h"
|
||||
#include "gdbthread.h"
|
||||
#include "valprint.h"
|
||||
|
||||
static void cplus_class_num_children (struct type *type, int children[3]);
|
||||
|
||||
/* The names of varobjs representing anonymous structs or unions. */
|
||||
#define ANONYMOUS_STRUCT_NAME _("<anonymous struct>")
|
||||
#define ANONYMOUS_UNION_NAME _("<anonymous union>")
|
||||
|
||||
/* Does CHILD represent a child with no name? This happens when
|
||||
the child is an anonmous struct or union and it has no field name
|
||||
in its parent variable.
|
||||
|
||||
This has already been determined by *_describe_child. The easiest
|
||||
thing to do is to compare the child's name with ANONYMOUS_*_NAME. */
|
||||
|
||||
int
|
||||
varobj_is_anonymous_child (struct varobj *child)
|
||||
{
|
||||
return (strcmp (child->name, ANONYMOUS_STRUCT_NAME) == 0
|
||||
|| strcmp (child->name, ANONYMOUS_UNION_NAME) == 0);
|
||||
}
|
||||
|
||||
/* Given the value and the type of a variable object,
|
||||
adjust the value and type to those necessary
|
||||
for getting children of the variable object.
|
||||
This includes dereferencing top-level references
|
||||
to all types and dereferencing pointers to
|
||||
structures.
|
||||
|
||||
If LOOKUP_ACTUAL_TYPE is set the enclosing type of the
|
||||
value will be fetched and if it differs from static type
|
||||
the value will be casted to it.
|
||||
|
||||
Both TYPE and *TYPE should be non-null. VALUE
|
||||
can be null if we want to only translate type.
|
||||
*VALUE can be null as well -- if the parent
|
||||
value is not known.
|
||||
|
||||
If WAS_PTR is not NULL, set *WAS_PTR to 0 or 1
|
||||
depending on whether pointer was dereferenced
|
||||
in this function. */
|
||||
|
||||
static void
|
||||
adjust_value_for_child_access (struct value **value,
|
||||
struct type **type,
|
||||
int *was_ptr,
|
||||
int lookup_actual_type)
|
||||
{
|
||||
gdb_assert (type && *type);
|
||||
|
||||
if (was_ptr)
|
||||
*was_ptr = 0;
|
||||
|
||||
*type = check_typedef (*type);
|
||||
|
||||
/* The type of value stored in varobj, that is passed
|
||||
to us, is already supposed to be
|
||||
reference-stripped. */
|
||||
|
||||
gdb_assert (TYPE_CODE (*type) != TYPE_CODE_REF);
|
||||
|
||||
/* Pointers to structures are treated just like
|
||||
structures when accessing children. Don't
|
||||
dererences pointers to other types. */
|
||||
if (TYPE_CODE (*type) == TYPE_CODE_PTR)
|
||||
{
|
||||
struct type *target_type = get_target_type (*type);
|
||||
if (TYPE_CODE (target_type) == TYPE_CODE_STRUCT
|
||||
|| TYPE_CODE (target_type) == TYPE_CODE_UNION)
|
||||
{
|
||||
if (value && *value)
|
||||
{
|
||||
volatile struct gdb_exception except;
|
||||
|
||||
TRY_CATCH (except, RETURN_MASK_ERROR)
|
||||
{
|
||||
*value = value_ind (*value);
|
||||
}
|
||||
|
||||
if (except.reason < 0)
|
||||
*value = NULL;
|
||||
}
|
||||
*type = target_type;
|
||||
if (was_ptr)
|
||||
*was_ptr = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* The 'get_target_type' function calls check_typedef on
|
||||
result, so we can immediately check type code. No
|
||||
need to call check_typedef here. */
|
||||
|
||||
/* Access a real type of the value (if necessary and possible). */
|
||||
if (value && *value && lookup_actual_type)
|
||||
{
|
||||
struct type *enclosing_type;
|
||||
int real_type_found = 0;
|
||||
|
||||
enclosing_type = value_actual_type (*value, 1, &real_type_found);
|
||||
if (real_type_found)
|
||||
{
|
||||
*type = enclosing_type;
|
||||
*value = value_cast (enclosing_type, *value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* C */
|
||||
|
||||
static int
|
||||
c_number_of_children (struct varobj *var)
|
||||
{
|
||||
struct type *type = varobj_get_value_type (var);
|
||||
int children = 0;
|
||||
struct type *target;
|
||||
|
||||
adjust_value_for_child_access (NULL, &type, NULL, 0);
|
||||
target = get_target_type (type);
|
||||
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
case TYPE_CODE_ARRAY:
|
||||
if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (target) > 0
|
||||
&& !TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type))
|
||||
children = TYPE_LENGTH (type) / TYPE_LENGTH (target);
|
||||
else
|
||||
/* If we don't know how many elements there are, don't display
|
||||
any. */
|
||||
children = 0;
|
||||
break;
|
||||
|
||||
case TYPE_CODE_STRUCT:
|
||||
case TYPE_CODE_UNION:
|
||||
children = TYPE_NFIELDS (type);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_PTR:
|
||||
/* The type here is a pointer to non-struct. Typically, pointers
|
||||
have one child, except for function ptrs, which have no children,
|
||||
and except for void*, as we don't know what to show.
|
||||
|
||||
We can show char* so we allow it to be dereferenced. If you decide
|
||||
to test for it, please mind that a little magic is necessary to
|
||||
properly identify it: char* has TYPE_CODE == TYPE_CODE_INT and
|
||||
TYPE_NAME == "char". */
|
||||
if (TYPE_CODE (target) == TYPE_CODE_FUNC
|
||||
|| TYPE_CODE (target) == TYPE_CODE_VOID)
|
||||
children = 0;
|
||||
else
|
||||
children = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Other types have no children. */
|
||||
break;
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
static char *
|
||||
c_name_of_variable (struct varobj *parent)
|
||||
{
|
||||
return xstrdup (parent->name);
|
||||
}
|
||||
|
||||
/* Return the value of element TYPE_INDEX of a structure
|
||||
value VALUE. VALUE's type should be a structure,
|
||||
or union, or a typedef to struct/union.
|
||||
|
||||
Returns NULL if getting the value fails. Never throws. */
|
||||
|
||||
static struct value *
|
||||
value_struct_element_index (struct value *value, int type_index)
|
||||
{
|
||||
struct value *result = NULL;
|
||||
volatile struct gdb_exception e;
|
||||
struct type *type = value_type (value);
|
||||
|
||||
type = check_typedef (type);
|
||||
|
||||
gdb_assert (TYPE_CODE (type) == TYPE_CODE_STRUCT
|
||||
|| TYPE_CODE (type) == TYPE_CODE_UNION);
|
||||
|
||||
TRY_CATCH (e, RETURN_MASK_ERROR)
|
||||
{
|
||||
if (field_is_static (&TYPE_FIELD (type, type_index)))
|
||||
result = value_static_field (type, type_index);
|
||||
else
|
||||
result = value_primitive_field (value, 0, type_index, type);
|
||||
}
|
||||
if (e.reason < 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/* Obtain the information about child INDEX of the variable
|
||||
object PARENT.
|
||||
If CNAME is not null, sets *CNAME to the name of the child relative
|
||||
to the parent.
|
||||
If CVALUE is not null, sets *CVALUE to the value of the child.
|
||||
If CTYPE is not null, sets *CTYPE to the type of the child.
|
||||
|
||||
If any of CNAME, CVALUE, or CTYPE is not null, but the corresponding
|
||||
information cannot be determined, set *CNAME, *CVALUE, or *CTYPE
|
||||
to NULL. */
|
||||
|
||||
static void
|
||||
c_describe_child (struct varobj *parent, int index,
|
||||
char **cname, struct value **cvalue, struct type **ctype,
|
||||
char **cfull_expression)
|
||||
{
|
||||
struct value *value = parent->value;
|
||||
struct type *type = varobj_get_value_type (parent);
|
||||
char *parent_expression = NULL;
|
||||
int was_ptr;
|
||||
volatile struct gdb_exception except;
|
||||
|
||||
if (cname)
|
||||
*cname = NULL;
|
||||
if (cvalue)
|
||||
*cvalue = NULL;
|
||||
if (ctype)
|
||||
*ctype = NULL;
|
||||
if (cfull_expression)
|
||||
{
|
||||
*cfull_expression = NULL;
|
||||
parent_expression
|
||||
= varobj_get_path_expr (varobj_get_path_expr_parent (parent));
|
||||
}
|
||||
adjust_value_for_child_access (&value, &type, &was_ptr, 0);
|
||||
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
case TYPE_CODE_ARRAY:
|
||||
if (cname)
|
||||
*cname
|
||||
= xstrdup (int_string (index
|
||||
+ TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)),
|
||||
10, 1, 0, 0));
|
||||
|
||||
if (cvalue && value)
|
||||
{
|
||||
int real_index = index + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type));
|
||||
|
||||
TRY_CATCH (except, RETURN_MASK_ERROR)
|
||||
{
|
||||
*cvalue = value_subscript (value, real_index);
|
||||
}
|
||||
}
|
||||
|
||||
if (ctype)
|
||||
*ctype = get_target_type (type);
|
||||
|
||||
if (cfull_expression)
|
||||
*cfull_expression =
|
||||
xstrprintf ("(%s)[%s]", parent_expression,
|
||||
int_string (index
|
||||
+ TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)),
|
||||
10, 1, 0, 0));
|
||||
|
||||
|
||||
break;
|
||||
|
||||
case TYPE_CODE_STRUCT:
|
||||
case TYPE_CODE_UNION:
|
||||
{
|
||||
const char *field_name;
|
||||
|
||||
/* If the type is anonymous and the field has no name,
|
||||
set an appropriate name. */
|
||||
field_name = TYPE_FIELD_NAME (type, index);
|
||||
if (field_name == NULL || *field_name == '\0')
|
||||
{
|
||||
if (cname)
|
||||
{
|
||||
if (TYPE_CODE (TYPE_FIELD_TYPE (type, index))
|
||||
== TYPE_CODE_STRUCT)
|
||||
*cname = xstrdup (ANONYMOUS_STRUCT_NAME);
|
||||
else
|
||||
*cname = xstrdup (ANONYMOUS_UNION_NAME);
|
||||
}
|
||||
|
||||
if (cfull_expression)
|
||||
*cfull_expression = xstrdup ("");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cname)
|
||||
*cname = xstrdup (field_name);
|
||||
|
||||
if (cfull_expression)
|
||||
{
|
||||
char *join = was_ptr ? "->" : ".";
|
||||
|
||||
*cfull_expression = xstrprintf ("(%s)%s%s", parent_expression,
|
||||
join, field_name);
|
||||
}
|
||||
}
|
||||
|
||||
if (cvalue && value)
|
||||
{
|
||||
/* For C, varobj index is the same as type index. */
|
||||
*cvalue = value_struct_element_index (value, index);
|
||||
}
|
||||
|
||||
if (ctype)
|
||||
*ctype = TYPE_FIELD_TYPE (type, index);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_PTR:
|
||||
if (cname)
|
||||
*cname = xstrprintf ("*%s", parent->name);
|
||||
|
||||
if (cvalue && value)
|
||||
{
|
||||
TRY_CATCH (except, RETURN_MASK_ERROR)
|
||||
{
|
||||
*cvalue = value_ind (value);
|
||||
}
|
||||
|
||||
if (except.reason < 0)
|
||||
*cvalue = NULL;
|
||||
}
|
||||
|
||||
/* Don't use get_target_type because it calls
|
||||
check_typedef and here, we want to show the true
|
||||
declared type of the variable. */
|
||||
if (ctype)
|
||||
*ctype = TYPE_TARGET_TYPE (type);
|
||||
|
||||
if (cfull_expression)
|
||||
*cfull_expression = xstrprintf ("*(%s)", parent_expression);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
/* This should not happen. */
|
||||
if (cname)
|
||||
*cname = xstrdup ("???");
|
||||
if (cfull_expression)
|
||||
*cfull_expression = xstrdup ("???");
|
||||
/* Don't set value and type, we don't know then. */
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
c_name_of_child (struct varobj *parent, int index)
|
||||
{
|
||||
char *name;
|
||||
|
||||
c_describe_child (parent, index, &name, NULL, NULL, NULL);
|
||||
return name;
|
||||
}
|
||||
|
||||
static char *
|
||||
c_path_expr_of_child (struct varobj *child)
|
||||
{
|
||||
c_describe_child (child->parent, child->index, NULL, NULL, NULL,
|
||||
&child->path_expr);
|
||||
return child->path_expr;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* This returns the type of the variable. It also skips past typedefs
|
||||
to return the real type of the variable. */
|
||||
|
||||
static struct type *
|
||||
get_type (struct varobj *var)
|
||||
{
|
||||
struct type *type;
|
||||
|
||||
type = var->type;
|
||||
if (type != NULL)
|
||||
type = check_typedef (type);
|
||||
|
||||
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 varobj_value_get_print_value (var->value, format, var);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* varobj operations for c. */
|
||||
|
||||
const struct lang_varobj_ops c_varobj_ops =
|
||||
{
|
||||
c_number_of_children,
|
||||
c_name_of_variable,
|
||||
c_name_of_child,
|
||||
c_path_expr_of_child,
|
||||
c_value_of_child,
|
||||
c_type_of_child,
|
||||
c_value_of_variable,
|
||||
varobj_default_value_is_changeable_p,
|
||||
NULL /* value_has_mutated */
|
||||
};
|
||||
|
||||
/* A little convenience enum for dealing with C++/Java. */
|
||||
enum vsections
|
||||
{
|
||||
v_public = 0, v_private, v_protected
|
||||
};
|
||||
|
||||
/* 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 = varobj_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 = varobj_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 = varobj_get_value_type (var);
|
||||
if (cfull_expression)
|
||||
parent_expression
|
||||
= varobj_get_path_expr (varobj_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_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);
|
||||
}
|
||||
|
||||
|
||||
/* varobj operations for c++. */
|
||||
|
||||
const struct lang_varobj_ops cplus_varobj_ops =
|
||||
{
|
||||
cplus_number_of_children,
|
||||
cplus_name_of_variable,
|
||||
cplus_name_of_child,
|
||||
cplus_path_expr_of_child,
|
||||
cplus_value_of_child,
|
||||
cplus_type_of_child,
|
||||
cplus_value_of_variable,
|
||||
varobj_default_value_is_changeable_p,
|
||||
NULL /* value_has_mutated */
|
||||
};
|
||||
|
||||
|
|
@ -239,6 +239,21 @@ get_type_arch (const struct type *type)
|
|||
return TYPE_OWNER (type).gdbarch;
|
||||
}
|
||||
|
||||
/* See gdbtypes.h. */
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Alloc a new type instance structure, fill it with some defaults,
|
||||
and point it at OLDTYPE. Allocate the new type instance from the
|
||||
same place as OLDTYPE. */
|
||||
|
|
|
@ -1431,6 +1431,10 @@ extern struct type *alloc_type_copy (const struct type *);
|
|||
objfile's architecture is returned. */
|
||||
extern struct gdbarch *get_type_arch (const struct type *);
|
||||
|
||||
/* This returns the target type (or NULL) of TYPE, also skipping
|
||||
past typedefs. */
|
||||
extern struct type *get_target_type (struct type *type);
|
||||
|
||||
/* Helper function to construct objfile-owned types. */
|
||||
extern struct type *init_type (enum type_code, int, int, const char *,
|
||||
struct objfile *);
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
/* varobj support for Java.
|
||||
|
||||
Copyright (C) 1999-2013 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "varobj.h"
|
||||
|
||||
/* Java */
|
||||
|
||||
static int
|
||||
java_number_of_children (struct varobj *var)
|
||||
{
|
||||
return cplus_varobj_ops.number_of_children (var);
|
||||
}
|
||||
|
||||
static char *
|
||||
java_name_of_variable (struct varobj *parent)
|
||||
{
|
||||
char *p, *name;
|
||||
|
||||
name = cplus_varobj_ops.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_varobj_ops.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_child (struct varobj *parent, int index)
|
||||
{
|
||||
return cplus_varobj_ops.value_of_child (parent, index);
|
||||
}
|
||||
|
||||
static struct type *
|
||||
java_type_of_child (struct varobj *parent, int index)
|
||||
{
|
||||
return cplus_varobj_ops.type_of_child (parent, index);
|
||||
}
|
||||
|
||||
static char *
|
||||
java_value_of_variable (struct varobj *var, enum varobj_display_formats format)
|
||||
{
|
||||
return cplus_varobj_ops.value_of_variable (var, format);
|
||||
}
|
||||
|
||||
/* varobj operations for java. */
|
||||
|
||||
const struct lang_varobj_ops java_varobj_ops =
|
||||
{
|
||||
java_number_of_children,
|
||||
java_name_of_variable,
|
||||
java_name_of_child,
|
||||
java_path_expr_of_child,
|
||||
java_value_of_child,
|
||||
java_type_of_child,
|
||||
java_value_of_variable,
|
||||
varobj_default_value_is_changeable_p,
|
||||
NULL /* value_has_mutated */
|
||||
};
|
1328
gdb/varobj.c
1328
gdb/varobj.c
File diff suppressed because it is too large
Load Diff
80
gdb/varobj.h
80
gdb/varobj.h
|
@ -168,6 +168,68 @@ struct varobj
|
|||
struct varobj_dynamic *dynamic;
|
||||
};
|
||||
|
||||
/* Is the variable X one of our "fake" children? */
|
||||
#define CPLUS_FAKE_CHILD(x) \
|
||||
((x) != NULL && (x)->type == NULL && (x)->value == NULL)
|
||||
|
||||
/* The language specific vector */
|
||||
|
||||
struct lang_varobj_ops
|
||||
{
|
||||
/* The number of children of PARENT. */
|
||||
int (*number_of_children) (struct varobj * parent);
|
||||
|
||||
/* The name (expression) of a root varobj. */
|
||||
char *(*name_of_variable) (struct varobj * parent);
|
||||
|
||||
/* The name of the INDEX'th child of PARENT. */
|
||||
char *(*name_of_child) (struct varobj * parent, int index);
|
||||
|
||||
/* Returns the rooted expression of CHILD, which is a variable
|
||||
obtain that has some parent. */
|
||||
char *(*path_expr_of_child) (struct varobj * child);
|
||||
|
||||
/* The ``struct value *'' of the INDEX'th child of PARENT. */
|
||||
struct value *(*value_of_child) (struct varobj * parent, int index);
|
||||
|
||||
/* The type of the INDEX'th child of PARENT. */
|
||||
struct type *(*type_of_child) (struct varobj * parent, int index);
|
||||
|
||||
/* The current value of VAR. */
|
||||
char *(*value_of_variable) (struct varobj * var,
|
||||
enum varobj_display_formats format);
|
||||
|
||||
/* Return non-zero if changes in value of VAR must be detected and
|
||||
reported by -var-update. Return zero if -var-update should never
|
||||
report changes of such values. This makes sense for structures
|
||||
(since the changes in children values will be reported separately),
|
||||
or for artifical objects (like 'public' pseudo-field in C++).
|
||||
|
||||
Return value of 0 means that gdb need not call value_fetch_lazy
|
||||
for the value of this variable object. */
|
||||
int (*value_is_changeable_p) (struct varobj *var);
|
||||
|
||||
/* Return nonzero if the type of VAR has mutated.
|
||||
|
||||
VAR's value is still the varobj's previous value, while NEW_VALUE
|
||||
is VAR's new value and NEW_TYPE is the var's new type. NEW_VALUE
|
||||
may be NULL indicating that there is no value available (the varobj
|
||||
may be out of scope, of may be the child of a null pointer, for
|
||||
instance). NEW_TYPE, on the other hand, must never be NULL.
|
||||
|
||||
This function should also be able to assume that var's number of
|
||||
children is set (not < 0).
|
||||
|
||||
Languages where types do not mutate can set this to NULL. */
|
||||
int (*value_has_mutated) (struct varobj *var, struct value *new_value,
|
||||
struct type *new_type);
|
||||
};
|
||||
|
||||
const struct lang_varobj_ops c_varobj_ops;
|
||||
const struct lang_varobj_ops cplus_varobj_ops;
|
||||
const struct lang_varobj_ops java_varobj_ops;
|
||||
const struct lang_varobj_ops ada_varobj_ops;
|
||||
|
||||
/* API functions */
|
||||
|
||||
extern struct varobj *varobj_create (char *objname,
|
||||
|
@ -255,4 +317,22 @@ extern int varobj_has_more (struct varobj *var, int to);
|
|||
|
||||
extern int varobj_pretty_printed_p (struct varobj *var);
|
||||
|
||||
extern int varobj_default_value_is_changeable_p (struct varobj *var);
|
||||
extern int varobj_value_is_changeable_p (struct varobj *var);
|
||||
|
||||
extern struct type *varobj_get_value_type (struct varobj *var);
|
||||
|
||||
extern int varobj_is_anonymous_child (struct varobj *child);
|
||||
|
||||
extern struct varobj *varobj_get_path_expr_parent (struct varobj *var);
|
||||
|
||||
extern char *varobj_value_get_print_value (struct value *value,
|
||||
enum varobj_display_formats format,
|
||||
struct varobj *var);
|
||||
|
||||
extern void varobj_formatted_print_options (struct value_print_options *opts,
|
||||
enum varobj_display_formats format);
|
||||
|
||||
extern void varobj_restrict_range (VEC (varobj_p) *children, int *from,
|
||||
int *to);
|
||||
#endif /* VAROBJ_H */
|
||||
|
|
Loading…
Reference in New Issue