Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
209 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
172 changes: 172 additions & 0 deletions
172
src/apps/debugger/user_interface/cli/CliPrintVariableCommand.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
/* | ||
* Copyright 2012, Rene Gollent, rene@gollent.com. | ||
* Distributed under the terms of the MIT License. | ||
*/ | ||
|
||
|
||
#include "CliPrintVariableCommand.h" | ||
|
||
#include <stdio.h> | ||
|
||
#include <AutoLocker.h> | ||
|
||
#include "CliContext.h" | ||
#include "StackFrame.h" | ||
#include "StackTrace.h" | ||
#include "Team.h" | ||
#include "Type.h" | ||
#include "UiUtils.h" | ||
#include "UserInterface.h" | ||
#include "ValueLoader.h" | ||
#include "ValueLocation.h" | ||
#include "ValueNode.h" | ||
#include "ValueNodeContainer.h" | ||
#include "ValueNodeManager.h" | ||
|
||
|
||
CliPrintVariableCommand::CliPrintVariableCommand() | ||
: | ||
CliCommand("print value(s) of a variable", | ||
"%s [--depth n] variable [variable2 ...]\n" | ||
"Prints the value and members of the named variable.") | ||
{ | ||
} | ||
|
||
|
||
void | ||
CliPrintVariableCommand::Execute(int argc, const char* const* argv, | ||
CliContext& context) | ||
{ | ||
if (argc < 2) { | ||
PrintUsage(argv[0]); | ||
return; | ||
} | ||
|
||
ValueNodeManager* manager = context.GetValueNodeManager(); | ||
|
||
ValueNodeContainer* container = manager->GetContainer(); | ||
AutoLocker<ValueNodeContainer> containerLocker(container); | ||
if (container == NULL || container->CountChildren() == 0) { | ||
printf("No variables available.\n"); | ||
return; | ||
} | ||
|
||
int32 depth = 1; | ||
int32 i = 1; | ||
for (; i < argc; i++) { | ||
if (strcmp(argv[i], "--depth") == 0) { | ||
if (i == argc - 1) { | ||
printf("Error: An argument must be supplied for depth.\n"); | ||
return; | ||
} | ||
char* endPointer; | ||
depth = strtol(argv[i + 1], &endPointer, 0); | ||
if (*endPointer != '\0' || depth < 0) { | ||
printf("Error: Invalid parameter \"%s\"\n", argv[i + 1]); | ||
return; | ||
} | ||
i++; | ||
} | ||
else | ||
break; | ||
} | ||
|
||
if (i == argc) { | ||
printf("Error: At least one variable name must be supplied.\n"); | ||
return; | ||
} | ||
|
||
bool found = false; | ||
while (i < argc) { | ||
// TODO: support variable expressions in addition to just names. | ||
const char* variableName = argv[i++]; | ||
for (int32 j = 0; ValueNodeChild* child = container->ChildAt(j); j++) { | ||
if (child->Name() == variableName) { | ||
found = true; | ||
containerLocker.Unlock(); | ||
_ResolveValueIfNeeded(child->Node(), context, depth); | ||
containerLocker.Lock(); | ||
BString data; | ||
UiUtils::PrintValueNodeGraph(data, child, 1, depth); | ||
printf("%s", data.String()); | ||
} | ||
} | ||
|
||
if (!found) | ||
printf("No such variable: %s\n", variableName); | ||
found = false; | ||
} | ||
} | ||
|
||
|
||
status_t | ||
CliPrintVariableCommand::_ResolveValueIfNeeded(ValueNode* node, | ||
CliContext& context, int32 maxDepth) | ||
{ | ||
StackFrame* frame = context.GetStackTrace()->FrameAt( | ||
context.CurrentStackFrameIndex()); | ||
if (frame == NULL) | ||
return B_BAD_DATA; | ||
|
||
status_t result = B_OK; | ||
ValueNodeManager* manager = context.GetValueNodeManager(); | ||
ValueNodeContainer* container = manager->GetContainer(); | ||
AutoLocker<ValueNodeContainer> containerLocker(container); | ||
if (node->LocationAndValueResolutionState() == VALUE_NODE_UNRESOLVED) { | ||
context.GetUserInterfaceListener()->ValueNodeValueRequested( | ||
context.CurrentThread()->GetCpuState(), container, node); | ||
|
||
// TODO: implement proper waiting | ||
while (!context.IsTerminating()) { | ||
context.ProcessPendingEvents(); | ||
if (node->LocationAndValueResolutionState() | ||
!= VALUE_NODE_UNRESOLVED) { | ||
break; | ||
} | ||
containerLocker.Unlock(); | ||
snooze(20000); | ||
containerLocker.Lock(); | ||
} | ||
} | ||
|
||
if (node->LocationAndValueResolutionState() == B_OK && maxDepth > 0) { | ||
for (int32 i = 0; i < node->CountChildren(); i++) { | ||
ValueNodeChild* child = node->ChildAt(i); | ||
containerLocker.Unlock(); | ||
result = _ResolveLocationIfNeeded(child, frame, context.GetTeam()); | ||
if (result != B_OK) | ||
continue; | ||
|
||
result = manager->AddChildNodes(child); | ||
if (result != B_OK) | ||
continue; | ||
|
||
// since in the case of a pointer to a compound we hide | ||
// the intervening compound, don't consider the hidden node | ||
// a level for the purposes of depth traversal | ||
if (node->GetType()->Kind() == TYPE_ADDRESS | ||
&& child->GetType()->Kind() == TYPE_COMPOUND) { | ||
_ResolveValueIfNeeded(child->Node(), context, maxDepth); | ||
} else | ||
_ResolveValueIfNeeded(child->Node(), context, maxDepth - 1); | ||
containerLocker.Lock(); | ||
} | ||
} | ||
|
||
return result; | ||
} | ||
|
||
|
||
status_t | ||
CliPrintVariableCommand::_ResolveLocationIfNeeded(ValueNodeChild* child, | ||
StackFrame* frame, ::Team* team) | ||
{ | ||
ValueLocation* location = NULL; | ||
ValueLoader loader(team->GetArchitecture(), team->GetTeamMemory(), | ||
team->GetTeamTypeInformation(), frame->GetCpuState()); | ||
status_t result = child->ResolveLocation(&loader, location); | ||
child->SetLocation(location, result); | ||
if (location != NULL) | ||
location->ReleaseReference(); | ||
return result; | ||
} |
33 changes: 33 additions & 0 deletions
33
src/apps/debugger/user_interface/cli/CliPrintVariableCommand.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/* | ||
* Copyright 2012, Rene Gollent, rene@gollent.com. | ||
* Distributed under the terms of the MIT License. | ||
*/ | ||
#ifndef CLI_PRINT_VARIABLE_COMMAND_H | ||
#define CLI_PRINT_VARIABLE_COMMAND_H | ||
|
||
|
||
#include "CliCommand.h" | ||
|
||
|
||
class Team; | ||
class StackFrame; | ||
class ValueNode; | ||
class ValueNodeChild; | ||
|
||
|
||
class CliPrintVariableCommand : public CliCommand { | ||
public: | ||
CliPrintVariableCommand(); | ||
virtual void Execute(int argc, const char* const* argv, | ||
CliContext& context); | ||
|
||
private: | ||
status_t _ResolveValueIfNeeded(ValueNode* node, | ||
CliContext& context, int32 maxDepth); | ||
|
||
status_t _ResolveLocationIfNeeded(ValueNodeChild* child, | ||
StackFrame* frame, ::Team* team); | ||
}; | ||
|
||
|
||
#endif // CLI_PRINT_VARIABLE_COMMAND_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters