Skip to content

Commit

Permalink
Add CLI print variable command.
Browse files Browse the repository at this point in the history
  • Loading branch information
anevilyak committed Dec 18, 2012
1 parent c56757f commit 596922b
Show file tree
Hide file tree
Showing 4 changed files with 209 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/apps/debugger/Jamfile
Expand Up @@ -193,12 +193,13 @@ Application Debugger :
CliContext.cpp
CliContinueCommand.cpp
CliDebugReportCommand.cpp
CliPrintVariableCommand.cpp
CliQuitCommand.cpp
CliStackFrameCommand.cpp
CliStackTraceCommand.cpp
CliStopCommand.cpp
CliThreadCommand.cpp
CliThreadsCommand.cpp
CliQuitCommand.cpp
CliVariablesCommand.cpp
CommandLineUserInterface.cpp

Expand Down
172 changes: 172 additions & 0 deletions src/apps/debugger/user_interface/cli/CliPrintVariableCommand.cpp
@@ -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 src/apps/debugger/user_interface/cli/CliPrintVariableCommand.h
@@ -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
Expand Up @@ -18,6 +18,7 @@
#include "CliContext.h"
#include "CliContinueCommand.h"
#include "CliDebugReportCommand.h"
#include "CliPrintVariableCommand.h"
#include "CliQuitCommand.h"
#include "CliStackFrameCommand.h"
#include "CliStackTraceCommand.h"
Expand Down Expand Up @@ -313,6 +314,7 @@ CommandLineUserInterface::_RegisterCommands()
&& _RegisterCommand("continue", new(std::nothrow) CliContinueCommand)
&& _RegisterCommand("frame", new(std::nothrow) CliStackFrameCommand)
&& _RegisterCommand("help", new(std::nothrow) HelpCommand(this))
&& _RegisterCommand("print", new(std::nothrow) CliPrintVariableCommand)
&& _RegisterCommand("quit", new(std::nothrow) CliQuitCommand)
&& _RegisterCommand("save-report",
new(std::nothrow) CliDebugReportCommand)
Expand Down

0 comments on commit 596922b

Please sign in to comment.