f9197ff35c
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.
211 linhas
6.6 KiB
C++
211 linhas
6.6 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_extended.h"
|
|
#include "hphp/runtime/eval/debugger/cmd/all.h"
|
|
#include "hphp/util/logger.h"
|
|
|
|
namespace HPHP { namespace Eval {
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRACE_SET_MOD(debugger);
|
|
|
|
void CmdExtended::list(DebuggerClient &client) {
|
|
if (client.argCount() == 0) {
|
|
const ExtendedCommandMap &cmds = getCommandMap();
|
|
for (ExtendedCommandMap::const_iterator iter = cmds.begin();
|
|
iter != cmds.end(); ++iter) {
|
|
client.addCompletion(iter->first.c_str());
|
|
}
|
|
} else {
|
|
ExtendedCommandMap matches = match(client, 1);
|
|
if (matches.size() == 1) {
|
|
invokeList(client, matches.begin()->second);
|
|
}
|
|
}
|
|
}
|
|
|
|
static string format_unique_prefix(const std::string &cmd,
|
|
const std::string &prev,
|
|
const std::string &next) {
|
|
for (unsigned int i = 1; i < cmd.size(); i++) {
|
|
if (strncasecmp(cmd.c_str(), prev.c_str(), i) &&
|
|
strncasecmp(cmd.c_str(), next.c_str(), i)) {
|
|
return "[" + cmd.substr(0, i) + "]" + cmd.substr(i);
|
|
}
|
|
}
|
|
return cmd + " (ambiguous command)";
|
|
}
|
|
|
|
void CmdExtended::helpImpl(DebuggerClient &client, const char *name) {
|
|
const char *cmd = "{cmd} {arg1} {arg2} ...";
|
|
const char *help = "invoke specified command";
|
|
client.helpCmds((string(name) + " " + cmd).c_str(), help,
|
|
(string(name) + cmd).c_str(), help,
|
|
nullptr);
|
|
|
|
const ExtendedCommandMap &cmds = getCommandMap();
|
|
if (!cmds.empty()) {
|
|
client.help("");
|
|
client.help("where {cmd} can be:");
|
|
client.help("");
|
|
vector<string> vcmds;
|
|
for (ExtendedCommandMap::const_iterator iter = cmds.begin();
|
|
iter != cmds.end(); ++iter) {
|
|
vcmds.push_back(iter->first);
|
|
}
|
|
for (unsigned int i = 0; i < vcmds.size(); i++) {
|
|
client.help("\t%s", format_unique_prefix
|
|
(vcmds[i], i ? vcmds[i-1] : "",
|
|
i < vcmds.size() - 1 ? vcmds[i+1] : "").c_str());
|
|
}
|
|
client.help("");
|
|
client.help("Type '%s [h]elp|? {cmd} to read their usages.", name);
|
|
}
|
|
}
|
|
|
|
ExtendedCommandMap CmdExtended::match(DebuggerClient &client, int argIndex) {
|
|
ExtendedCommandMap matches;
|
|
const ExtendedCommandMap &cmds = getCommandMap();
|
|
for (ExtendedCommandMap::const_iterator iter = cmds.begin();
|
|
iter != cmds.end(); ++iter) {
|
|
if (client.arg(argIndex, iter->first.c_str())) {
|
|
matches[iter->first] = iter->second;
|
|
}
|
|
}
|
|
if (matches.empty()) {
|
|
client.error("Cannot find the specified user command: %s",
|
|
client.argValue(argIndex).c_str());
|
|
}
|
|
return matches;
|
|
}
|
|
|
|
void CmdExtended::helpCommands(DebuggerClient &client,
|
|
const ExtendedCommandMap &matches) {
|
|
for (ExtendedCommandMap::const_iterator iter = matches.begin();
|
|
iter != matches.end(); ++iter) {
|
|
invokeHelp(client, iter->second);
|
|
}
|
|
}
|
|
|
|
void CmdExtended::onClientImpl(DebuggerClient &client) {
|
|
if (client.arg(1, "help") || client.arg(1, "?")) {
|
|
if (client.argCount() == 1) {
|
|
help(client);
|
|
return;
|
|
}
|
|
ExtendedCommandMap matches = match(client, 2);
|
|
if (matches.empty()) {
|
|
help(client);
|
|
} else {
|
|
helpCommands(client, matches);
|
|
}
|
|
return;
|
|
}
|
|
|
|
ExtendedCommandMap matches = match(client, 1);
|
|
if (matches.empty()) {
|
|
help(client);
|
|
} else if (matches.size() > 1) {
|
|
client.error("Need more letters to tell which one of these:");
|
|
for (ExtendedCommandMap::const_iterator iter = matches.begin();
|
|
iter != matches.end(); ++iter) {
|
|
client.error("\t%s", iter->first.c_str());
|
|
}
|
|
} else if (!invokeClient(client, matches.begin()->second)) {
|
|
if (client.arg(2, "help") || client.arg(2, "?")) {
|
|
helpCommands(client, matches);
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CmdExtended::help(DebuggerClient &client) {
|
|
client.helpTitle("Extended Command");
|
|
helpImpl(client, "x");
|
|
}
|
|
|
|
const ExtendedCommandMap &CmdExtended::getCommandMap() {
|
|
return GetExtendedCommandMap();
|
|
}
|
|
|
|
void CmdExtended::invokeList(DebuggerClient &client, const std::string &cls){
|
|
DebuggerCommandPtr cmd = CreateExtendedCommand(cls);
|
|
if (cmd) {
|
|
cmd->list(client);
|
|
}
|
|
}
|
|
|
|
bool CmdExtended::invokeHelp(DebuggerClient &client, const std::string &cls) {
|
|
DebuggerCommandPtr cmd = CreateExtendedCommand(cls);
|
|
if (cmd) {
|
|
cmd->help(client);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CmdExtended::invokeClient(DebuggerClient &client, const std::string &cls){
|
|
DebuggerCommandPtr cmd = CreateExtendedCommand(cls);
|
|
if (cmd) {
|
|
cmd->onClient(client);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CmdExtended::onServer(DebuggerProxy &proxy) {
|
|
assert(false);
|
|
return false;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
const ExtendedCommandMap &CmdExtended::GetExtendedCommandMap() {
|
|
static ExtendedCommandMap s_command_map;
|
|
if (s_command_map.empty()) {
|
|
// add one line for each command
|
|
s_command_map["ample"] = "CmdExample";
|
|
s_command_map["tension"] = "CmdExtension";
|
|
}
|
|
return s_command_map;
|
|
}
|
|
|
|
#define ELSE_IF_CMD(name) \
|
|
} else if (cls == "Cmd" #name) { ret = CmdExtendedPtr(new Cmd ## name());
|
|
|
|
DebuggerCommandPtr CmdExtended::CreateExtendedCommand(const std::string &cls) {
|
|
CmdExtendedPtr ret;
|
|
if (cls.empty()) {
|
|
|
|
// add one line for each command
|
|
ELSE_IF_CMD(Example);
|
|
ELSE_IF_CMD(Extension);
|
|
|
|
}
|
|
|
|
if (ret) {
|
|
ret->m_class = cls;
|
|
} else {
|
|
Logger::Error("Unable to create %s extended command", cls.c_str());
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
}}
|