Fix GetRepeatCommand so it works with multi-word commands.
Move the "source", "alias", and "unalias" commands to "commands *".
Move "source-file" to "source list".
Added a "source info" command but it isn't implemented yet.
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@107751 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Commands/CommandObjectSource.cpp b/source/Commands/CommandObjectSource.cpp
index 9be4dcc..2fd0f9c 100644
--- a/source/Commands/CommandObjectSource.cpp
+++ b/source/Commands/CommandObjectSource.cpp
@@ -17,110 +17,347 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Core/FileSpec.h"
#include "lldb/Target/Process.h"
+#include "lldb/Core/SourceManager.h"
#include "lldb/Target/TargetList.h"
+#include "lldb/Interpreter/CommandCompletions.h"
+#include "lldb/Interpreter/Options.h"
using namespace lldb;
using namespace lldb_private;
-const char *k_space_characters = "\t\n\v\f\r ";
-
//-------------------------------------------------------------------------
-// CommandObjectSource
+// CommandObjectSourceList
//-------------------------------------------------------------------------
-CommandObjectSource::CommandObjectSource() :
- CommandObject ("source",
- "Reads in debugger commands from the file <filename> and executes them.",
- "source <filename>")
+class CommandObjectSourceInfo : public CommandObject
{
-}
-CommandObjectSource::~CommandObjectSource ()
-{
-}
-
-bool
-CommandObjectSource::Execute
-(
- CommandInterpreter &interpreter,
- Args& args,
- CommandReturnObject &result
-)
-{
- const int argc = args.GetArgumentCount();
- if (argc == 1)
+ class CommandOptions : public Options
{
- const char *filename = args.GetArgumentAtIndex(0);
- bool success = true;
-
- result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename);
-
- FileSpec cmd_file (filename);
- if (cmd_file.Exists())
+ public:
+ CommandOptions () :
+ Options()
{
- STLStringArray commands;
- success = cmd_file.ReadFileLines (commands);
+ }
- STLStringArray::iterator pos = commands.begin();
+ ~CommandOptions ()
+ {
+ }
- // Trim out any empty lines or lines that start with the comment
- // char '#'
- while (pos != commands.end())
+ Error
+ SetOptionValue (int option_idx, const char *option_arg)
+ {
+ Error error;
+ const char short_option = g_option_table[option_idx].short_option;
+ switch (short_option)
{
- bool remove_string = false;
- size_t non_space = pos->find_first_not_of (k_space_characters);
- if (non_space == std::string::npos)
- remove_string = true; // Empty line
- else if ((*pos)[non_space] == '#')
- remove_string = true; // Comment line that starts with '#'
+ case 'l':
+ start_line = Args::StringToUInt32 (option_arg, 0);
+ if (start_line == 0)
+ error.SetErrorStringWithFormat("Invalid line number: '%s'.\n", option_arg);
+ break;
- if (remove_string)
- pos = commands.erase(pos);
- else
- ++pos;
+ case 'f':
+ file_name = option_arg;
+ break;
+
+ default:
+ error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option);
+ break;
}
- if (commands.size() > 0)
- {
- const size_t num_commands = commands.size();
- size_t i;
- for (i = 0; i<num_commands; ++i)
- {
- result.GetOutputStream().Printf("%s %s\n", interpreter.GetPrompt(), commands[i].c_str());
- if (!interpreter.HandleCommand(commands[i].c_str(), false, result))
- break;
- }
+ return error;
+ }
- if (i < num_commands)
+ void
+ ResetOptionValues ()
+ {
+ Options::ResetOptionValues();
+
+ file_spec.Clear();
+ file_name.clear();
+ start_line = 0;
+ }
+
+ const lldb::OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+ static lldb::OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+ FileSpec file_spec;
+ std::string file_name;
+ uint32_t start_line;
+
+ };
+
+public:
+ CommandObjectSourceInfo() :
+ CommandObject ("source info",
+ "Display info on the source lines from the current executable's debug info.",
+ "source info [<cmd-options>]")
+ {
+ }
+
+ ~CommandObjectSourceInfo ()
+ {
+ }
+
+
+ Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+
+ bool
+ Execute
+ (
+ CommandInterpreter &interpreter,
+ Args& args,
+ CommandReturnObject &result
+ )
+ {
+ result.AppendError ("Not yet implemented");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+protected:
+ CommandOptions m_options;
+};
+
+lldb::OptionDefinition
+CommandObjectSourceInfo::CommandOptions::g_option_table[] =
+{
+{ LLDB_OPT_SET_1, false, "line", 'l', required_argument, NULL, 0, "<line>", "The line number at which to start the display source."},
+{ LLDB_OPT_SET_1, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, "<file>", "The file from which to display source."},
+{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+#pragma mark CommandObjectSourceList
+//-------------------------------------------------------------------------
+// CommandObjectSourceList
+//-------------------------------------------------------------------------
+
+class CommandObjectSourceList : public CommandObject
+{
+
+ class CommandOptions : public Options
+ {
+ public:
+ CommandOptions () :
+ Options()
+ {
+ }
+
+ ~CommandOptions ()
+ {
+ }
+
+ Error
+ SetOptionValue (int option_idx, const char *option_arg)
+ {
+ Error error;
+ const char short_option = g_option_table[option_idx].short_option;
+ switch (short_option)
+ {
+ case 'l':
+ start_line = Args::StringToUInt32 (option_arg, 0);
+ if (start_line == 0)
+ error.SetErrorStringWithFormat("Invalid line number: '%s'.\n", option_arg);
+ break;
+
+ case 'n':
+ num_lines = Args::StringToUInt32 (option_arg, 0);
+ if (num_lines == 0)
+ error.SetErrorStringWithFormat("Invalid line count: '%s'.\n", option_arg);
+ break;
+
+ case 'f':
+ file_name = option_arg;
+ break;
+
+ default:
+ error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option);
+ break;
+ }
+
+ return error;
+ }
+
+ void
+ ResetOptionValues ()
+ {
+ Options::ResetOptionValues();
+
+ file_spec.Clear();
+ file_name.clear();
+ start_line = 0;
+ num_lines = 10;
+ }
+
+ const lldb::OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+ static lldb::OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+ FileSpec file_spec;
+ std::string file_name;
+ uint32_t start_line;
+ uint32_t num_lines;
+
+ };
+
+public:
+ CommandObjectSourceList() :
+ CommandObject ("source list",
+ "Display source files from the current executable's debug info.",
+ "source list [<cmd-options>] [<filename>]")
+ {
+ }
+
+ ~CommandObjectSourceList ()
+ {
+ }
+
+
+ Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+
+ bool
+ Execute
+ (
+ CommandInterpreter &interpreter,
+ Args& args,
+ CommandReturnObject &result
+ )
+ {
+ const int argc = args.GetArgumentCount();
+
+ if (argc != 0)
+ {
+ result.AppendErrorWithFormat("'%s' takes no arguments, only flags.\n", GetCommandName());
+ result.SetStatus (eReturnStatusFailed);
+ }
+
+ ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext());
+ if (m_options.file_name.empty())
+ {
+ // Last valid source manager context, or the current frame if no
+ // valid last context in source manager.
+ // One little trick here, if you type the exact same list command twice in a row, it is
+ // more likely because you typed it once, then typed it again
+ if (m_options.start_line == 0)
+ {
+ if (interpreter.GetDebugger().GetSourceManager().DisplayMoreWithLineNumbers (&result.GetOutputStream()))
{
- result.AppendErrorWithFormat("Aborting source of '%s' after command '%s' failed.\n", filename, commands[i].c_str());
result.SetStatus (eReturnStatusSuccessFinishResult);
}
- else
+ }
+ else
+ {
+ if (interpreter.GetDebugger().GetSourceManager().DisplaySourceLinesWithLineNumbersUsingLastFile(
+ m_options.start_line, // Line to display
+ 0, // Lines before line to display
+ m_options.num_lines, // Lines after line to display
+ "", // Don't mark "line"
+ &result.GetOutputStream()))
{
- success = true;
- result.SetStatus (eReturnStatusFailed);
+ result.SetStatus (eReturnStatusSuccessFinishResult);
}
+
}
}
else
{
- result.AppendErrorWithFormat ("File '%s' does not exist.\n", filename);
- result.SetStatus (eReturnStatusFailed);
- success = false;
+ const char *filename = m_options.file_name.c_str();
+ Target *target = interpreter.GetDebugger().GetCurrentTarget().get();
+ if (target == NULL)
+ {
+ result.AppendError ("invalid target, set executable file using 'file' command");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+
+ bool check_inlines = false;
+ SymbolContextList sc_list;
+ size_t num_matches = target->GetImages().ResolveSymbolContextForFilePath (filename,
+ 0,
+ check_inlines,
+ eSymbolContextModule | eSymbolContextCompUnit,
+ sc_list);
+ if (num_matches > 0)
+ {
+ SymbolContext sc;
+ if (sc_list.GetContextAtIndex(0, sc))
+ {
+ if (sc.comp_unit)
+ {
+ interpreter.GetDebugger().GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.comp_unit,
+ m_options.start_line, // Line to display
+ 0, // Lines before line to display
+ m_options.num_lines, // Lines after line to display
+ "", // Don't mark "line"
+ &result.GetOutputStream());
+
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+
+ }
+ }
+ }
}
- if (success)
- {
- result.SetStatus (eReturnStatusSuccessFinishNoResult);
- }
+ return result.Succeeded();
}
- else
+
+ virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index)
{
- result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName());
- result.SetStatus (eReturnStatusFailed);
+ return m_cmd_name.c_str();
}
- return result.Succeeded();
+protected:
+ CommandOptions m_options;
+
+};
+
+lldb::OptionDefinition
+CommandObjectSourceList::CommandOptions::g_option_table[] =
+{
+{ LLDB_OPT_SET_1, false, "line", 'l', required_argument, NULL, 0, "<line>", "The line number at which to start the display source."},
+{ LLDB_OPT_SET_1, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, "<file>", "The file from which to display source."},
+{ LLDB_OPT_SET_1, false, "count", 'n', required_argument, NULL, 0, "<count>", "The number of source lines to display."},
+{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+#pragma mark CommandObjectMultiwordSource
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordSource
+//-------------------------------------------------------------------------
+
+CommandObjectMultiwordSource::CommandObjectMultiwordSource (CommandInterpreter &interpreter) :
+ CommandObjectMultiword ("source",
+ "Commands for accessing source file information",
+ "source <subcommand> [<subcommand-options>]")
+{
+ LoadSubCommand (interpreter, "info", CommandObjectSP (new CommandObjectSourceInfo ()));
+ LoadSubCommand (interpreter, "list", CommandObjectSP (new CommandObjectSourceList ()));
}
+
+CommandObjectMultiwordSource::~CommandObjectMultiwordSource ()
+{
+}
+