diff options
author | Enrico Granata <egranata@apple.com> | 2015-03-13 02:20:41 +0000 |
---|---|---|
committer | Enrico Granata <egranata@apple.com> | 2015-03-13 02:20:41 +0000 |
commit | 9fe00e52d3dc12e80428648d84542f800c362163 (patch) | |
tree | 397f77d6aa9a2d566e2f8d6f4ce8a47d858ecece /lldb/source/Commands/CommandObjectCommands.cpp | |
parent | 9f611e3a89c3a87d2748061d149c30e3b132f3a8 (diff) | |
download | llvm-9fe00e52d3dc12e80428648d84542f800c362163.zip llvm-9fe00e52d3dc12e80428648d84542f800c362163.tar.gz llvm-9fe00e52d3dc12e80428648d84542f800c362163.tar.bz2 |
Bulk of the infrastructure work to allow script commands to be backed by object instances in addition to free functions
This works by creating a command backed by a class whose interface should - at least - include
def __init__(self, debugger, session_dict)
def __call__(self, args, return_obj, exe_ctx)
What works:
- adding a command via command script add --class
- calling a thusly created command
What is missing:
- support for custom help
- test cases
The missing parts will follow over the next couple of days
This is an improvement over the existing system as:
a) it provides an obvious location for commands to provide help strings (i.e. methods)
b) it allows commands to store state in an obvious fashion
c) it allows us to easily add features to script commands over time (option parsing and subcommands registration, I am looking at you :-)
llvm-svn: 232136
Diffstat (limited to 'lldb/source/Commands/CommandObjectCommands.cpp')
-rw-r--r-- | lldb/source/Commands/CommandObjectCommands.cpp | 162 |
1 files changed, 149 insertions, 13 deletions
diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp index 0740329..febbfa8 100644 --- a/lldb/source/Commands/CommandObjectCommands.cpp +++ b/lldb/source/Commands/CommandObjectCommands.cpp @@ -1430,6 +1430,96 @@ protected: }; +class CommandObjectScriptingObject : public CommandObjectRaw +{ +private: + lldb::ScriptInterpreterObjectSP m_cmd_obj_sp; + ScriptedCommandSynchronicity m_synchro; + +public: + + CommandObjectScriptingObject (CommandInterpreter &interpreter, + std::string name, + lldb::ScriptInterpreterObjectSP cmd_obj_sp, + ScriptedCommandSynchronicity synch) : + CommandObjectRaw (interpreter, + name.c_str(), + NULL, + NULL), + m_cmd_obj_sp(cmd_obj_sp), + m_synchro(synch) + { + StreamString stream; + stream.Printf("For more information run 'help %s'",name.c_str()); + SetHelp(stream.GetData()); + } + + virtual + ~CommandObjectScriptingObject () + { + } + + virtual bool + IsRemovable () const + { + return true; + } + + lldb::ScriptInterpreterObjectSP + GetImplementingObject () + { + return m_cmd_obj_sp; + } + + ScriptedCommandSynchronicity + GetSynchronicity () + { + return m_synchro; + } + + virtual const char * + GetHelpLong () + { + return CommandObjectRaw::GetHelpLong(); + } + +protected: + virtual bool + DoExecute (const char *raw_command_line, CommandReturnObject &result) + { + ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); + + Error error; + + result.SetStatus(eReturnStatusInvalid); + + if (!scripter || scripter->RunScriptBasedCommand(m_cmd_obj_sp, + raw_command_line, + m_synchro, + result, + error, + m_exe_ctx) == false) + { + result.AppendError(error.AsCString()); + result.SetStatus(eReturnStatusFailed); + } + else + { + // Don't change the status if the command already set it... + if (result.GetStatus() == eReturnStatusInvalid) + { + if (result.GetOutputData() == NULL || result.GetOutputData()[0] == '\0') + result.SetStatus(eReturnStatusSuccessFinishNoResult); + else + result.SetStatus(eReturnStatusSuccessFinishResult); + } + } + + return result.Succeeded(); + } + +}; + //------------------------------------------------------------------------- // CommandObjectCommandsScriptImport //------------------------------------------------------------------------- @@ -1652,7 +1742,11 @@ protected: public: CommandOptions (CommandInterpreter &interpreter) : - Options (interpreter) + Options (interpreter), + m_class_name(), + m_funct_name(), + m_short_help(), + m_synchronicity(eScriptedCommandSynchronicitySynchronous) { } @@ -1671,6 +1765,10 @@ protected: if (option_arg) m_funct_name.assign(option_arg); break; + case 'c': + if (option_arg) + m_class_name.assign(option_arg); + break; case 'h': if (option_arg) m_short_help.assign(option_arg); @@ -1691,6 +1789,7 @@ protected: void OptionParsingStarting () { + m_class_name.clear(); m_funct_name.clear(); m_short_help.clear(); m_synchronicity = eScriptedCommandSynchronicitySynchronous; @@ -1708,6 +1807,7 @@ protected: // Instance variables to hold the values for command options. + std::string m_class_name; std::string m_funct_name; std::string m_short_help; ScriptedCommandSynchronicity m_synchronicity; @@ -1812,20 +1912,55 @@ protected: m_short_help.assign(m_options.m_short_help); m_synchronicity = m_options.m_synchronicity; - if (m_options.m_funct_name.empty()) + if (m_options.m_class_name.empty()) { - m_interpreter.GetPythonCommandsFromIOHandler (" ", // Prompt - *this, // IOHandlerDelegate - true, // Run IOHandler in async mode - NULL); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions + if (m_options.m_funct_name.empty()) + { + m_interpreter.GetPythonCommandsFromIOHandler (" ", // Prompt + *this, // IOHandlerDelegate + true, // Run IOHandler in async mode + NULL); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions + } + else + { + CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter, + m_cmd_name, + m_options.m_funct_name, + m_options.m_short_help, + m_synchronicity)); + if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) + { + result.SetStatus (eReturnStatusSuccessFinishNoResult); + } + else + { + result.AppendError("cannot add command"); + result.SetStatus (eReturnStatusFailed); + } + } } else { - CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter, - m_cmd_name, - m_options.m_funct_name, - m_options.m_short_help, - m_synchronicity)); + ScriptInterpreter *interpreter = GetCommandInterpreter().GetScriptInterpreter(); + if (!interpreter) + { + result.AppendError("cannot find ScriptInterpreter"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + auto cmd_obj_sp = interpreter->CreateScriptCommandObject(m_options.m_class_name.c_str()); + if (!cmd_obj_sp) + { + result.AppendError("cannot create helper object"); + result.SetStatus(eReturnStatusFailed); + return false; + } + + CommandObjectSP new_cmd(new CommandObjectScriptingObject(m_interpreter, + m_cmd_name, + cmd_obj_sp, + m_synchronicity)); if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) { result.SetStatus (eReturnStatusSuccessFinishNoResult); @@ -1859,8 +1994,9 @@ OptionDefinition CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] = { { LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name."}, - { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeHelpText, "The help text to display for this command."}, - { LLDB_OPT_SET_1, false, "synchronicity", 's', OptionParser::eRequiredArgument, NULL, g_script_synchro_type, 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system."}, + { LLDB_OPT_SET_2, false, "class", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonClass, "Name of the Python class to bind to this command name."}, + { LLDB_OPT_SET_ALL, false, "help" , 'h', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeHelpText, "The help text to display for this command."}, + { LLDB_OPT_SET_ALL, false, "synchronicity", 's', OptionParser::eRequiredArgument, NULL, g_script_synchro_type, 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system."}, { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } }; |