diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 0d245d92ae..fb8e1a8d82 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -27,6 +27,7 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui util ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui value ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) util ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) value ] ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) value type_handlers ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) value value_handlers ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) value value_nodes ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) value values ] ; @@ -210,17 +211,22 @@ Application Debugger : ValueNode.cpp ValueNodeContainer.cpp + # value/type_handlers + CStringTypeHandler.cpp + # value/value_handlers AddressValueHandler.cpp BoolValueHandler.cpp EnumerationValueHandler.cpp FloatValueHandler.cpp IntegerValueHandler.cpp + StringValueHandler.cpp # value/value_nodes AddressValueNode.cpp ArrayValueNode.cpp CompoundValueNode.cpp + CStringValueNode.cpp EnumerationValueNode.cpp PointerToMemberValueNode.cpp PrimitiveValueNode.cpp @@ -232,6 +238,7 @@ Application Debugger : EnumerationValue.cpp FloatValue.cpp IntegerValue.cpp + StringValue.cpp : Debugger_demangler.o diff --git a/src/apps/debugger/user_interface/gui/value/TableCellStringRenderer.cpp b/src/apps/debugger/user_interface/gui/value/TableCellStringRenderer.cpp index b6f8ac538b..02d6f8dee2 100644 --- a/src/apps/debugger/user_interface/gui/value/TableCellStringRenderer.cpp +++ b/src/apps/debugger/user_interface/gui/value/TableCellStringRenderer.cpp @@ -6,6 +6,8 @@ #include "TableCellStringRenderer.h" +#include + #include #include "TableCellValueRendererUtils.h" @@ -16,9 +18,50 @@ void TableCellStringRenderer::RenderValue(Value* value, BRect rect, BView* targetView) { - BString string; - if (!value->ToString(string)) + BString string = "\""; + BString tempString; + if (!value->ToString(tempString)) return; + for (int32 i = 0; i < tempString.Length(); i++) { + if (tempString[i] < 31) { + switch (tempString[i]) { + case '\0': + string << "\\0"; + break; + case '\a': + string << "\\a"; + break; + case '\b': + string << "\\b"; + break; + case '\t': + string << "\\t"; + break; + case '\r': + string << "\\r"; + break; + case '\n': + string << "\\n"; + break; + case '\f': + string << "\\f"; + break; + default: + { + char buffer[5]; + snprintf(buffer, sizeof(buffer), "\\x%x", + tempString.String()[i]); + string << buffer; + break; + } + } + } else if (tempString[i] == '\"') + string << "\\\""; + else + string << tempString[i]; + } + + string += "\""; TableCellValueRendererUtils::DrawString(targetView, rect, string, B_ALIGN_LEFT, true); diff --git a/src/apps/debugger/value/TypeHandlerRoster.cpp b/src/apps/debugger/value/TypeHandlerRoster.cpp index d4ae215567..43b1139d6d 100644 --- a/src/apps/debugger/value/TypeHandlerRoster.cpp +++ b/src/apps/debugger/value/TypeHandlerRoster.cpp @@ -14,6 +14,7 @@ #include "AddressValueNode.h" #include "ArrayValueNode.h" #include "CompoundValueNode.h" +#include "CStringTypeHandler.h" #include "EnumerationValueNode.h" #include "PointerToMemberValueNode.h" #include "PrimitiveValueNode.h" @@ -140,6 +141,11 @@ TypeHandlerRoster::RegisterDefaultHandlers() REGISTER_HANDLER(PointerToMember); REGISTER_HANDLER(Primitive); + handler = new(std::nothrow) CStringTypeHandler(); + handlerReference.SetTo(handler, true); + if (handler == NULL || !RegisterHandler(handler)) + return B_NO_MEMORY; + return B_OK; } diff --git a/src/apps/debugger/value/ValueHandlerRoster.cpp b/src/apps/debugger/value/ValueHandlerRoster.cpp index dd517397e0..8e17bdca3e 100644 --- a/src/apps/debugger/value/ValueHandlerRoster.cpp +++ b/src/apps/debugger/value/ValueHandlerRoster.cpp @@ -15,6 +15,7 @@ #include "BoolValueHandler.h" #include "EnumerationValueHandler.h" #include "FloatValueHandler.h" +#include "StringValueHandler.h" #include "Value.h" @@ -106,6 +107,7 @@ ValueHandlerRoster::RegisterDefaultHandlers() REGISTER_HANDLER(Enumeration) REGISTER_HANDLER(Float) REGISTER_HANDLER(Integer) + REGISTER_HANDLER(String) return B_OK; } diff --git a/src/apps/debugger/value/ValueLoader.cpp b/src/apps/debugger/value/ValueLoader.cpp index 75d53da3e3..adbefe3f89 100644 --- a/src/apps/debugger/value/ValueLoader.cpp +++ b/src/apps/debugger/value/ValueLoader.cpp @@ -185,3 +185,14 @@ ValueLoader::LoadValue(ValueLocation* location, type_code valueType, _value = value; return B_OK; } + + +status_t +ValueLoader::LoadStringValue(BVariant& location, type_code valueType, + BString& _value) +{ + static const size_t kMaxStringSize = 255; + + return fTeamMemory->ReadMemoryString(location.ToUInt64(), kMaxStringSize, + _value); +} diff --git a/src/apps/debugger/value/ValueLoader.h b/src/apps/debugger/value/ValueLoader.h index b69f89f9b2..2228f21c64 100644 --- a/src/apps/debugger/value/ValueLoader.h +++ b/src/apps/debugger/value/ValueLoader.h @@ -31,6 +31,10 @@ public: type_code valueType, bool shortValueIsFine, BVariant& _value); + status_t LoadStringValue(BVariant& location, + type_code valueType, + BString& _value); + private: Architecture* fArchitecture; TeamMemory* fTeamMemory; diff --git a/src/apps/debugger/value/type_handlers/CStringTypeHandler.cpp b/src/apps/debugger/value/type_handlers/CStringTypeHandler.cpp new file mode 100644 index 0000000000..1e957a6e0c --- /dev/null +++ b/src/apps/debugger/value/type_handlers/CStringTypeHandler.cpp @@ -0,0 +1,70 @@ +/* + * Copyright 2010, Rene Gollent, rene@gollent.com + * Distributed under the terms of the MIT License. + */ + + +#include "CStringTypeHandler.h" + +#include + +#include + +#include "CStringValueNode.h" +#include "Type.h" + + +CStringTypeHandler::~CStringTypeHandler() +{ +} + + +float +CStringTypeHandler::SupportsType(Type* type) +{ + AddressType* addressType = dynamic_cast(type); + if (addressType != NULL && addressType->AddressKind() + == DERIVED_TYPE_POINTER) { + PrimitiveType* baseType = dynamic_cast( + addressType->BaseType()); + + if (baseType == NULL) { + ModifiedType* modifiedType = dynamic_cast( + addressType->BaseType()); + if (modifiedType == NULL) + return 0.0f; + + baseType = dynamic_cast( + modifiedType->ResolveRawType(false)); + if (baseType == NULL) + return 0.0f; + } + + if (baseType->TypeConstant() == B_UINT8_TYPE + || baseType->TypeConstant() == B_INT8_TYPE) + return 0.8f; + } + + return 0.0f; +} + + +status_t +CStringTypeHandler::CreateValueNode(ValueNodeChild* nodeChild, Type* type, + ValueNode*& _node) +{ + if (SupportsType(type) == 0.0f) + return B_BAD_VALUE; + + AddressType* supportedType = dynamic_cast(type); + + ValueNode* node = new(std::nothrow) CStringValueNode(nodeChild, + supportedType); + + if (node == NULL) + return B_NO_MEMORY; + + _node = node; + + return B_OK; +} diff --git a/src/apps/debugger/value/type_handlers/CStringTypeHandler.h b/src/apps/debugger/value/type_handlers/CStringTypeHandler.h new file mode 100644 index 0000000000..1f8a146495 --- /dev/null +++ b/src/apps/debugger/value/type_handlers/CStringTypeHandler.h @@ -0,0 +1,21 @@ +/* + * Copyright 2010, Rene Gollent, rene@gollent.com + * Distributed under the terms of the MIT License. + */ +#ifndef CSTRING_TYPE_HANDLER_H +#define CSTRING_TYPE_HANDLER_H + + +#include "TypeHandler.h" + + +class CStringTypeHandler : public TypeHandler { +public: + virtual ~CStringTypeHandler(); + + virtual float SupportsType(Type* type); + virtual status_t CreateValueNode(ValueNodeChild* nodeChild, + Type* type, ValueNode*& _node); +}; + +#endif // CSTRING_TYPE_HANDLER_H diff --git a/src/apps/debugger/value/value_handlers/StringValueHandler.cpp b/src/apps/debugger/value/value_handlers/StringValueHandler.cpp new file mode 100644 index 0000000000..862b6aa9ea --- /dev/null +++ b/src/apps/debugger/value/value_handlers/StringValueHandler.cpp @@ -0,0 +1,65 @@ +/* + * Copyright 2010, Rene Gollent, rene@gollent.com + * Distributed under the terms of the MIT License. + */ + + +#include "StringValueHandler.h" + +#include + +#include + +#include "StringValue.h" +#include "TableCellStringRenderer.h" + + +StringValueHandler::StringValueHandler() +{ +} + + +StringValueHandler::~StringValueHandler() +{ +} + + +status_t +StringValueHandler::Init() +{ + return B_OK; +} + + +float +StringValueHandler::SupportsValue(Value* value) +{ + return dynamic_cast(value) != NULL ? 0.8f : 0; +} + + +status_t +StringValueHandler::GetValueFormatter(Value* value, + ValueFormatter*& _formatter) +{ + // TODO:... + return B_UNSUPPORTED; +} + + +status_t +StringValueHandler::GetTableCellValueRenderer(Value* value, + TableCellValueRenderer*& _renderer) +{ + if (dynamic_cast(value) == NULL) + return B_BAD_VALUE; + + // create the renderer + TableCellValueRenderer* renderer = new(std::nothrow) + TableCellStringRenderer; + if (renderer == NULL) + return B_NO_MEMORY; + + _renderer = renderer; + return B_OK; +} diff --git a/src/apps/debugger/value/value_handlers/StringValueHandler.h b/src/apps/debugger/value/value_handlers/StringValueHandler.h new file mode 100644 index 0000000000..14a0a1ae30 --- /dev/null +++ b/src/apps/debugger/value/value_handlers/StringValueHandler.h @@ -0,0 +1,27 @@ +/* + * Copyright 2010, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ +#ifndef STRING_VALUE_HANDLER_H +#define STRING_VALUE_HANDLER_H + + +#include "ValueHandler.h" + + +class StringValueHandler : public ValueHandler { +public: + StringValueHandler(); + ~StringValueHandler(); + + 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 // STRING_VALUE_HANDLER_H diff --git a/src/apps/debugger/value/value_nodes/CStringValueNode.cpp b/src/apps/debugger/value/value_nodes/CStringValueNode.cpp new file mode 100644 index 0000000000..5b0c862f57 --- /dev/null +++ b/src/apps/debugger/value/value_nodes/CStringValueNode.cpp @@ -0,0 +1,90 @@ +/* + * Copyright 2010, Rene Gollent, rene@gollent.com + * Distributed under the terms of the MIT License. + */ + + +#include "CStringValueNode.h" + +#include + +#include "Architecture.h" +#include "StringValue.h" +#include "Tracing.h" +#include "Type.h" +#include "ValueLoader.h" +#include "ValueLocation.h" +#include "ValueNodeContainer.h" + + +// #pragma mark - CStringValueNode + + +CStringValueNode::CStringValueNode(ValueNodeChild* nodeChild, + AddressType* type) + : + ChildlessValueNode(nodeChild), + fType(type) +{ + fType->AcquireReference(); +} + + +CStringValueNode::~CStringValueNode() +{ + fType->ReleaseReference(); +} + + +Type* +CStringValueNode::GetType() const +{ + return fType; +} + + +status_t +CStringValueNode::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 (C string)\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 addressData; + BString valueData; + status_t error = valueLoader->LoadValue(location, valueType, false, + addressData); + if (error != B_OK) + return error; + + error = valueLoader->LoadStringValue(addressData, valueType, + valueData); + if (error != B_OK) + return error; + + // create the type object + Value* value = new(std::nothrow) StringValue(valueData); + if (value == NULL) + return B_NO_MEMORY; + + location->AcquireReference(); + _location = location; + _value = value; + return B_OK; +} diff --git a/src/apps/debugger/value/value_nodes/CStringValueNode.h b/src/apps/debugger/value/value_nodes/CStringValueNode.h new file mode 100644 index 0000000000..93203ed62f --- /dev/null +++ b/src/apps/debugger/value/value_nodes/CStringValueNode.h @@ -0,0 +1,32 @@ +/* + * Copyright 2010, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ +#ifndef CSTRING_VALUE_NODE_H +#define CSTRING_VALUE_NODE_H + + +#include "ValueNode.h" + + +class AddressType; + + +class CStringValueNode : public ChildlessValueNode { +public: + CStringValueNode(ValueNodeChild* nodeChild, + AddressType* type); + virtual ~CStringValueNode(); + + virtual Type* GetType() const; + + virtual status_t ResolvedLocationAndValue( + ValueLoader* valueLoader, + ValueLocation*& _location, + Value*& _value); + +private: + AddressType* fType; +}; + +#endif // CSTRING_VALUE_NODE_H diff --git a/src/apps/debugger/value/values/StringValue.cpp b/src/apps/debugger/value/values/StringValue.cpp new file mode 100644 index 0000000000..0c335c37f3 --- /dev/null +++ b/src/apps/debugger/value/values/StringValue.cpp @@ -0,0 +1,45 @@ +/* + * Copyright 2010, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ + + +#include "StringValue.h" + +#include + + +StringValue::StringValue(const char* value) + : + fValue(value) +{ +} + + +StringValue::~StringValue() +{ +} + + +bool +StringValue::ToString(BString& _string) const +{ + _string = fValue; + return true; +} + + +bool +StringValue::ToVariant(BVariant& _value) const +{ + _value = fValue.String(); + return true; +} + + +bool +StringValue::operator==(const Value& other) const +{ + const StringValue* otherString = dynamic_cast(&other); + return otherString != NULL ? fValue == otherString->fValue : false; +} diff --git a/src/apps/debugger/value/values/StringValue.h b/src/apps/debugger/value/values/StringValue.h new file mode 100644 index 0000000000..c47b52f288 --- /dev/null +++ b/src/apps/debugger/value/values/StringValue.h @@ -0,0 +1,30 @@ +/* + * Copyright 2010, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ +#ifndef STRING_VALUE_H +#define STRING_VALUE_H + + +#include "Value.h" + + +class StringValue : public Value { +public: + StringValue(const char* value); + virtual ~StringValue(); + + BString GetValue() const + { return fValue; } + + virtual bool ToString(BString& _string) const; + virtual bool ToVariant(BVariant& _value) const; + + virtual bool operator==(const Value& other) const; + +private: + BString fValue; +}; + + +#endif // STRING_VALUE_H