Arquivos
hhvm/hphp/runtime/eval/debugger/cmd/cmd_extension.cpp
T
Herman Venter f9197ff35c Use & rather than * for pointers that should never be null
This is a rather mechanical refactor that uses references (&) rather than pointers (*) for parameters that are not permitted to ever be given null arguments. In effect, the onus for checking null pointers is shifted from the callee to the caller. The & type annotation makes it clear that the callee is not prepared to deal with a null pointer.
2013-05-20 13:52:30 -07:00

171 linhas
5.9 KiB
C++

/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/runtime/eval/debugger/cmd/cmd_extension.h"
#include "hphp/runtime/ext/ext_array.h"
#include "hphp/util/text_art.h"
using namespace HPHP::Util::TextArt;
namespace HPHP { namespace Eval {
///////////////////////////////////////////////////////////////////////////////
TRACE_SET_MOD(debugger);
void CmdExtension::sendImpl(DebuggerThriftBuffer &thrift) {
CmdExtended::sendImpl(thrift);
thrift.write(m_args);
thrift.write(m_out);
thrift.write(m_err);
}
void CmdExtension::recvImpl(DebuggerThriftBuffer &thrift) {
CmdExtended::recvImpl(thrift);
thrift.read(m_args);
thrift.read(m_out);
thrift.read(m_err);
}
void CmdExtension::list(DebuggerClient &client) {
if (client.argCount() == 2) {
client.addCompletion("dump");
} else if (client.argCount() > 2) {
client.addCompletion(DebuggerClient::AutoCompleteFileNames);
} else {
// This is cheating, assuming server has same list of extensions.
Array exts = Extension::GetLoadedExtensions();
vector<std::string> items;
for (ArrayIter iter(exts); iter; ++iter) {
items.push_back(iter.second().toString()->toCPPString());
}
client.addCompletion(items);
}
}
void CmdExtension::help(DebuggerClient &client) {
client.helpTitle("Extension Command");
client.helpCmds(
"x [t]ension", "lists all extensions",
"x [t]ension {name}", "shows summary info of the extension",
"x [t]ension {name} dump", "shows detailed info of the extension",
"x [t]ension {name} {verb} {args} ...", "executes an action",
nullptr
);
client.helpBody(
"In PHP, a lot of library functions are implemented as \"extensions\". "
"This command allows extensions to support debugger by providing their "
"version numbers, current status and cached data and by providing "
"additional verbs to update runtime states for debugging purposes."
);
}
void CmdExtension::onClientImpl(DebuggerClient &client) {
if (DebuggerCommand::displayedHelp(client)) return;
m_args = *client.args();
CmdExtensionPtr cmd = client.xend<CmdExtension>(this);
if (cmd->m_out.empty()) {
client.error(cmd->m_err);
} else {
client.print(cmd->m_out);
}
}
bool CmdExtension::processList(DebuggerProxy &proxy) {
IDebuggable::InfoVec info;
Array exts = Extension::GetLoadedExtensions();
typedef std::set<std::string, string_lessi> sorted_iset;
sorted_iset names;
for (ArrayIter iter(exts); iter; ++iter) {
names.insert(iter.second().toString().data());
}
for (sorted_iset::const_iterator iter = names.begin();
iter != names.end(); ++iter) {
Extension *ext = Extension::GetExtension(*iter);
assert(ext);
if (ext) {
int support = ext->debuggerSupport();
string line;
line += (support & IDebuggable::SupportInfo) ? "Yes " : " ";
line += (support & IDebuggable::SupportDump) ? "Yes " : " ";
line += (support & IDebuggable::SupportVerb) ? "Yes " : " ";
line += ext->getVersion();
IDebuggable::Add(info, iter->c_str(), line);
}
}
int nameLen;
String body = DebuggerClient::FormatInfoVec(info, &nameLen);
int hrLen = nameLen + 42;
if (hrLen > DebuggerClient::LineWidth) hrLen = DebuggerClient::LineWidth;
StringBuffer sb;
for (int i = 0; i < hrLen; i++) sb.append(BOX_H); sb.append("\n");
sb.append(StringUtil::Pad("Name\\Support", nameLen));
sb.append("Info Dump Verb Version\n");
for (int i = 0; i < hrLen; i++) sb.append(BOX_H); sb.append("\n");
sb.append(body);
for (int i = 0; i < hrLen; i++) sb.append(BOX_H); sb.append("\n");
m_out = sb.detach();
return proxy.sendToClient(this);
}
bool CmdExtension::onServer(DebuggerProxy &proxy) {
if (m_args.size() <= 1) {
return processList(proxy);
}
string name = m_args[1];
Extension *ext = Extension::GetExtension(name);
if (ext) {
if (m_args.size() == 2) {
if (ext->debuggerSupport() & IDebuggable::SupportInfo) {
IDebuggable::InfoVec info;
ext->debuggerInfo(info);
m_out = DebuggerClient::FormatInfoVec(info);
} else {
m_err = "Extension doesn't have summary information.";
}
} else if (DebuggerClient::Match(m_args[2].c_str(), "dump")) {
if (ext->debuggerSupport() & IDebuggable::SupportDump) {
m_out = ext->debuggerDump();
m_out += "\n";
} else {
m_err = "Extension doesn't have detailed dumps.";
}
} else {
if (ext->debuggerSupport() & IDebuggable::SupportVerb) {
string verb = m_args[2];
StringVec args;
if (m_args.size() > 3) {
args.insert(args.end(), m_args.begin() + 3, m_args.end());
}
m_out = ext->debuggerVerb(verb, args);
m_out += "\n";
} else {
m_err = "Extension doesn't support any debugger actions.";
}
}
} else {
m_err = "Unable to find the specified extension: ";
m_err += String(name);
}
return proxy.sendToClient(this);
}
///////////////////////////////////////////////////////////////////////////////
}}