diff --git a/src/apps/debugger/controllers/TeamDebugger.cpp b/src/apps/debugger/controllers/TeamDebugger.cpp index 5485e67ef6..133a3955b8 100644 --- a/src/apps/debugger/controllers/TeamDebugger.cpp +++ b/src/apps/debugger/controllers/TeamDebugger.cpp @@ -732,7 +732,16 @@ TeamDebugger::MessageReceived(BMessage* message) frame = NULL; } - _HandleEvaluateExpression(language, expression, resultType, frame); + ::Thread* thread; + if (message->FindPointer("thread", + reinterpret_cast(&thread)) != B_OK) { + // the thread isn't needed, unless variable + // evaluation is desired. + thread = NULL; + } + + _HandleEvaluateExpression(language, expression, resultType, + frame, thread); break; } @@ -1087,7 +1096,8 @@ TeamDebugger::InspectRequested(target_addr_t address, void TeamDebugger::ExpressionEvaluationRequested(SourceLanguage* language, - const char* expression, type_code resultType, StackFrame* frame) + const char* expression, type_code resultType, StackFrame* frame, + ::Thread* thread) { BMessage message(MSG_EVALUATE_EXPRESSION); message.AddPointer("language", language); @@ -1095,6 +1105,8 @@ TeamDebugger::ExpressionEvaluationRequested(SourceLanguage* language, message.AddInt32("type", resultType); if (frame != NULL) message.AddPointer("frame", frame); + if (thread != NULL) + message.AddPointer("thread", thread); BReference reference(language); if (PostMessage(&message) == B_OK) @@ -1982,11 +1994,12 @@ TeamDebugger::_HandleInspectAddress(target_addr_t address, void TeamDebugger::_HandleEvaluateExpression(SourceLanguage* language, - const char* expression, type_code resultType, StackFrame* frame) + const char* expression, type_code resultType, StackFrame* frame, + ::Thread* thread) { status_t result = fWorker->ScheduleJob( - new(std::nothrow) ExpressionEvaluationJob(fTeam, language, - expression, resultType, frame)); + new(std::nothrow) ExpressionEvaluationJob(fTeam, fDebuggerInterface, + language, expression, resultType, frame, thread)); if (result != B_OK) { _NotifyUser("Evaluate Expression", "Failed to evaluate expression: %s", strerror(result)); diff --git a/src/apps/debugger/controllers/TeamDebugger.h b/src/apps/debugger/controllers/TeamDebugger.h index 4ef9cba66f..ef5a9f2345 100644 --- a/src/apps/debugger/controllers/TeamDebugger.h +++ b/src/apps/debugger/controllers/TeamDebugger.h @@ -27,6 +27,7 @@ class FileManager; class SettingsManager; class TeamDebugInfo; class TeamMemoryBlockManager; +class Thread; class WatchpointManager; @@ -106,7 +107,8 @@ private: SourceLanguage* language, const char* expression, type_code resultType, - StackFrame* frame = NULL); + StackFrame* frame = NULL, + ::Thread* thread = NULL); virtual void DebugReportRequested(entry_ref* targetPath); @@ -193,7 +195,8 @@ private: SourceLanguage* language, const char* expression, type_code resultType, - StackFrame* frame); + StackFrame* frame, + ::Thread* thread); status_t _HandleSetArguments(int argc, const char* const* argv); diff --git a/src/apps/debugger/jobs/ExpressionEvaluationJob.cpp b/src/apps/debugger/jobs/ExpressionEvaluationJob.cpp index ea42f19a6c..b98f783a84 100644 --- a/src/apps/debugger/jobs/ExpressionEvaluationJob.cpp +++ b/src/apps/debugger/jobs/ExpressionEvaluationJob.cpp @@ -9,26 +9,38 @@ #include +#include "DebuggerInterface.h" #include "SourceLanguage.h" #include "StackFrame.h" #include "Team.h" +#include "Thread.h" #include "Value.h" +#include "ValueNode.h" +#include "ValueNodeManager.h" ExpressionEvaluationJob::ExpressionEvaluationJob(Team* team, - SourceLanguage* language, const char* expression, type_code resultType, - StackFrame* frame) + DebuggerInterface* debuggerInterface, SourceLanguage* language, + const char* expression, type_code resultType, StackFrame* frame, + Thread* thread) : fKey(expression, JOB_TYPE_EVALUATE_EXPRESSION), fTeam(team), + fDebuggerInterface(debuggerInterface), + fArchitecture(debuggerInterface->GetArchitecture()), + fTypeInformation(team->GetTeamTypeInformation()), fLanguage(language), fExpression(expression), fResultType(resultType), - fFrame(frame) + fFrame(frame), + fThread(thread), + fManager(NULL) { fLanguage->AcquireReference(); if (fFrame != NULL) fFrame->AcquireReference(); + if (fThread != NULL) + fThread->AcquireReference(); } @@ -37,6 +49,10 @@ ExpressionEvaluationJob::~ExpressionEvaluationJob() fLanguage->ReleaseReference(); if (fFrame != NULL) fFrame->ReleaseReference(); + if (fThread != NULL) + fThread->ReleaseReference(); + if (fManager != NULL) + fManager->ReleaseReference(); } @@ -50,15 +66,80 @@ ExpressionEvaluationJob::Key() const status_t ExpressionEvaluationJob::Do() { + Value* value = NULL; - status_t result = fLanguage->EvaluateExpression(fExpression, fResultType, - value); BReference reference; - if (value != NULL) - reference.SetTo(value, true); + status_t result = B_OK; + if (fFrame != NULL && fManager == NULL) { + fManager = new(std::nothrow) ValueNodeManager(); + if (fManager == NULL) + result = B_NO_MEMORY; + else + result = fManager->SetStackFrame(fThread, fFrame); + } + + if (result != B_OK) { + fTeam->NotifyExpressionEvaluated(fExpression.String(), result, NULL); + return result; + } + + ValueNode* neededNode = NULL; + result = fLanguage->EvaluateExpression(fExpression, + fResultType, fManager, value, neededNode); + if (neededNode != NULL) { + result = ResolveNodeValue(neededNode); + if (State() == JOB_STATE_WAITING) + return B_OK; + else if (value != NULL) + reference.SetTo(value, true); + // if result != B_OK, fall through + } AutoLocker teamLocker(fTeam); fTeam->NotifyExpressionEvaluated(fExpression.String(), result, value); return B_OK; } + + +status_t +ExpressionEvaluationJob::ResolveNodeValue(ValueNode* node) +{ + AutoLocker workerLocker(GetWorker()); + SimpleJobKey jobKey(node, JOB_TYPE_RESOLVE_VALUE_NODE_VALUE); + + status_t error = B_OK; + if (GetWorker()->GetJob(jobKey) == NULL) { + workerLocker.Unlock(); + + // schedule the job + error = GetWorker()->ScheduleJob( + new(std::nothrow) ResolveValueNodeValueJob(fDebuggerInterface, + fArchitecture, fThread->GetCpuState(), fTypeInformation, + fManager->GetContainer(), node)); + if (error != B_OK) { + // scheduling failed -- set the value to invalid + node->SetLocationAndValue(NULL, NULL, error); + return error; + } + } + + // wait for the job to finish + workerLocker.Unlock(); + + + switch (WaitFor(jobKey)) { + case JOB_DEPENDENCY_SUCCEEDED: + case JOB_DEPENDENCY_NOT_FOUND: + case JOB_DEPENDENCY_ACTIVE: + error = B_OK; + break; + case JOB_DEPENDENCY_FAILED: + case JOB_DEPENDENCY_ABORTED: + default: + error = B_ERROR; + break; + } + + return error; +} diff --git a/src/apps/debugger/jobs/Jobs.h b/src/apps/debugger/jobs/Jobs.h index 7a01f870e0..6ae378e5a8 100644 --- a/src/apps/debugger/jobs/Jobs.h +++ b/src/apps/debugger/jobs/Jobs.h @@ -36,6 +36,7 @@ class ValueLocation; class ValueNode; class ValueNodeChild; class ValueNodeContainer; +class ValueNodeManager; class Variable; @@ -233,22 +234,32 @@ private: class ExpressionEvaluationJob : public Job { public: ExpressionEvaluationJob(Team* team, + DebuggerInterface* debuggerInterface, SourceLanguage* language, const char* expression, type_code resultType, - StackFrame* frame); + StackFrame* frame, + Thread* thread); virtual ~ExpressionEvaluationJob(); virtual const JobKey& Key() const; virtual status_t Do(); +private: + status_t ResolveNodeValue(ValueNode* node); + private: SimpleJobKey fKey; Team* fTeam; + DebuggerInterface* fDebuggerInterface; + Architecture* fArchitecture; + TeamTypeInformation* fTypeInformation; SourceLanguage* fLanguage; BString fExpression; type_code fResultType; StackFrame* fFrame; + Thread* fThread; + ValueNodeManager* fManager; }; diff --git a/src/apps/debugger/source_language/CLanguageFamily.cpp b/src/apps/debugger/source_language/CLanguageFamily.cpp index eb4884cf7a..88c6be77c3 100644 --- a/src/apps/debugger/source_language/CLanguageFamily.cpp +++ b/src/apps/debugger/source_language/CLanguageFamily.cpp @@ -167,14 +167,15 @@ CLanguageFamily::ParseTypeExpression(const BString& expression, status_t -CLanguageFamily::EvaluateExpression(const BString& expression, - type_code type, Value*& _output) +CLanguageFamily::EvaluateExpression(const BString& expression, type_code type, + ValueNodeManager* manager, Value*& _output, ValueNode*& _neededNode) { _output = NULL; + _neededNode = NULL; CLanguageExpressionEvaluator evaluator; Number result; try { - result = evaluator.Evaluate(expression, type); + result = evaluator.Evaluate(expression, type, manager); BVariant resultValue = result.GetValue(); switch (type) { case B_INT8_TYPE: @@ -207,6 +208,8 @@ CLanguageFamily::EvaluateExpression(const BString& expression, ex.position, ex.message.String()); _output = new(std::nothrow) StringValue(stringValue); return B_BAD_DATA; + } catch (ValueNeededException ex) { + _neededNode = ex.value; } return B_OK; diff --git a/src/apps/debugger/source_language/CLanguageFamily.h b/src/apps/debugger/source_language/CLanguageFamily.h index a5e74306ac..7159df0d07 100644 --- a/src/apps/debugger/source_language/CLanguageFamily.h +++ b/src/apps/debugger/source_language/CLanguageFamily.h @@ -22,7 +22,8 @@ public: Type*& _resultType) const; virtual status_t EvaluateExpression(const BString& expression, - type_code type, Value*& _output); + type_code type, ValueNodeManager* manager, + Value*& _output, ValueNode*& _neededNode); protected: virtual bool IsModifierValid(char modifier) const = 0; diff --git a/src/apps/debugger/source_language/SourceLanguage.cpp b/src/apps/debugger/source_language/SourceLanguage.cpp index da77ea7136..7f16327765 100644 --- a/src/apps/debugger/source_language/SourceLanguage.cpp +++ b/src/apps/debugger/source_language/SourceLanguage.cpp @@ -30,7 +30,8 @@ SourceLanguage::ParseTypeExpression(const BString& expression, status_t SourceLanguage::EvaluateExpression(const BString& expression, - type_code type, Value*& _resultValue) + type_code type, ValueNodeManager* manager, Value*& _resultValue, + ValueNode*& _neededNode) { return B_NOT_SUPPORTED; } diff --git a/src/apps/debugger/source_language/SourceLanguage.h b/src/apps/debugger/source_language/SourceLanguage.h index f609f0f512..c732b3b66f 100644 --- a/src/apps/debugger/source_language/SourceLanguage.h +++ b/src/apps/debugger/source_language/SourceLanguage.h @@ -15,6 +15,8 @@ class SyntaxHighlighter; class TeamTypeInformation; class Type; class Value; +class ValueNode; +class ValueNodeManager; class SourceLanguage : public BReferenceable { @@ -32,7 +34,8 @@ public: Type*& _resultType) const; virtual status_t EvaluateExpression(const BString& expression, - type_code type, Value*& _output); + type_code type, ValueNodeManager* manager, + Value*& _output, ValueNode*& _neededNode); }; diff --git a/src/apps/debugger/source_language/expression_evaluators/CLanguageExpressionEvaluator.cpp b/src/apps/debugger/source_language/expression_evaluators/CLanguageExpressionEvaluator.cpp index dfaf727aff..1575364f17 100644 --- a/src/apps/debugger/source_language/expression_evaluators/CLanguageExpressionEvaluator.cpp +++ b/src/apps/debugger/source_language/expression_evaluators/CLanguageExpressionEvaluator.cpp @@ -11,13 +11,21 @@ #include "CLanguageExpressionEvaluator.h" -#include "Number.h" - #include #include #include #include +#include "AutoLocker.h" + +#include "Number.h" +#include "StackFrame.h" +#include "Thread.h" +#include "Value.h" +#include "ValueNode.h" +#include "ValueNodeManager.h" +#include "Variable.h" + enum { TOKEN_NONE = 0, @@ -299,7 +307,7 @@ class CLanguageExpressionEvaluator::Tokenizer { fCurrentToken = Token(begin, length, _CurrentPos() - length, TOKEN_CONSTANT); fCurrentToken.value.SetTo(fType, temp.String()); - } else if (isalpha(*fCurrentChar) && *fCurrentChar != 'x') { + } else if (isalpha(*fCurrentChar)) { const char* begin = fCurrentChar; while (*fCurrentChar != 0 && (isalpha(*fCurrentChar) || isdigit(*fCurrentChar))) { @@ -308,10 +316,6 @@ class CLanguageExpressionEvaluator::Tokenizer { int32 length = fCurrentChar - begin; fCurrentToken = Token(begin, length, _CurrentPos() - length, TOKEN_IDENTIFIER); - } else if (strncmp(fCurrentChar, "π", 2) == 0) { - fCurrentToken = Token(fCurrentChar, 2, _CurrentPos() - 1, - TOKEN_IDENTIFIER); - fCurrentChar += 2; } else { if (!_ParseOperator()) { int32 type = TOKEN_NONE; @@ -517,7 +521,8 @@ class CLanguageExpressionEvaluator::Tokenizer { CLanguageExpressionEvaluator::CLanguageExpressionEvaluator() : fTokenizer(new Tokenizer()), - fCurrentType(B_INT64_TYPE) + fCurrentType(B_INT64_TYPE), + fNodeManager(NULL) { } @@ -530,10 +535,10 @@ CLanguageExpressionEvaluator::~CLanguageExpressionEvaluator() Number CLanguageExpressionEvaluator::Evaluate(const char* expressionString, - type_code type) + type_code type, ValueNodeManager* manager) { fCurrentType = type; - + fNodeManager = manager; fTokenizer->SetType(type); fTokenizer->SetTo(expressionString); @@ -745,6 +750,7 @@ CLanguageExpressionEvaluator::_ParseUnary() return Number((int32)(_ParseUnary() == Number(BVariant(0L)))); case TOKEN_IDENTIFIER: + fTokenizer->RewindToken(); return _ParseIdentifier(); default: @@ -756,32 +762,63 @@ CLanguageExpressionEvaluator::_ParseUnary() } -struct Function { - const char* name; - int argumentCount; - void* function; - Number value; -}; - - Number CLanguageExpressionEvaluator::_ParseIdentifier() { - throw ParseException("Identifiers not implemented", 0); + Token token = fTokenizer->NextToken(); + Number value; - return Number(); -} + if (fNodeManager == NULL) { + throw ParseException("Identifiers not resolvable without manager.", + token.position); + } + const BString& identifierName = token.string; -void -CLanguageExpressionEvaluator::_InitArguments(Number values[], int32 argumentCount) -{ - _EatToken(TOKEN_OPENING_BRACKET); + ValueNodeContainer* container = fNodeManager->GetContainer(); + AutoLocker containerLocker(container); - for (int32 i = 0; i < argumentCount; i++) - values[i] = _ParseBinary(); + ValueNodeChild* child = NULL; + for (int32 i = 0; i < container->CountChildren(); i++) { + ValueNodeChild* current = container->ChildAt(i); + if (current->Name() == identifierName) { + child = current; + break; + } + } - _EatToken(TOKEN_CLOSING_BRACKET); + BString errorMessage; + if (child == NULL) { + errorMessage.SetToFormat("Unable to resolve variable name: '%s'", + identifierName.String()); + throw ParseException(errorMessage, token.position); + } + + status_t state = child->LocationResolutionState(); + if (state != B_OK) { + errorMessage.SetToFormat("Unable to resolve variable value for '%s': " + "%s", identifierName.String(), + strerror(state)); + throw ParseException(errorMessage, token.position); + } + + ValueNode* node = child->Node(); + state = node->LocationAndValueResolutionState(); + if (state == VALUE_NODE_UNRESOLVED) { + throw ValueNeededException(node); + } else if (state != B_OK) { + errorMessage.SetToFormat("Unable to resolve variable value for '%s': " + "%s", identifierName.String(), + strerror(state)); + throw ParseException(errorMessage, token.position); + } + + BVariant variant; + Value* nodeValue = node->GetValue(); + nodeValue->ToVariant(variant); + value.SetTo(variant); + + return value; } diff --git a/src/apps/debugger/source_language/expression_evaluators/CLanguageExpressionEvaluator.h b/src/apps/debugger/source_language/expression_evaluators/CLanguageExpressionEvaluator.h index d0161788aa..4e56b5ea92 100644 --- a/src/apps/debugger/source_language/expression_evaluators/CLanguageExpressionEvaluator.h +++ b/src/apps/debugger/source_language/expression_evaluators/CLanguageExpressionEvaluator.h @@ -15,6 +15,10 @@ #include +class ValueNode; +class ValueNodeManager; + + class ParseException { public: ParseException(const char* message, int32 position) @@ -33,9 +37,21 @@ class ParseException { int32 position; }; -struct Function; +class ValueNeededException { +public: + ValueNeededException(ValueNode* node) + : + value(node) + { + } + + ValueNode* value; +}; + + class Number; + class CLanguageExpressionEvaluator { public: @@ -43,7 +59,7 @@ class CLanguageExpressionEvaluator { ~CLanguageExpressionEvaluator(); Number Evaluate(const char* expressionString, - type_code type); + type_code type, ValueNodeManager* manager); private: struct Token; @@ -56,14 +72,13 @@ class CLanguageExpressionEvaluator { Number _ParsePower(); Number _ParseUnary(); Number _ParseIdentifier(); - void _InitArguments(Number values[], - int32 argumentCount); Number _ParseAtom(); void _EatToken(int32 type); Tokenizer* fTokenizer; type_code fCurrentType; + ValueNodeManager* fNodeManager; }; #endif // C_LANGUAGE_EXPRESSION_EVALUATOR_H diff --git a/src/apps/debugger/user_interface/UserInterface.h b/src/apps/debugger/user_interface/UserInterface.h index 748b6a8625..565f0b9edb 100644 --- a/src/apps/debugger/user_interface/UserInterface.h +++ b/src/apps/debugger/user_interface/UserInterface.h @@ -141,7 +141,8 @@ public: SourceLanguage* language, const char* expression, type_code resultType, - StackFrame* frame = NULL) = 0; + StackFrame* frame = NULL, + Thread* thread = NULL) = 0; virtual void DebugReportRequested(entry_ref* path) = 0; diff --git a/src/apps/debugger/user_interface/gui/team_window/ExpressionEvaluationWindow.cpp b/src/apps/debugger/user_interface/gui/team_window/ExpressionEvaluationWindow.cpp index 350cce4381..8236450293 100644 --- a/src/apps/debugger/user_interface/gui/team_window/ExpressionEvaluationWindow.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/ExpressionEvaluationWindow.cpp @@ -16,6 +16,8 @@ #include "MessageCodes.h" #include "SourceLanguage.h" +#include "StackFrame.h" +#include "Thread.h" #include "UserInterface.h" #include "Value.h" @@ -26,8 +28,8 @@ enum { ExpressionEvaluationWindow::ExpressionEvaluationWindow( - ::Team* team, SourceLanguage* language, UserInterfaceListener* listener, - BHandler* target) + ::Team* team, SourceLanguage* language, StackFrame* frame, + ::Thread* thread, UserInterfaceListener* listener, BHandler* target) : BWindow(BRect(), "Evaluate Expression", B_FLOATING_WINDOW, B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE), @@ -37,11 +39,19 @@ ExpressionEvaluationWindow::ExpressionEvaluationWindow( fExpressionOutput(NULL), fEvaluateButton(NULL), fListener(listener), + fStackFrame(frame), + fThread(thread), fCloseTarget(target), fCurrentEvaluationType(B_INT64_TYPE) { fLanguage->AcquireReference(); + if (fStackFrame != NULL) + fStackFrame->AcquireReference(); + + if (fThread != NULL) + fThread->AcquireReference(); + AutoLocker< ::Team> teamLocker(fTeam); fTeam->AddListener(this); } @@ -51,6 +61,12 @@ ExpressionEvaluationWindow::~ExpressionEvaluationWindow() { fLanguage->ReleaseReference(); + if (fStackFrame != NULL) + fStackFrame->ReleaseReference(); + + if (fThread != NULL) + fThread->ReleaseReference(); + AutoLocker< ::Team> teamLocker(fTeam); fTeam->RemoveListener(this); } @@ -58,10 +74,11 @@ ExpressionEvaluationWindow::~ExpressionEvaluationWindow() ExpressionEvaluationWindow* ExpressionEvaluationWindow::Create(::Team* team, SourceLanguage* language, - UserInterfaceListener* listener, BHandler* target) + StackFrame* frame, ::Thread* thread, UserInterfaceListener* listener, + BHandler* target) { ExpressionEvaluationWindow* self = new ExpressionEvaluationWindow(team, - language, listener, target); + language, frame, thread, listener, target); try { self->_Init(); @@ -216,7 +233,8 @@ ExpressionEvaluationWindow::MessageReceived(BMessage* message) break; fListener->ExpressionEvaluationRequested(fLanguage, - fExpressionInput->Text(), fCurrentEvaluationType); + fExpressionInput->Text(), fCurrentEvaluationType, fStackFrame, + fThread); break; } diff --git a/src/apps/debugger/user_interface/gui/team_window/ExpressionEvaluationWindow.h b/src/apps/debugger/user_interface/gui/team_window/ExpressionEvaluationWindow.h index 4740132537..d256b77e94 100644 --- a/src/apps/debugger/user_interface/gui/team_window/ExpressionEvaluationWindow.h +++ b/src/apps/debugger/user_interface/gui/team_window/ExpressionEvaluationWindow.h @@ -16,7 +16,9 @@ class BButton; class BStringView; class BTextControl; class Team; +class Thread; class SourceLanguage; +class StackFrame; class UserInterfaceListener; @@ -26,6 +28,8 @@ public: ExpressionEvaluationWindow( ::Team* team, SourceLanguage* language, + StackFrame* frame, + ::Thread* thread, UserInterfaceListener* listener, BHandler* target); @@ -34,6 +38,8 @@ public: static ExpressionEvaluationWindow* Create( ::Team* team, SourceLanguage* language, + StackFrame* frame, + ::Thread* thread, UserInterfaceListener* listener, BHandler* target); // throws @@ -60,6 +66,8 @@ private: BStringView* fExpressionOutput; BButton* fEvaluateButton; UserInterfaceListener* fListener; + StackFrame* fStackFrame; + ::Thread* fThread; BHandler* fCloseTarget; type_code fCurrentEvaluationType; }; diff --git a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp index b962600ba6..32c1543e09 100644 --- a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp @@ -356,7 +356,8 @@ TeamWindow::MessageReceived(BMessage* message) BReference languageReference(language, true); fExpressionWindow = ExpressionEvaluationWindow::Create( - fTeam, language, fListener, this); + fTeam, language, fActiveStackFrame, fActiveThread, + fListener, this); if (fExpressionWindow != NULL) fExpressionWindow->Show(); } catch (...) {