* EnumerationValue -> EnumeratorValue
* Since some types don't have names (e.g. pointer types or anonymous structs or
unions), each type does now also have a unique ID. The global type cache
registers types by ID and by name (if they have one). This fixes clashes of
types with empty names.
* Completely refactored the code dealing with variable values. Formerly we had
Variable and TypeComponentPath to navigate to a component, mapped to a
BVariant representing the value. Now we have:
* Interface Value with various subclasses (BoolValue, IntegerValue, etc.) to
represent a value, with the flexibility for more esoteric values.
* A tree of ValueNode+ValueNodeChild objects to represent the components of a
variable. On top of each ValueNodeChild sits a ValueNode representing the
value of the component, potentially having ValueNodeChild children. This
should allow casting a component value, simply by replacing its ValueNode.
* Interface ValueHandler and various implementations for the different value
types. It is basically a factory for classes allowing to format/display a
value.
* ValueHandlerRoster -- a registry for ValueHandlers, finding the best one
for a given value.
* Interface TypeHandler and various implementions for the different type
kinds (primitive, compound, address, etc.). It is basically a factory for
ValueNodes for that type.
* TypeHandlerRoster -- a registry for TypeHandlers, finding the best one
for a given type.
That's still a bit work in progress. It introduces at least one regression:
The VariablesView doesn't save/restore its state anymore. Will take a while
until that is added back.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33907 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -23,6 +23,8 @@
|
||||
#include "MessageCodes.h"
|
||||
#include "SettingsManager.h"
|
||||
#include "TeamDebugger.h"
|
||||
#include "TypeHandlerRoster.h"
|
||||
#include "ValueHandlerRoster.h"
|
||||
|
||||
|
||||
extern const char* __progname;
|
||||
@@ -178,10 +180,20 @@ public:
|
||||
|
||||
~Debugger()
|
||||
{
|
||||
ValueHandlerRoster::DeleteDefault();
|
||||
TypeHandlerRoster::DeleteDefault();
|
||||
}
|
||||
|
||||
status_t Init()
|
||||
{
|
||||
status_t error = TypeHandlerRoster::CreateDefault();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
error = ValueHandlerRoster::CreateDefault();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
return fSettingsManager.Init();
|
||||
}
|
||||
|
||||
|
||||
+85
-30
@@ -12,17 +12,23 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) debug_info ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) debugger_interface ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) elf ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) files ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) ids ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) model ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) settings ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) settings generic ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) source_language ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) types ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui model ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui team_window ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui util ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) ids ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) model ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) settings ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) source_language ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) types ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui value ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) util ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) value ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) value value_handlers ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) value value_nodes ] ;
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) value values ] ;
|
||||
|
||||
local debugAnalyzerSources
|
||||
= [ FDirName $(HAIKU_TOP) src apps debuganalyzer ] ;
|
||||
@@ -96,31 +102,6 @@ Application Debugger :
|
||||
LocatableFile.cpp
|
||||
SourceFile.cpp
|
||||
|
||||
# user_interface
|
||||
UserInterface.cpp
|
||||
|
||||
# user_interface/gui
|
||||
GraphicalUserInterface.cpp
|
||||
|
||||
# user_interface/gui/model
|
||||
VariablesViewState.cpp
|
||||
VariablesViewStateHistory.cpp
|
||||
|
||||
# user_interface/gui/team_window
|
||||
BreakpointListView.cpp
|
||||
BreakpointsView.cpp
|
||||
ImageFunctionsView.cpp
|
||||
ImageListView.cpp
|
||||
RegistersView.cpp
|
||||
SourceView.cpp
|
||||
StackTraceView.cpp
|
||||
TeamWindow.cpp
|
||||
ThreadListView.cpp
|
||||
VariablesView.cpp
|
||||
|
||||
# user_interface/gui/util
|
||||
TargetAddressTableColumn.cpp
|
||||
|
||||
# ids
|
||||
FunctionID.cpp
|
||||
LocalVariableID.cpp
|
||||
@@ -154,6 +135,11 @@ Application Debugger :
|
||||
TeamSettings.cpp
|
||||
SettingsManager.cpp
|
||||
|
||||
# settings/generic
|
||||
Setting.cpp
|
||||
Settings.cpp
|
||||
SettingsDescription.cpp
|
||||
|
||||
# source_language
|
||||
CLanguage.cpp
|
||||
CLanguageFamily.cpp
|
||||
@@ -168,11 +154,80 @@ Application Debugger :
|
||||
TargetAddressRangeList.cpp
|
||||
ValueLocation.cpp
|
||||
|
||||
# user_interface
|
||||
UserInterface.cpp
|
||||
|
||||
# user_interface/gui
|
||||
GraphicalUserInterface.cpp
|
||||
|
||||
# user_interface/gui/model
|
||||
VariablesViewState.cpp
|
||||
VariablesViewStateHistory.cpp
|
||||
|
||||
# user_interface/gui/team_window
|
||||
BreakpointListView.cpp
|
||||
BreakpointsView.cpp
|
||||
ImageFunctionsView.cpp
|
||||
ImageListView.cpp
|
||||
RegistersView.cpp
|
||||
SourceView.cpp
|
||||
StackTraceView.cpp
|
||||
TeamWindow.cpp
|
||||
ThreadListView.cpp
|
||||
VariablesView.cpp
|
||||
|
||||
# user_interface/gui/util
|
||||
SettingsMenu.cpp
|
||||
TargetAddressTableColumn.cpp
|
||||
|
||||
# user_interface/gui/value
|
||||
TableCellBoolRenderer.cpp
|
||||
TableCellEnumerationRenderer.cpp
|
||||
TableCellFloatRenderer.cpp
|
||||
TableCellIntegerRenderer.cpp
|
||||
TableCellStringRenderer.cpp
|
||||
TableCellValueRenderer.cpp
|
||||
TableCellValueRendererUtils.cpp
|
||||
|
||||
# util
|
||||
ArchivingUtils.cpp
|
||||
BitBuffer.cpp
|
||||
IntegerFormatter.cpp
|
||||
StringUtils.cpp
|
||||
|
||||
# value
|
||||
TypeHandler.cpp
|
||||
TypeHandlerRoster.cpp
|
||||
Value.cpp
|
||||
ValueHandler.cpp
|
||||
ValueHandlerRoster.cpp
|
||||
ValueLoader.cpp
|
||||
ValueNode.cpp
|
||||
ValueNodeContainer.cpp
|
||||
|
||||
# value/value_handlers
|
||||
AddressValueHandler.cpp
|
||||
BoolValueHandler.cpp
|
||||
EnumerationValueHandler.cpp
|
||||
FloatValueHandler.cpp
|
||||
IntegerValueHandler.cpp
|
||||
|
||||
# value/value_nodes
|
||||
AddressValueNode.cpp
|
||||
ArrayValueNode.cpp
|
||||
CompoundValueNode.cpp
|
||||
EnumerationValueNode.cpp
|
||||
PointerToMemberValueNode.cpp
|
||||
PrimitiveValueNode.cpp
|
||||
VariableValueNodeChild.cpp
|
||||
|
||||
# value/values
|
||||
AddressValue.cpp
|
||||
BoolValue.cpp
|
||||
EnumerationValue.cpp
|
||||
FloatValue.cpp
|
||||
IntegerValue.cpp
|
||||
|
||||
:
|
||||
<nogrist>Debugger_demangler.o
|
||||
<nogrist>Debugger_disasm_x86.o
|
||||
|
||||
+146
-562
@@ -29,7 +29,11 @@
|
||||
#include "Tracing.h"
|
||||
#include "Type.h"
|
||||
#include "TypeComponentPath.h"
|
||||
#include "Value.h"
|
||||
#include "ValueLoader.h"
|
||||
#include "ValueLocation.h"
|
||||
#include "ValueNode.h"
|
||||
#include "ValueNodeContainer.h"
|
||||
#include "Variable.h"
|
||||
|
||||
|
||||
@@ -406,627 +410,211 @@ LoadSourceCodeJob::Do()
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - GetStackFrameValueJobKey
|
||||
// #pragma mark - ResolveValueNodeValueJob
|
||||
|
||||
|
||||
GetStackFrameValueJobKey::GetStackFrameValueJobKey(StackFrame* stackFrame,
|
||||
Variable* variable, TypeComponentPath* path)
|
||||
:
|
||||
stackFrame(stackFrame),
|
||||
variable(variable),
|
||||
path(path)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
GetStackFrameValueJobKey::HashValue() const
|
||||
{
|
||||
uint32 hash = (uint32)(addr_t)stackFrame;
|
||||
hash = hash * 13 + (uint32)(addr_t)variable;
|
||||
return hash * 13 + path->HashValue();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
GetStackFrameValueJobKey::operator==(const JobKey& other) const
|
||||
{
|
||||
const GetStackFrameValueJobKey* otherKey
|
||||
= dynamic_cast<const GetStackFrameValueJobKey*>(&other);
|
||||
return otherKey != NULL && stackFrame == otherKey->stackFrame
|
||||
&& variable == otherKey->variable && *path == *otherKey->path;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - GetStackFrameValueJob
|
||||
|
||||
|
||||
GetStackFrameValueJob::GetStackFrameValueJob(
|
||||
ResolveValueNodeValueJob::ResolveValueNodeValueJob(
|
||||
DebuggerInterface* debuggerInterface, Architecture* architecture,
|
||||
Thread* thread, StackFrame* stackFrame, Variable* variable,
|
||||
TypeComponentPath* path)
|
||||
CpuState* cpuState, ValueNodeContainer* container, ValueNode* valueNode)
|
||||
:
|
||||
fKey(stackFrame, variable, path),
|
||||
fKey(valueNode, JOB_TYPE_RESOLVE_VALUE_NODE_VALUE),
|
||||
fDebuggerInterface(debuggerInterface),
|
||||
fArchitecture(architecture),
|
||||
fThread(thread),
|
||||
fStackFrame(stackFrame),
|
||||
fVariable(variable),
|
||||
fPath(path)
|
||||
fCpuState(cpuState),
|
||||
fContainer(container),
|
||||
fValueNode(valueNode)
|
||||
{
|
||||
fThread->AcquireReference();
|
||||
fStackFrame->AcquireReference();
|
||||
fVariable->AcquireReference();
|
||||
fPath->AcquireReference();
|
||||
if (fCpuState != NULL)
|
||||
fCpuState->AcquireReference();
|
||||
fContainer->AcquireReference();
|
||||
fValueNode->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
GetStackFrameValueJob::~GetStackFrameValueJob()
|
||||
ResolveValueNodeValueJob::~ResolveValueNodeValueJob()
|
||||
{
|
||||
fThread->ReleaseReference();
|
||||
fStackFrame->ReleaseReference();
|
||||
fVariable->ReleaseReference();
|
||||
fPath->ReleaseReference();
|
||||
if (fCpuState != NULL)
|
||||
fCpuState->ReleaseReference();
|
||||
fContainer->ReleaseReference();
|
||||
fValueNode->ReleaseReference();
|
||||
}
|
||||
|
||||
|
||||
const JobKey&
|
||||
GetStackFrameValueJob::Key() const
|
||||
ResolveValueNodeValueJob::Key() const
|
||||
{
|
||||
return fKey;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
GetStackFrameValueJob::Do()
|
||||
ResolveValueNodeValueJob::Do()
|
||||
{
|
||||
status_t error = _GetValue();
|
||||
if (error == B_OK)
|
||||
return B_OK;
|
||||
// check whether the node still belongs to the container
|
||||
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
|
||||
if (fValueNode->Container() != fContainer)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// in case of error, set the value to invalid to avoid triggering this job
|
||||
// again
|
||||
AutoLocker<Team> locker(fThread->GetTeam());
|
||||
fStackFrame->Values()->SetValue(fVariable->ID(), fPath, BVariant());
|
||||
// if already resolved, we're done
|
||||
status_t nodeResolutionState
|
||||
= fValueNode->LocationAndValueResolutionState();
|
||||
if (nodeResolutionState != VALUE_NODE_UNRESOLVED)
|
||||
return nodeResolutionState;
|
||||
|
||||
containerLocker.Unlock();
|
||||
|
||||
// resolve
|
||||
status_t error = _ResolveNodeValue();
|
||||
if (error != B_OK) {
|
||||
nodeResolutionState = fValueNode->LocationAndValueResolutionState();
|
||||
if (nodeResolutionState != VALUE_NODE_UNRESOLVED)
|
||||
return nodeResolutionState;
|
||||
|
||||
containerLocker.Lock();
|
||||
fValueNode->SetLocationAndValue(NULL, NULL, error);
|
||||
containerLocker.Unlock();
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
GetStackFrameValueJob::_GetValue()
|
||||
ResolveValueNodeValueJob::_ResolveNodeValue()
|
||||
{
|
||||
TRACE_LOCALS_ONLY(
|
||||
TRACE_LOCALS("GetStackFrameValueJob::_GetValue(): %s ",
|
||||
fVariable->Name().String());
|
||||
fPath->Dump();
|
||||
TRACE_LOCALS("\n");
|
||||
)
|
||||
// get the node child and parent node
|
||||
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
|
||||
ValueNodeChild* nodeChild = fValueNode->NodeChild();
|
||||
Reference<ValueNodeChild> nodeChildReference(nodeChild);
|
||||
|
||||
Type* type;
|
||||
ValueNode* parentNode = nodeChild->Parent();
|
||||
Reference<ValueNode> parentNodeReference(parentNode);
|
||||
|
||||
// Check whether the node child location has been resolved already
|
||||
// (successfully).
|
||||
status_t nodeChildResolutionState = nodeChild->LocationResolutionState();
|
||||
bool nodeChildDone = nodeChildResolutionState != VALUE_NODE_UNRESOLVED;
|
||||
if (nodeChildDone && nodeChildResolutionState != B_OK)
|
||||
return nodeChildResolutionState;
|
||||
|
||||
// If the child node location has not been resolved yet, check whether the
|
||||
// parent node location and value have been resolved already (successfully).
|
||||
bool parentDone = true;
|
||||
if (!nodeChildDone && parentNode != NULL) {
|
||||
status_t parentResolutionState
|
||||
= parentNode->LocationAndValueResolutionState();
|
||||
parentDone = parentResolutionState != VALUE_NODE_UNRESOLVED;
|
||||
if (parentDone && parentResolutionState != B_OK)
|
||||
return parentResolutionState;
|
||||
}
|
||||
|
||||
containerLocker.Unlock();
|
||||
|
||||
// resolve the parent node location and value, if necessary
|
||||
if (!parentDone) {
|
||||
status_t error = _ResolveParentNodeValue(parentNode);
|
||||
if (error != B_OK) {
|
||||
TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value "
|
||||
"node: %p (\"%s\"): _ResolveParentNodeValue(%p) failed\n",
|
||||
fValueNode, fValueNode->Name().String(), parentNode);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
// resolve the node child location, if necessary
|
||||
if (!nodeChildDone) {
|
||||
status_t error = _ResolveNodeChildLocation(nodeChild);
|
||||
if (error != B_OK) {
|
||||
TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value "
|
||||
"node: %p (\"%s\"): _ResolveNodeChildLocation(%p) failed\n",
|
||||
fValueNode, fValueNode->Name().String(), nodeChild);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
// resolve the node location and value
|
||||
ValueLoader valueLoader(fArchitecture, fDebuggerInterface, fCpuState);
|
||||
ValueLocation* location;
|
||||
bool valueResolved;
|
||||
status_t error = _ResolveTypeAndLocation(type, location, valueResolved);
|
||||
if (error != B_OK || valueResolved) {
|
||||
TRACE_LOCALS(" -> error: %#lx, valueResolved: %d\n", error,
|
||||
valueResolved);
|
||||
return error;
|
||||
}
|
||||
Type* actualType = type;
|
||||
Reference<Type> typeReference(type);
|
||||
Reference<Type> actualTypeReference(actualType);
|
||||
Reference<ValueLocation> locationReference(location);
|
||||
|
||||
// find out the type of the data we want to read
|
||||
type_code valueType = 0;
|
||||
bool shortValueIsFine = false;
|
||||
while (valueType == 0) {
|
||||
switch (type->Kind()) {
|
||||
case TYPE_PRIMITIVE:
|
||||
valueType = dynamic_cast<PrimitiveType*>(type)->TypeConstant();
|
||||
shortValueIsFine = BVariant::TypeIsInteger(valueType)
|
||||
|| valueType == B_BOOL_TYPE;
|
||||
|
||||
TRACE_LOCALS(" TYPE_PRIMITIVE: '%c%c%c%c'\n",
|
||||
int(valueType >> 24), int(valueType >> 16),
|
||||
int(valueType >> 8), int(valueType));
|
||||
|
||||
if (valueType == 0) {
|
||||
TRACE_LOCALS(" -> unknown type constant\n");
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
break;
|
||||
case TYPE_MODIFIED:
|
||||
TRACE_LOCALS(" TYPE_MODIFIED\n");
|
||||
// ignore modifiers
|
||||
type = dynamic_cast<ModifiedType*>(type)->BaseType();
|
||||
break;
|
||||
case TYPE_TYPEDEF:
|
||||
TRACE_LOCALS(" TYPE_TYPEDEF\n");
|
||||
type = dynamic_cast<TypedefType*>(type)->BaseType();
|
||||
break;
|
||||
case TYPE_ADDRESS:
|
||||
case TYPE_POINTER_TO_MEMBER:
|
||||
TRACE_LOCALS(" TYPE_ADDRESS/TYPE_POINTER_TO_MEMBER\n");
|
||||
if (fArchitecture->AddressSize() == 4) {
|
||||
valueType = B_UINT32_TYPE;
|
||||
TRACE_LOCALS(" -> 32 bit\n");
|
||||
} else {
|
||||
valueType = B_UINT64_TYPE;
|
||||
TRACE_LOCALS(" -> 64 bit\n");
|
||||
}
|
||||
break;
|
||||
case TYPE_COMPOUND:
|
||||
case TYPE_ARRAY:
|
||||
TRACE_LOCALS(" TYPE_COMPOUND/TYPE_ARRAY\n");
|
||||
// We can't retrieve the actual value of the compound object/
|
||||
// array (just of its components/elements), but to make the
|
||||
// recursion work smoothly, we have to set the type and
|
||||
// location at least.
|
||||
return _SetValue(BVariant(), actualType, location);
|
||||
case TYPE_ENUMERATION:
|
||||
{
|
||||
TRACE_LOCALS(" TYPE_ENUMERATION\n");
|
||||
// If a base type is known, use that.
|
||||
EnumerationType* enumType
|
||||
= dynamic_cast<EnumerationType*>(type);
|
||||
if (enumType->BaseType() != NULL) {
|
||||
type = enumType->BaseType();
|
||||
break;
|
||||
}
|
||||
|
||||
// get the value type constant
|
||||
// TODO: This is C source language specific!
|
||||
switch (enumType->ByteSize()) {
|
||||
case 1:
|
||||
valueType = B_INT8_TYPE;
|
||||
break;
|
||||
case 2:
|
||||
valueType = B_INT16_TYPE;
|
||||
break;
|
||||
case 4:
|
||||
default:
|
||||
valueType = B_INT32_TYPE;
|
||||
break;
|
||||
case 8:
|
||||
valueType = B_INT64_TYPE;
|
||||
break;
|
||||
}
|
||||
|
||||
shortValueIsFine = true;
|
||||
break;
|
||||
}
|
||||
case TYPE_SUBRANGE:
|
||||
TRACE_LOCALS(" TYPE_SUBRANGE -> unsupported\n");
|
||||
return B_UNSUPPORTED;
|
||||
case TYPE_UNSPECIFIED:
|
||||
// Can't get the value for an unspecified type!
|
||||
return B_BAD_VALUE;
|
||||
case TYPE_FUNCTION:
|
||||
TRACE_LOCALS(" TYPE_FUNCTION\n");
|
||||
// Can't get the value for a function type!
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
// update the reference in case the type has changed
|
||||
typeReference.SetTo(type);
|
||||
|
||||
if (valueType == B_STRING_TYPE) {
|
||||
TRACE_LOCALS(" -> B_STRING_TYPE: unsupported\n");
|
||||
return B_UNSUPPORTED;
|
||||
// TODO:...
|
||||
}
|
||||
|
||||
// check whether we know the complete location
|
||||
int32 count = location->CountPieces();
|
||||
|
||||
TRACE_LOCALS_ONLY(location->Dump();)
|
||||
|
||||
if (count == 0) {
|
||||
TRACE_LOCALS(" -> no location\n");
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
// If the source language implementation uses descriptors to point to
|
||||
// objects, we need to resolve the object address to the data address.
|
||||
if (count == 1) {
|
||||
ValuePieceLocation piece = location->PieceAt(0);
|
||||
if (piece.type == VALUE_PIECE_LOCATION_MEMORY) {
|
||||
ValueLocation* dataLocation;
|
||||
error = type->ResolveObjectDataLocation(*location, dataLocation);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
location = dataLocation;
|
||||
locationReference.SetTo(location, true);
|
||||
}
|
||||
}
|
||||
|
||||
static const size_t kMaxPieceSize = 16;
|
||||
uint64 totalBitSize = 0;
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
ValuePieceLocation piece = location->PieceAt(i);
|
||||
switch (piece.type) {
|
||||
case VALUE_PIECE_LOCATION_INVALID:
|
||||
case VALUE_PIECE_LOCATION_UNKNOWN:
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
case VALUE_PIECE_LOCATION_MEMORY:
|
||||
case VALUE_PIECE_LOCATION_REGISTER:
|
||||
break;
|
||||
}
|
||||
|
||||
if (piece.size > kMaxPieceSize) {
|
||||
TRACE_LOCALS(" -> overly long piece size (%llu bytes)\n",
|
||||
piece.size);
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
totalBitSize += piece.bitSize;
|
||||
}
|
||||
|
||||
TRACE_LOCALS(" -> totalBitSize: %llu\n", totalBitSize);
|
||||
|
||||
if (totalBitSize == 0) {
|
||||
TRACE_LOCALS(" -> no size\n");
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (totalBitSize > 64) {
|
||||
TRACE_LOCALS(" -> longer than 64 bits: unsupported\n");
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
uint64 valueBitSize = BVariant::SizeOfType(valueType) * 8;
|
||||
if (!shortValueIsFine && totalBitSize < valueBitSize) {
|
||||
TRACE_LOCALS(" -> too short for value type (%llu vs. %llu bits)\n",
|
||||
totalBitSize, valueBitSize);
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
// Load the data. Since the BitBuffer class we're using only supports big
|
||||
// endian bit semantics, we convert all data to big endian before pushing
|
||||
// them to the buffer. For later conversion to BVariant we need to make sure
|
||||
// the final buffer has the size of the value type, so we pad the most
|
||||
// significant bits with zeros.
|
||||
BitBuffer valueBuffer;
|
||||
if (totalBitSize < valueBitSize)
|
||||
valueBuffer.AddZeroBits(valueBitSize - totalBitSize);
|
||||
|
||||
bool bigEndian = fArchitecture->IsBigEndian();
|
||||
const Register* registers = fArchitecture->Registers();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
ValuePieceLocation piece = location->PieceAt(
|
||||
bigEndian ? i : count - i - 1);
|
||||
uint32 bytesToRead = piece.size;
|
||||
uint32 bitSize = piece.bitSize;
|
||||
uint8 bitOffset = piece.bitOffset;
|
||||
|
||||
switch (piece.type) {
|
||||
case VALUE_PIECE_LOCATION_INVALID:
|
||||
case VALUE_PIECE_LOCATION_UNKNOWN:
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
case VALUE_PIECE_LOCATION_MEMORY:
|
||||
{
|
||||
target_addr_t address = piece.address;
|
||||
|
||||
TRACE_LOCALS(" piece %ld: memory address: %#llx, bits: %lu\n",
|
||||
i, address, bitSize);
|
||||
|
||||
uint8 pieceBuffer[kMaxPieceSize];
|
||||
ssize_t bytesRead = fDebuggerInterface->ReadMemory(address,
|
||||
pieceBuffer, bytesToRead);
|
||||
if (bytesRead < 0)
|
||||
return bytesRead;
|
||||
if ((uint32)bytesRead != bytesToRead)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
TRACE_LOCALS_ONLY(
|
||||
TRACE_LOCALS(" -> read: ");
|
||||
for (ssize_t k = 0; k < bytesRead; k++)
|
||||
TRACE_LOCALS("%02x", pieceBuffer[k]);
|
||||
TRACE_LOCALS("\n");
|
||||
)
|
||||
|
||||
// convert to big endian
|
||||
if (!bigEndian) {
|
||||
for (int32 k = bytesRead / 2 - 1; k >= 0; k--) {
|
||||
std::swap(pieceBuffer[k],
|
||||
pieceBuffer[bytesRead - k - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
valueBuffer.AddBits(pieceBuffer, bitSize, bitOffset);
|
||||
break;
|
||||
}
|
||||
case VALUE_PIECE_LOCATION_REGISTER:
|
||||
{
|
||||
TRACE_LOCALS(" piece %ld: register: %lu, bits: %lu\n", i,
|
||||
piece.reg, bitSize);
|
||||
|
||||
BVariant registerValue;
|
||||
if (!fStackFrame->GetCpuState()->GetRegisterValue(
|
||||
registers + piece.reg, registerValue)) {
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
if (registerValue.Size() < bytesToRead)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
if (!bigEndian)
|
||||
registerValue.SwapEndianess();
|
||||
valueBuffer.AddBits(registerValue.Bytes(), bitSize, bitOffset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we don't have enough bits in the buffer apparently adding some failed.
|
||||
if (valueBuffer.BitSize() < valueBitSize)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
// convert the bits into something we can work with
|
||||
BVariant value;
|
||||
error = value.SetToTypedData(valueBuffer.Bytes(), valueType);
|
||||
Value* value;
|
||||
status_t error = fValueNode->ResolvedLocationAndValue(&valueLoader,
|
||||
location, value);
|
||||
if (error != B_OK) {
|
||||
TRACE_LOCALS(" -> failed to set typed data: %s\n", strerror(error));
|
||||
TRACE_LOCALS("ResolveValueNodeValueJob::_ResolveNodeValue(): value "
|
||||
"node: %p (\"%s\"): fValueNode->ResolvedLocationAndValue() "
|
||||
"failed\n", fValueNode, fValueNode->Name().String());
|
||||
return error;
|
||||
}
|
||||
Reference<ValueLocation> locationReference(location, true);
|
||||
Reference<Value> valueReference(value, true);
|
||||
|
||||
// convert to host endianess
|
||||
#if B_HOST_IS_LENDIAN
|
||||
value.SwapEndianess();
|
||||
#endif
|
||||
// set location and value on the node
|
||||
containerLocker.Lock();
|
||||
status_t nodeResolutionState
|
||||
= fValueNode->LocationAndValueResolutionState();
|
||||
if (nodeResolutionState != VALUE_NODE_UNRESOLVED)
|
||||
return nodeResolutionState;
|
||||
fValueNode->SetLocationAndValue(location, value, B_OK);
|
||||
containerLocker.Unlock();
|
||||
|
||||
return _SetValue(value, actualType, location);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
GetStackFrameValueJob::_SetValue(const BVariant& value, Type* type,
|
||||
ValueLocation* location)
|
||||
{
|
||||
// set the value
|
||||
AutoLocker<Team> locker(fThread->GetTeam());
|
||||
|
||||
status_t error = fStackFrame->Values()->SetValue(fVariable->ID(), fPath,
|
||||
value);
|
||||
if (error != B_OK) {
|
||||
TRACE_LOCALS(" -> failed to set value: %s\n", strerror(error));
|
||||
return error;
|
||||
}
|
||||
|
||||
fStackFrame->ValueInfos()->SetInfo(fVariable->ID(), fPath, type, location);
|
||||
|
||||
fStackFrame->NotifyValueRetrieved(fVariable, fPath);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
GetStackFrameValueJob::_ResolveTypeAndLocation(Type*& _type,
|
||||
ValueLocation*& _location, bool& _valueResolved)
|
||||
ResolveValueNodeValueJob::_ResolveNodeChildLocation(ValueNodeChild* nodeChild)
|
||||
{
|
||||
if (fPath->CountComponents() == 0) {
|
||||
fVariable->GetType()->AcquireReference();
|
||||
fVariable->Location()->AcquireReference();
|
||||
_type = fVariable->GetType();
|
||||
_location = fVariable->Location();
|
||||
_valueResolved = false;
|
||||
return B_OK;
|
||||
}
|
||||
// resolve the location
|
||||
ValueLoader valueLoader(fArchitecture, fDebuggerInterface, fCpuState);
|
||||
ValueLocation* location = NULL;
|
||||
status_t error = nodeChild->ResolveLocation(&valueLoader, location);
|
||||
Reference<ValueLocation> locationReference(location, true);
|
||||
|
||||
// get the parent value
|
||||
int32 componentCount = fPath->CountComponents();
|
||||
TypeComponentPath* parentPath = fPath->CreateSubPath(componentCount - 1);
|
||||
if (parentPath == NULL)
|
||||
return B_NO_MEMORY;
|
||||
Reference<TypeComponentPath> parentPathReference(parentPath, true);
|
||||
// set the location on the node child
|
||||
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
|
||||
status_t nodeChildResolutionState = nodeChild->LocationResolutionState();
|
||||
if (nodeChildResolutionState == VALUE_NODE_UNRESOLVED)
|
||||
nodeChild->SetLocation(location, error);
|
||||
else
|
||||
error = nodeChildResolutionState;
|
||||
|
||||
Type* parentType;
|
||||
ValueLocation* parentLocation;
|
||||
BVariant parentValue;
|
||||
status_t error = _GetTypeLocationAndValue(parentPath, parentType,
|
||||
parentLocation, parentValue);
|
||||
if (error != B_OK) {
|
||||
TRACE_LOCALS("GetStackFrameValueJob::_ResolveTypeAndLocation(): "
|
||||
"_GetTypeLocationAndValue() failed: %s\n", strerror(error));
|
||||
return error;
|
||||
}
|
||||
Reference<Type> parentTypeReference(parentType, true);
|
||||
Reference<ValueLocation> parentLocationReference(parentLocation, true);
|
||||
|
||||
// resolve the last component
|
||||
TypeComponent component = fPath->ComponentAt(componentCount - 1);
|
||||
switch (component.typeKind) {
|
||||
case TYPE_PRIMITIVE:
|
||||
case TYPE_ENUMERATION:
|
||||
case TYPE_SUBRANGE:
|
||||
case TYPE_UNSPECIFIED:
|
||||
case TYPE_FUNCTION:
|
||||
case TYPE_POINTER_TO_MEMBER:
|
||||
// cannot happen
|
||||
TRACE_LOCALS("GetStackFrameValueJob::_ResolveTypeAndLocation(): "
|
||||
"TYPE_PRIMITIVE/TYPE_ENUMERATION/TYPE_SUBRANGE/"
|
||||
"TYPE_UNSPECIFIED/TYPE_FUNCTION/TYPE_POINTER_TO_MEMBER "
|
||||
"subcomponent!\n");
|
||||
return B_BAD_VALUE;
|
||||
case TYPE_COMPOUND:
|
||||
{
|
||||
CompoundType* compoundType
|
||||
= dynamic_cast<CompoundType*>(parentType);
|
||||
|
||||
// base type
|
||||
if (component.componentKind == TYPE_COMPONENT_BASE_TYPE) {
|
||||
BaseType* baseType = compoundType->BaseTypeAt(
|
||||
component.index);
|
||||
if (baseType == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// The parent's location refers to the location of the complete
|
||||
// object. We want to extract the location of a member.
|
||||
ValueLocation* location;
|
||||
error = compoundType->ResolveBaseTypeLocation(baseType,
|
||||
*parentLocation, location);
|
||||
if (error != B_OK) {
|
||||
TRACE_LOCALS("GetStackFrameValueJob::"
|
||||
"_ResolveTypeAndLocation(): TYPE_COMPOUND: "
|
||||
"ResolveBaseTypeLocation() failed: %s\n",
|
||||
strerror(error));
|
||||
return error;
|
||||
}
|
||||
|
||||
baseType->GetType()->AcquireReference();
|
||||
_type = baseType->GetType();
|
||||
_location = location;
|
||||
_valueResolved = false;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// data member
|
||||
if (component.componentKind == TYPE_COMPONENT_DATA_MEMBER) {
|
||||
DataMember* dataMember = compoundType->DataMemberAt(
|
||||
component.index);
|
||||
if (dataMember == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// The parent's location refers to the location of the complete
|
||||
// object. We want to extract the location of a member.
|
||||
ValueLocation* location;
|
||||
error = compoundType->ResolveDataMemberLocation(dataMember,
|
||||
*parentLocation, location);
|
||||
if (error != B_OK) {
|
||||
TRACE_LOCALS("GetStackFrameValueJob::"
|
||||
"_ResolveTypeAndLocation(): TYPE_COMPOUND: "
|
||||
"ResolveDataMemberLocation() failed: %s\n",
|
||||
strerror(error));
|
||||
return error;
|
||||
}
|
||||
|
||||
dataMember->GetType()->AcquireReference();
|
||||
_type = dataMember->GetType();
|
||||
_location = location;
|
||||
_valueResolved = false;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
case TYPE_MODIFIED:
|
||||
case TYPE_TYPEDEF:
|
||||
{
|
||||
Type* type = component.typeKind == TYPE_MODIFIED
|
||||
? dynamic_cast<ModifiedType*>(parentType)->BaseType()
|
||||
: dynamic_cast<TypedefType*>(parentType)->BaseType();
|
||||
_valueResolved = true;
|
||||
return _SetValue(parentValue, type, parentLocation);
|
||||
}
|
||||
case TYPE_ADDRESS:
|
||||
{
|
||||
// The parent's value is an address pointing to this component.
|
||||
// resolve the location
|
||||
Type* type = dynamic_cast<AddressType*>(parentType)->BaseType();
|
||||
ValueLocation* location;
|
||||
error = type->ResolveObjectDataLocation(parentValue.ToUInt64(),
|
||||
location);
|
||||
if (error != B_OK) {
|
||||
TRACE_LOCALS("GetStackFrameValueJob::"
|
||||
"_ResolveTypeAndLocation(): "
|
||||
"TYPE_ADDRESS/TYPE_POINTER_TO_MEMBER: "
|
||||
"ResolveObjectDataLocation() failed: %s\n",
|
||||
strerror(error));
|
||||
return error;
|
||||
}
|
||||
|
||||
type->AcquireReference();
|
||||
_type = type;
|
||||
_location = location;
|
||||
_valueResolved = false;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
case TYPE_ARRAY:
|
||||
{
|
||||
ArrayType* arrayType = dynamic_cast<ArrayType*>(parentType);
|
||||
|
||||
if (component.componentKind != TYPE_COMPONENT_ARRAY_ELEMENT)
|
||||
return B_UNSUPPORTED;
|
||||
|
||||
// get the index path
|
||||
ArrayIndexPath indexPath;
|
||||
error = indexPath.SetTo(component.name.String());
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
if (indexPath.CountIndices() != arrayType->CountDimensions())
|
||||
return B_UNSUPPORTED;
|
||||
|
||||
// resolve the element location
|
||||
ValueLocation* location;
|
||||
error = arrayType->ResolveElementLocation(indexPath,
|
||||
*parentLocation, location);
|
||||
if (error != B_OK) {
|
||||
TRACE_LOCALS("GetStackFrameValueJob::"
|
||||
"_ResolveTypeAndLocation(): TYPE_ARRAY: "
|
||||
"ResolveElementLocation() failed: %s\n",
|
||||
strerror(error));
|
||||
return error;
|
||||
}
|
||||
|
||||
arrayType->BaseType()->AcquireReference();
|
||||
_type = arrayType->BaseType();
|
||||
_location = location;
|
||||
_valueResolved = false;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// Can never get here.
|
||||
return B_UNSUPPORTED;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
GetStackFrameValueJob::_GetTypeLocationAndValue(TypeComponentPath* parentPath,
|
||||
Type*& _parentType, ValueLocation*& _parentLocation, BVariant& _parentValue)
|
||||
ResolveValueNodeValueJob::_ResolveParentNodeValue(ValueNode* parentNode)
|
||||
{
|
||||
AutoLocker<Team> teamLocker(fThread->GetTeam());
|
||||
AutoLocker<ValueNodeContainer> containerLocker(fContainer);
|
||||
|
||||
// If there's already a value for the parent path, we're done.
|
||||
StackFrameValues* values = fStackFrame->Values();
|
||||
StackFrameValueInfos* valueInfos = fStackFrame->ValueInfos();
|
||||
if (values->HasValue(fVariable->ID(), parentPath)) {
|
||||
if (!values->GetValue(fVariable->ID(), parentPath, _parentValue)
|
||||
|| !valueInfos->GetInfo(fVariable->ID(), parentPath, &_parentType,
|
||||
&_parentLocation)) {
|
||||
return B_ERROR;
|
||||
}
|
||||
if (parentNode->Container() != fContainer)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
// if the parent node already has a value, we're done
|
||||
status_t nodeResolutionState
|
||||
= parentNode->LocationAndValueResolutionState();
|
||||
if (nodeResolutionState != VALUE_NODE_UNRESOLVED)
|
||||
return nodeResolutionState;
|
||||
|
||||
// check whether a job is already in progress
|
||||
AutoLocker<Worker> workerLocker(GetWorker());
|
||||
GetStackFrameValueJobKey jobKey(fStackFrame, fVariable, parentPath);
|
||||
SimpleJobKey jobKey(parentNode, JOB_TYPE_RESOLVE_VALUE_NODE_VALUE);
|
||||
if (GetWorker()->GetJob(jobKey) == NULL) {
|
||||
workerLocker.Unlock();
|
||||
|
||||
// schedule the job
|
||||
status_t error = GetWorker()->ScheduleJob(
|
||||
new(std::nothrow) GetStackFrameValueJob(fDebuggerInterface,
|
||||
fArchitecture, fThread, fStackFrame, fVariable, parentPath));
|
||||
new(std::nothrow) ResolveValueNodeValueJob(fDebuggerInterface,
|
||||
fArchitecture, fCpuState, fContainer, parentNode));
|
||||
if (error != B_OK) {
|
||||
// scheduling failed -- set the value to invalid
|
||||
values->SetValue(fVariable->ID(), parentPath, BVariant());
|
||||
parentNode->SetLocationAndValue(NULL, NULL, error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
// wait for the job to finish
|
||||
workerLocker.Unlock();
|
||||
teamLocker.Unlock();
|
||||
containerLocker.Unlock();
|
||||
|
||||
switch (WaitFor(jobKey)) {
|
||||
case JOB_DEPENDENCY_SUCCEEDED:
|
||||
@@ -1040,14 +628,10 @@ GetStackFrameValueJob::_GetTypeLocationAndValue(TypeComponentPath* parentPath,
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
teamLocker.Lock();
|
||||
containerLocker.Lock();
|
||||
|
||||
// now there should be a value for the path
|
||||
if (!values->GetValue(fVariable->ID(), parentPath, _parentValue)
|
||||
|| !valueInfos->GetInfo(fVariable->ID(), parentPath, &_parentType,
|
||||
&_parentLocation)) {
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
// now there should be a value for the node
|
||||
nodeResolutionState = parentNode->LocationAndValueResolutionState();
|
||||
return nodeResolutionState != VALUE_NODE_UNRESOLVED
|
||||
? nodeResolutionState : B_ERROR;
|
||||
}
|
||||
|
||||
+20
-46
@@ -24,6 +24,9 @@ class Thread;
|
||||
class Type;
|
||||
class TypeComponentPath;
|
||||
class ValueLocation;
|
||||
class ValueNode;
|
||||
class ValueNodeChild;
|
||||
class ValueNodeContainer;
|
||||
class Variable;
|
||||
|
||||
|
||||
@@ -34,7 +37,8 @@ enum {
|
||||
JOB_TYPE_GET_STACK_TRACE,
|
||||
JOB_TYPE_LOAD_IMAGE_DEBUG_INFO,
|
||||
JOB_TYPE_LOAD_SOURCE_CODE,
|
||||
JOB_TYPE_GET_STACK_FRAME_VALUE
|
||||
JOB_TYPE_GET_STACK_FRAME_VALUE,
|
||||
JOB_TYPE_RESOLVE_VALUE_NODE_VALUE
|
||||
};
|
||||
|
||||
|
||||
@@ -143,63 +147,33 @@ private:
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct GetStackFrameValueJobKey : JobKey {
|
||||
StackFrame* stackFrame;
|
||||
Variable* variable;
|
||||
TypeComponentPath* path;
|
||||
|
||||
class ResolveValueNodeValueJob : public Job {
|
||||
public:
|
||||
GetStackFrameValueJobKey(
|
||||
StackFrame* stackFrame,
|
||||
Variable* variable,
|
||||
TypeComponentPath* path);
|
||||
|
||||
virtual uint32 HashValue() const;
|
||||
|
||||
virtual bool operator==(const JobKey& other) const;
|
||||
};
|
||||
|
||||
|
||||
class GetStackFrameValueJob : public Job {
|
||||
public:
|
||||
GetStackFrameValueJob(
|
||||
ResolveValueNodeValueJob(
|
||||
DebuggerInterface* debuggerInterface,
|
||||
Architecture* architecture,
|
||||
Thread* thread, StackFrame* stackFrame,
|
||||
Variable* variable,
|
||||
TypeComponentPath* path);
|
||||
virtual ~GetStackFrameValueJob();
|
||||
CpuState* cpuState,
|
||||
ValueNodeContainer* container,
|
||||
ValueNode* valueNode);
|
||||
virtual ~ResolveValueNodeValueJob();
|
||||
|
||||
virtual const JobKey& Key() const;
|
||||
virtual status_t Do();
|
||||
|
||||
private:
|
||||
struct ValueJobKey;
|
||||
status_t _ResolveNodeValue();
|
||||
status_t _ResolveNodeChildLocation(
|
||||
ValueNodeChild* nodeChild);
|
||||
status_t _ResolveParentNodeValue(ValueNode* parentNode);
|
||||
|
||||
|
||||
private:
|
||||
status_t _GetValue();
|
||||
status_t _SetValue(const BVariant& value, Type* type,
|
||||
ValueLocation* location);
|
||||
status_t _ResolveTypeAndLocation(Type*& _type,
|
||||
ValueLocation*& _location,
|
||||
bool& _valueResolved);
|
||||
// returns references
|
||||
status_t _GetTypeLocationAndValue(
|
||||
TypeComponentPath* parentPath,
|
||||
Type*& _parentType,
|
||||
ValueLocation*& _parentLocation,
|
||||
BVariant& _parentValue);
|
||||
// returns references
|
||||
|
||||
private:
|
||||
GetStackFrameValueJobKey fKey;
|
||||
SimpleJobKey fKey;
|
||||
DebuggerInterface* fDebuggerInterface;
|
||||
Architecture* fArchitecture;
|
||||
Thread* fThread;
|
||||
StackFrame* fStackFrame;
|
||||
Variable* fVariable;
|
||||
TypeComponentPath* fPath;
|
||||
CpuState* fCpuState;
|
||||
ValueNodeContainer* fContainer;
|
||||
ValueNode* fValueNode;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -7,30 +7,41 @@
|
||||
|
||||
|
||||
enum {
|
||||
MSG_THREAD_RUN = 'run_',
|
||||
MSG_THREAD_STOP = 'stop',
|
||||
MSG_THREAD_STEP_OVER = 'stov',
|
||||
MSG_THREAD_STEP_INTO = 'stin',
|
||||
MSG_THREAD_STEP_OUT = 'stou',
|
||||
MSG_SET_BREAKPOINT = 'sbrk',
|
||||
MSG_CLEAR_BREAKPOINT = 'cbrk',
|
||||
MSG_ENABLE_BREAKPOINT = 'ebrk',
|
||||
MSG_DISABLE_BREAKPOINT = 'dbrk',
|
||||
MSG_THREAD_RUN = 'run_',
|
||||
MSG_THREAD_STOP = 'stop',
|
||||
MSG_THREAD_STEP_OVER = 'stov',
|
||||
MSG_THREAD_STEP_INTO = 'stin',
|
||||
MSG_THREAD_STEP_OUT = 'stou',
|
||||
MSG_SET_BREAKPOINT = 'sbrk',
|
||||
MSG_CLEAR_BREAKPOINT = 'cbrk',
|
||||
MSG_ENABLE_BREAKPOINT = 'ebrk',
|
||||
MSG_DISABLE_BREAKPOINT = 'dbrk',
|
||||
|
||||
MSG_THREAD_STATE_CHANGED = 'tsch',
|
||||
MSG_THREAD_CPU_STATE_CHANGED = 'tcsc',
|
||||
MSG_THREAD_STACK_TRACE_CHANGED = 'tstc',
|
||||
MSG_STACK_FRAME_VALUE_RETRIEVED = 'sfvr',
|
||||
MSG_IMAGE_DEBUG_INFO_CHANGED = 'idic',
|
||||
MSG_IMAGE_FILE_CHANGED = 'ifch',
|
||||
MSG_FUNCTION_SOURCE_CODE_CHANGED = 'fnsc',
|
||||
MSG_USER_BREAKPOINT_CHANGED = 'ubrc',
|
||||
MSG_DEBUGGER_EVENT = 'dbge',
|
||||
MSG_LOAD_SETTINGS = 'ldst',
|
||||
MSG_THREAD_STATE_CHANGED = 'tsch',
|
||||
MSG_THREAD_CPU_STATE_CHANGED = 'tcsc',
|
||||
MSG_THREAD_STACK_TRACE_CHANGED = 'tstc',
|
||||
MSG_STACK_FRAME_VALUE_RETRIEVED = 'sfvr',
|
||||
MSG_IMAGE_DEBUG_INFO_CHANGED = 'idic',
|
||||
MSG_IMAGE_FILE_CHANGED = 'ifch',
|
||||
MSG_FUNCTION_SOURCE_CODE_CHANGED = 'fnsc',
|
||||
MSG_USER_BREAKPOINT_CHANGED = 'ubrc',
|
||||
MSG_DEBUGGER_EVENT = 'dbge',
|
||||
MSG_LOAD_SETTINGS = 'ldst',
|
||||
|
||||
MSG_TEXTVIEW_AUTOSCROLL = 'tvas',
|
||||
MSG_SETTINGS_MENU_IMPL_ITEM_SELECTED = 'smii',
|
||||
MSG_SETTINGS_MENU_IMPL_OPTION_ITEM_SELECTED = 'smio',
|
||||
|
||||
MSG_TEAM_DEBUGGER_QUIT = 'dbqt'
|
||||
MSG_TEXTVIEW_AUTOSCROLL = 'tvas',
|
||||
|
||||
MSG_VARIABLES_VIEW_CONTEXT_MENU_DONE = 'ctxd',
|
||||
MSG_VARIABLES_VIEW_NODE_SETTINGS_CHANGED = 'vvns',
|
||||
|
||||
MSG_VALUE_NODE_CHANGED = 'vnch',
|
||||
MSG_VALUE_NODE_CHILDREN_CREATED = 'vncc',
|
||||
MSG_VALUE_NODE_CHILDREN_DELETED = 'vncd',
|
||||
MSG_VALUE_NODE_VALUE_CHANGED = 'vnvc',
|
||||
|
||||
MSG_TEAM_DEBUGGER_QUIT = 'dbqt'
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
#include "TeamDebugInfo.h"
|
||||
#include "TeamSettings.h"
|
||||
#include "Tracing.h"
|
||||
#include "ValueNode.h"
|
||||
#include "ValueNodeContainer.h"
|
||||
#include "Variable.h"
|
||||
|
||||
// #pragma mark - ImageHandler
|
||||
@@ -558,26 +560,29 @@ TeamDebugger::ImageDebugInfoRequested(Image* image)
|
||||
|
||||
|
||||
void
|
||||
TeamDebugger::StackFrameValueRequested(::Thread* thread, StackFrame* stackFrame,
|
||||
Variable* variable, TypeComponentPath* path)
|
||||
TeamDebugger::ValueNodeValueRequested(CpuState* cpuState,
|
||||
ValueNodeContainer* container, ValueNode* valueNode)
|
||||
{
|
||||
// the team is already locked
|
||||
AutoLocker<ValueNodeContainer> containerLocker(container);
|
||||
if (valueNode->Container() != container)
|
||||
return;
|
||||
|
||||
// check whether a job is already in progress
|
||||
AutoLocker<Worker> workerLocker(fWorker);
|
||||
GetStackFrameValueJobKey jobKey(stackFrame, variable, path);
|
||||
SimpleJobKey jobKey(valueNode, JOB_TYPE_RESOLVE_VALUE_NODE_VALUE);
|
||||
if (fWorker->GetJob(jobKey) != NULL)
|
||||
return;
|
||||
workerLocker.Unlock();
|
||||
|
||||
// schedule the job
|
||||
if (fWorker->ScheduleJob(
|
||||
new(std::nothrow) GetStackFrameValueJob(fDebuggerInterface,
|
||||
fDebuggerInterface->GetArchitecture(), thread, stackFrame,
|
||||
variable, path),
|
||||
this) != B_OK) {
|
||||
status_t error = fWorker->ScheduleJob(
|
||||
new(std::nothrow) ResolveValueNodeValueJob(fDebuggerInterface,
|
||||
fDebuggerInterface->GetArchitecture(), cpuState, container,
|
||||
valueNode),
|
||||
this);
|
||||
if (error != B_OK) {
|
||||
// scheduling failed -- set the value to invalid
|
||||
stackFrame->Values()->SetValue(variable->ID(), path, BVariant());
|
||||
valueNode->SetLocationAndValue(NULL, NULL, error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,9 +47,9 @@ private:
|
||||
virtual void FunctionSourceCodeRequested(
|
||||
FunctionInstance* function);
|
||||
virtual void ImageDebugInfoRequested(Image* image);
|
||||
virtual void StackFrameValueRequested(::Thread* thread,
|
||||
StackFrame* stackFrame, Variable* variable,
|
||||
TypeComponentPath* path);
|
||||
virtual void ValueNodeValueRequested(CpuState* cpuState,
|
||||
ValueNodeContainer* container,
|
||||
ValueNode* valueNode);
|
||||
virtual void ThreadActionRequested(thread_id threadID,
|
||||
uint32 action);
|
||||
virtual void SetBreakpointRequested(target_addr_t address,
|
||||
|
||||
@@ -193,6 +193,13 @@ DwarfTypeFactory::CreateType(DIEType* typeEntry, DwarfType*& _type)
|
||||
AutoLocker<GlobalTypeCache> cacheLocker(fTypeCache);
|
||||
Type* globalType = name.Length() > 0
|
||||
? fTypeCache->GetType(name) : NULL;
|
||||
if (globalType == NULL) {
|
||||
// lookup by name failed -- try lookup by ID
|
||||
BString id;
|
||||
if (DwarfType::GetTypeID(typeEntry, id))
|
||||
globalType = fTypeCache->GetTypeByID(id);
|
||||
}
|
||||
|
||||
if (globalType != NULL) {
|
||||
DwarfType* globalDwarfType = dynamic_cast<DwarfType*>(globalType);
|
||||
if (globalDwarfType != NULL) {
|
||||
@@ -228,15 +235,15 @@ DwarfTypeFactory::CreateType(DIEType* typeEntry, DwarfType*& _type)
|
||||
|
||||
// Insert the type into the cache. Re-check, as the type may already
|
||||
// have been inserted (e.g. in the compound type case).
|
||||
if (name.Length() > 0) {
|
||||
cacheLocker.Lock();
|
||||
if (fTypeCache->GetType(name) == NULL) {
|
||||
error = fTypeCache->AddType(name, type);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
}
|
||||
cacheLocker.Unlock();
|
||||
cacheLocker.Lock();
|
||||
if (name.Length() > 0
|
||||
? fTypeCache->GetType(name) == NULL
|
||||
: fTypeCache->GetTypeByID(type->ID()) == NULL) {
|
||||
error = fTypeCache->AddType(type);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
}
|
||||
cacheLocker.Unlock();
|
||||
|
||||
// try to get the type's size
|
||||
uint64 size;
|
||||
@@ -354,9 +361,12 @@ DwarfTypeFactory::_CreateCompoundType(const BString& name,
|
||||
// incomplete type could become visible to other threads. Hence we keep the
|
||||
// context locked, but that essentially kills multi-threading for this context.
|
||||
AutoLocker<GlobalTypeCache> cacheLocker(fTypeCache);
|
||||
status_t error = fTypeCache->AddType(name, type);
|
||||
status_t error = fTypeCache->AddType(type);
|
||||
if (error != B_OK)
|
||||
{
|
||||
printf(" -> failed to add type to cache\n");
|
||||
return error;
|
||||
}
|
||||
// cacheLocker.Unlock();
|
||||
|
||||
// find the abstract origin or specification that defines the data members
|
||||
@@ -388,7 +398,7 @@ DwarfTypeFactory::_CreateCompoundType(const BString& name,
|
||||
Reference<DwarfDataMember> memberReference(member, true);
|
||||
if (member == NULL || !type->AddDataMember(member)) {
|
||||
cacheLocker.Lock();
|
||||
fTypeCache->RemoveType(name);
|
||||
fTypeCache->RemoveType(type);
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
@@ -423,7 +433,7 @@ DwarfTypeFactory::_CreateCompoundType(const BString& name,
|
||||
true);
|
||||
if (inheritance == NULL || !type->AddInheritance(inheritance)) {
|
||||
cacheLocker.Lock();
|
||||
fTypeCache->RemoveType(name);
|
||||
fTypeCache->RemoveType(type);
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
@@ -808,10 +818,10 @@ DwarfTypeFactory::_CreateEnumerationType(const BString& name,
|
||||
}
|
||||
|
||||
// create and add the enumeration value object
|
||||
DwarfEnumerationValue* enumValue
|
||||
= new(std::nothrow) DwarfEnumerationValue(enumeratorEntry,
|
||||
DwarfEnumeratorValue* enumValue
|
||||
= new(std::nothrow) DwarfEnumeratorValue(enumeratorEntry,
|
||||
enumeratorEntry->Name(), value);
|
||||
Reference<DwarfEnumerationValue> enumValueReference(enumValue, true);
|
||||
Reference<DwarfEnumeratorValue> enumValueReference(enumValue, true);
|
||||
if (enumValue == NULL || !type->AddValue(enumValue))
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ class DwarfArrayType;
|
||||
class DwarfCompoundType;
|
||||
class DwarfDataMember;
|
||||
class DwarfEnumerationType;
|
||||
class DwarfEnumerationValue;
|
||||
class DwarfEnumeratorValue;
|
||||
class DwarfFile;
|
||||
class DwarfFunctionParameter;
|
||||
class DwarfFunctionType;
|
||||
|
||||
@@ -85,13 +85,16 @@ DwarfTypeContext::~DwarfTypeContext()
|
||||
// #pragma mark - DwarfType
|
||||
|
||||
|
||||
DwarfType::DwarfType(DwarfTypeContext* typeContext, const BString& name)
|
||||
DwarfType::DwarfType(DwarfTypeContext* typeContext, const BString& name,
|
||||
const DIEType* entry)
|
||||
:
|
||||
fTypeContext(typeContext),
|
||||
fName(name),
|
||||
fByteSize(0)
|
||||
{
|
||||
fTypeContext->AcquireReference();
|
||||
|
||||
GetTypeID(entry, fID);
|
||||
}
|
||||
|
||||
|
||||
@@ -101,6 +104,20 @@ DwarfType::~DwarfType()
|
||||
}
|
||||
|
||||
|
||||
/*static*/ bool
|
||||
DwarfType::GetTypeID(const DIEType* entry, BString& _id)
|
||||
{
|
||||
char buffer[32];
|
||||
snprintf(buffer, sizeof(buffer), "dwarf:%p", entry);
|
||||
BString id = buffer;
|
||||
if (id.Length() == 0)
|
||||
return false;
|
||||
|
||||
_id = id;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
image_id
|
||||
DwarfType::ImageID() const
|
||||
{
|
||||
@@ -108,10 +125,17 @@ DwarfType::ImageID() const
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
const BString&
|
||||
DwarfType::ID() const
|
||||
{
|
||||
return fID;
|
||||
}
|
||||
|
||||
|
||||
const BString&
|
||||
DwarfType::Name() const
|
||||
{
|
||||
return fName.Length() > 0 ? fName.String() : NULL;
|
||||
return fName;
|
||||
}
|
||||
|
||||
|
||||
@@ -308,10 +332,10 @@ DwarfDataMember::GetType() const
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - DwarfEnumerationValue
|
||||
// #pragma mark - DwarfEnumeratorValue
|
||||
|
||||
|
||||
DwarfEnumerationValue::DwarfEnumerationValue(DIEEnumerator* entry,
|
||||
DwarfEnumeratorValue::DwarfEnumeratorValue(DIEEnumerator* entry,
|
||||
const BString& name, const BVariant& value)
|
||||
:
|
||||
fEntry(entry),
|
||||
@@ -321,19 +345,19 @@ DwarfEnumerationValue::DwarfEnumerationValue(DIEEnumerator* entry,
|
||||
}
|
||||
|
||||
|
||||
DwarfEnumerationValue::~DwarfEnumerationValue()
|
||||
DwarfEnumeratorValue::~DwarfEnumeratorValue()
|
||||
{
|
||||
}
|
||||
|
||||
const char*
|
||||
DwarfEnumerationValue::Name() const
|
||||
DwarfEnumeratorValue::Name() const
|
||||
{
|
||||
return fName.Length() > 0 ? fName.String() : NULL;
|
||||
}
|
||||
|
||||
|
||||
BVariant
|
||||
DwarfEnumerationValue::Value() const
|
||||
DwarfEnumeratorValue::Value() const
|
||||
{
|
||||
return fValue;
|
||||
}
|
||||
@@ -403,7 +427,7 @@ DwarfFunctionParameter::GetType() const
|
||||
DwarfPrimitiveType::DwarfPrimitiveType(DwarfTypeContext* typeContext,
|
||||
const BString& name, DIEBaseType* entry, uint32 typeConstant)
|
||||
:
|
||||
DwarfType(typeContext, name),
|
||||
DwarfType(typeContext, name, entry),
|
||||
fEntry(entry),
|
||||
fTypeConstant(typeConstant)
|
||||
{
|
||||
@@ -430,7 +454,7 @@ DwarfPrimitiveType::TypeConstant() const
|
||||
DwarfCompoundType::DwarfCompoundType(DwarfTypeContext* typeContext,
|
||||
const BString& name, DIECompoundType* entry)
|
||||
:
|
||||
DwarfType(typeContext, name),
|
||||
DwarfType(typeContext, name, entry),
|
||||
fEntry(entry)
|
||||
{
|
||||
}
|
||||
@@ -684,7 +708,7 @@ DwarfCompoundType::_ResolveDataMemberLocation(DwarfType* memberType,
|
||||
DwarfArrayType::DwarfArrayType(DwarfTypeContext* typeContext,
|
||||
const BString& name, DIEArrayType* entry, DwarfType* baseType)
|
||||
:
|
||||
DwarfType(typeContext, name),
|
||||
DwarfType(typeContext, name, entry),
|
||||
fEntry(entry),
|
||||
fBaseType(baseType)
|
||||
{
|
||||
@@ -908,7 +932,7 @@ DwarfModifiedType::DwarfModifiedType(DwarfTypeContext* typeContext,
|
||||
const BString& name, DIEModifiedType* entry, uint32 modifiers,
|
||||
DwarfType* baseType)
|
||||
:
|
||||
DwarfType(typeContext, name),
|
||||
DwarfType(typeContext, name, entry),
|
||||
fEntry(entry),
|
||||
fModifiers(modifiers),
|
||||
fBaseType(baseType)
|
||||
@@ -950,7 +974,7 @@ DwarfModifiedType::GetDIEType() const
|
||||
DwarfTypedefType::DwarfTypedefType(DwarfTypeContext* typeContext,
|
||||
const BString& name, DIETypedef* entry, DwarfType* baseType)
|
||||
:
|
||||
DwarfType(typeContext, name),
|
||||
DwarfType(typeContext, name, entry),
|
||||
fEntry(entry),
|
||||
fBaseType(baseType)
|
||||
{
|
||||
@@ -985,7 +1009,7 @@ DwarfAddressType::DwarfAddressType(DwarfTypeContext* typeContext,
|
||||
const BString& name, DIEAddressingType* entry,
|
||||
address_type_kind addressKind, DwarfType* baseType)
|
||||
:
|
||||
DwarfType(typeContext, name),
|
||||
DwarfType(typeContext, name, entry),
|
||||
fEntry(entry),
|
||||
fAddressKind(addressKind),
|
||||
fBaseType(baseType)
|
||||
@@ -1027,7 +1051,7 @@ DwarfAddressType::GetDIEType() const
|
||||
DwarfEnumerationType::DwarfEnumerationType(DwarfTypeContext* typeContext,
|
||||
const BString& name, DIEEnumerationType* entry, DwarfType* baseType)
|
||||
:
|
||||
DwarfType(typeContext, name),
|
||||
DwarfType(typeContext, name, entry),
|
||||
fEntry(entry),
|
||||
fBaseType(baseType)
|
||||
{
|
||||
@@ -1038,7 +1062,7 @@ DwarfEnumerationType::DwarfEnumerationType(DwarfTypeContext* typeContext,
|
||||
|
||||
DwarfEnumerationType::~DwarfEnumerationType()
|
||||
{
|
||||
for (int32 i = 0; DwarfEnumerationValue* value = fValues.ItemAt(i); i++)
|
||||
for (int32 i = 0; DwarfEnumeratorValue* value = fValues.ItemAt(i); i++)
|
||||
value->ReleaseReference();
|
||||
|
||||
if (fBaseType != NULL)
|
||||
@@ -1060,7 +1084,7 @@ DwarfEnumerationType::CountValues() const
|
||||
}
|
||||
|
||||
|
||||
EnumerationValue*
|
||||
EnumeratorValue*
|
||||
DwarfEnumerationType::ValueAt(int32 index) const
|
||||
{
|
||||
return fValues.ItemAt(index);
|
||||
@@ -1075,7 +1099,7 @@ DwarfEnumerationType::GetDIEType() const
|
||||
|
||||
|
||||
bool
|
||||
DwarfEnumerationType::AddValue(DwarfEnumerationValue* value)
|
||||
DwarfEnumerationType::AddValue(DwarfEnumeratorValue* value)
|
||||
{
|
||||
if (!fValues.AddItem(value))
|
||||
return false;
|
||||
@@ -1092,7 +1116,7 @@ DwarfSubrangeType::DwarfSubrangeType(DwarfTypeContext* typeContext,
|
||||
const BString& name, DIESubrangeType* entry, DwarfType* baseType,
|
||||
const BVariant& lowerBound, const BVariant& upperBound)
|
||||
:
|
||||
DwarfType(typeContext, name),
|
||||
DwarfType(typeContext, name, entry),
|
||||
fEntry(entry),
|
||||
fBaseType(baseType),
|
||||
fLowerBound(lowerBound),
|
||||
@@ -1142,7 +1166,7 @@ DwarfSubrangeType::UpperBound() const
|
||||
DwarfUnspecifiedType::DwarfUnspecifiedType(DwarfTypeContext* typeContext,
|
||||
const BString& name, DIEUnspecifiedType* entry)
|
||||
:
|
||||
DwarfType(typeContext, name),
|
||||
DwarfType(typeContext, name, entry),
|
||||
fEntry(entry)
|
||||
{
|
||||
}
|
||||
@@ -1166,7 +1190,7 @@ DwarfUnspecifiedType::GetDIEType() const
|
||||
DwarfFunctionType::DwarfFunctionType(DwarfTypeContext* typeContext,
|
||||
const BString& name, DIESubroutineType* entry, DwarfType* returnType)
|
||||
:
|
||||
DwarfType(typeContext, name),
|
||||
DwarfType(typeContext, name, entry),
|
||||
fEntry(entry),
|
||||
fReturnType(returnType),
|
||||
fHasVariableArguments(false)
|
||||
@@ -1249,7 +1273,7 @@ DwarfPointerToMemberType::DwarfPointerToMemberType(
|
||||
DIEPointerToMemberType* entry, DwarfCompoundType* containingType,
|
||||
DwarfType* baseType)
|
||||
:
|
||||
DwarfType(typeContext, name),
|
||||
DwarfType(typeContext, name, entry),
|
||||
fEntry(entry),
|
||||
fContainingType(containingType),
|
||||
fBaseType(baseType)
|
||||
|
||||
@@ -88,11 +88,14 @@ private:
|
||||
class DwarfType : public virtual Type {
|
||||
public:
|
||||
DwarfType(DwarfTypeContext* typeContext,
|
||||
const BString& name);
|
||||
const BString& name, const DIEType* entry);
|
||||
~DwarfType();
|
||||
|
||||
static bool GetTypeID(const DIEType* entry, BString& _id);
|
||||
|
||||
virtual image_id ImageID() const;
|
||||
virtual const char* Name() const;
|
||||
virtual const BString& ID() const;
|
||||
virtual const BString& Name() const;
|
||||
virtual target_size_t ByteSize() const;
|
||||
|
||||
virtual status_t ResolveObjectDataLocation(
|
||||
@@ -118,6 +121,7 @@ public:
|
||||
private:
|
||||
DwarfTypeContext* fTypeContext;
|
||||
BString fName;
|
||||
BString fID;
|
||||
target_size_t fByteSize;
|
||||
};
|
||||
|
||||
@@ -162,11 +166,11 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class DwarfEnumerationValue : public EnumerationValue {
|
||||
class DwarfEnumeratorValue : public EnumeratorValue {
|
||||
public:
|
||||
DwarfEnumerationValue(DIEEnumerator* entry,
|
||||
DwarfEnumeratorValue(DIEEnumerator* entry,
|
||||
const BString& name, const BVariant& value);
|
||||
~DwarfEnumerationValue();
|
||||
~DwarfEnumeratorValue();
|
||||
|
||||
virtual const char* Name() const;
|
||||
virtual BVariant Value() const;
|
||||
@@ -396,17 +400,17 @@ public:
|
||||
virtual Type* BaseType() const;
|
||||
|
||||
virtual int32 CountValues() const;
|
||||
virtual EnumerationValue* ValueAt(int32 index) const;
|
||||
virtual EnumeratorValue* ValueAt(int32 index) const;
|
||||
|
||||
virtual DIEType* GetDIEType() const;
|
||||
|
||||
bool AddValue(DwarfEnumerationValue* value);
|
||||
bool AddValue(DwarfEnumeratorValue* value);
|
||||
|
||||
DIEEnumerationType* Entry() const
|
||||
{ return fEntry; }
|
||||
|
||||
private:
|
||||
typedef BObjectList<DwarfEnumerationValue> ValueList;
|
||||
typedef BObjectList<DwarfEnumeratorValue> ValueList;
|
||||
|
||||
private:
|
||||
DIEEnumerationType* fEntry;
|
||||
|
||||
@@ -17,13 +17,12 @@
|
||||
|
||||
|
||||
struct GlobalTypeCache::TypeEntry {
|
||||
BString name;
|
||||
Type* type;
|
||||
TypeEntry* fNext;
|
||||
TypeEntry* fNextByName;
|
||||
TypeEntry* fNextByID;
|
||||
|
||||
TypeEntry(const BString& name, Type* type)
|
||||
TypeEntry(Type* type)
|
||||
:
|
||||
name(name),
|
||||
type(type)
|
||||
{
|
||||
type->AcquireReference();
|
||||
@@ -36,7 +35,7 @@ struct GlobalTypeCache::TypeEntry {
|
||||
};
|
||||
|
||||
|
||||
struct GlobalTypeCache::TypeEntryHashDefinition {
|
||||
struct GlobalTypeCache::TypeEntryHashDefinitionByName {
|
||||
typedef const BString KeyType;
|
||||
typedef TypeEntry ValueType;
|
||||
|
||||
@@ -47,17 +46,43 @@ struct GlobalTypeCache::TypeEntryHashDefinition {
|
||||
|
||||
size_t Hash(const TypeEntry* value) const
|
||||
{
|
||||
return HashKey(value->name);
|
||||
return HashKey(value->type->Name());
|
||||
}
|
||||
|
||||
bool Compare(const BString& key, const TypeEntry* value) const
|
||||
{
|
||||
return key == value->name;
|
||||
return key == value->type->Name();
|
||||
}
|
||||
|
||||
TypeEntry*& GetLink(TypeEntry* value) const
|
||||
{
|
||||
return value->fNext;
|
||||
return value->fNextByName;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct GlobalTypeCache::TypeEntryHashDefinitionByID {
|
||||
typedef const BString KeyType;
|
||||
typedef TypeEntry ValueType;
|
||||
|
||||
size_t HashKey(const BString& key) const
|
||||
{
|
||||
return StringUtils::HashValue(key);
|
||||
}
|
||||
|
||||
size_t Hash(const TypeEntry* value) const
|
||||
{
|
||||
return HashKey(value->type->ID());
|
||||
}
|
||||
|
||||
bool Compare(const BString& key, const TypeEntry* value) const
|
||||
{
|
||||
return key == value->type->ID();
|
||||
}
|
||||
|
||||
TypeEntry*& GetLink(TypeEntry* value) const
|
||||
{
|
||||
return value->fNextByID;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -67,19 +92,23 @@ struct GlobalTypeCache::TypeEntryHashDefinition {
|
||||
|
||||
GlobalTypeCache::GlobalTypeCache()
|
||||
:
|
||||
fLock("global type lookup"),
|
||||
fTypes(NULL)
|
||||
fLock("global type cache"),
|
||||
fTypesByName(NULL),
|
||||
fTypesByID(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
GlobalTypeCache::~GlobalTypeCache()
|
||||
{
|
||||
if (fTypesByName != NULL)
|
||||
fTypesByName->Clear();
|
||||
|
||||
// release all cached type references
|
||||
if (fTypes != NULL) {
|
||||
TypeEntry* entry = fTypes->Clear(true);
|
||||
if (fTypesByID != NULL) {
|
||||
TypeEntry* entry = fTypesByID->Clear(true);
|
||||
while (entry != NULL) {
|
||||
TypeEntry* nextEntry = entry->fNext;
|
||||
TypeEntry* nextEntry = entry->fNextByID;
|
||||
delete entry;
|
||||
entry = nextEntry;
|
||||
}
|
||||
@@ -90,48 +119,85 @@ GlobalTypeCache::~GlobalTypeCache()
|
||||
status_t
|
||||
GlobalTypeCache::Init()
|
||||
{
|
||||
// check lock
|
||||
status_t error = fLock.InitCheck();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
fTypes = new(std::nothrow) TypeTable;
|
||||
if (fTypes == NULL)
|
||||
// create name table
|
||||
fTypesByName = new(std::nothrow) NameTable;
|
||||
if (fTypesByName == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
return fTypes->Init();
|
||||
error = fTypesByName->Init();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
// create ID table
|
||||
fTypesByID = new(std::nothrow) IDTable;
|
||||
if (fTypesByID == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
error = fTypesByID->Init();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
Type*
|
||||
GlobalTypeCache::GetType(const BString& name) const
|
||||
{
|
||||
TypeEntry* typeEntry = fTypes->Lookup(name);
|
||||
TypeEntry* typeEntry = fTypesByName->Lookup(name);
|
||||
return typeEntry != NULL ? typeEntry->type : NULL;
|
||||
}
|
||||
|
||||
|
||||
Type*
|
||||
GlobalTypeCache::GetTypeByID(const BString& id) const
|
||||
{
|
||||
TypeEntry* typeEntry = fTypesByID->Lookup(id);
|
||||
return typeEntry != NULL ? typeEntry->type : NULL;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
GlobalTypeCache::AddType(const BString& name, Type* type)
|
||||
GlobalTypeCache::AddType(Type* type)
|
||||
{
|
||||
TypeEntry* typeEntry = fTypes->Lookup(name);
|
||||
if (typeEntry != NULL)
|
||||
return B_BAD_VALUE;
|
||||
const BString& id = type->ID();
|
||||
const BString& name = type->Name();
|
||||
|
||||
typeEntry = new(std::nothrow) TypeEntry(name, type);
|
||||
if (fTypesByID->Lookup(id) != NULL
|
||||
|| (name.Length() > 0 && fTypesByID->Lookup(name) != NULL)) {
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
TypeEntry* typeEntry = new(std::nothrow) TypeEntry(type);
|
||||
if (typeEntry == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
fTypes->Insert(typeEntry);
|
||||
fTypesByID->Insert(typeEntry);
|
||||
|
||||
if (name.Length() > 0)
|
||||
fTypesByName->Insert(typeEntry);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
GlobalTypeCache::RemoveType(const BString& name)
|
||||
GlobalTypeCache::RemoveType(Type* type)
|
||||
{
|
||||
if (TypeEntry* typeEntry = fTypes->Lookup(name)) {
|
||||
fTypes->Remove(typeEntry);
|
||||
delete typeEntry;
|
||||
if (TypeEntry* typeEntry = fTypesByID->Lookup(type->ID())) {
|
||||
if (typeEntry->type == type) {
|
||||
fTypesByID->Remove(typeEntry);
|
||||
|
||||
if (type->Name().Length() > 0)
|
||||
fTypesByName->Remove(typeEntry);
|
||||
|
||||
delete typeEntry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,10 +207,14 @@ GlobalTypeCache::RemoveTypes(image_id imageID)
|
||||
{
|
||||
AutoLocker<GlobalTypeCache> locker(this);
|
||||
|
||||
for (TypeTable::Iterator it = fTypes->GetIterator();
|
||||
for (IDTable::Iterator it = fTypesByID->GetIterator();
|
||||
TypeEntry* typeEntry = it.Next();) {
|
||||
if (typeEntry->type->ImageID() == imageID) {
|
||||
fTypes->RemoveUnchecked(typeEntry);
|
||||
fTypesByID->RemoveUnchecked(typeEntry);
|
||||
|
||||
if (typeEntry->type->Name().Length() > 0)
|
||||
fTypesByName->Remove(typeEntry);
|
||||
|
||||
delete typeEntry;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,12 @@ class BString;
|
||||
class Type;
|
||||
|
||||
|
||||
enum global_type_cache_scope {
|
||||
GLOBAL_TYPE_CACHE_SCOPE_GLOBAL,
|
||||
GLOBAL_TYPE_CACHE_SCOPE_COMPILATION_UNIT
|
||||
};
|
||||
|
||||
|
||||
class GlobalTypeCache : public Referenceable {
|
||||
public:
|
||||
GlobalTypeCache();
|
||||
@@ -29,21 +35,25 @@ public:
|
||||
|
||||
// cache must be locked
|
||||
Type* GetType(const BString& name) const;
|
||||
status_t AddType(const BString& name, Type* type);
|
||||
void RemoveType(const BString& name);
|
||||
Type* GetTypeByID(const BString& id) const;
|
||||
status_t AddType(Type* type);
|
||||
void RemoveType(Type* type);
|
||||
|
||||
// cache locked by method
|
||||
void RemoveTypes(image_id imageID);
|
||||
|
||||
private:
|
||||
struct TypeEntry;
|
||||
struct TypeEntryHashDefinition;
|
||||
struct TypeEntryHashDefinitionByName;
|
||||
struct TypeEntryHashDefinitionByID;
|
||||
|
||||
typedef BOpenHashTable<TypeEntryHashDefinition> TypeTable;
|
||||
typedef BOpenHashTable<TypeEntryHashDefinitionByName> NameTable;
|
||||
typedef BOpenHashTable<TypeEntryHashDefinitionByID> IDTable;
|
||||
|
||||
private:
|
||||
BLocker fLock;
|
||||
TypeTable* fTypes;
|
||||
NameTable* fTypesByName;
|
||||
IDTable* fTypesByID;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -23,10 +23,10 @@ DataMember::~DataMember()
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - EnumerationValue
|
||||
// #pragma mark - EnumeratorValue
|
||||
|
||||
|
||||
EnumerationValue::~EnumerationValue()
|
||||
EnumeratorValue::~EnumeratorValue()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ Type::~Type()
|
||||
|
||||
|
||||
Type*
|
||||
Type::ResolveRawType() const
|
||||
Type::ResolveRawType(bool nextOneOnly) const
|
||||
{
|
||||
return const_cast<Type*>(this);
|
||||
}
|
||||
@@ -133,9 +133,10 @@ ModifiedType::Kind() const
|
||||
|
||||
|
||||
Type*
|
||||
ModifiedType::ResolveRawType() const
|
||||
ModifiedType::ResolveRawType(bool nextOneOnly) const
|
||||
{
|
||||
return BaseType();
|
||||
Type* baseType = BaseType();
|
||||
return nextOneOnly ? baseType : baseType->ResolveRawType(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -155,9 +156,10 @@ TypedefType::Kind() const
|
||||
|
||||
|
||||
Type*
|
||||
TypedefType::ResolveRawType() const
|
||||
TypedefType::ResolveRawType(bool nextOneOnly) const
|
||||
{
|
||||
return BaseType();
|
||||
Type* baseType = BaseType();
|
||||
return nextOneOnly ? baseType : baseType->ResolveRawType(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -191,11 +193,11 @@ EnumerationType::Kind() const
|
||||
}
|
||||
|
||||
|
||||
EnumerationValue*
|
||||
EnumeratorValue*
|
||||
EnumerationType::ValueFor(const BVariant& value) const
|
||||
{
|
||||
// TODO: Optimize?
|
||||
for (int32 i = 0; EnumerationValue* enumValue = ValueAt(i); i++) {
|
||||
for (int32 i = 0; EnumeratorValue* enumValue = ValueAt(i); i++) {
|
||||
if (enumValue->Value() == value)
|
||||
return enumValue;
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ enum {
|
||||
|
||||
|
||||
class ArrayIndexPath;
|
||||
class BString;
|
||||
class Type;
|
||||
class ValueLocation;
|
||||
|
||||
@@ -66,9 +67,9 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class EnumerationValue : public Referenceable {
|
||||
class EnumeratorValue : public Referenceable {
|
||||
public:
|
||||
virtual ~EnumerationValue();
|
||||
virtual ~EnumeratorValue();
|
||||
|
||||
virtual const char* Name() const = 0;
|
||||
virtual BVariant Value() const = 0;
|
||||
@@ -100,11 +101,13 @@ public:
|
||||
virtual ~Type();
|
||||
|
||||
virtual image_id ImageID() const = 0;
|
||||
virtual const char* Name() const = 0;
|
||||
virtual const BString& ID() const = 0;
|
||||
virtual const BString& Name() const = 0;
|
||||
virtual type_kind Kind() const = 0;
|
||||
virtual target_size_t ByteSize() const = 0;
|
||||
virtual Type* ResolveRawType() const;
|
||||
// strips modifiers and typedefs
|
||||
virtual Type* ResolveRawType(bool nextOneOnly) const;
|
||||
// strips modifiers and typedefs (only one,
|
||||
// if requested)
|
||||
|
||||
virtual status_t ResolveObjectDataLocation(
|
||||
const ValueLocation& objectLocation,
|
||||
@@ -158,7 +161,7 @@ public:
|
||||
|
||||
virtual uint32 Modifiers() const = 0;
|
||||
virtual Type* BaseType() const = 0;
|
||||
virtual Type* ResolveRawType() const;
|
||||
virtual Type* ResolveRawType(bool nextOneOnly) const;
|
||||
};
|
||||
|
||||
|
||||
@@ -169,7 +172,7 @@ public:
|
||||
virtual type_kind Kind() const;
|
||||
|
||||
virtual Type* BaseType() const = 0;
|
||||
virtual Type* ResolveRawType() const;
|
||||
virtual Type* ResolveRawType(bool nextOneOnly) const;
|
||||
};
|
||||
|
||||
|
||||
@@ -194,8 +197,8 @@ public:
|
||||
// may return NULL
|
||||
|
||||
virtual int32 CountValues() const = 0;
|
||||
virtual EnumerationValue* ValueAt(int32 index) const = 0;
|
||||
virtual EnumerationValue* ValueFor(const BVariant& value) const;
|
||||
virtual EnumeratorValue* ValueAt(int32 index) const = 0;
|
||||
virtual EnumeratorValue* ValueFor(const BVariant& value) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "Types.h"
|
||||
|
||||
|
||||
class CpuState;
|
||||
class FunctionInstance;
|
||||
class Image;
|
||||
class StackFrame;
|
||||
@@ -21,6 +22,8 @@ class Thread;
|
||||
class TypeComponentPath;
|
||||
class UserBreakpoint;
|
||||
class UserInterfaceListener;
|
||||
class ValueNode;
|
||||
class ValueNodeContainer;
|
||||
class Variable;
|
||||
|
||||
|
||||
@@ -59,10 +62,9 @@ public:
|
||||
virtual void FunctionSourceCodeRequested(
|
||||
FunctionInstance* function) = 0;
|
||||
virtual void ImageDebugInfoRequested(Image* image) = 0;
|
||||
virtual void StackFrameValueRequested(Thread* thread,
|
||||
StackFrame* stackFrame, Variable* variable,
|
||||
TypeComponentPath* path) = 0;
|
||||
// called with team locked
|
||||
virtual void ValueNodeValueRequested(CpuState* cpuState,
|
||||
ValueNodeContainer* container,
|
||||
ValueNode* valueNode) = 0;
|
||||
virtual void ThreadActionRequested(thread_id threadID,
|
||||
uint32 action) = 0;
|
||||
|
||||
|
||||
@@ -211,24 +211,6 @@ TeamWindow::MessageReceived(BMessage* message)
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_STACK_FRAME_VALUE_RETRIEVED:
|
||||
{
|
||||
void* _stackFrame;
|
||||
void* _variable;
|
||||
void* _path;
|
||||
if (message->FindPointer("stackFrame", &_stackFrame) == B_OK
|
||||
&& message->FindPointer("variable", &_variable) == B_OK
|
||||
&& message->FindPointer("path", &_path) == B_OK) {
|
||||
StackFrame* stackFrame = (StackFrame*)_stackFrame;
|
||||
Variable* variable = (Variable*)_variable;
|
||||
TypeComponentPath* path = (TypeComponentPath*)_path;
|
||||
_HandleStackFrameValueRetrieved(stackFrame, variable, path);
|
||||
path->ReleaseReference();
|
||||
variable->ReleaseReference();
|
||||
stackFrame->ReleaseReference();
|
||||
}
|
||||
}
|
||||
|
||||
case MSG_IMAGE_DEBUG_INFO_CHANGED:
|
||||
{
|
||||
int32 imageID;
|
||||
@@ -339,10 +321,10 @@ TeamWindow::ClearBreakpointRequested(target_addr_t address)
|
||||
|
||||
|
||||
void
|
||||
TeamWindow::StackFrameValueRequested(::Thread* thread, StackFrame* stackFrame,
|
||||
Variable* variable, TypeComponentPath* path)
|
||||
TeamWindow::ValueNodeValueRequested(CpuState* cpuState,
|
||||
ValueNodeContainer* container, ValueNode* valueNode)
|
||||
{
|
||||
fListener->StackFrameValueRequested(thread, stackFrame, variable, path);
|
||||
fListener->ValueNodeValueRequested(cpuState, container, valueNode);
|
||||
}
|
||||
|
||||
|
||||
@@ -405,22 +387,6 @@ TeamWindow::FunctionSourceCodeChanged(Function* function)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TeamWindow::StackFrameValueRetrieved(StackFrame* stackFrame, Variable* variable,
|
||||
TypeComponentPath* path)
|
||||
{
|
||||
BMessage message(MSG_STACK_FRAME_VALUE_RETRIEVED);
|
||||
if (message.AddPointer("stackFrame", stackFrame) == B_OK
|
||||
&& message.AddPointer("variable", variable) == B_OK
|
||||
&& message.AddPointer("path", path) == B_OK
|
||||
&& PostMessage(&message) == B_OK) {
|
||||
stackFrame->AcquireReference();
|
||||
variable->AcquireReference();
|
||||
path->AcquireReference();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TeamWindow::_Init()
|
||||
{
|
||||
@@ -906,17 +872,6 @@ TeamWindow::_HandleStackTraceChanged(thread_id threadID)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TeamWindow::_HandleStackFrameValueRetrieved(StackFrame* stackFrame,
|
||||
Variable* variable, TypeComponentPath* path)
|
||||
{
|
||||
if (stackFrame != fActiveStackFrame)
|
||||
return;
|
||||
|
||||
fVariablesView->StackFrameValueRetrieved(stackFrame, variable, path);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TeamWindow::_HandleImageDebugInfoChanged(image_id imageID)
|
||||
{
|
||||
|
||||
@@ -89,9 +89,9 @@ private:
|
||||
virtual void ClearBreakpointRequested(target_addr_t address);
|
||||
|
||||
// VariablesView::Listener
|
||||
virtual void StackFrameValueRequested(::Thread* thread,
|
||||
StackFrame* stackFrame, Variable* variable,
|
||||
TypeComponentPath* path);
|
||||
virtual void ValueNodeValueRequested(CpuState* cpuState,
|
||||
ValueNodeContainer* container,
|
||||
ValueNode* valueNode);
|
||||
|
||||
// Team::Listener
|
||||
virtual void ThreadStateChanged(
|
||||
@@ -108,11 +108,6 @@ private:
|
||||
// Function::Listener
|
||||
virtual void FunctionSourceCodeChanged(Function* function);
|
||||
|
||||
// StackFrame::Listener
|
||||
virtual void StackFrameValueRetrieved(StackFrame* stackFrame,
|
||||
Variable* variable,
|
||||
TypeComponentPath* path);
|
||||
|
||||
void _Init();
|
||||
|
||||
void _SetActiveThread(::Thread* thread);
|
||||
@@ -130,9 +125,6 @@ private:
|
||||
void _HandleThreadStateChanged(thread_id threadID);
|
||||
void _HandleCpuStateChanged(thread_id threadID);
|
||||
void _HandleStackTraceChanged(thread_id threadID);
|
||||
void _HandleStackFrameValueRetrieved(
|
||||
StackFrame* stackFrame, Variable* variable,
|
||||
TypeComponentPath* path);
|
||||
void _HandleImageDebugInfoChanged(image_id imageID);
|
||||
void _HandleSourceCodeChanged();
|
||||
void _HandleUserBreakpointChanged(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,9 +11,13 @@
|
||||
#include "table/TreeTable.h"
|
||||
|
||||
|
||||
class CpuState;
|
||||
class SettingsMenu;
|
||||
class StackFrame;
|
||||
class Thread;
|
||||
class TypeComponentPath;
|
||||
class ValueNode;
|
||||
class ValueNodeContainer;
|
||||
class Variable;
|
||||
class VariablesViewState;
|
||||
class VariablesViewStateHistory;
|
||||
@@ -32,41 +36,53 @@ public:
|
||||
|
||||
void SetStackFrame(Thread* thread,
|
||||
StackFrame* stackFrame);
|
||||
void StackFrameValueRetrieved(StackFrame* stackFrame,
|
||||
Variable* variable,
|
||||
TypeComponentPath* path);
|
||||
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
|
||||
virtual void DetachedFromWindow();
|
||||
|
||||
private:
|
||||
// TreeTableListener
|
||||
virtual void TreeTableNodeExpandedChanged(TreeTable* table,
|
||||
const TreeTablePath& path, bool expanded);
|
||||
|
||||
virtual void TreeTableCellMouseDown(TreeTable* table,
|
||||
const TreeTablePath& path,
|
||||
int32 columnIndex, BPoint screenWhere,
|
||||
uint32 buttons);
|
||||
|
||||
private:
|
||||
class ValueNode;
|
||||
class ContainerListener;
|
||||
class ModelNode;
|
||||
class VariableValueColumn;
|
||||
class VariableTableModel;
|
||||
class ContextMenu;
|
||||
class TableCellContextMenuTracker;
|
||||
|
||||
private:
|
||||
void _Init();
|
||||
|
||||
void _RequestVariableValue(Variable* variable);
|
||||
void _RequestNodeValue(ModelNode* node);
|
||||
void _FinishContextMenu(bool force);
|
||||
|
||||
void _SaveViewState() const;
|
||||
void _RestoreViewState();
|
||||
status_t _AddViewStateDescendentNodeInfos(
|
||||
VariablesViewState* viewState, void* parent,
|
||||
TreeTablePath& path) const;
|
||||
status_t _ApplyViewStateDescendentNodeInfos(
|
||||
VariablesViewState* viewState, void* parent,
|
||||
TreeTablePath& path);
|
||||
// void _SaveViewState() const;
|
||||
// void _RestoreViewState();
|
||||
// status_t _AddViewStateDescendentNodeInfos(
|
||||
// VariablesViewState* viewState, void* parent,
|
||||
// TreeTablePath& path) const;
|
||||
// status_t _ApplyViewStateDescendentNodeInfos(
|
||||
// VariablesViewState* viewState, void* parent,
|
||||
// TreeTablePath& path);
|
||||
|
||||
private:
|
||||
Thread* fThread;
|
||||
StackFrame* fStackFrame;
|
||||
TreeTable* fVariableTable;
|
||||
VariableTableModel* fVariableTableModel;
|
||||
ContainerListener* fContainerListener;
|
||||
VariablesViewState* fPreviousViewState;
|
||||
VariablesViewStateHistory* fViewStateHistory;
|
||||
TableCellContextMenuTracker* fTableCellContextMenuTracker;
|
||||
Listener* fListener;
|
||||
};
|
||||
|
||||
@@ -75,10 +91,9 @@ class VariablesView::Listener {
|
||||
public:
|
||||
virtual ~Listener();
|
||||
|
||||
virtual void StackFrameValueRequested(Thread* thread,
|
||||
StackFrame* stackFrame, Variable* variable,
|
||||
TypeComponentPath* path) = 0;
|
||||
// called with team locked
|
||||
virtual void ValueNodeValueRequested(CpuState* cpuState,
|
||||
ValueNodeContainer* container,
|
||||
ValueNode* valueNode) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "TableCellBoolRenderer.h"
|
||||
|
||||
#include "BoolValue.h"
|
||||
#include "TableCellValueRendererUtils.h"
|
||||
|
||||
|
||||
static inline const char*
|
||||
bool_value_string(BoolValue* value)
|
||||
{
|
||||
return value->GetValue() ? "true" : "false";
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TableCellBoolRenderer::RenderValue(Value* _value, BRect rect, BView* targetView)
|
||||
{
|
||||
BoolValue* value = dynamic_cast<BoolValue*>(_value);
|
||||
if (value == NULL)
|
||||
return;
|
||||
|
||||
TableCellValueRendererUtils::DrawString(targetView, rect,
|
||||
bool_value_string(value), B_ALIGN_RIGHT, true);
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
TableCellBoolRenderer::PreferredValueWidth(Value* _value, BView* targetView)
|
||||
{
|
||||
BoolValue* value = dynamic_cast<BoolValue*>(_value);
|
||||
if (value == NULL)
|
||||
return 0;
|
||||
|
||||
return TableCellValueRendererUtils::PreferredStringWidth(targetView,
|
||||
bool_value_string(value));
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef TABLE_CELL_BOOL_RENDERER_H
|
||||
#define TABLE_CELL_BOOL_RENDERER_H
|
||||
|
||||
|
||||
#include <Referenceable.h>
|
||||
|
||||
#include "TableCellValueRenderer.h"
|
||||
|
||||
|
||||
class TableCellBoolRenderer : public TableCellValueRenderer {
|
||||
public:
|
||||
virtual void RenderValue(Value* value, BRect rect,
|
||||
BView* targetView);
|
||||
virtual float PreferredValueWidth(Value* value,
|
||||
BView* targetView);
|
||||
};
|
||||
|
||||
|
||||
#endif // TABLE_CELL_BOOL_RENDERER_H
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "TableCellEnumerationRenderer.h"
|
||||
|
||||
#include "EnumerationValue.h"
|
||||
#include "TableCellValueRendererUtils.h"
|
||||
#include "Type.h"
|
||||
|
||||
|
||||
TableCellEnumerationRenderer::TableCellEnumerationRenderer(Config* config)
|
||||
:
|
||||
TableCellIntegerRenderer(config)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TableCellEnumerationRenderer::RenderValue(Value* _value, BRect rect,
|
||||
BView* targetView)
|
||||
{
|
||||
Config* config = GetConfig();
|
||||
if (config != NULL && config->IntegerFormat() == INTEGER_FORMAT_DEFAULT) {
|
||||
EnumerationValue* value = dynamic_cast<EnumerationValue*>(_value);
|
||||
if (value == NULL)
|
||||
return;
|
||||
|
||||
if (EnumeratorValue* enumValue
|
||||
= value->GetType()->ValueFor(value->GetValue())) {
|
||||
TableCellValueRendererUtils::DrawString(targetView, rect,
|
||||
enumValue->Name(), B_ALIGN_RIGHT, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
TableCellIntegerRenderer::RenderValue(_value, rect, targetView);
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
TableCellEnumerationRenderer::PreferredValueWidth(Value* _value,
|
||||
BView* targetView)
|
||||
{
|
||||
Config* config = GetConfig();
|
||||
if (config != NULL && config->IntegerFormat() == INTEGER_FORMAT_DEFAULT) {
|
||||
EnumerationValue* value = dynamic_cast<EnumerationValue*>(_value);
|
||||
if (value == NULL)
|
||||
return 0;
|
||||
|
||||
if (EnumeratorValue* enumValue
|
||||
= value->GetType()->ValueFor(value->GetValue())) {
|
||||
return TableCellValueRendererUtils::PreferredStringWidth(targetView,
|
||||
enumValue->Name());
|
||||
}
|
||||
}
|
||||
|
||||
return TableCellIntegerRenderer::PreferredValueWidth(_value, targetView);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef TABLE_CELL_ENUMERATION_RENDERER_H
|
||||
#define TABLE_CELL_ENUMERATION_RENDERER_H
|
||||
|
||||
|
||||
#include <Referenceable.h>
|
||||
|
||||
#include "TableCellIntegerRenderer.h"
|
||||
|
||||
|
||||
class TableCellEnumerationRenderer : public TableCellIntegerRenderer {
|
||||
public:
|
||||
TableCellEnumerationRenderer(Config* config);
|
||||
|
||||
virtual void RenderValue(Value* value, BRect rect,
|
||||
BView* targetView);
|
||||
virtual float PreferredValueWidth(Value* value,
|
||||
BView* targetView);
|
||||
};
|
||||
|
||||
|
||||
#endif // TABLE_CELL_ENUMERATION_RENDERER_H
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "TableCellFloatRenderer.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "FloatValue.h"
|
||||
#include "TableCellValueRendererUtils.h"
|
||||
|
||||
|
||||
void
|
||||
TableCellFloatRenderer::RenderValue(Value* _value, BRect rect, BView* targetView)
|
||||
{
|
||||
FloatValue* value = dynamic_cast<FloatValue*>(_value);
|
||||
if (value == NULL)
|
||||
return;
|
||||
|
||||
char buffer[64];
|
||||
snprintf(buffer, sizeof(buffer), "%g", value->GetValue());
|
||||
|
||||
TableCellValueRendererUtils::DrawString(targetView, rect, buffer,
|
||||
B_ALIGN_RIGHT, true);
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
TableCellFloatRenderer::PreferredValueWidth(Value* _value, BView* targetView)
|
||||
{
|
||||
FloatValue* value = dynamic_cast<FloatValue*>(_value);
|
||||
if (value == NULL)
|
||||
return 0;
|
||||
|
||||
char buffer[64];
|
||||
snprintf(buffer, sizeof(buffer), "%g", value->GetValue());
|
||||
|
||||
return TableCellValueRendererUtils::PreferredStringWidth(targetView,
|
||||
buffer);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef TABLE_CELL_FLOAT_RENDERER_H
|
||||
#define TABLE_CELL_FLOAT_RENDERER_H
|
||||
|
||||
|
||||
#include <Referenceable.h>
|
||||
|
||||
#include "TableCellValueRenderer.h"
|
||||
|
||||
|
||||
class TableCellFloatRenderer : public TableCellValueRenderer {
|
||||
public:
|
||||
virtual void RenderValue(Value* value, BRect rect,
|
||||
BView* targetView);
|
||||
virtual float PreferredValueWidth(Value* value,
|
||||
BView* targetView);
|
||||
};
|
||||
|
||||
|
||||
#endif // TABLE_CELL_FLOAT_RENDERER_H
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "TableCellIntegerRenderer.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <TypeConstants.h>
|
||||
|
||||
#include "TableCellValueRendererUtils.h"
|
||||
#include "IntegerValue.h"
|
||||
|
||||
|
||||
// #pragma mark - TableCellIntegerRenderer
|
||||
|
||||
|
||||
TableCellIntegerRenderer::TableCellIntegerRenderer(Config* config)
|
||||
:
|
||||
fConfig(config)
|
||||
{
|
||||
if (fConfig != NULL)
|
||||
fConfig->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
TableCellIntegerRenderer::~TableCellIntegerRenderer()
|
||||
{
|
||||
if (fConfig != NULL)
|
||||
fConfig->ReleaseReference();
|
||||
}
|
||||
|
||||
|
||||
Settings*
|
||||
TableCellIntegerRenderer::GetSettings() const
|
||||
{
|
||||
return fConfig != NULL ? fConfig->GetSettings() : NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TableCellIntegerRenderer::RenderValue(Value* _value, BRect rect,
|
||||
BView* targetView)
|
||||
{
|
||||
IntegerValue* value = dynamic_cast<IntegerValue*>(_value);
|
||||
if (value == NULL)
|
||||
return;
|
||||
|
||||
// format the value
|
||||
integer_format format = fConfig != NULL
|
||||
? fConfig->IntegerFormat() : INTEGER_FORMAT_DEFAULT;
|
||||
char buffer[32];
|
||||
if (!IntegerFormatter::FormatValue(value->GetValue(), format, buffer,
|
||||
sizeof(buffer))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// render
|
||||
TableCellValueRendererUtils::DrawString(targetView, rect, buffer,
|
||||
B_ALIGN_RIGHT, true);
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
TableCellIntegerRenderer::PreferredValueWidth(Value* _value, BView* targetView)
|
||||
{
|
||||
IntegerValue* value = dynamic_cast<IntegerValue*>(_value);
|
||||
if (value == NULL)
|
||||
return 0;
|
||||
|
||||
// format the value
|
||||
integer_format format = fConfig != NULL
|
||||
? fConfig->IntegerFormat() : INTEGER_FORMAT_DEFAULT;
|
||||
char buffer[32];
|
||||
if (!IntegerFormatter::FormatValue(value->GetValue(), format, buffer,
|
||||
sizeof(buffer))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// render
|
||||
return TableCellValueRendererUtils::PreferredStringWidth(targetView,
|
||||
buffer);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - Config
|
||||
|
||||
|
||||
TableCellIntegerRenderer::Config::~Config()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef TABLE_CELL_INTEGER_RENDERER_H
|
||||
#define TABLE_CELL_INTEGER_RENDERER_H
|
||||
|
||||
|
||||
#include <Referenceable.h>
|
||||
|
||||
#include "IntegerFormatter.h"
|
||||
#include "TableCellValueRenderer.h"
|
||||
|
||||
|
||||
class TableCellIntegerRenderer : public TableCellValueRenderer {
|
||||
public:
|
||||
class Config;
|
||||
|
||||
public:
|
||||
TableCellIntegerRenderer(Config* config);
|
||||
virtual ~TableCellIntegerRenderer();
|
||||
|
||||
Config* GetConfig() const
|
||||
{ return fConfig; }
|
||||
|
||||
virtual Settings* GetSettings() const;
|
||||
|
||||
virtual void RenderValue(Value* value, BRect rect,
|
||||
BView* targetView);
|
||||
virtual float PreferredValueWidth(Value* value,
|
||||
BView* targetView);
|
||||
|
||||
private:
|
||||
Config* fConfig;
|
||||
};
|
||||
|
||||
|
||||
class TableCellIntegerRenderer::Config : public BReferenceable {
|
||||
public:
|
||||
virtual ~Config();
|
||||
|
||||
virtual Settings* GetSettings() const = 0;
|
||||
virtual integer_format IntegerFormat() const = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif // TABLE_CELL_INTEGER_RENDERER_H
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "TableCellStringRenderer.h"
|
||||
|
||||
#include <String.h>
|
||||
|
||||
#include "TableCellValueRendererUtils.h"
|
||||
#include "Value.h"
|
||||
|
||||
|
||||
void
|
||||
TableCellStringRenderer::RenderValue(Value* value, BRect rect,
|
||||
BView* targetView)
|
||||
{
|
||||
BString string;
|
||||
if (!value->ToString(string))
|
||||
return;
|
||||
|
||||
TableCellValueRendererUtils::DrawString(targetView, rect, string,
|
||||
B_ALIGN_LEFT, true);
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
TableCellStringRenderer::PreferredValueWidth(Value* value, BView* targetView)
|
||||
{
|
||||
BString string;
|
||||
if (!value->ToString(string))
|
||||
return 0;
|
||||
|
||||
return TableCellValueRendererUtils::PreferredStringWidth(targetView,
|
||||
string);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef TABLE_CELL_STRING_RENDERER_H
|
||||
#define TABLE_CELL_STRING_RENDERER_H
|
||||
|
||||
|
||||
#include "TableCellValueRenderer.h"
|
||||
|
||||
#include <Referenceable.h>
|
||||
|
||||
|
||||
class TableCellStringRenderer : public TableCellValueRenderer {
|
||||
public:
|
||||
virtual void RenderValue(Value* value, BRect rect,
|
||||
BView* targetView);
|
||||
virtual float PreferredValueWidth(Value* value,
|
||||
BView* targetView);
|
||||
};
|
||||
|
||||
|
||||
#endif // TABLE_CELL_STRING_RENDERER_H
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "TableCellValueRenderer.h"
|
||||
|
||||
|
||||
TableCellValueRenderer::~TableCellValueRenderer()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Settings*
|
||||
TableCellValueRenderer::GetSettings() const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef TABLE_CELL_VALUE_RENDERER_H
|
||||
#define TABLE_CELL_VALUE_RENDERER_H
|
||||
|
||||
|
||||
#include <Rect.h>
|
||||
|
||||
#include <Referenceable.h>
|
||||
|
||||
|
||||
class BView;
|
||||
class Settings;
|
||||
class Value;
|
||||
|
||||
|
||||
class TableCellValueRenderer : public BReferenceable {
|
||||
public:
|
||||
virtual ~TableCellValueRenderer();
|
||||
|
||||
virtual Settings* GetSettings() const;
|
||||
// returns NULL, if no settings
|
||||
|
||||
virtual void RenderValue(Value* value, BRect rect,
|
||||
BView* targetView) = 0;
|
||||
virtual float PreferredValueWidth(Value* value,
|
||||
BView* targetView) = 0;
|
||||
};
|
||||
|
||||
|
||||
#endif // TABLE_CELL_VALUE_RENDERER_H
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "TableCellValueRendererUtils.h"
|
||||
|
||||
#include <Font.h>
|
||||
#include <String.h>
|
||||
#include <View.h>
|
||||
|
||||
|
||||
static const float kTextMargin = 8;
|
||||
|
||||
|
||||
/*static*/ void
|
||||
TableCellValueRendererUtils::DrawString(BView* view, BRect rect,
|
||||
const char* string, enum alignment alignment, bool truncate)
|
||||
{
|
||||
// get font height info
|
||||
font_height fontHeight;
|
||||
view->GetFontHeight(&fontHeight);
|
||||
|
||||
// truncate, if requested
|
||||
BString truncatedString;
|
||||
if (truncate) {
|
||||
truncatedString = string;
|
||||
view->TruncateString(&truncatedString, B_TRUNCATE_END,
|
||||
rect.Width() - 2 * kTextMargin + 2);
|
||||
string = truncatedString.String();
|
||||
}
|
||||
|
||||
// compute horizontal position according to alignment
|
||||
float x;
|
||||
switch (alignment) {
|
||||
default:
|
||||
case B_ALIGN_LEFT:
|
||||
x = rect.left + kTextMargin;
|
||||
break;
|
||||
|
||||
case B_ALIGN_CENTER:
|
||||
x = rect.left + (rect.Width() - view->StringWidth(string)) / 2;
|
||||
break;
|
||||
|
||||
case B_ALIGN_RIGHT:
|
||||
x = rect.right - kTextMargin - view->StringWidth(string);
|
||||
break;
|
||||
}
|
||||
|
||||
// compute vertical position (base line)
|
||||
float y = rect.top
|
||||
+ (rect.Height() - (fontHeight.ascent + fontHeight.descent
|
||||
+ fontHeight.leading)) / 2
|
||||
+ (fontHeight.ascent + fontHeight.descent) - 2;
|
||||
// TODO: This is the computation BColumnListView (respectively
|
||||
// BTitledColumn) is using, which I find somewhat weird.
|
||||
|
||||
view->DrawString(string, BPoint(x, y));
|
||||
}
|
||||
|
||||
|
||||
/*static*/ float
|
||||
TableCellValueRendererUtils::PreferredStringWidth(BView* view,
|
||||
const char* string)
|
||||
{
|
||||
return view->StringWidth(string) + 2 * kTextMargin;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef TABLE_CELL_VALUE_RENDERER_UTILS_H
|
||||
#define TABLE_CELL_VALUE_RENDERER_UTILS_H
|
||||
|
||||
|
||||
#include <InterfaceDefs.h>
|
||||
#include <Rect.h>
|
||||
|
||||
|
||||
class BView;
|
||||
|
||||
|
||||
class TableCellValueRendererUtils {
|
||||
public:
|
||||
static void DrawString(BView* view, BRect rect,
|
||||
const char* string,
|
||||
enum alignment alignment,
|
||||
bool truncate = false);
|
||||
static float PreferredStringWidth(BView* view,
|
||||
const char* string);
|
||||
};
|
||||
|
||||
|
||||
#endif // TABLE_CELL_VALUE_RENDERER_UTILS_H
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "TypeHandler.h"
|
||||
|
||||
|
||||
TypeHandler::~TypeHandler()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef TYPE_HANDLER_H
|
||||
#define TYPE_HANDLER_H
|
||||
|
||||
|
||||
#include <Referenceable.h>
|
||||
|
||||
|
||||
class Type;
|
||||
class ValueNode;
|
||||
class ValueNodeChild;
|
||||
|
||||
|
||||
class TypeHandler : public BReferenceable {
|
||||
public:
|
||||
virtual ~TypeHandler();
|
||||
|
||||
virtual float SupportsType(Type* type) = 0;
|
||||
virtual status_t CreateValueNode(ValueNodeChild* nodeChild,
|
||||
Type* type, ValueNode*& _node) = 0;
|
||||
// returns a reference
|
||||
};
|
||||
|
||||
|
||||
#endif // TYPE_HANDLER_H
|
||||
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "TypeHandlerRoster.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
#include <AutoLocker.h>
|
||||
|
||||
#include "AddressValueNode.h"
|
||||
#include "ArrayValueNode.h"
|
||||
#include "CompoundValueNode.h"
|
||||
#include "EnumerationValueNode.h"
|
||||
#include "PointerToMemberValueNode.h"
|
||||
#include "PrimitiveValueNode.h"
|
||||
#include "Type.h"
|
||||
#include "TypeHandler.h"
|
||||
|
||||
|
||||
// #pragma mark - BasicTypeHandler
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
template<typename TypeClass, typename NodeClass>
|
||||
class BasicTypeHandler : public TypeHandler {
|
||||
public:
|
||||
virtual float SupportsType(Type* type)
|
||||
{
|
||||
return dynamic_cast<TypeClass*>(type) != NULL ? 0.5f : 0;
|
||||
}
|
||||
|
||||
virtual status_t CreateValueNode(ValueNodeChild* nodeChild,
|
||||
Type* type, ValueNode*& _node)
|
||||
{
|
||||
TypeClass* supportedType = dynamic_cast<TypeClass*>(type);
|
||||
if (supportedType == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
ValueNode* node = new(std::nothrow) NodeClass(nodeChild, supportedType);
|
||||
if (node == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
_node = node;
|
||||
return B_OK;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
|
||||
// #pragma mark - TypeHandlerRoster
|
||||
|
||||
|
||||
/*static*/ TypeHandlerRoster* TypeHandlerRoster::sDefaultInstance = NULL;
|
||||
|
||||
|
||||
TypeHandlerRoster::TypeHandlerRoster()
|
||||
:
|
||||
fLock("type handler roster")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
TypeHandlerRoster::~TypeHandlerRoster()
|
||||
{
|
||||
}
|
||||
|
||||
/*static*/ TypeHandlerRoster*
|
||||
TypeHandlerRoster::Default()
|
||||
{
|
||||
return sDefaultInstance;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ status_t
|
||||
TypeHandlerRoster::CreateDefault()
|
||||
{
|
||||
if (sDefaultInstance != NULL)
|
||||
return B_OK;
|
||||
|
||||
TypeHandlerRoster* roster = new(std::nothrow) TypeHandlerRoster;
|
||||
if (roster == NULL)
|
||||
return B_NO_MEMORY;
|
||||
ObjectDeleter<TypeHandlerRoster> rosterDeleter(roster);
|
||||
|
||||
status_t error = roster->Init();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
error = roster->RegisterDefaultHandlers();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
sDefaultInstance = rosterDeleter.Detach();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ void
|
||||
TypeHandlerRoster::DeleteDefault()
|
||||
{
|
||||
TypeHandlerRoster* roster = sDefaultInstance;
|
||||
sDefaultInstance = NULL;
|
||||
delete roster;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TypeHandlerRoster::Init()
|
||||
{
|
||||
return fLock.InitCheck();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TypeHandlerRoster::RegisterDefaultHandlers()
|
||||
{
|
||||
TypeHandler* handler;
|
||||
Reference<TypeHandler> handlerReference;
|
||||
|
||||
#undef REGISTER_HANDLER
|
||||
#define REGISTER_HANDLER(name) \
|
||||
handler = new(std::nothrow) \
|
||||
BasicTypeHandler<name##Type, name##ValueNode>(); \
|
||||
handlerReference.SetTo(handler, true); \
|
||||
if (handler == NULL || !RegisterHandler(handler)) \
|
||||
return B_NO_MEMORY;
|
||||
|
||||
REGISTER_HANDLER(Address);
|
||||
REGISTER_HANDLER(Array);
|
||||
REGISTER_HANDLER(Compound);
|
||||
REGISTER_HANDLER(Enumeration);
|
||||
REGISTER_HANDLER(PointerToMember);
|
||||
REGISTER_HANDLER(Primitive);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TypeHandlerRoster::FindTypeHandler(ValueNodeChild* nodeChild, Type* type,
|
||||
TypeHandler*& _handler)
|
||||
{
|
||||
// find the best-supporting handler
|
||||
AutoLocker<BLocker> locker(fLock);
|
||||
|
||||
TypeHandler* bestHandler = NULL;
|
||||
float bestSupport = 0;
|
||||
|
||||
for (int32 i = 0; TypeHandler* handler = fTypeHandlers.ItemAt(i); i++) {
|
||||
float support = handler->SupportsType(type);
|
||||
if (support > 0 && support > bestSupport) {
|
||||
bestHandler = handler;
|
||||
bestSupport = support;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestHandler == NULL)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
bestHandler->AcquireReference();
|
||||
_handler = bestHandler;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TypeHandlerRoster::CreateValueNode(ValueNodeChild* nodeChild, Type* type,
|
||||
ValueNode*& _node)
|
||||
{
|
||||
// find the best-supporting handler
|
||||
while (true) {
|
||||
TypeHandler* handler;
|
||||
status_t error = FindTypeHandler(nodeChild, type, handler);
|
||||
if (error == B_OK) {
|
||||
// let the handler create the node
|
||||
Reference<TypeHandler> handlerReference(handler, true);
|
||||
return handler->CreateValueNode(nodeChild, type, _node);
|
||||
}
|
||||
|
||||
// not found yet -- try to strip a modifier/typedef from the type
|
||||
Type* nextType = type->ResolveRawType(true);
|
||||
if (nextType == NULL || nextType == type)
|
||||
return B_UNSUPPORTED;
|
||||
|
||||
type = nextType;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
TypeHandlerRoster::RegisterHandler(TypeHandler* handler)
|
||||
{
|
||||
if (!fTypeHandlers.AddItem(handler))
|
||||
return false;
|
||||
|
||||
handler->AcquireReference();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TypeHandlerRoster::UnregisterHandler(TypeHandler* handler)
|
||||
{
|
||||
if (fTypeHandlers.RemoveItem(handler))
|
||||
handler->RemoveReference();
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef TYPE_HANDLER_ROSTER_H
|
||||
#define TYPE_HANDLER_ROSTER_H
|
||||
|
||||
|
||||
#include <Locker.h>
|
||||
#include <ObjectList.h>
|
||||
|
||||
|
||||
class Type;
|
||||
class TypeHandler;
|
||||
class ValueNode;
|
||||
class ValueNodeChild;
|
||||
|
||||
|
||||
typedef BObjectList<TypeHandler> TypeHandlerList;
|
||||
|
||||
|
||||
class TypeHandlerRoster {
|
||||
public:
|
||||
TypeHandlerRoster();
|
||||
~TypeHandlerRoster();
|
||||
|
||||
static TypeHandlerRoster* Default();
|
||||
static status_t CreateDefault();
|
||||
static void DeleteDefault();
|
||||
|
||||
status_t Init();
|
||||
status_t RegisterDefaultHandlers();
|
||||
|
||||
status_t FindTypeHandler(ValueNodeChild* nodeChild,
|
||||
Type* type, TypeHandler*& _handler);
|
||||
// returns a reference
|
||||
status_t CreateValueNode(ValueNodeChild* nodeChild,
|
||||
Type* type, ValueNode*& _node);
|
||||
// returns a reference
|
||||
|
||||
bool RegisterHandler(TypeHandler* handler);
|
||||
void UnregisterHandler(TypeHandler* handler);
|
||||
|
||||
private:
|
||||
BLocker fLock;
|
||||
TypeHandlerList fTypeHandlers;
|
||||
static TypeHandlerRoster* sDefaultInstance;
|
||||
};
|
||||
|
||||
|
||||
#endif // TYPE_HANDLER_ROSTER_H
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "Value.h"
|
||||
|
||||
|
||||
Value::~Value()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef VALUE_H
|
||||
#define VALUE_H
|
||||
|
||||
|
||||
#include <String.h>
|
||||
|
||||
#include <Variant.h>
|
||||
|
||||
|
||||
class Value : public BReferenceable {
|
||||
public:
|
||||
virtual ~Value();
|
||||
|
||||
virtual bool ToString(BString& _string) const = 0;
|
||||
virtual bool ToVariant(BVariant& _value) const = 0;
|
||||
|
||||
virtual bool operator==(const Value& other) const = 0;
|
||||
inline bool operator!=(const Value& other) const
|
||||
{ return !(*this == other); }
|
||||
};
|
||||
|
||||
|
||||
#endif // VALUE_H
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "ValueHandler.h"
|
||||
|
||||
|
||||
ValueHandler::~ValueHandler()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ValueHandler::CreateTableCellValueSettingsMenu(Value* value, Settings* settings,
|
||||
SettingsMenu*& _menu)
|
||||
{
|
||||
_menu = NULL;
|
||||
return B_OK;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef VALUE_HANDLER_H
|
||||
#define VALUE_HANDLER_H
|
||||
|
||||
|
||||
#include <Referenceable.h>
|
||||
|
||||
|
||||
class Settings;
|
||||
class SettingsMenu;
|
||||
class TableCellValueRenderer;
|
||||
class Value;
|
||||
class ValueFormatter;
|
||||
|
||||
|
||||
class ValueHandler : public BReferenceable {
|
||||
public:
|
||||
virtual ~ValueHandler();
|
||||
|
||||
virtual float SupportsValue(Value* value) = 0;
|
||||
virtual status_t GetValueFormatter(Value* value,
|
||||
ValueFormatter*& _formatter) = 0;
|
||||
// returns a reference
|
||||
virtual status_t GetTableCellValueRenderer(Value* value,
|
||||
TableCellValueRenderer*& _renderer) = 0;
|
||||
// returns a reference
|
||||
virtual status_t CreateTableCellValueSettingsMenu(Value* value,
|
||||
Settings* settings, SettingsMenu*& _menu);
|
||||
// may return NULL, otherwise a reference
|
||||
};
|
||||
|
||||
|
||||
#endif // VALUE_HANDLER_H
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "ValueHandlerRoster.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
#include <AutoLocker.h>
|
||||
|
||||
#include "AddressValueHandler.h"
|
||||
#include "BoolValueHandler.h"
|
||||
#include "EnumerationValueHandler.h"
|
||||
#include "FloatValueHandler.h"
|
||||
#include "Value.h"
|
||||
|
||||
|
||||
/*static*/ ValueHandlerRoster* ValueHandlerRoster::sDefaultInstance = NULL;
|
||||
|
||||
|
||||
ValueHandlerRoster::ValueHandlerRoster()
|
||||
:
|
||||
fLock("value handler roster")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ValueHandlerRoster::~ValueHandlerRoster()
|
||||
{
|
||||
}
|
||||
|
||||
/*static*/ ValueHandlerRoster*
|
||||
ValueHandlerRoster::Default()
|
||||
{
|
||||
return sDefaultInstance;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ status_t
|
||||
ValueHandlerRoster::CreateDefault()
|
||||
{
|
||||
if (sDefaultInstance != NULL)
|
||||
return B_OK;
|
||||
|
||||
ValueHandlerRoster* roster = new(std::nothrow) ValueHandlerRoster;
|
||||
if (roster == NULL)
|
||||
return B_NO_MEMORY;
|
||||
ObjectDeleter<ValueHandlerRoster> rosterDeleter(roster);
|
||||
|
||||
status_t error = roster->Init();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
error = roster->RegisterDefaultHandlers();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
sDefaultInstance = rosterDeleter.Detach();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ void
|
||||
ValueHandlerRoster::DeleteDefault()
|
||||
{
|
||||
ValueHandlerRoster* roster = sDefaultInstance;
|
||||
sDefaultInstance = NULL;
|
||||
delete roster;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ValueHandlerRoster::Init()
|
||||
{
|
||||
return fLock.InitCheck();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ValueHandlerRoster::RegisterDefaultHandlers()
|
||||
{
|
||||
status_t error;
|
||||
|
||||
#undef REGISTER_HANDLER
|
||||
#define REGISTER_HANDLER(name) \
|
||||
{ \
|
||||
name##ValueHandler* handler \
|
||||
= new(std::nothrow) name##ValueHandler; \
|
||||
if (handler == NULL) \
|
||||
return B_NO_MEMORY; \
|
||||
BReference<name##ValueHandler> handlerReference(handler, true); \
|
||||
\
|
||||
error = handler->Init(); \
|
||||
if (error != B_OK) \
|
||||
return error; \
|
||||
\
|
||||
if (!RegisterHandler(handler)) \
|
||||
return B_NO_MEMORY; \
|
||||
}
|
||||
|
||||
REGISTER_HANDLER(Address)
|
||||
REGISTER_HANDLER(Bool)
|
||||
REGISTER_HANDLER(Enumeration)
|
||||
REGISTER_HANDLER(Float)
|
||||
REGISTER_HANDLER(Integer)
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ValueHandlerRoster::FindValueHandler(Value* value, ValueHandler*& _handler)
|
||||
{
|
||||
// find the best-supporting handler
|
||||
AutoLocker<BLocker> locker(fLock);
|
||||
|
||||
ValueHandler* bestHandler = NULL;
|
||||
float bestSupport = 0;
|
||||
|
||||
for (int32 i = 0; ValueHandler* handler = fValueHandlers.ItemAt(i); i++) {
|
||||
float support = handler->SupportsValue(value);
|
||||
if (support > 0 && support > bestSupport) {
|
||||
bestHandler = handler;
|
||||
bestSupport = support;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestHandler == NULL)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
bestHandler->AcquireReference();
|
||||
_handler = bestHandler;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ValueHandlerRoster::GetValueFormatter(Value* value,
|
||||
ValueFormatter*& _formatter)
|
||||
{
|
||||
// get the best supporting value handler
|
||||
ValueHandler* handler;
|
||||
status_t error = FindValueHandler(value, handler);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
BReference<ValueHandler> handlerReference(handler, true);
|
||||
|
||||
// create the formatter
|
||||
return handler->GetValueFormatter(value, _formatter);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ValueHandlerRoster::GetTableCellValueRenderer(Value* value,
|
||||
TableCellValueRenderer*& _renderer)
|
||||
{
|
||||
// get the best supporting value handler
|
||||
ValueHandler* handler;
|
||||
status_t error = FindValueHandler(value, handler);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
BReference<ValueHandler> handlerReference(handler, true);
|
||||
|
||||
// create the renderer
|
||||
return handler->GetTableCellValueRenderer(value, _renderer);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ValueHandlerRoster::RegisterHandler(ValueHandler* handler)
|
||||
{
|
||||
if (!fValueHandlers.AddItem(handler))
|
||||
return false;
|
||||
|
||||
handler->AcquireReference();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueHandlerRoster::UnregisterHandler(ValueHandler* handler)
|
||||
{
|
||||
if (fValueHandlers.RemoveItem(handler))
|
||||
handler->RemoveReference();
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef VALUE_HANDLER_ROSTER_H
|
||||
#define VALUE_HANDLER_ROSTER_H
|
||||
|
||||
|
||||
#include <Locker.h>
|
||||
#include <ObjectList.h>
|
||||
|
||||
|
||||
class TableCellValueRenderer;
|
||||
class Value;
|
||||
class ValueFormatter;
|
||||
class ValueHandler;
|
||||
|
||||
|
||||
typedef BObjectList<ValueHandler> ValueHandlerList;
|
||||
|
||||
|
||||
class ValueHandlerRoster {
|
||||
public:
|
||||
ValueHandlerRoster();
|
||||
~ValueHandlerRoster();
|
||||
|
||||
static ValueHandlerRoster* Default();
|
||||
static status_t CreateDefault();
|
||||
static void DeleteDefault();
|
||||
|
||||
status_t Init();
|
||||
status_t RegisterDefaultHandlers();
|
||||
|
||||
status_t FindValueHandler(Value* value,
|
||||
ValueHandler*& _handler);
|
||||
// returns a reference
|
||||
status_t GetValueFormatter(Value* value,
|
||||
ValueFormatter*& _formatter);
|
||||
// returns a reference
|
||||
status_t GetTableCellValueRenderer(Value* value,
|
||||
TableCellValueRenderer*& _renderer);
|
||||
// returns a reference
|
||||
|
||||
bool RegisterHandler(ValueHandler* handler);
|
||||
void UnregisterHandler(ValueHandler* handler);
|
||||
|
||||
private:
|
||||
BLocker fLock;
|
||||
ValueHandlerList fValueHandlers;
|
||||
static ValueHandlerRoster* sDefaultInstance;
|
||||
};
|
||||
|
||||
|
||||
#endif // VALUE_HANDLER_ROSTER_H
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "ValueLoader.h"
|
||||
|
||||
#include "Architecture.h"
|
||||
#include "BitBuffer.h"
|
||||
#include "CpuState.h"
|
||||
#include "Register.h"
|
||||
#include "TeamMemory.h"
|
||||
#include "Tracing.h"
|
||||
#include "ValueLocation.h"
|
||||
|
||||
|
||||
ValueLoader::ValueLoader(Architecture* architecture, TeamMemory* teamMemory,
|
||||
CpuState* cpuState)
|
||||
:
|
||||
fArchitecture(architecture),
|
||||
fTeamMemory(teamMemory),
|
||||
fCpuState(cpuState)
|
||||
{
|
||||
// TODO: TeamMemory is not BReferenceable!
|
||||
fArchitecture->AcquireReference();
|
||||
if (fCpuState != NULL)
|
||||
fCpuState->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
ValueLoader::~ValueLoader()
|
||||
{
|
||||
fArchitecture->ReleaseReference();
|
||||
if (fCpuState != NULL)
|
||||
fCpuState->ReleaseReference();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ValueLoader::LoadValue(ValueLocation* location, type_code valueType,
|
||||
bool shortValueIsFine, BVariant& _value)
|
||||
{
|
||||
static const size_t kMaxPieceSize = 16;
|
||||
uint64 totalBitSize = 0;
|
||||
int32 count = location->CountPieces();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
ValuePieceLocation piece = location->PieceAt(i);
|
||||
switch (piece.type) {
|
||||
case VALUE_PIECE_LOCATION_INVALID:
|
||||
case VALUE_PIECE_LOCATION_UNKNOWN:
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
case VALUE_PIECE_LOCATION_MEMORY:
|
||||
case VALUE_PIECE_LOCATION_REGISTER:
|
||||
break;
|
||||
}
|
||||
|
||||
if (piece.size > kMaxPieceSize) {
|
||||
TRACE_LOCALS(" -> overly long piece size (%llu bytes)\n",
|
||||
piece.size);
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
totalBitSize += piece.bitSize;
|
||||
}
|
||||
|
||||
TRACE_LOCALS(" -> totalBitSize: %llu\n", totalBitSize);
|
||||
|
||||
if (totalBitSize == 0) {
|
||||
TRACE_LOCALS(" -> no size\n");
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (totalBitSize > 64) {
|
||||
TRACE_LOCALS(" -> longer than 64 bits: unsupported\n");
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
uint64 valueBitSize = BVariant::SizeOfType(valueType) * 8;
|
||||
if (!shortValueIsFine && totalBitSize < valueBitSize) {
|
||||
TRACE_LOCALS(" -> too short for value type (%llu vs. %llu bits)\n",
|
||||
totalBitSize, valueBitSize);
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
// Load the data. Since the BitBuffer class we're using only supports big
|
||||
// endian bit semantics, we convert all data to big endian before pushing
|
||||
// them to the buffer. For later conversion to BVariant we need to make sure
|
||||
// the final buffer has the size of the value type, so we pad the most
|
||||
// significant bits with zeros.
|
||||
BitBuffer valueBuffer;
|
||||
if (totalBitSize < valueBitSize)
|
||||
valueBuffer.AddZeroBits(valueBitSize - totalBitSize);
|
||||
|
||||
bool bigEndian = fArchitecture->IsBigEndian();
|
||||
const Register* registers = fArchitecture->Registers();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
ValuePieceLocation piece = location->PieceAt(
|
||||
bigEndian ? i : count - i - 1);
|
||||
uint32 bytesToRead = piece.size;
|
||||
uint32 bitSize = piece.bitSize;
|
||||
uint8 bitOffset = piece.bitOffset;
|
||||
|
||||
switch (piece.type) {
|
||||
case VALUE_PIECE_LOCATION_INVALID:
|
||||
case VALUE_PIECE_LOCATION_UNKNOWN:
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
case VALUE_PIECE_LOCATION_MEMORY:
|
||||
{
|
||||
target_addr_t address = piece.address;
|
||||
|
||||
TRACE_LOCALS(" piece %ld: memory address: %#llx, bits: %lu\n",
|
||||
i, address, bitSize);
|
||||
|
||||
uint8 pieceBuffer[kMaxPieceSize];
|
||||
ssize_t bytesRead = fTeamMemory->ReadMemory(address,
|
||||
pieceBuffer, bytesToRead);
|
||||
if (bytesRead < 0)
|
||||
return bytesRead;
|
||||
if ((uint32)bytesRead != bytesToRead)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
TRACE_LOCALS_ONLY(
|
||||
TRACE_LOCALS(" -> read: ");
|
||||
for (ssize_t k = 0; k < bytesRead; k++)
|
||||
TRACE_LOCALS("%02x", pieceBuffer[k]);
|
||||
TRACE_LOCALS("\n");
|
||||
)
|
||||
|
||||
// convert to big endian
|
||||
if (!bigEndian) {
|
||||
for (int32 k = bytesRead / 2 - 1; k >= 0; k--) {
|
||||
std::swap(pieceBuffer[k],
|
||||
pieceBuffer[bytesRead - k - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
valueBuffer.AddBits(pieceBuffer, bitSize, bitOffset);
|
||||
break;
|
||||
}
|
||||
case VALUE_PIECE_LOCATION_REGISTER:
|
||||
{
|
||||
TRACE_LOCALS(" piece %ld: register: %lu, bits: %lu\n", i,
|
||||
piece.reg, bitSize);
|
||||
|
||||
if (fCpuState == NULL) {
|
||||
WARNING("ValueLoader::LoadValue(): register piece, but no "
|
||||
"CpuState\n");
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
BVariant registerValue;
|
||||
if (!fCpuState->GetRegisterValue(registers + piece.reg,
|
||||
registerValue)) {
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
if (registerValue.Size() < bytesToRead)
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
|
||||
if (!bigEndian)
|
||||
registerValue.SwapEndianess();
|
||||
valueBuffer.AddBits(registerValue.Bytes(), bitSize, bitOffset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we don't have enough bits in the buffer apparently adding some failed.
|
||||
if (valueBuffer.BitSize() < valueBitSize)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
// convert the bits into something we can work with
|
||||
BVariant value;
|
||||
status_t error = value.SetToTypedData(valueBuffer.Bytes(), valueType);
|
||||
if (error != B_OK) {
|
||||
TRACE_LOCALS(" -> failed to set typed data: %s\n", strerror(error));
|
||||
return error;
|
||||
}
|
||||
|
||||
// convert to host endianess
|
||||
#if B_HOST_IS_LENDIAN
|
||||
value.SwapEndianess();
|
||||
#endif
|
||||
|
||||
_value = value;
|
||||
return B_OK;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef VALUE_LOADER_H
|
||||
#define VALUE_LOADER_H
|
||||
|
||||
|
||||
#include <String.h>
|
||||
|
||||
#include <Variant.h>
|
||||
|
||||
|
||||
class Architecture;
|
||||
class CpuState;
|
||||
class TeamMemory;
|
||||
class ValueLocation;
|
||||
|
||||
|
||||
class ValueLoader {
|
||||
public:
|
||||
ValueLoader(Architecture* architecture,
|
||||
TeamMemory* teamMemory, CpuState* cpuState);
|
||||
// cpuState can be NULL
|
||||
~ValueLoader();
|
||||
|
||||
Architecture* GetArchitecture() const
|
||||
{ return fArchitecture; }
|
||||
|
||||
status_t LoadValue(ValueLocation* location,
|
||||
type_code valueType, bool shortValueIsFine,
|
||||
BVariant& _value);
|
||||
|
||||
private:
|
||||
Architecture* fArchitecture;
|
||||
TeamMemory* fTeamMemory;
|
||||
CpuState* fCpuState;
|
||||
};
|
||||
|
||||
|
||||
#endif // VALUE_LOADER_H
|
||||
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "ValueNode.h"
|
||||
|
||||
#include "Value.h"
|
||||
#include "ValueLocation.h"
|
||||
#include "ValueNodeContainer.h"
|
||||
|
||||
|
||||
// #pragma mark - ValueNode
|
||||
|
||||
|
||||
ValueNode::ValueNode(ValueNodeChild* nodeChild)
|
||||
:
|
||||
fContainer(NULL),
|
||||
fNodeChild(nodeChild),
|
||||
fLocation(NULL),
|
||||
fValue(NULL),
|
||||
fLocationResolutionState(VALUE_NODE_UNRESOLVED),
|
||||
fChildrenCreated(false)
|
||||
{
|
||||
fNodeChild->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
ValueNode::~ValueNode()
|
||||
{
|
||||
SetLocationAndValue(NULL, NULL, VALUE_NODE_UNRESOLVED);
|
||||
SetContainer(NULL);
|
||||
fNodeChild->ReleaseReference();
|
||||
}
|
||||
|
||||
|
||||
const BString&
|
||||
ValueNode::Name() const
|
||||
{
|
||||
return fNodeChild->Name();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueNode::SetContainer(ValueNodeContainer* container)
|
||||
{
|
||||
if (container == fContainer)
|
||||
return;
|
||||
|
||||
if (fContainer != NULL)
|
||||
fContainer->ReleaseReference();
|
||||
|
||||
fContainer = container;
|
||||
|
||||
if (fContainer != NULL)
|
||||
fContainer->AcquireReference();
|
||||
|
||||
// propagate to children
|
||||
int32 childCount = CountChildren();
|
||||
for (int32 i = 0; i < childCount; i++)
|
||||
ChildAt(i)->SetContainer(fContainer);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueNode::SetLocationAndValue(ValueLocation* location, Value* value,
|
||||
status_t resolutionState)
|
||||
{
|
||||
if (fLocation != location) {
|
||||
if (fLocation != NULL)
|
||||
fLocation->ReleaseReference();
|
||||
|
||||
fLocation = location;
|
||||
|
||||
if (fLocation != NULL)
|
||||
fLocation->AcquireReference();
|
||||
}
|
||||
|
||||
if (fValue != value) {
|
||||
if (fValue != NULL)
|
||||
fValue->ReleaseReference();
|
||||
|
||||
fValue = value;
|
||||
|
||||
if (fValue != NULL)
|
||||
fValue->AcquireReference();
|
||||
}
|
||||
|
||||
fLocationResolutionState = resolutionState;
|
||||
|
||||
// notify listeners
|
||||
if (fContainer != NULL)
|
||||
fContainer->NotifyValueNodeValueChanged(this);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - ValueNodeChild
|
||||
|
||||
|
||||
ValueNodeChild::ValueNodeChild()
|
||||
:
|
||||
fContainer(NULL),
|
||||
fNode(NULL),
|
||||
fLocation(NULL),
|
||||
fLocationResolutionState(VALUE_NODE_UNRESOLVED)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ValueNodeChild::~ValueNodeChild()
|
||||
{
|
||||
SetLocation(NULL, VALUE_NODE_UNRESOLVED);
|
||||
SetNode(NULL);
|
||||
SetContainer(NULL);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ValueNodeChild::IsInternal() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ValueNodeChild::CreateInternalNode(ValueNode*& _node)
|
||||
{
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueNodeChild::SetContainer(ValueNodeContainer* container)
|
||||
{
|
||||
if (container == fContainer)
|
||||
return;
|
||||
|
||||
if (fContainer != NULL)
|
||||
fContainer->ReleaseReference();
|
||||
|
||||
fContainer = container;
|
||||
|
||||
if (fContainer != NULL)
|
||||
fContainer->AcquireReference();
|
||||
|
||||
// propagate to node
|
||||
if (fNode != NULL)
|
||||
fNode->SetContainer(fContainer);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueNodeChild::SetNode(ValueNode* node)
|
||||
{
|
||||
if (node == fNode)
|
||||
return;
|
||||
|
||||
ValueNode* oldNode = fNode;
|
||||
Reference<ValueNode> oldNodeReference(oldNode, true);
|
||||
|
||||
if (fNode != NULL)
|
||||
fNode->SetContainer(NULL);
|
||||
|
||||
fNode = node;
|
||||
|
||||
if (fNode != NULL) {
|
||||
fNode->AcquireReference();
|
||||
fNode->SetContainer(fContainer);
|
||||
}
|
||||
|
||||
if (fContainer != NULL)
|
||||
fContainer->NotifyValueNodeChanged(this, oldNode, fNode);
|
||||
}
|
||||
|
||||
|
||||
ValueLocation*
|
||||
ValueNodeChild::Location() const
|
||||
{
|
||||
return fLocation;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueNodeChild::SetLocation(ValueLocation* location, status_t resolutionState)
|
||||
{
|
||||
if (fLocation != location) {
|
||||
if (fLocation != NULL)
|
||||
fLocation->ReleaseReference();
|
||||
|
||||
fLocation = location;
|
||||
|
||||
if (fLocation != NULL)
|
||||
fLocation->AcquireReference();
|
||||
}
|
||||
|
||||
fLocationResolutionState = resolutionState;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - ChildlessValueNode
|
||||
|
||||
|
||||
ChildlessValueNode::ChildlessValueNode(ValueNodeChild* nodeChild)
|
||||
:
|
||||
ValueNode(nodeChild)
|
||||
{
|
||||
fChildrenCreated = true;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ChildlessValueNode::CreateChildren()
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
int32
|
||||
ChildlessValueNode::CountChildren() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ValueNodeChild*
|
||||
ChildlessValueNode::ChildAt(int32 index) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef VALUE_NODE_H
|
||||
#define VALUE_NODE_H
|
||||
|
||||
|
||||
#include <String.h>
|
||||
|
||||
#include <Referenceable.h>
|
||||
|
||||
|
||||
class Type;
|
||||
class Value;
|
||||
class ValueLoader;
|
||||
class ValueLocation;
|
||||
class ValueNodeChild;
|
||||
class ValueNodeContainer;
|
||||
|
||||
|
||||
enum {
|
||||
VALUE_NODE_UNRESOLVED = 1
|
||||
};
|
||||
|
||||
|
||||
class ValueNode : public BReferenceable {
|
||||
public:
|
||||
ValueNode(ValueNodeChild* nodeChild);
|
||||
virtual ~ValueNode();
|
||||
|
||||
ValueNodeChild* NodeChild() const { return fNodeChild; }
|
||||
|
||||
virtual const BString& Name() const;
|
||||
virtual Type* GetType() const = 0;
|
||||
|
||||
virtual status_t ResolvedLocationAndValue(
|
||||
ValueLoader* valueLoader,
|
||||
ValueLocation*& _location,
|
||||
Value*& _value) = 0;
|
||||
// returns references, a NULL value can be
|
||||
// returned
|
||||
|
||||
// locking required
|
||||
|
||||
ValueNodeContainer* Container() const
|
||||
{ return fContainer; }
|
||||
void SetContainer(ValueNodeContainer* container);
|
||||
|
||||
bool ChildrenCreated() const
|
||||
{ return fChildrenCreated; }
|
||||
virtual status_t CreateChildren() = 0;
|
||||
virtual int32 CountChildren() const = 0;
|
||||
virtual ValueNodeChild* ChildAt(int32 index) const = 0;
|
||||
|
||||
status_t LocationAndValueResolutionState() const
|
||||
{ return fLocationResolutionState; }
|
||||
void SetLocationAndValue(ValueLocation* location,
|
||||
Value* value, status_t resolutionState);
|
||||
ValueLocation* Location() const { return fLocation; }
|
||||
Value* GetValue() const { return fValue; }
|
||||
// immutable after SetLocationAndValue()
|
||||
|
||||
protected:
|
||||
ValueNodeContainer* fContainer;
|
||||
ValueNodeChild* fNodeChild;
|
||||
ValueLocation* fLocation;
|
||||
Value* fValue;
|
||||
status_t fLocationResolutionState;
|
||||
bool fChildrenCreated;
|
||||
};
|
||||
|
||||
|
||||
class ValueNodeChild : public BReferenceable {
|
||||
public:
|
||||
ValueNodeChild();
|
||||
virtual ~ValueNodeChild();
|
||||
|
||||
virtual const BString& Name() const = 0;
|
||||
virtual Type* GetType() const = 0;
|
||||
virtual ValueNode* Parent() const = 0;
|
||||
|
||||
virtual bool IsInternal() const;
|
||||
virtual status_t CreateInternalNode(ValueNode*& _node);
|
||||
|
||||
virtual status_t ResolveLocation(ValueLoader* valueLoader,
|
||||
ValueLocation*& _location) = 0;
|
||||
// returns a reference
|
||||
|
||||
// locking required
|
||||
|
||||
ValueNodeContainer* Container() const
|
||||
{ return fContainer; }
|
||||
void SetContainer(ValueNodeContainer* container);
|
||||
|
||||
ValueNode* Node() const { return fNode; }
|
||||
void SetNode(ValueNode* node);
|
||||
|
||||
status_t LocationResolutionState() const
|
||||
{ return fLocationResolutionState; }
|
||||
ValueLocation* Location() const;
|
||||
// immutable after SetLocation()
|
||||
void SetLocation(ValueLocation* location,
|
||||
status_t resolutionState);
|
||||
|
||||
protected:
|
||||
ValueNodeContainer* fContainer;
|
||||
ValueNode* fNode;
|
||||
ValueLocation* fLocation;
|
||||
status_t fLocationResolutionState;
|
||||
};
|
||||
|
||||
|
||||
class ChildlessValueNode : public ValueNode {
|
||||
public:
|
||||
ChildlessValueNode(ValueNodeChild* nodeChild);
|
||||
|
||||
virtual status_t CreateChildren();
|
||||
virtual int32 CountChildren() const;
|
||||
virtual ValueNodeChild* ChildAt(int32 index) const;
|
||||
};
|
||||
|
||||
|
||||
#endif // VALUE_NODE_H
|
||||
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "ValueNodeContainer.h"
|
||||
|
||||
#include <AutoLocker.h>
|
||||
|
||||
#include "ValueNode.h"
|
||||
|
||||
|
||||
// #pragma mark - ValueNodeContainer
|
||||
|
||||
|
||||
ValueNodeContainer::ValueNodeContainer()
|
||||
:
|
||||
fLock("value node container")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ValueNodeContainer::~ValueNodeContainer()
|
||||
{
|
||||
RemoveAllChildren();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ValueNodeContainer::Init()
|
||||
{
|
||||
return fLock.InitCheck();
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
ValueNodeContainer::CountChildren() const
|
||||
{
|
||||
return fChildren.CountItems();
|
||||
}
|
||||
|
||||
|
||||
ValueNodeChild*
|
||||
ValueNodeContainer::ChildAt(int32 index) const
|
||||
{
|
||||
return fChildren.ItemAt(index);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ValueNodeContainer::AddChild(ValueNodeChild* child)
|
||||
{
|
||||
AutoLocker<ValueNodeContainer> locker(this);
|
||||
|
||||
if (!fChildren.AddItem(child))
|
||||
return false;
|
||||
|
||||
child->AcquireReference();
|
||||
child->SetContainer(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueNodeContainer::RemoveChild(ValueNodeChild* child)
|
||||
{
|
||||
if (child->Container() != this || !fChildren.RemoveItem(child))
|
||||
return;
|
||||
|
||||
child->SetContainer(NULL);
|
||||
child->RemoveReference();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueNodeContainer::RemoveAllChildren()
|
||||
{
|
||||
for (int32 i = 0; ValueNodeChild* child = ChildAt(i); i++) {
|
||||
child->SetContainer(NULL);
|
||||
child->RemoveReference();
|
||||
}
|
||||
|
||||
fChildren.MakeEmpty();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ValueNodeContainer::AddListener(Listener* listener)
|
||||
{
|
||||
return fListeners.AddItem(listener);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueNodeContainer::RemoveListener(Listener* listener)
|
||||
{
|
||||
fListeners.RemoveItem(listener);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueNodeContainer::NotifyValueNodeChanged(ValueNodeChild* nodeChild,
|
||||
ValueNode* oldNode, ValueNode* newNode)
|
||||
{
|
||||
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
|
||||
fListeners.ItemAt(i)->ValueNodeChanged(nodeChild, oldNode, newNode);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueNodeContainer::NotifyValueNodeChildrenCreated(ValueNode* node)
|
||||
{
|
||||
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
|
||||
fListeners.ItemAt(i)->ValueNodeChildrenCreated(node);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueNodeContainer::NotifyValueNodeChildrenDeleted(ValueNode* node)
|
||||
{
|
||||
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
|
||||
fListeners.ItemAt(i)->ValueNodeChildrenDeleted(node);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueNodeContainer::NotifyValueNodeValueChanged(ValueNode* node)
|
||||
{
|
||||
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--)
|
||||
fListeners.ItemAt(i)->ValueNodeValueChanged(node);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - ValueNodeContainer
|
||||
|
||||
|
||||
ValueNodeContainer::Listener::~Listener()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueNodeContainer::Listener::ValueNodeChanged(ValueNodeChild* nodeChild,
|
||||
ValueNode* oldNode, ValueNode* newNode)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueNodeContainer::Listener::ValueNodeChildrenCreated(ValueNode* node)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueNodeContainer::Listener::ValueNodeChildrenDeleted(ValueNode* node)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ValueNodeContainer::Listener::ValueNodeValueChanged(ValueNode* node)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef VALUE_NODE_CONTAINER_H
|
||||
#define VALUE_NODE_CONTAINER_H
|
||||
|
||||
|
||||
#include <Locker.h>
|
||||
|
||||
#include <ObjectList.h>
|
||||
#include <Referenceable.h>
|
||||
|
||||
|
||||
class ValueNode;
|
||||
class ValueNodeChild;
|
||||
|
||||
|
||||
class ValueNodeContainer : public BReferenceable {
|
||||
public:
|
||||
class Listener;
|
||||
|
||||
public:
|
||||
ValueNodeContainer();
|
||||
virtual ~ValueNodeContainer();
|
||||
|
||||
status_t Init();
|
||||
|
||||
inline bool Lock() { return fLock.Lock(); }
|
||||
inline void Unlock() { fLock.Unlock(); }
|
||||
|
||||
int32 CountChildren() const;
|
||||
ValueNodeChild* ChildAt(int32 index) const;
|
||||
bool AddChild(ValueNodeChild* child);
|
||||
void RemoveChild(ValueNodeChild* child);
|
||||
void RemoveAllChildren();
|
||||
|
||||
bool AddListener(Listener* listener);
|
||||
void RemoveListener(Listener* listener);
|
||||
|
||||
// container must be locked
|
||||
|
||||
void NotifyValueNodeChanged(
|
||||
ValueNodeChild* nodeChild,
|
||||
ValueNode* oldNode, ValueNode* newNode);
|
||||
void NotifyValueNodeChildrenCreated(ValueNode* node);
|
||||
void NotifyValueNodeChildrenDeleted(ValueNode* node);
|
||||
void NotifyValueNodeValueChanged(ValueNode* node);
|
||||
|
||||
private:
|
||||
typedef BObjectList<ValueNodeChild> NodeChildList;
|
||||
typedef BObjectList<Listener> ListenerList;
|
||||
|
||||
private:
|
||||
BLocker fLock;
|
||||
NodeChildList fChildren;
|
||||
ListenerList fListeners;
|
||||
};
|
||||
|
||||
|
||||
class ValueNodeContainer::Listener {
|
||||
public:
|
||||
virtual ~Listener();
|
||||
|
||||
// container is locked
|
||||
|
||||
virtual void ValueNodeChanged(ValueNodeChild* nodeChild,
|
||||
ValueNode* oldNode, ValueNode* newNode);
|
||||
virtual void ValueNodeChildrenCreated(ValueNode* node);
|
||||
virtual void ValueNodeChildrenDeleted(ValueNode* node);
|
||||
virtual void ValueNodeValueChanged(ValueNode* node);
|
||||
};
|
||||
|
||||
|
||||
#endif // VALUE_NODE_CONTAINER_H
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "AddressValueHandler.h"
|
||||
|
||||
#include "AddressValue.h"
|
||||
|
||||
|
||||
float
|
||||
AddressValueHandler::SupportsValue(Value* value)
|
||||
{
|
||||
return dynamic_cast<AddressValue*>(value) ? 0.8f : 0;
|
||||
}
|
||||
|
||||
|
||||
integer_format
|
||||
AddressValueHandler::DefaultIntegerFormat(IntegerValue* value)
|
||||
{
|
||||
return INTEGER_FORMAT_HEX_DEFAULT;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef ADDRESS_VALUE_HANDLER_H
|
||||
#define ADDRESS_VALUE_HANDLER_H
|
||||
|
||||
|
||||
#include "IntegerValueHandler.h"
|
||||
|
||||
|
||||
class AddressValueHandler : public IntegerValueHandler {
|
||||
public:
|
||||
virtual float SupportsValue(Value* value);
|
||||
|
||||
protected:
|
||||
virtual integer_format DefaultIntegerFormat(IntegerValue* value);
|
||||
};
|
||||
|
||||
|
||||
#endif // ADDRESS_VALUE_HANDLER_H
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "BoolValueHandler.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "BoolValue.h"
|
||||
#include "TableCellBoolRenderer.h"
|
||||
|
||||
|
||||
BoolValueHandler::BoolValueHandler()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BoolValueHandler::~BoolValueHandler()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BoolValueHandler::Init()
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
BoolValueHandler::SupportsValue(Value* value)
|
||||
{
|
||||
return dynamic_cast<BoolValue*>(value) != NULL ? 0.5f : 0;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BoolValueHandler::GetValueFormatter(Value* value,
|
||||
ValueFormatter*& _formatter)
|
||||
{
|
||||
// TODO:...
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BoolValueHandler::GetTableCellValueRenderer(Value* value,
|
||||
TableCellValueRenderer*& _renderer)
|
||||
{
|
||||
if (dynamic_cast<BoolValue*>(value) == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// create the renderer
|
||||
TableCellValueRenderer* renderer = new(std::nothrow) TableCellBoolRenderer;
|
||||
if (renderer == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
_renderer = renderer;
|
||||
return B_OK;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef BOOL_VALUE_HANDLER_H
|
||||
#define BOOL_VALUE_HANDLER_H
|
||||
|
||||
|
||||
#include "ValueHandler.h"
|
||||
|
||||
|
||||
class BoolValueHandler : public ValueHandler {
|
||||
public:
|
||||
BoolValueHandler();
|
||||
~BoolValueHandler();
|
||||
|
||||
status_t Init();
|
||||
|
||||
virtual float SupportsValue(Value* value);
|
||||
virtual status_t GetValueFormatter(Value* value,
|
||||
ValueFormatter*& _formatter);
|
||||
virtual status_t GetTableCellValueRenderer(Value* value,
|
||||
TableCellValueRenderer*& _renderer);
|
||||
};
|
||||
|
||||
|
||||
#endif // BOOL_VALUE_HANDLER_H
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "EnumerationValueHandler.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "EnumerationValue.h"
|
||||
#include "TableCellEnumerationRenderer.h"
|
||||
#include "Type.h"
|
||||
|
||||
|
||||
EnumerationValueHandler::EnumerationValueHandler()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
EnumerationValueHandler::~EnumerationValueHandler()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
EnumerationValueHandler::Init()
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
EnumerationValueHandler::SupportsValue(Value* value)
|
||||
{
|
||||
return dynamic_cast<EnumerationValue*>(value) != NULL ? 0.7f : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
integer_format
|
||||
EnumerationValueHandler::DefaultIntegerFormat(IntegerValue* _value)
|
||||
{
|
||||
EnumerationValue* value = dynamic_cast<EnumerationValue*>(_value);
|
||||
if (value != NULL && value->GetType()->ValueFor(value->GetValue()) != NULL)
|
||||
return INTEGER_FORMAT_DEFAULT;
|
||||
|
||||
return IntegerValueHandler::DefaultIntegerFormat(_value);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
EnumerationValueHandler::AddIntegerFormatSettingOptions(IntegerValue* _value,
|
||||
OptionsSettingImpl* setting)
|
||||
{
|
||||
EnumerationValue* value = dynamic_cast<EnumerationValue*>(_value);
|
||||
if (value != NULL
|
||||
&& value->GetType()->ValueFor(value->GetValue()) != NULL) {
|
||||
status_t error = AddIntegerFormatOption(setting, "name", "Enum Name",
|
||||
INTEGER_FORMAT_DEFAULT);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
}
|
||||
|
||||
return IntegerValueHandler::AddIntegerFormatSettingOptions(_value, setting);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
EnumerationValueHandler::CreateTableCellValueRenderer(IntegerValue* _value,
|
||||
TableCellIntegerRenderer::Config* config,
|
||||
TableCellValueRenderer*& _renderer)
|
||||
{
|
||||
EnumerationValue* value = dynamic_cast<EnumerationValue*>(_value);
|
||||
if (value != NULL
|
||||
&& value->GetType()->ValueFor(value->GetValue()) != NULL) {
|
||||
TableCellValueRenderer* renderer
|
||||
= new(std::nothrow) TableCellEnumerationRenderer(config);
|
||||
if (renderer == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
_renderer = renderer;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
return IntegerValueHandler::CreateTableCellValueRenderer(_value, config,
|
||||
_renderer);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef ENUMERATION_VALUE_HANDLER_H
|
||||
#define ENUMERATION_VALUE_HANDLER_H
|
||||
|
||||
|
||||
#include "IntegerValueHandler.h"
|
||||
|
||||
|
||||
class EnumerationValueHandler : public IntegerValueHandler {
|
||||
public:
|
||||
EnumerationValueHandler();
|
||||
~EnumerationValueHandler();
|
||||
|
||||
status_t Init();
|
||||
|
||||
virtual float SupportsValue(Value* value);
|
||||
|
||||
protected:
|
||||
virtual integer_format DefaultIntegerFormat(IntegerValue* value);
|
||||
virtual status_t AddIntegerFormatSettingOptions(
|
||||
IntegerValue* value,
|
||||
OptionsSettingImpl* setting);
|
||||
virtual status_t CreateTableCellValueRenderer(
|
||||
IntegerValue* value,
|
||||
TableCellIntegerRenderer::Config* config,
|
||||
TableCellValueRenderer*& _renderer);
|
||||
};
|
||||
|
||||
|
||||
#endif // ENUMERATION_VALUE_HANDLER_H
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "FloatValueHandler.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "FloatValue.h"
|
||||
#include "TableCellFloatRenderer.h"
|
||||
|
||||
|
||||
FloatValueHandler::FloatValueHandler()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
FloatValueHandler::~FloatValueHandler()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
FloatValueHandler::Init()
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
FloatValueHandler::SupportsValue(Value* value)
|
||||
{
|
||||
return dynamic_cast<FloatValue*>(value) != NULL ? 0.5f : 0;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
FloatValueHandler::GetValueFormatter(Value* value,
|
||||
ValueFormatter*& _formatter)
|
||||
{
|
||||
// TODO:...
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
FloatValueHandler::GetTableCellValueRenderer(Value* value,
|
||||
TableCellValueRenderer*& _renderer)
|
||||
{
|
||||
if (dynamic_cast<FloatValue*>(value) == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// create the renderer
|
||||
TableCellValueRenderer* renderer = new(std::nothrow) TableCellFloatRenderer;
|
||||
if (renderer == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
_renderer = renderer;
|
||||
return B_OK;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef FLOAT_VALUE_HANDLER_H
|
||||
#define FLOAT_VALUE_HANDLER_H
|
||||
|
||||
|
||||
#include "ValueHandler.h"
|
||||
|
||||
|
||||
class FloatValueHandler : public ValueHandler {
|
||||
public:
|
||||
FloatValueHandler();
|
||||
~FloatValueHandler();
|
||||
|
||||
status_t Init();
|
||||
|
||||
virtual float SupportsValue(Value* value);
|
||||
virtual status_t GetValueFormatter(Value* value,
|
||||
ValueFormatter*& _formatter);
|
||||
virtual status_t GetTableCellValueRenderer(Value* value,
|
||||
TableCellValueRenderer*& _renderer);
|
||||
};
|
||||
|
||||
|
||||
#endif // FLOAT_VALUE_HANDLER_H
|
||||
@@ -0,0 +1,306 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "IntegerValueHandler.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
|
||||
#include "IntegerValue.h"
|
||||
#include "Setting.h"
|
||||
#include "Settings.h"
|
||||
#include "SettingsDescription.h"
|
||||
#include "SettingsMenu.h"
|
||||
#include "TableCellIntegerRenderer.h"
|
||||
|
||||
|
||||
static const char* const kFormatSettingID = "format";
|
||||
|
||||
|
||||
// #pragma mark - FormatOption
|
||||
|
||||
|
||||
class IntegerValueHandler::FormatOption : public SettingsOption {
|
||||
public:
|
||||
FormatOption(const char* id, const char* name, integer_format format)
|
||||
:
|
||||
fID(id),
|
||||
fName(name),
|
||||
fFormat(format)
|
||||
{
|
||||
}
|
||||
|
||||
virtual const char* ID() const
|
||||
{
|
||||
return fID;
|
||||
}
|
||||
|
||||
virtual const char* Name() const
|
||||
{
|
||||
return fName;
|
||||
}
|
||||
|
||||
integer_format Format() const
|
||||
{
|
||||
return fFormat;
|
||||
}
|
||||
|
||||
private:
|
||||
const char* fID;
|
||||
const char* fName;
|
||||
integer_format fFormat;
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - TableCellRendererConfig
|
||||
|
||||
|
||||
class IntegerValueHandler::TableCellRendererConfig
|
||||
: public TableCellIntegerRenderer::Config {
|
||||
public:
|
||||
TableCellRendererConfig()
|
||||
:
|
||||
fSettings(NULL),
|
||||
fFormatSetting(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
~TableCellRendererConfig()
|
||||
{
|
||||
if (fSettings != NULL)
|
||||
fSettings->ReleaseReference();
|
||||
}
|
||||
|
||||
status_t Init(SettingsDescription* settingsDescription)
|
||||
{
|
||||
fSettings = new(std::nothrow) Settings(settingsDescription);
|
||||
if (fSettings == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t error = fSettings->Init();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
fFormatSetting = dynamic_cast<OptionsSetting*>(
|
||||
settingsDescription->SettingByID(kFormatSettingID));
|
||||
if (fFormatSetting == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
virtual Settings* GetSettings() const
|
||||
{
|
||||
return fSettings;
|
||||
}
|
||||
|
||||
virtual integer_format IntegerFormat() const
|
||||
{
|
||||
FormatOption* option = dynamic_cast<FormatOption*>(
|
||||
fSettings->OptionValue(fFormatSetting));
|
||||
return option != NULL ? option->Format() : INTEGER_FORMAT_DEFAULT;
|
||||
}
|
||||
|
||||
private:
|
||||
Settings* fSettings;
|
||||
OptionsSetting* fFormatSetting;
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - IntegerValueHandler
|
||||
|
||||
|
||||
IntegerValueHandler::IntegerValueHandler()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
IntegerValueHandler::~IntegerValueHandler()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
IntegerValueHandler::Init()
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
IntegerValueHandler::SupportsValue(Value* value)
|
||||
{
|
||||
return dynamic_cast<IntegerValue*>(value) != NULL ? 0.5f : 0;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
IntegerValueHandler::GetValueFormatter(Value* value,
|
||||
ValueFormatter*& _formatter)
|
||||
{
|
||||
// TODO:...
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
IntegerValueHandler::GetTableCellValueRenderer(Value* _value,
|
||||
TableCellValueRenderer*& _renderer)
|
||||
{
|
||||
IntegerValue* value = dynamic_cast<IntegerValue*>(_value);
|
||||
if (value == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// create a settings description
|
||||
SettingsDescription* settingsDescription
|
||||
= _CreateTableCellSettingsDescription(value);
|
||||
if (settingsDescription == NULL)
|
||||
return B_NO_MEMORY;
|
||||
Reference<SettingsDescription> settingsDescriptionReference(
|
||||
settingsDescription, true);
|
||||
|
||||
// create config
|
||||
TableCellRendererConfig* config = new(std::nothrow) TableCellRendererConfig;
|
||||
if (config == NULL)
|
||||
return B_NO_MEMORY;
|
||||
Reference<TableCellRendererConfig> configReference(config, true);
|
||||
|
||||
status_t error = config->Init(settingsDescription);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
// create the renderer
|
||||
return CreateTableCellValueRenderer(value, config, _renderer);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
IntegerValueHandler::CreateTableCellValueSettingsMenu(Value* value,
|
||||
Settings* settings, SettingsMenu*& _menu)
|
||||
{
|
||||
// get the format option
|
||||
OptionsSetting* formatSetting = dynamic_cast<OptionsSetting*>(
|
||||
settings->Description()->SettingByID(kFormatSettingID));
|
||||
if (formatSetting == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// create the settings menu
|
||||
SettingsMenuImpl* menu = new(std::nothrow) SettingsMenuImpl(settings);
|
||||
if (menu == NULL)
|
||||
return B_NO_MEMORY;
|
||||
ObjectDeleter<SettingsMenu> menuDeleter(menu);
|
||||
|
||||
// add the format option menu item
|
||||
if (!menu->AddOptionsItem(formatSetting))
|
||||
return B_NO_MEMORY;
|
||||
|
||||
_menu = menuDeleter.Detach();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
integer_format
|
||||
IntegerValueHandler::DefaultIntegerFormat(IntegerValue* value)
|
||||
{
|
||||
return value->IsSigned() ? INTEGER_FORMAT_SIGNED : INTEGER_FORMAT_UNSIGNED;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
IntegerValueHandler::AddIntegerFormatSettingOptions(IntegerValue* value,
|
||||
OptionsSettingImpl* setting)
|
||||
{
|
||||
status_t error = AddIntegerFormatOption(setting, "signed", "Signed",
|
||||
INTEGER_FORMAT_SIGNED);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
error = AddIntegerFormatOption(setting, "unsigned", "Unsigned",
|
||||
INTEGER_FORMAT_UNSIGNED);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
error = AddIntegerFormatOption(setting, "hex", "Hexadecimal",
|
||||
INTEGER_FORMAT_HEX_DEFAULT);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
IntegerValueHandler::CreateTableCellValueRenderer(IntegerValue* value,
|
||||
TableCellIntegerRenderer::Config* config,
|
||||
TableCellValueRenderer*& _renderer)
|
||||
{
|
||||
TableCellValueRenderer* renderer
|
||||
= new(std::nothrow) TableCellIntegerRenderer(config);
|
||||
if (renderer == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
_renderer = renderer;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
IntegerValueHandler::AddIntegerFormatOption(OptionsSettingImpl* setting,
|
||||
const char* id, const char* name, integer_format format)
|
||||
{
|
||||
FormatOption* option = new(std::nothrow) FormatOption(id, name, format);
|
||||
if (option == NULL || !setting->AddOption(option)) {
|
||||
delete option;
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
SettingsDescription*
|
||||
IntegerValueHandler::_CreateTableCellSettingsDescription(
|
||||
IntegerValue* value)
|
||||
{
|
||||
// create description object
|
||||
SettingsDescription* description = new(std::nothrow) SettingsDescription;
|
||||
if (description == NULL)
|
||||
return NULL;
|
||||
Reference<SettingsDescription> descriptionReference(description, true);
|
||||
|
||||
// integer format setting
|
||||
OptionsSettingImpl* setting = new(std::nothrow) OptionsSettingImpl(
|
||||
kFormatSettingID, "Format");
|
||||
if (setting == NULL)
|
||||
return NULL;
|
||||
Reference<OptionsSettingImpl> settingReference(setting, true);
|
||||
|
||||
// add options
|
||||
if (AddIntegerFormatSettingOptions(value, setting) != B_OK)
|
||||
return NULL;
|
||||
|
||||
// set default
|
||||
integer_format defaultFormat = DefaultIntegerFormat(value);
|
||||
SettingsOption* defaultOption = setting->OptionAt(0);
|
||||
for (int32 i = 0;
|
||||
FormatOption* option
|
||||
= dynamic_cast<FormatOption*>(setting->OptionAt(i));
|
||||
i++) {
|
||||
if (option->Format() == defaultFormat) {
|
||||
defaultOption = option;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
setting->SetDefaultOption(defaultOption);
|
||||
|
||||
// add setting
|
||||
if (!description->AddSetting(setting))
|
||||
return NULL;
|
||||
|
||||
return descriptionReference.Detach();
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef INTEGER_VALUE_HANDLER_H
|
||||
#define INTEGER_VALUE_HANDLER_H
|
||||
|
||||
|
||||
#include "IntegerFormatter.h"
|
||||
#include "TableCellIntegerRenderer.h"
|
||||
#include "ValueHandler.h"
|
||||
|
||||
|
||||
class IntegerValue;
|
||||
class OptionsSettingImpl;
|
||||
class SettingsDescription;
|
||||
|
||||
|
||||
class IntegerValueHandler : public ValueHandler {
|
||||
public:
|
||||
IntegerValueHandler();
|
||||
~IntegerValueHandler();
|
||||
|
||||
status_t Init();
|
||||
|
||||
virtual float SupportsValue(Value* value);
|
||||
virtual status_t GetValueFormatter(Value* value,
|
||||
ValueFormatter*& _formatter);
|
||||
virtual status_t GetTableCellValueRenderer(Value* value,
|
||||
TableCellValueRenderer*& _renderer);
|
||||
virtual status_t CreateTableCellValueSettingsMenu(Value* value,
|
||||
Settings* settings, SettingsMenu*& _menu);
|
||||
|
||||
protected:
|
||||
virtual integer_format DefaultIntegerFormat(IntegerValue* value);
|
||||
virtual status_t AddIntegerFormatSettingOptions(
|
||||
IntegerValue* value,
|
||||
OptionsSettingImpl* setting);
|
||||
virtual status_t CreateTableCellValueRenderer(
|
||||
IntegerValue* value,
|
||||
TableCellIntegerRenderer::Config* config,
|
||||
TableCellValueRenderer*& _renderer);
|
||||
|
||||
status_t AddIntegerFormatOption(
|
||||
OptionsSettingImpl* setting, const char* id,
|
||||
const char* name, integer_format format);
|
||||
|
||||
private:
|
||||
class FormatOption;
|
||||
class TableCellRendererConfig;
|
||||
|
||||
private:
|
||||
SettingsDescription* _CreateTableCellSettingsDescription(
|
||||
IntegerValue* value);
|
||||
};
|
||||
|
||||
|
||||
#endif // INTEGER_VALUE_HANDLER_H
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "AddressValueNode.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "AddressValue.h"
|
||||
#include "Architecture.h"
|
||||
#include "Tracing.h"
|
||||
#include "Type.h"
|
||||
#include "ValueLoader.h"
|
||||
#include "ValueLocation.h"
|
||||
#include "ValueNodeContainer.h"
|
||||
|
||||
|
||||
// #pragma mark - AddressValueNode
|
||||
|
||||
|
||||
AddressValueNode::AddressValueNode(ValueNodeChild* nodeChild,
|
||||
AddressType* type)
|
||||
:
|
||||
ValueNode(nodeChild),
|
||||
fType(type),
|
||||
fChild(NULL)
|
||||
{
|
||||
fType->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
AddressValueNode::~AddressValueNode()
|
||||
{
|
||||
if (fChild != NULL)
|
||||
fChild->ReleaseReference();
|
||||
fType->ReleaseReference();
|
||||
}
|
||||
|
||||
|
||||
Type*
|
||||
AddressValueNode::GetType() const
|
||||
{
|
||||
return fType;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
AddressValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader,
|
||||
ValueLocation*& _location, Value*& _value)
|
||||
{
|
||||
// get the location
|
||||
ValueLocation* location = NodeChild()->Location();
|
||||
if (location == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
TRACE_LOCALS(" TYPE_ADDRESS\n");
|
||||
|
||||
// get the value type
|
||||
type_code valueType;
|
||||
if (valueLoader->GetArchitecture()->AddressSize() == 4) {
|
||||
valueType = B_UINT32_TYPE;
|
||||
TRACE_LOCALS(" -> 32 bit\n");
|
||||
} else {
|
||||
valueType = B_UINT64_TYPE;
|
||||
TRACE_LOCALS(" -> 64 bit\n");
|
||||
}
|
||||
|
||||
// load the value data
|
||||
BVariant valueData;
|
||||
status_t error = valueLoader->LoadValue(location, valueType, false,
|
||||
valueData);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
// create the type object
|
||||
Value* value = new(std::nothrow) AddressValue(valueData);
|
||||
if (value == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
location->AcquireReference();
|
||||
_location = location;
|
||||
_value = value;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
AddressValueNode::CreateChildren()
|
||||
{
|
||||
if (fChild != NULL)
|
||||
return B_OK;
|
||||
|
||||
// construct name
|
||||
BString name = "*";
|
||||
name << Name();
|
||||
|
||||
// create the child
|
||||
fChild = new(std::nothrow) AddressValueNodeChild(this, name,
|
||||
fType->BaseType());
|
||||
if (fChild == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
fChild->SetContainer(fContainer);
|
||||
|
||||
if (fContainer != NULL)
|
||||
fContainer->NotifyValueNodeChildrenCreated(this);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
AddressValueNode::CountChildren() const
|
||||
{
|
||||
return fChild != NULL ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
ValueNodeChild*
|
||||
AddressValueNode::ChildAt(int32 index) const
|
||||
{
|
||||
return index == 0 ? fChild : NULL;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - AddressValueNodeChild
|
||||
|
||||
|
||||
AddressValueNodeChild::AddressValueNodeChild(AddressValueNode* parent,
|
||||
const BString& name, Type* type)
|
||||
:
|
||||
fParent(parent),
|
||||
fName(name),
|
||||
fType(type)
|
||||
{
|
||||
fType->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
AddressValueNodeChild::~AddressValueNodeChild()
|
||||
{
|
||||
fType->ReleaseReference();
|
||||
}
|
||||
|
||||
|
||||
const BString&
|
||||
AddressValueNodeChild::Name() const
|
||||
{
|
||||
return fName;
|
||||
}
|
||||
|
||||
|
||||
Type*
|
||||
AddressValueNodeChild::GetType() const
|
||||
{
|
||||
return fType;
|
||||
}
|
||||
|
||||
|
||||
ValueNode*
|
||||
AddressValueNodeChild::Parent() const
|
||||
{
|
||||
return fParent;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
AddressValueNodeChild::ResolveLocation(ValueLoader* valueLoader,
|
||||
ValueLocation*& _location)
|
||||
{
|
||||
// The parent's value is an address pointing to this component.
|
||||
AddressValue* parentValue = dynamic_cast<AddressValue*>(
|
||||
fParent->GetValue());
|
||||
if (parentValue == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// resolve the location
|
||||
ValueLocation* location;
|
||||
status_t error = fType->ResolveObjectDataLocation(parentValue->ToUInt64(),
|
||||
location);
|
||||
if (error != B_OK) {
|
||||
TRACE_LOCALS("AddressValueNodeChild::ResolveLocation(): "
|
||||
"ResolveObjectDataLocation() failed: %s\n", strerror(error));
|
||||
return error;
|
||||
}
|
||||
|
||||
_location = location;
|
||||
return B_OK;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef ADDRESS_VALUE_NODE_H
|
||||
#define ADDRESS_VALUE_NODE_H
|
||||
|
||||
|
||||
#include "ValueNode.h"
|
||||
|
||||
|
||||
class AddressValueNodeChild;
|
||||
class AddressType;
|
||||
|
||||
|
||||
class AddressValueNode : public ValueNode {
|
||||
public:
|
||||
AddressValueNode(ValueNodeChild* nodeChild,
|
||||
AddressType* type);
|
||||
virtual ~AddressValueNode();
|
||||
|
||||
virtual Type* GetType() const;
|
||||
|
||||
virtual status_t ResolvedLocationAndValue(
|
||||
ValueLoader* valueLoader,
|
||||
ValueLocation*& _location,
|
||||
Value*& _value);
|
||||
|
||||
// locking required
|
||||
|
||||
virtual status_t CreateChildren();
|
||||
virtual int32 CountChildren() const;
|
||||
virtual ValueNodeChild* ChildAt(int32 index) const;
|
||||
|
||||
private:
|
||||
AddressType* fType;
|
||||
AddressValueNodeChild* fChild;
|
||||
};
|
||||
|
||||
|
||||
class AddressValueNodeChild : public ValueNodeChild {
|
||||
public:
|
||||
AddressValueNodeChild(AddressValueNode* parent,
|
||||
const BString& name, Type* type);
|
||||
virtual ~AddressValueNodeChild();
|
||||
|
||||
virtual const BString& Name() const;
|
||||
virtual Type* GetType() const;
|
||||
virtual ValueNode* Parent() const;
|
||||
|
||||
virtual status_t ResolveLocation(ValueLoader* valueLoader,
|
||||
ValueLocation*& _location);
|
||||
|
||||
private:
|
||||
AddressValueNode* fParent;
|
||||
BString fName;
|
||||
Type* fType;
|
||||
};
|
||||
|
||||
|
||||
#endif // ADDRESS_VALUE_NODE_H
|
||||
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "ArrayValueNode.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "Architecture.h"
|
||||
#include "ArrayIndexPath.h"
|
||||
#include "IntegerValue.h"
|
||||
#include "Tracing.h"
|
||||
#include "Type.h"
|
||||
#include "ValueLoader.h"
|
||||
#include "ValueLocation.h"
|
||||
#include "ValueNodeContainer.h"
|
||||
|
||||
|
||||
// maximum number of array elements to show by default
|
||||
static const uint64 kMaxArrayElementCount = 10;
|
||||
|
||||
|
||||
// #pragma mark - AbstractArrayValueNode
|
||||
|
||||
|
||||
AbstractArrayValueNode::AbstractArrayValueNode(ValueNodeChild* nodeChild,
|
||||
ArrayType* type, int32 dimension)
|
||||
:
|
||||
ValueNode(nodeChild),
|
||||
fType(type),
|
||||
fDimension(dimension)
|
||||
{
|
||||
fType->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
AbstractArrayValueNode::~AbstractArrayValueNode()
|
||||
{
|
||||
fType->ReleaseReference();
|
||||
|
||||
for (int32 i = 0; AbstractArrayValueNodeChild* child = fChildren.ItemAt(i);
|
||||
i++) {
|
||||
child->RemoveReference();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Type*
|
||||
AbstractArrayValueNode::GetType() const
|
||||
{
|
||||
return fType;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
AbstractArrayValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader,
|
||||
ValueLocation*& _location, Value*& _value)
|
||||
{
|
||||
// get the location
|
||||
ValueLocation* location = NodeChild()->Location();
|
||||
if (location == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
location->AcquireReference();
|
||||
_location = location;
|
||||
_value = NULL;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
AbstractArrayValueNode::CreateChildren()
|
||||
{
|
||||
if (!fChildren.IsEmpty())
|
||||
return B_OK;
|
||||
|
||||
TRACE_LOCALS("TYPE_ARRAY\n");
|
||||
|
||||
int32 dimensionCount = fType->CountDimensions();
|
||||
bool isFinalDimension = fDimension + 1 == dimensionCount;
|
||||
|
||||
ArrayDimension* dimension = fType->DimensionAt(fDimension);
|
||||
uint64 elementCount = dimension->CountElements();
|
||||
if (elementCount == 0 || elementCount > kMaxArrayElementCount)
|
||||
elementCount = kMaxArrayElementCount;
|
||||
|
||||
// create children for the array elements
|
||||
for (int32 i = 0; i < (int32)elementCount; i++) {
|
||||
BString name(Name());
|
||||
name << '[' << i << ']';
|
||||
if (name.Length() <= Name().Length())
|
||||
return B_NO_MEMORY;
|
||||
|
||||
AbstractArrayValueNodeChild* child;
|
||||
if (isFinalDimension) {
|
||||
child = new(std::nothrow) ArrayValueNodeChild(this, name, i,
|
||||
fType->BaseType());
|
||||
} else {
|
||||
child = new(std::nothrow) InternalArrayValueNodeChild(this, name, i,
|
||||
fType);
|
||||
}
|
||||
|
||||
if (child == NULL || !fChildren.AddItem(child)) {
|
||||
delete child;
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
child->SetContainer(fContainer);
|
||||
}
|
||||
|
||||
if (fContainer != NULL)
|
||||
fContainer->NotifyValueNodeChildrenCreated(this);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
AbstractArrayValueNode::CountChildren() const
|
||||
{
|
||||
return fChildren.CountItems();
|
||||
}
|
||||
|
||||
|
||||
ValueNodeChild*
|
||||
AbstractArrayValueNode::ChildAt(int32 index) const
|
||||
{
|
||||
return fChildren.ItemAt(index);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - ArrayValueNode
|
||||
|
||||
|
||||
ArrayValueNode::ArrayValueNode(ValueNodeChild* nodeChild, ArrayType* type)
|
||||
:
|
||||
AbstractArrayValueNode(nodeChild, type, 0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ArrayValueNode::~ArrayValueNode()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - InternalArrayValueNode
|
||||
|
||||
|
||||
InternalArrayValueNode::InternalArrayValueNode(ValueNodeChild* nodeChild,
|
||||
ArrayType* type, int32 dimension)
|
||||
:
|
||||
AbstractArrayValueNode(nodeChild, type, dimension)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
InternalArrayValueNode::~InternalArrayValueNode()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - AbstractArrayValueNodeChild
|
||||
|
||||
|
||||
AbstractArrayValueNodeChild::AbstractArrayValueNodeChild(
|
||||
AbstractArrayValueNode* parent, const BString& name, int64 elementIndex)
|
||||
:
|
||||
fParent(parent),
|
||||
fName(name),
|
||||
fElementIndex(elementIndex)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
AbstractArrayValueNodeChild::~AbstractArrayValueNodeChild()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
const BString&
|
||||
AbstractArrayValueNodeChild::Name() const
|
||||
{
|
||||
return fName;
|
||||
}
|
||||
|
||||
|
||||
ValueNode*
|
||||
AbstractArrayValueNodeChild::Parent() const
|
||||
{
|
||||
return fParent;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - ArrayValueNodeChild
|
||||
|
||||
|
||||
ArrayValueNodeChild::ArrayValueNodeChild(AbstractArrayValueNode* parent,
|
||||
const BString& name, int64 elementIndex, Type* type)
|
||||
:
|
||||
AbstractArrayValueNodeChild(parent, name, elementIndex),
|
||||
fType(type)
|
||||
{
|
||||
fType->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
ArrayValueNodeChild::~ArrayValueNodeChild()
|
||||
{
|
||||
fType->ReleaseReference();
|
||||
}
|
||||
|
||||
|
||||
Type*
|
||||
ArrayValueNodeChild::GetType() const
|
||||
{
|
||||
return fType;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ArrayValueNodeChild::ResolveLocation(ValueLoader* valueLoader,
|
||||
ValueLocation*& _location)
|
||||
{
|
||||
// get the parent (== array) location
|
||||
ValueLocation* parentLocation = fParent->Location();
|
||||
if (parentLocation == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// create an array index path
|
||||
ArrayType* arrayType = fParent->GetArrayType();
|
||||
int32 dimensionCount = arrayType->CountDimensions();
|
||||
|
||||
// add dummy indices first -- we'll replace them on our way back through
|
||||
// our ancestors
|
||||
ArrayIndexPath indexPath;
|
||||
for (int32 i = 0; i < dimensionCount; i++) {
|
||||
if (!indexPath.AddIndex(0))
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
AbstractArrayValueNodeChild* child = this;
|
||||
for (int32 i = dimensionCount - 1; i >= 0; i--) {
|
||||
indexPath.SetIndexAt(i, child->ElementIndex());
|
||||
|
||||
child = dynamic_cast<AbstractArrayValueNodeChild*>(
|
||||
child->ArrayParent()->NodeChild());
|
||||
}
|
||||
|
||||
// resolve the element location
|
||||
ValueLocation* location;
|
||||
status_t error = arrayType->ResolveElementLocation(indexPath,
|
||||
*parentLocation, location);
|
||||
if (error != B_OK) {
|
||||
TRACE_LOCALS("ArrayValueNodeChild::ResolveLocation(): "
|
||||
"ResolveElementLocation() failed: %s\n", strerror(error));
|
||||
return error;
|
||||
}
|
||||
|
||||
_location = location;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - InternalArrayValueNodeChild
|
||||
|
||||
|
||||
InternalArrayValueNodeChild::InternalArrayValueNodeChild(
|
||||
AbstractArrayValueNode* parent, const BString& name, int64 elementIndex,
|
||||
ArrayType* type)
|
||||
:
|
||||
AbstractArrayValueNodeChild(parent, name, elementIndex),
|
||||
fType(type)
|
||||
{
|
||||
fType->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
InternalArrayValueNodeChild::~InternalArrayValueNodeChild()
|
||||
{
|
||||
fType->ReleaseReference();
|
||||
}
|
||||
|
||||
|
||||
Type*
|
||||
InternalArrayValueNodeChild::GetType() const
|
||||
{
|
||||
return fType;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
InternalArrayValueNodeChild::IsInternal() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
InternalArrayValueNodeChild::CreateInternalNode(ValueNode*& _node)
|
||||
{
|
||||
ValueNode* node = new(std::nothrow) InternalArrayValueNode(this, fType,
|
||||
fParent->Dimension() + 1);
|
||||
if (node == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
_node = node;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
InternalArrayValueNodeChild::ResolveLocation(ValueLoader* valueLoader,
|
||||
ValueLocation*& _location)
|
||||
{
|
||||
// This is an internal child node for a non-final dimension -- just clone
|
||||
// the parent's location.
|
||||
ValueLocation* parentLocation = fParent->Location();
|
||||
if (parentLocation == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
parentLocation->AcquireReference();
|
||||
_location = parentLocation;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef ARRAY_VALUE_NODE_H
|
||||
#define ARRAY_VALUE_NODE_H
|
||||
|
||||
|
||||
#include <ObjectList.h>
|
||||
|
||||
#include "ValueNode.h"
|
||||
|
||||
|
||||
class AbstractArrayValueNodeChild;
|
||||
class ArrayType;
|
||||
|
||||
|
||||
class AbstractArrayValueNode : public ValueNode {
|
||||
public:
|
||||
AbstractArrayValueNode(
|
||||
ValueNodeChild* nodeChild, ArrayType* type,
|
||||
int32 dimension);
|
||||
virtual ~AbstractArrayValueNode();
|
||||
|
||||
ArrayType* GetArrayType() const
|
||||
{ return fType; }
|
||||
int32 Dimension() const
|
||||
{ return fDimension; }
|
||||
|
||||
virtual Type* GetType() const;
|
||||
|
||||
virtual status_t ResolvedLocationAndValue(
|
||||
ValueLoader* valueLoader,
|
||||
ValueLocation*& _location,
|
||||
Value*& _value);
|
||||
|
||||
// locking required
|
||||
|
||||
virtual status_t CreateChildren();
|
||||
virtual int32 CountChildren() const;
|
||||
virtual ValueNodeChild* ChildAt(int32 index) const;
|
||||
|
||||
protected:
|
||||
typedef BObjectList<AbstractArrayValueNodeChild> ChildList;
|
||||
|
||||
protected:
|
||||
ArrayType* fType;
|
||||
ChildList fChildren;
|
||||
int32 fDimension;
|
||||
};
|
||||
|
||||
|
||||
// TODO: Are ArrayValueNode and InternalArrayValueNode still needed?
|
||||
|
||||
class ArrayValueNode : public AbstractArrayValueNode {
|
||||
public:
|
||||
ArrayValueNode(ValueNodeChild* nodeChild,
|
||||
ArrayType* type);
|
||||
virtual ~ArrayValueNode();
|
||||
};
|
||||
|
||||
|
||||
class InternalArrayValueNode : public AbstractArrayValueNode {
|
||||
public:
|
||||
InternalArrayValueNode(
|
||||
ValueNodeChild* nodeChild,
|
||||
ArrayType* type, int32 dimension);
|
||||
virtual ~InternalArrayValueNode();
|
||||
};
|
||||
|
||||
|
||||
class AbstractArrayValueNodeChild : public ValueNodeChild {
|
||||
public:
|
||||
AbstractArrayValueNodeChild(
|
||||
AbstractArrayValueNode* parent,
|
||||
const BString& name, int64 elementIndex);
|
||||
virtual ~AbstractArrayValueNodeChild();
|
||||
|
||||
AbstractArrayValueNode* ArrayParent() const { return fParent; }
|
||||
int32 ElementIndex() const { return fElementIndex; }
|
||||
|
||||
virtual const BString& Name() const;
|
||||
virtual ValueNode* Parent() const;
|
||||
|
||||
protected:
|
||||
AbstractArrayValueNode* fParent;
|
||||
BString fName;
|
||||
int64 fElementIndex;
|
||||
};
|
||||
|
||||
|
||||
class ArrayValueNodeChild : public AbstractArrayValueNodeChild {
|
||||
public:
|
||||
ArrayValueNodeChild(
|
||||
AbstractArrayValueNode* parent,
|
||||
const BString& name, int64 elementIndex,
|
||||
Type* type);
|
||||
virtual ~ArrayValueNodeChild();
|
||||
|
||||
virtual Type* GetType() const;
|
||||
|
||||
virtual status_t ResolveLocation(ValueLoader* valueLoader,
|
||||
ValueLocation*& _location);
|
||||
|
||||
private:
|
||||
Type* fType;
|
||||
};
|
||||
|
||||
|
||||
class InternalArrayValueNodeChild : public AbstractArrayValueNodeChild {
|
||||
public:
|
||||
InternalArrayValueNodeChild(
|
||||
AbstractArrayValueNode* parent,
|
||||
const BString& name, int64 elementIndex,
|
||||
ArrayType* type);
|
||||
virtual ~InternalArrayValueNodeChild();
|
||||
|
||||
virtual Type* GetType() const;
|
||||
|
||||
virtual bool IsInternal() const;
|
||||
virtual status_t CreateInternalNode(ValueNode*& _node);
|
||||
|
||||
virtual status_t ResolveLocation(ValueLoader* valueLoader,
|
||||
ValueLocation*& _location);
|
||||
|
||||
private:
|
||||
ArrayType* fType;
|
||||
};
|
||||
|
||||
|
||||
#endif // ARRAY_VALUE_NODE_H
|
||||
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "CompoundValueNode.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "Architecture.h"
|
||||
#include "IntegerValue.h"
|
||||
#include "Tracing.h"
|
||||
#include "Type.h"
|
||||
#include "ValueLoader.h"
|
||||
#include "ValueLocation.h"
|
||||
#include "ValueNodeContainer.h"
|
||||
|
||||
|
||||
// #pragma mark - Child
|
||||
|
||||
|
||||
class CompoundValueNode::Child : public ValueNodeChild {
|
||||
public:
|
||||
Child(CompoundValueNode* parent, const BString& name)
|
||||
:
|
||||
fParent(parent),
|
||||
fName(name)
|
||||
{
|
||||
}
|
||||
|
||||
virtual const BString& Name() const
|
||||
{
|
||||
return fName;
|
||||
}
|
||||
|
||||
virtual ValueNode* Parent() const
|
||||
{
|
||||
return fParent;
|
||||
}
|
||||
|
||||
protected:
|
||||
CompoundValueNode* fParent;
|
||||
BString fName;
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - BaseTypeChild
|
||||
|
||||
|
||||
class CompoundValueNode::BaseTypeChild : public Child {
|
||||
public:
|
||||
BaseTypeChild(CompoundValueNode* parent, BaseType* baseType)
|
||||
:
|
||||
Child(parent, baseType->GetType()->Name()),
|
||||
fBaseType(baseType)
|
||||
{
|
||||
fBaseType->AcquireReference();
|
||||
}
|
||||
|
||||
virtual ~BaseTypeChild()
|
||||
{
|
||||
fBaseType->ReleaseReference();
|
||||
}
|
||||
|
||||
virtual Type* GetType() const
|
||||
{
|
||||
return fBaseType->GetType();
|
||||
}
|
||||
|
||||
virtual status_t ResolveLocation(ValueLoader* valueLoader,
|
||||
ValueLocation*& _location)
|
||||
{
|
||||
// The parent's location refers to the location of the complete
|
||||
// object. We want to extract the location of a member.
|
||||
ValueLocation* parentLocation = fParent->Location();
|
||||
if (parentLocation == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
ValueLocation* location;
|
||||
status_t error = fParent->fType->ResolveBaseTypeLocation(fBaseType,
|
||||
*parentLocation, location);
|
||||
if (error != B_OK) {
|
||||
TRACE_LOCALS("CompoundValueNode::BaseTypeChild::ResolveLocation(): "
|
||||
"ResolveBaseTypeLocation() failed: %s\n", strerror(error));
|
||||
return error;
|
||||
}
|
||||
|
||||
_location = location;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
BaseType* fBaseType;
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - MemberChild
|
||||
|
||||
|
||||
class CompoundValueNode::MemberChild : public Child {
|
||||
public:
|
||||
MemberChild(CompoundValueNode* parent, DataMember* member)
|
||||
:
|
||||
Child(parent, member->Name()),
|
||||
fMember(member)
|
||||
{
|
||||
fMember->AcquireReference();
|
||||
}
|
||||
|
||||
virtual ~MemberChild()
|
||||
{
|
||||
fMember->ReleaseReference();
|
||||
}
|
||||
|
||||
virtual Type* GetType() const
|
||||
{
|
||||
return fMember->GetType();
|
||||
}
|
||||
|
||||
virtual status_t ResolveLocation(ValueLoader* valueLoader,
|
||||
ValueLocation*& _location)
|
||||
{
|
||||
// The parent's location refers to the location of the complete
|
||||
// object. We want to extract the location of a member.
|
||||
ValueLocation* parentLocation = fParent->Location();
|
||||
if (parentLocation == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
ValueLocation* location;
|
||||
status_t error = fParent->fType->ResolveDataMemberLocation(fMember,
|
||||
*parentLocation, location);
|
||||
if (error != B_OK) {
|
||||
TRACE_LOCALS("CompoundValueNode::MemberChild::ResolveLocation(): "
|
||||
"ResolveDataMemberLocation() failed: %s\n", strerror(error));
|
||||
return error;
|
||||
}
|
||||
|
||||
_location = location;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
DataMember* fMember;
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - CompoundValueNode
|
||||
|
||||
|
||||
CompoundValueNode::CompoundValueNode(ValueNodeChild* nodeChild,
|
||||
CompoundType* type)
|
||||
:
|
||||
ValueNode(nodeChild),
|
||||
fType(type)
|
||||
{
|
||||
fType->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
CompoundValueNode::~CompoundValueNode()
|
||||
{
|
||||
fType->ReleaseReference();
|
||||
|
||||
for (int32 i = 0; Child* child = fChildren.ItemAt(i); i++)
|
||||
child->RemoveReference();
|
||||
}
|
||||
|
||||
|
||||
Type*
|
||||
CompoundValueNode::GetType() const
|
||||
{
|
||||
return fType;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
CompoundValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader,
|
||||
ValueLocation*& _location, Value*& _value)
|
||||
{
|
||||
// get the location
|
||||
ValueLocation* location = NodeChild()->Location();
|
||||
if (location == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
location->AcquireReference();
|
||||
_location = location;
|
||||
_value = NULL;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
CompoundValueNode::CreateChildren()
|
||||
{
|
||||
if (!fChildren.IsEmpty())
|
||||
return B_OK;
|
||||
|
||||
// base types
|
||||
for (int32 i = 0; BaseType* baseType = fType->BaseTypeAt(i); i++) {
|
||||
TRACE_LOCALS(" base %ld\n", i);
|
||||
|
||||
BaseTypeChild* child = new(std::nothrow) BaseTypeChild(this, baseType);
|
||||
if (child == NULL || !fChildren.AddItem(child)) {
|
||||
delete child;
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
child->SetContainer(fContainer);
|
||||
}
|
||||
|
||||
// members
|
||||
for (int32 i = 0; DataMember* member = fType->DataMemberAt(i); i++) {
|
||||
TRACE_LOCALS(" member %ld: \"%s\"\n", i, member->Name());
|
||||
|
||||
MemberChild* child = new(std::nothrow) MemberChild(this, member);
|
||||
if (child == NULL || !fChildren.AddItem(child)) {
|
||||
delete child;
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
child->SetContainer(fContainer);
|
||||
}
|
||||
|
||||
if (fContainer != NULL)
|
||||
fContainer->NotifyValueNodeChildrenCreated(this);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
CompoundValueNode::CountChildren() const
|
||||
{
|
||||
return fChildren.CountItems();
|
||||
}
|
||||
|
||||
|
||||
ValueNodeChild*
|
||||
CompoundValueNode::ChildAt(int32 index) const
|
||||
{
|
||||
return fChildren.ItemAt(index);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef COMPOUND_VALUE_NODE_H
|
||||
#define COMPOUND_VALUE_NODE_H
|
||||
|
||||
|
||||
#include <ObjectList.h>
|
||||
|
||||
#include "ValueNode.h"
|
||||
|
||||
|
||||
class CompoundType;
|
||||
|
||||
|
||||
class CompoundValueNode : public ValueNode {
|
||||
public:
|
||||
CompoundValueNode(ValueNodeChild* nodeChild,
|
||||
CompoundType* type);
|
||||
virtual ~CompoundValueNode();
|
||||
|
||||
virtual Type* GetType() const;
|
||||
|
||||
virtual status_t ResolvedLocationAndValue(
|
||||
ValueLoader* valueLoader,
|
||||
ValueLocation*& _location,
|
||||
Value*& _value);
|
||||
|
||||
// locking required
|
||||
|
||||
virtual status_t CreateChildren();
|
||||
virtual int32 CountChildren() const;
|
||||
virtual ValueNodeChild* ChildAt(int32 index) const;
|
||||
|
||||
private:
|
||||
class Child;
|
||||
class BaseTypeChild;
|
||||
class MemberChild;
|
||||
|
||||
typedef BObjectList<Child> ChildList;
|
||||
|
||||
private:
|
||||
CompoundType* fType;
|
||||
ChildList fChildren;
|
||||
};
|
||||
|
||||
|
||||
#endif // ADDRESS_VALUE_NODE_H
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "EnumerationValueNode.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "EnumerationValue.h"
|
||||
#include "Tracing.h"
|
||||
#include "Type.h"
|
||||
#include "ValueLoader.h"
|
||||
#include "ValueLocation.h"
|
||||
|
||||
|
||||
EnumerationValueNode::EnumerationValueNode(ValueNodeChild* nodeChild,
|
||||
EnumerationType* type)
|
||||
:
|
||||
ChildlessValueNode(nodeChild),
|
||||
fType(type)
|
||||
{
|
||||
fType->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
EnumerationValueNode::~EnumerationValueNode()
|
||||
{
|
||||
fType->ReleaseReference();
|
||||
}
|
||||
|
||||
|
||||
Type*
|
||||
EnumerationValueNode::GetType() const
|
||||
{
|
||||
return fType;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
EnumerationValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader,
|
||||
ValueLocation*& _location, Value*& _value)
|
||||
{
|
||||
// get the location
|
||||
ValueLocation* location = NodeChild()->Location();
|
||||
if (location == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
TRACE_LOCALS(" TYPE_ENUMERATION\n");
|
||||
|
||||
// get the value type
|
||||
type_code valueType = 0;
|
||||
|
||||
// If a base type is known, try that.
|
||||
if (PrimitiveType* baseType = dynamic_cast<PrimitiveType*>(
|
||||
fType->BaseType())) {
|
||||
valueType = baseType->TypeConstant();
|
||||
if (!BVariant::TypeIsInteger(valueType))
|
||||
valueType = 0;
|
||||
}
|
||||
|
||||
// If we don't have a value type yet, guess it from the type size.
|
||||
if (valueType == 0) {
|
||||
// TODO: This is C source language specific!
|
||||
switch (fType->ByteSize()) {
|
||||
case 1:
|
||||
valueType = B_INT8_TYPE;
|
||||
break;
|
||||
case 2:
|
||||
valueType = B_INT16_TYPE;
|
||||
break;
|
||||
case 4:
|
||||
default:
|
||||
valueType = B_INT32_TYPE;
|
||||
break;
|
||||
case 8:
|
||||
valueType = B_INT64_TYPE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// load the value data
|
||||
BVariant valueData;
|
||||
status_t error = valueLoader->LoadValue(location, valueType, true,
|
||||
valueData);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
// create the type object
|
||||
Value* value = new(std::nothrow) EnumerationValue(fType, valueData);
|
||||
if (value == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
location->AcquireReference();
|
||||
_location = location;
|
||||
_value = value;
|
||||
return B_OK;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef ENUMERATION_VALUE_NODE_H
|
||||
#define ENUMERATION_VALUE_NODE_H
|
||||
|
||||
|
||||
#include "ValueNode.h"
|
||||
|
||||
|
||||
class EnumerationType;
|
||||
|
||||
|
||||
class EnumerationValueNode : public ChildlessValueNode {
|
||||
public:
|
||||
EnumerationValueNode(ValueNodeChild* nodeChild,
|
||||
EnumerationType* type);
|
||||
virtual ~EnumerationValueNode();
|
||||
|
||||
virtual Type* GetType() const;
|
||||
|
||||
virtual status_t ResolvedLocationAndValue(
|
||||
ValueLoader* valueLoader,
|
||||
ValueLocation*& _location,
|
||||
Value*& _value);
|
||||
|
||||
private:
|
||||
EnumerationType* fType;
|
||||
};
|
||||
|
||||
|
||||
#endif // ENUMERATION_VALUE_NODE_H
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "PointerToMemberValueNode.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "Architecture.h"
|
||||
#include "IntegerValue.h"
|
||||
#include "Tracing.h"
|
||||
#include "Type.h"
|
||||
#include "ValueLoader.h"
|
||||
#include "ValueLocation.h"
|
||||
|
||||
|
||||
PointerToMemberValueNode::PointerToMemberValueNode(ValueNodeChild* nodeChild,
|
||||
PointerToMemberType* type)
|
||||
:
|
||||
ChildlessValueNode(nodeChild),
|
||||
fType(type)
|
||||
{
|
||||
fType->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
PointerToMemberValueNode::~PointerToMemberValueNode()
|
||||
{
|
||||
fType->ReleaseReference();
|
||||
}
|
||||
|
||||
|
||||
Type*
|
||||
PointerToMemberValueNode::GetType() const
|
||||
{
|
||||
return fType;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PointerToMemberValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader,
|
||||
ValueLocation*& _location, Value*& _value)
|
||||
{
|
||||
// get the location
|
||||
ValueLocation* location = NodeChild()->Location();
|
||||
if (location == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
TRACE_LOCALS(" TYPE_POINTER_TO_MEMBER\n");
|
||||
|
||||
// get the value type
|
||||
type_code valueType;
|
||||
if (valueLoader->GetArchitecture()->AddressSize() == 4) {
|
||||
valueType = B_UINT32_TYPE;
|
||||
TRACE_LOCALS(" -> 32 bit\n");
|
||||
} else {
|
||||
valueType = B_UINT64_TYPE;
|
||||
TRACE_LOCALS(" -> 64 bit\n");
|
||||
}
|
||||
|
||||
// load the value data
|
||||
BVariant valueData;
|
||||
status_t error = valueLoader->LoadValue(location, valueType, false,
|
||||
valueData);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
// create the type object
|
||||
Value* value = new(std::nothrow) IntegerValue(valueData);
|
||||
if (value == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
location->AcquireReference();
|
||||
_location = location;
|
||||
_value = value;
|
||||
return B_OK;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef POINTER_TO_MEMBER_VALUE_NODE_H
|
||||
#define POINTER_TO_MEMBER_VALUE_NODE_H
|
||||
|
||||
|
||||
#include "ValueNode.h"
|
||||
|
||||
|
||||
class PointerToMemberType;
|
||||
|
||||
|
||||
class PointerToMemberValueNode : public ChildlessValueNode {
|
||||
public:
|
||||
PointerToMemberValueNode(
|
||||
ValueNodeChild* nodeChild,
|
||||
PointerToMemberType* type);
|
||||
virtual ~PointerToMemberValueNode();
|
||||
|
||||
virtual Type* GetType() const;
|
||||
|
||||
virtual status_t ResolvedLocationAndValue(
|
||||
ValueLoader* valueLoader,
|
||||
ValueLocation*& _location,
|
||||
Value*& _value);
|
||||
|
||||
private:
|
||||
PointerToMemberType* fType;
|
||||
};
|
||||
|
||||
|
||||
#endif // POINTER_TO_MEMBER_VALUE_NODE_H
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "PrimitiveValueNode.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "BoolValue.h"
|
||||
#include "FloatValue.h"
|
||||
#include "IntegerValue.h"
|
||||
#include "Tracing.h"
|
||||
#include "Type.h"
|
||||
#include "ValueLoader.h"
|
||||
#include "ValueLocation.h"
|
||||
|
||||
|
||||
PrimitiveValueNode::PrimitiveValueNode(ValueNodeChild* nodeChild,
|
||||
PrimitiveType* type)
|
||||
:
|
||||
ChildlessValueNode(nodeChild),
|
||||
fType(type)
|
||||
{
|
||||
fType->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
PrimitiveValueNode::~PrimitiveValueNode()
|
||||
{
|
||||
fType->ReleaseReference();
|
||||
}
|
||||
|
||||
|
||||
Type*
|
||||
PrimitiveValueNode::GetType() const
|
||||
{
|
||||
return fType;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PrimitiveValueNode::ResolvedLocationAndValue(ValueLoader* valueLoader,
|
||||
ValueLocation*& _location, Value*& _value)
|
||||
{
|
||||
// get the location
|
||||
ValueLocation* location = NodeChild()->Location();
|
||||
if (location == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// get the value type
|
||||
type_code valueType = fType->TypeConstant();
|
||||
if (!BVariant::TypeIsNumber(valueType) && valueType != B_BOOL_TYPE) {
|
||||
TRACE_LOCALS(" -> unknown type constant\n");
|
||||
return B_UNSUPPORTED;
|
||||
}
|
||||
|
||||
bool shortValueIsFine = BVariant::TypeIsInteger(valueType)
|
||||
|| valueType == B_BOOL_TYPE;
|
||||
|
||||
TRACE_LOCALS(" TYPE_PRIMITIVE: '%c%c%c%c'\n",
|
||||
int(valueType >> 24), int(valueType >> 16),
|
||||
int(valueType >> 8), int(valueType));
|
||||
|
||||
// load the value data
|
||||
BVariant valueData;
|
||||
status_t error = valueLoader->LoadValue(location, valueType,
|
||||
shortValueIsFine, valueData);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
// create the type object
|
||||
Value* value;
|
||||
if (valueType == B_BOOL_TYPE)
|
||||
value = new(std::nothrow) BoolValue(valueData.ToBool());
|
||||
else if (BVariant::TypeIsInteger(valueType))
|
||||
value = new(std::nothrow) IntegerValue(valueData);
|
||||
else if (BVariant::TypeIsFloat(valueType))
|
||||
value = new(std::nothrow) FloatValue(valueData.ToDouble());
|
||||
else
|
||||
return B_UNSUPPORTED;
|
||||
|
||||
if (value == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
location->AcquireReference();
|
||||
_location = location;
|
||||
_value = value;
|
||||
return B_OK;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef PRIMITIVE_VALUE_NODE_H
|
||||
#define PRIMITIVE_VALUE_NODE_H
|
||||
|
||||
|
||||
#include "ValueNode.h"
|
||||
|
||||
|
||||
class PrimitiveType;
|
||||
|
||||
|
||||
class PrimitiveValueNode : public ChildlessValueNode {
|
||||
public:
|
||||
PrimitiveValueNode(ValueNodeChild* nodeChild,
|
||||
PrimitiveType* type);
|
||||
virtual ~PrimitiveValueNode();
|
||||
|
||||
virtual Type* GetType() const;
|
||||
|
||||
virtual status_t ResolvedLocationAndValue(
|
||||
ValueLoader* valueLoader,
|
||||
ValueLocation*& _location,
|
||||
Value*& _value);
|
||||
|
||||
private:
|
||||
PrimitiveType* fType;
|
||||
};
|
||||
|
||||
|
||||
#endif // PRIMITIVE_VALUE_NODE_H
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "VariableValueNodeChild.h"
|
||||
|
||||
#include "Variable.h"
|
||||
#include "ValueLocation.h"
|
||||
|
||||
|
||||
VariableValueNodeChild::VariableValueNodeChild(Variable* variable)
|
||||
:
|
||||
fVariable(variable)
|
||||
{
|
||||
fVariable->AcquireReference();
|
||||
SetLocation(fVariable->Location(), B_OK);
|
||||
}
|
||||
|
||||
|
||||
VariableValueNodeChild::~VariableValueNodeChild()
|
||||
{
|
||||
fVariable->ReleaseReference();
|
||||
}
|
||||
|
||||
|
||||
const BString&
|
||||
VariableValueNodeChild::Name() const
|
||||
{
|
||||
return fVariable->Name();
|
||||
}
|
||||
|
||||
|
||||
Type*
|
||||
VariableValueNodeChild::GetType() const
|
||||
{
|
||||
return fVariable->GetType();
|
||||
}
|
||||
|
||||
|
||||
ValueNode*
|
||||
VariableValueNodeChild::Parent() const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
VariableValueNodeChild::ResolveLocation(ValueLoader* valueLoader,
|
||||
ValueLocation*& _location)
|
||||
{
|
||||
_location = fVariable->Location();
|
||||
_location->AcquireReference();
|
||||
return B_OK;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef VARIABLE_VALUE_NODE_CHILD_H
|
||||
#define VARIABLE_VALUE_NODE_CHILD_H
|
||||
|
||||
|
||||
#include "ValueNode.h"
|
||||
|
||||
|
||||
class Variable;
|
||||
|
||||
|
||||
class VariableValueNodeChild : public ValueNodeChild {
|
||||
public:
|
||||
VariableValueNodeChild(Variable* variable);
|
||||
virtual ~VariableValueNodeChild();
|
||||
|
||||
virtual const BString& Name() const;
|
||||
virtual Type* GetType() const;
|
||||
virtual ValueNode* Parent() const;
|
||||
|
||||
virtual status_t ResolveLocation(ValueLoader* valueLoader,
|
||||
ValueLocation*& _location);
|
||||
|
||||
private:
|
||||
Variable* fVariable;
|
||||
};
|
||||
|
||||
|
||||
#endif // VARIABLE_VALUE_NODE_CHILD_H
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "AddressValue.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
AddressValue::AddressValue(const BVariant& value)
|
||||
:
|
||||
IntegerValue(value)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
AddressValue::~AddressValue()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
AddressValue::ToString(BString& _string) const
|
||||
{
|
||||
if (!fValue.IsInteger())
|
||||
return false;
|
||||
|
||||
char buffer[32];
|
||||
snprintf(buffer, sizeof(buffer), "%#llx", fValue.ToUInt64());
|
||||
|
||||
BString string(buffer);
|
||||
if (string.Length() == 0)
|
||||
return false;
|
||||
|
||||
_string = string;
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef ADDRESS_VALUE_H
|
||||
#define ADDRESS_VALUE_H
|
||||
|
||||
|
||||
#include "IntegerValue.h"
|
||||
|
||||
|
||||
class AddressValue : public IntegerValue {
|
||||
public:
|
||||
AddressValue(const BVariant& value);
|
||||
virtual ~AddressValue();
|
||||
|
||||
virtual bool ToString(BString& _string) const;
|
||||
};
|
||||
|
||||
|
||||
#endif // ADDRESS_VALUE_H
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "BoolValue.h"
|
||||
|
||||
|
||||
BoolValue::BoolValue(bool value)
|
||||
:
|
||||
fValue(value)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BoolValue::~BoolValue()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BoolValue::ToString(BString& _string) const
|
||||
{
|
||||
BString string = fValue ? "true" : "false";
|
||||
if (string.Length() == 0)
|
||||
return false;
|
||||
|
||||
_string = string;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BoolValue::ToVariant(BVariant& _value) const
|
||||
{
|
||||
_value = fValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BoolValue::operator==(const Value& other) const
|
||||
{
|
||||
const BoolValue* otherBool = dynamic_cast<const BoolValue*>(&other);
|
||||
return otherBool != NULL ? fValue == otherBool->fValue : false;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef BOOL_VALUE_H
|
||||
#define BOOL_VALUE_H
|
||||
|
||||
|
||||
#include "Value.h"
|
||||
|
||||
|
||||
class BoolValue : public Value {
|
||||
public:
|
||||
BoolValue(bool value);
|
||||
virtual ~BoolValue();
|
||||
|
||||
bool GetValue() const
|
||||
{ return fValue; }
|
||||
|
||||
virtual bool ToString(BString& _string) const;
|
||||
virtual bool ToVariant(BVariant& _value) const;
|
||||
|
||||
virtual bool operator==(const Value& other) const;
|
||||
|
||||
private:
|
||||
bool fValue;
|
||||
};
|
||||
|
||||
|
||||
#endif // BOOL_VALUE_H
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "EnumerationValue.h"
|
||||
|
||||
#include "Type.h"
|
||||
|
||||
|
||||
EnumerationValue::EnumerationValue(EnumerationType* type, const BVariant& value)
|
||||
:
|
||||
IntegerValue(value),
|
||||
fType(type)
|
||||
{
|
||||
fType->AcquireReference();
|
||||
}
|
||||
|
||||
|
||||
EnumerationValue::~EnumerationValue()
|
||||
{
|
||||
fType->ReleaseReference();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
EnumerationValue::ToString(BString& _string) const
|
||||
{
|
||||
if (!fValue.IsInteger())
|
||||
return false;
|
||||
|
||||
EnumeratorValue* enumValue = fType->ValueFor(fValue);
|
||||
if (enumValue == NULL)
|
||||
return IntegerValue::ToString(_string);
|
||||
|
||||
BString string(enumValue->Name());
|
||||
if (string.Length() == 0)
|
||||
return false;
|
||||
|
||||
_string = string;
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef ENUMERATION_VALUE_H
|
||||
#define ENUMERATION_VALUE_H
|
||||
|
||||
|
||||
#include "IntegerValue.h"
|
||||
|
||||
|
||||
class EnumerationType;
|
||||
|
||||
|
||||
class EnumerationValue : public IntegerValue {
|
||||
public:
|
||||
EnumerationValue(EnumerationType* type,
|
||||
const BVariant& value);
|
||||
virtual ~EnumerationValue();
|
||||
|
||||
EnumerationType* GetType() const
|
||||
{ return fType; }
|
||||
|
||||
virtual bool ToString(BString& _string) const;
|
||||
|
||||
private:
|
||||
EnumerationType* fType;
|
||||
};
|
||||
|
||||
|
||||
#endif // ENUMERATION_VALUE_H
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "FloatValue.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
FloatValue::FloatValue(double value)
|
||||
:
|
||||
fValue(value)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
FloatValue::~FloatValue()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
FloatValue::ToString(BString& _string) const
|
||||
{
|
||||
char buffer[128];
|
||||
snprintf(buffer, sizeof(buffer), "%g", fValue);
|
||||
|
||||
BString string(buffer);
|
||||
if (string.Length() == 0)
|
||||
return false;
|
||||
|
||||
_string = string;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
FloatValue::ToVariant(BVariant& _value) const
|
||||
{
|
||||
_value = fValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
FloatValue::operator==(const Value& other) const
|
||||
{
|
||||
const FloatValue* otherInt = dynamic_cast<const FloatValue*>(&other);
|
||||
return otherInt != NULL ? fValue == otherInt->fValue : false;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef FLOAT_VALUE_H
|
||||
#define FLOAT_VALUE_H
|
||||
|
||||
|
||||
#include "Value.h"
|
||||
|
||||
|
||||
class FloatValue : public Value {
|
||||
public:
|
||||
FloatValue(double value);
|
||||
virtual ~FloatValue();
|
||||
|
||||
double GetValue() const
|
||||
{ return fValue; }
|
||||
|
||||
virtual bool ToString(BString& _string) const;
|
||||
virtual bool ToVariant(BVariant& _value) const;
|
||||
|
||||
virtual bool operator==(const Value& other) const;
|
||||
|
||||
private:
|
||||
double fValue;
|
||||
};
|
||||
|
||||
|
||||
#endif // FLOAT_VALUE_H
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "IntegerValue.h"
|
||||
|
||||
|
||||
IntegerValue::IntegerValue(const BVariant& value)
|
||||
:
|
||||
fValue(value)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
IntegerValue::~IntegerValue()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
IntegerValue::IsSigned() const
|
||||
{
|
||||
bool isSigned;
|
||||
return fValue.IsInteger(&isSigned) && isSigned;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
IntegerValue::ToString(BString& _string) const
|
||||
{
|
||||
bool isSigned;
|
||||
if (!fValue.IsInteger(&isSigned))
|
||||
return false;
|
||||
|
||||
BString string;
|
||||
if (isSigned)
|
||||
string << fValue.ToInt64();
|
||||
else
|
||||
string << fValue.ToUInt64();
|
||||
|
||||
if (string.Length() == 0)
|
||||
return false;
|
||||
|
||||
_string = string;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
IntegerValue::ToVariant(BVariant& _value) const
|
||||
{
|
||||
_value = fValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
IntegerValue::operator==(const Value& other) const
|
||||
{
|
||||
const IntegerValue* otherInt = dynamic_cast<const IntegerValue*>(&other);
|
||||
return otherInt != NULL ? fValue == otherInt->fValue : false;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef INTEGER_VALUE_H
|
||||
#define INTEGER_VALUE_H
|
||||
|
||||
|
||||
#include "Value.h"
|
||||
|
||||
|
||||
class IntegerValue : public Value {
|
||||
public:
|
||||
IntegerValue(const BVariant& value);
|
||||
virtual ~IntegerValue();
|
||||
|
||||
bool IsSigned() const;
|
||||
|
||||
int64 ToInt64() const
|
||||
{ return fValue.ToInt64(); }
|
||||
uint64 ToUInt64() const
|
||||
{ return fValue.ToUInt64(); }
|
||||
const BVariant& GetValue() const
|
||||
{ return fValue; }
|
||||
|
||||
virtual bool ToString(BString& _string) const;
|
||||
virtual bool ToVariant(BVariant& _value) const;
|
||||
|
||||
virtual bool operator==(const Value& other) const;
|
||||
|
||||
protected:
|
||||
BVariant fValue;
|
||||
};
|
||||
|
||||
|
||||
#endif // INTEGER_VALUE_H
|
||||
Reference in New Issue
Block a user