1254721Semaste//===-- CommandInterpreter.cpp ----------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "lldb/lldb-python.h"
11254721Semaste
12254721Semaste#include <string>
13254721Semaste#include <vector>
14254721Semaste#include <stdlib.h>
15254721Semaste
16254721Semaste#include "CommandObjectScript.h"
17254721Semaste#include "lldb/Interpreter/CommandObjectRegexCommand.h"
18254721Semaste
19254721Semaste#include "../Commands/CommandObjectApropos.h"
20254721Semaste#include "../Commands/CommandObjectArgs.h"
21254721Semaste#include "../Commands/CommandObjectBreakpoint.h"
22254721Semaste#include "../Commands/CommandObjectDisassemble.h"
23254721Semaste#include "../Commands/CommandObjectExpression.h"
24254721Semaste#include "../Commands/CommandObjectFrame.h"
25269024Semaste#include "../Commands/CommandObjectGUI.h"
26254721Semaste#include "../Commands/CommandObjectHelp.h"
27254721Semaste#include "../Commands/CommandObjectLog.h"
28254721Semaste#include "../Commands/CommandObjectMemory.h"
29254721Semaste#include "../Commands/CommandObjectPlatform.h"
30254721Semaste#include "../Commands/CommandObjectPlugin.h"
31254721Semaste#include "../Commands/CommandObjectProcess.h"
32254721Semaste#include "../Commands/CommandObjectQuit.h"
33254721Semaste#include "../Commands/CommandObjectRegister.h"
34254721Semaste#include "../Commands/CommandObjectSettings.h"
35254721Semaste#include "../Commands/CommandObjectSource.h"
36254721Semaste#include "../Commands/CommandObjectCommands.h"
37254721Semaste#include "../Commands/CommandObjectSyntax.h"
38254721Semaste#include "../Commands/CommandObjectTarget.h"
39254721Semaste#include "../Commands/CommandObjectThread.h"
40254721Semaste#include "../Commands/CommandObjectType.h"
41254721Semaste#include "../Commands/CommandObjectVersion.h"
42254721Semaste#include "../Commands/CommandObjectWatchpoint.h"
43254721Semaste
44254721Semaste
45254721Semaste#include "lldb/Core/Debugger.h"
46254721Semaste#include "lldb/Core/Log.h"
47254721Semaste#include "lldb/Core/Stream.h"
48269024Semaste#include "lldb/Core/StreamFile.h"
49254721Semaste#include "lldb/Core/Timer.h"
50254721Semaste
51269024Semaste#include "lldb/Host/Editline.h"
52254721Semaste#include "lldb/Host/Host.h"
53254721Semaste
54254721Semaste#include "lldb/Interpreter/Args.h"
55254721Semaste#include "lldb/Interpreter/CommandCompletions.h"
56254721Semaste#include "lldb/Interpreter/CommandInterpreter.h"
57254721Semaste#include "lldb/Interpreter/CommandReturnObject.h"
58254721Semaste#include "lldb/Interpreter/Options.h"
59254721Semaste#include "lldb/Interpreter/ScriptInterpreterNone.h"
60254721Semaste#include "lldb/Interpreter/ScriptInterpreterPython.h"
61254721Semaste
62254721Semaste
63254721Semaste#include "lldb/Target/Process.h"
64254721Semaste#include "lldb/Target/Thread.h"
65254721Semaste#include "lldb/Target/TargetList.h"
66254721Semaste
67254721Semaste#include "lldb/Utility/CleanUp.h"
68254721Semaste
69254721Semasteusing namespace lldb;
70254721Semasteusing namespace lldb_private;
71254721Semaste
72254721Semaste
73254721Semastestatic PropertyDefinition
74254721Semasteg_properties[] =
75254721Semaste{
76254721Semaste    { "expand-regex-aliases", OptionValue::eTypeBoolean, true, false, NULL, NULL, "If true, regular expression alias commands will show the expanded command that will be executed. This can be used to debug new regular expression alias commands." },
77254721Semaste    { "prompt-on-quit", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will prompt you before quitting if there are any live processes being debugged. If false, LLDB will quit without asking in any case." },
78254721Semaste    { "stop-command-source-on-error", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will stop running a 'command source' script upon encountering an error." },
79254721Semaste    { NULL                  , OptionValue::eTypeInvalid, true, 0    , NULL, NULL, NULL }
80254721Semaste};
81254721Semaste
82254721Semasteenum
83254721Semaste{
84254721Semaste    ePropertyExpandRegexAliases = 0,
85254721Semaste    ePropertyPromptOnQuit = 1,
86254721Semaste    ePropertyStopCmdSourceOnError = 2
87254721Semaste};
88254721Semaste
89254721SemasteConstString &
90254721SemasteCommandInterpreter::GetStaticBroadcasterClass ()
91254721Semaste{
92254721Semaste    static ConstString class_name ("lldb.commandInterpreter");
93254721Semaste    return class_name;
94254721Semaste}
95254721Semaste
96254721SemasteCommandInterpreter::CommandInterpreter
97254721Semaste(
98254721Semaste    Debugger &debugger,
99254721Semaste    ScriptLanguage script_language,
100254721Semaste    bool synchronous_execution
101254721Semaste) :
102254721Semaste    Broadcaster (&debugger, "lldb.command-interpreter"),
103254721Semaste    Properties(OptionValuePropertiesSP(new OptionValueProperties(ConstString("interpreter")))),
104269024Semaste    IOHandlerDelegate (IOHandlerDelegate::Completion::LLDBCommand),
105254721Semaste    m_debugger (debugger),
106254721Semaste    m_synchronous_execution (synchronous_execution),
107254721Semaste    m_skip_lldbinit_files (false),
108254721Semaste    m_skip_app_init_files (false),
109254721Semaste    m_script_interpreter_ap (),
110269024Semaste    m_command_io_handler_sp (),
111254721Semaste    m_comment_char ('#'),
112254721Semaste    m_batch_command_mode (false),
113254721Semaste    m_truncation_warning(eNoTruncation),
114254721Semaste    m_command_source_depth (0)
115254721Semaste{
116254721Semaste    debugger.SetScriptLanguage (script_language);
117254721Semaste    SetEventName (eBroadcastBitThreadShouldExit, "thread-should-exit");
118254721Semaste    SetEventName (eBroadcastBitResetPrompt, "reset-prompt");
119254721Semaste    SetEventName (eBroadcastBitQuitCommandReceived, "quit");
120254721Semaste    CheckInWithManager ();
121254721Semaste    m_collection_sp->Initialize (g_properties);
122254721Semaste}
123254721Semaste
124254721Semastebool
125254721SemasteCommandInterpreter::GetExpandRegexAliases () const
126254721Semaste{
127254721Semaste    const uint32_t idx = ePropertyExpandRegexAliases;
128254721Semaste    return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
129254721Semaste}
130254721Semaste
131254721Semastebool
132254721SemasteCommandInterpreter::GetPromptOnQuit () const
133254721Semaste{
134254721Semaste    const uint32_t idx = ePropertyPromptOnQuit;
135254721Semaste    return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
136254721Semaste}
137254721Semaste
138254721Semastebool
139254721SemasteCommandInterpreter::GetStopCmdSourceOnError () const
140254721Semaste{
141254721Semaste    const uint32_t idx = ePropertyStopCmdSourceOnError;
142254721Semaste    return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
143254721Semaste}
144254721Semaste
145254721Semastevoid
146254721SemasteCommandInterpreter::Initialize ()
147254721Semaste{
148254721Semaste    Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
149254721Semaste
150254721Semaste    CommandReturnObject result;
151254721Semaste
152254721Semaste    LoadCommandDictionary ();
153254721Semaste
154254721Semaste    // Set up some initial aliases.
155254721Semaste    CommandObjectSP cmd_obj_sp = GetCommandSPExact ("quit", false);
156254721Semaste    if (cmd_obj_sp)
157254721Semaste    {
158254721Semaste        AddAlias ("q", cmd_obj_sp);
159254721Semaste        AddAlias ("exit", cmd_obj_sp);
160254721Semaste    }
161254721Semaste
162254721Semaste    cmd_obj_sp = GetCommandSPExact ("_regexp-attach",false);
163254721Semaste    if (cmd_obj_sp)
164254721Semaste    {
165254721Semaste        AddAlias ("attach", cmd_obj_sp);
166254721Semaste    }
167254721Semaste
168254721Semaste    cmd_obj_sp = GetCommandSPExact ("process detach",false);
169254721Semaste    if (cmd_obj_sp)
170254721Semaste    {
171254721Semaste        AddAlias ("detach", cmd_obj_sp);
172254721Semaste    }
173254721Semaste
174254721Semaste    cmd_obj_sp = GetCommandSPExact ("process continue", false);
175254721Semaste    if (cmd_obj_sp)
176254721Semaste    {
177254721Semaste        AddAlias ("c", cmd_obj_sp);
178254721Semaste        AddAlias ("continue", cmd_obj_sp);
179254721Semaste    }
180254721Semaste
181254721Semaste    cmd_obj_sp = GetCommandSPExact ("_regexp-break",false);
182254721Semaste    if (cmd_obj_sp)
183254721Semaste        AddAlias ("b", cmd_obj_sp);
184254721Semaste
185254721Semaste    cmd_obj_sp = GetCommandSPExact ("_regexp-tbreak",false);
186254721Semaste    if (cmd_obj_sp)
187254721Semaste        AddAlias ("tbreak", cmd_obj_sp);
188254721Semaste
189254721Semaste    cmd_obj_sp = GetCommandSPExact ("thread step-inst", false);
190254721Semaste    if (cmd_obj_sp)
191254721Semaste    {
192254721Semaste        AddAlias ("stepi", cmd_obj_sp);
193254721Semaste        AddAlias ("si", cmd_obj_sp);
194254721Semaste    }
195254721Semaste
196254721Semaste    cmd_obj_sp = GetCommandSPExact ("thread step-inst-over", false);
197254721Semaste    if (cmd_obj_sp)
198254721Semaste    {
199254721Semaste        AddAlias ("nexti", cmd_obj_sp);
200254721Semaste        AddAlias ("ni", cmd_obj_sp);
201254721Semaste    }
202254721Semaste
203254721Semaste    cmd_obj_sp = GetCommandSPExact ("thread step-in", false);
204254721Semaste    if (cmd_obj_sp)
205254721Semaste    {
206254721Semaste        AddAlias ("s", cmd_obj_sp);
207254721Semaste        AddAlias ("step", cmd_obj_sp);
208254721Semaste    }
209254721Semaste
210254721Semaste    cmd_obj_sp = GetCommandSPExact ("thread step-over", false);
211254721Semaste    if (cmd_obj_sp)
212254721Semaste    {
213254721Semaste        AddAlias ("n", cmd_obj_sp);
214254721Semaste        AddAlias ("next", cmd_obj_sp);
215254721Semaste    }
216254721Semaste
217254721Semaste    cmd_obj_sp = GetCommandSPExact ("thread step-out", false);
218254721Semaste    if (cmd_obj_sp)
219254721Semaste    {
220254721Semaste        AddAlias ("finish", cmd_obj_sp);
221254721Semaste    }
222254721Semaste
223254721Semaste    cmd_obj_sp = GetCommandSPExact ("frame select", false);
224254721Semaste    if (cmd_obj_sp)
225254721Semaste    {
226254721Semaste        AddAlias ("f", cmd_obj_sp);
227254721Semaste    }
228254721Semaste
229254721Semaste    cmd_obj_sp = GetCommandSPExact ("thread select", false);
230254721Semaste    if (cmd_obj_sp)
231254721Semaste    {
232254721Semaste        AddAlias ("t", cmd_obj_sp);
233254721Semaste    }
234254721Semaste
235263363Semaste    cmd_obj_sp = GetCommandSPExact ("_regexp-jump",false);
236263363Semaste    if (cmd_obj_sp)
237263363Semaste    {
238263363Semaste        AddAlias ("j", cmd_obj_sp);
239263363Semaste        AddAlias ("jump", cmd_obj_sp);
240263363Semaste    }
241263363Semaste
242254721Semaste    cmd_obj_sp = GetCommandSPExact ("_regexp-list", false);
243254721Semaste    if (cmd_obj_sp)
244254721Semaste    {
245254721Semaste        AddAlias ("l", cmd_obj_sp);
246254721Semaste        AddAlias ("list", cmd_obj_sp);
247254721Semaste    }
248254721Semaste
249254721Semaste    cmd_obj_sp = GetCommandSPExact ("_regexp-env", false);
250254721Semaste    if (cmd_obj_sp)
251254721Semaste    {
252254721Semaste        AddAlias ("env", cmd_obj_sp);
253254721Semaste    }
254254721Semaste
255254721Semaste    cmd_obj_sp = GetCommandSPExact ("memory read", false);
256254721Semaste    if (cmd_obj_sp)
257254721Semaste        AddAlias ("x", cmd_obj_sp);
258254721Semaste
259254721Semaste    cmd_obj_sp = GetCommandSPExact ("_regexp-up", false);
260254721Semaste    if (cmd_obj_sp)
261254721Semaste        AddAlias ("up", cmd_obj_sp);
262254721Semaste
263254721Semaste    cmd_obj_sp = GetCommandSPExact ("_regexp-down", false);
264254721Semaste    if (cmd_obj_sp)
265254721Semaste        AddAlias ("down", cmd_obj_sp);
266254721Semaste
267254721Semaste    cmd_obj_sp = GetCommandSPExact ("_regexp-display", false);
268254721Semaste    if (cmd_obj_sp)
269254721Semaste        AddAlias ("display", cmd_obj_sp);
270254721Semaste
271254721Semaste    cmd_obj_sp = GetCommandSPExact ("disassemble", false);
272254721Semaste    if (cmd_obj_sp)
273254721Semaste        AddAlias ("dis", cmd_obj_sp);
274254721Semaste
275254721Semaste    cmd_obj_sp = GetCommandSPExact ("disassemble", false);
276254721Semaste    if (cmd_obj_sp)
277254721Semaste        AddAlias ("di", cmd_obj_sp);
278254721Semaste
279254721Semaste
280254721Semaste
281254721Semaste    cmd_obj_sp = GetCommandSPExact ("_regexp-undisplay", false);
282254721Semaste    if (cmd_obj_sp)
283254721Semaste        AddAlias ("undisplay", cmd_obj_sp);
284254721Semaste
285254721Semaste    cmd_obj_sp = GetCommandSPExact ("_regexp-bt", false);
286254721Semaste    if (cmd_obj_sp)
287254721Semaste        AddAlias ("bt", cmd_obj_sp);
288254721Semaste
289254721Semaste    cmd_obj_sp = GetCommandSPExact ("target create", false);
290254721Semaste    if (cmd_obj_sp)
291254721Semaste        AddAlias ("file", cmd_obj_sp);
292254721Semaste
293254721Semaste    cmd_obj_sp = GetCommandSPExact ("target modules", false);
294254721Semaste    if (cmd_obj_sp)
295254721Semaste        AddAlias ("image", cmd_obj_sp);
296254721Semaste
297254721Semaste
298254721Semaste    OptionArgVectorSP alias_arguments_vector_sp (new OptionArgVector);
299254721Semaste
300254721Semaste    cmd_obj_sp = GetCommandSPExact ("expression", false);
301254721Semaste    if (cmd_obj_sp)
302254721Semaste    {
303254721Semaste        ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp);
304254721Semaste        AddAlias ("p", cmd_obj_sp);
305254721Semaste        AddAlias ("print", cmd_obj_sp);
306254721Semaste        AddAlias ("call", cmd_obj_sp);
307254721Semaste        AddOrReplaceAliasOptions ("p", alias_arguments_vector_sp);
308254721Semaste        AddOrReplaceAliasOptions ("print", alias_arguments_vector_sp);
309254721Semaste        AddOrReplaceAliasOptions ("call", alias_arguments_vector_sp);
310254721Semaste
311254721Semaste        alias_arguments_vector_sp.reset (new OptionArgVector);
312254721Semaste        ProcessAliasOptionsArgs (cmd_obj_sp, "-O -- ", alias_arguments_vector_sp);
313254721Semaste        AddAlias ("po", cmd_obj_sp);
314254721Semaste        AddOrReplaceAliasOptions ("po", alias_arguments_vector_sp);
315254721Semaste    }
316254721Semaste
317254721Semaste    cmd_obj_sp = GetCommandSPExact ("process kill", false);
318254721Semaste    if (cmd_obj_sp)
319254721Semaste    {
320254721Semaste        AddAlias ("kill", cmd_obj_sp);
321254721Semaste    }
322254721Semaste
323254721Semaste    cmd_obj_sp = GetCommandSPExact ("process launch", false);
324254721Semaste    if (cmd_obj_sp)
325254721Semaste    {
326254721Semaste        alias_arguments_vector_sp.reset (new OptionArgVector);
327254721Semaste#if defined (__arm__)
328254721Semaste        ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp);
329254721Semaste#else
330263363Semaste        ProcessAliasOptionsArgs (cmd_obj_sp, "--shell=" LLDB_DEFAULT_SHELL " --", alias_arguments_vector_sp);
331254721Semaste#endif
332254721Semaste        AddAlias ("r", cmd_obj_sp);
333254721Semaste        AddAlias ("run", cmd_obj_sp);
334254721Semaste        AddOrReplaceAliasOptions ("r", alias_arguments_vector_sp);
335254721Semaste        AddOrReplaceAliasOptions ("run", alias_arguments_vector_sp);
336254721Semaste    }
337254721Semaste
338254721Semaste    cmd_obj_sp = GetCommandSPExact ("target symbols add", false);
339254721Semaste    if (cmd_obj_sp)
340254721Semaste    {
341254721Semaste        AddAlias ("add-dsym", cmd_obj_sp);
342254721Semaste    }
343254721Semaste
344254721Semaste    cmd_obj_sp = GetCommandSPExact ("breakpoint set", false);
345254721Semaste    if (cmd_obj_sp)
346254721Semaste    {
347254721Semaste        alias_arguments_vector_sp.reset (new OptionArgVector);
348254721Semaste        ProcessAliasOptionsArgs (cmd_obj_sp, "--func-regex %1", alias_arguments_vector_sp);
349254721Semaste        AddAlias ("rbreak", cmd_obj_sp);
350254721Semaste        AddOrReplaceAliasOptions("rbreak", alias_arguments_vector_sp);
351254721Semaste    }
352254721Semaste}
353254721Semaste
354254721Semasteconst char *
355254721SemasteCommandInterpreter::ProcessEmbeddedScriptCommands (const char *arg)
356254721Semaste{
357254721Semaste    // This function has not yet been implemented.
358254721Semaste
359254721Semaste    // Look for any embedded script command
360254721Semaste    // If found,
361254721Semaste    //    get interpreter object from the command dictionary,
362254721Semaste    //    call execute_one_command on it,
363254721Semaste    //    get the results as a string,
364254721Semaste    //    substitute that string for current stuff.
365254721Semaste
366254721Semaste    return arg;
367254721Semaste}
368254721Semaste
369254721Semaste
370254721Semastevoid
371254721SemasteCommandInterpreter::LoadCommandDictionary ()
372254721Semaste{
373254721Semaste    Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
374254721Semaste
375254721Semaste    lldb::ScriptLanguage script_language = m_debugger.GetScriptLanguage();
376254721Semaste
377254721Semaste    m_command_dict["apropos"]   = CommandObjectSP (new CommandObjectApropos (*this));
378254721Semaste    m_command_dict["breakpoint"]= CommandObjectSP (new CommandObjectMultiwordBreakpoint (*this));
379254721Semaste    m_command_dict["command"]   = CommandObjectSP (new CommandObjectMultiwordCommands (*this));
380254721Semaste    m_command_dict["disassemble"] = CommandObjectSP (new CommandObjectDisassemble (*this));
381254721Semaste    m_command_dict["expression"]= CommandObjectSP (new CommandObjectExpression (*this));
382254721Semaste    m_command_dict["frame"]     = CommandObjectSP (new CommandObjectMultiwordFrame (*this));
383269024Semaste    m_command_dict["gui"]       = CommandObjectSP (new CommandObjectGUI (*this));
384254721Semaste    m_command_dict["help"]      = CommandObjectSP (new CommandObjectHelp (*this));
385254721Semaste    m_command_dict["log"]       = CommandObjectSP (new CommandObjectLog (*this));
386254721Semaste    m_command_dict["memory"]    = CommandObjectSP (new CommandObjectMemory (*this));
387254721Semaste    m_command_dict["platform"]  = CommandObjectSP (new CommandObjectPlatform (*this));
388254721Semaste    m_command_dict["plugin"]    = CommandObjectSP (new CommandObjectPlugin (*this));
389254721Semaste    m_command_dict["process"]   = CommandObjectSP (new CommandObjectMultiwordProcess (*this));
390254721Semaste    m_command_dict["quit"]      = CommandObjectSP (new CommandObjectQuit (*this));
391254721Semaste    m_command_dict["register"]  = CommandObjectSP (new CommandObjectRegister (*this));
392254721Semaste    m_command_dict["script"]    = CommandObjectSP (new CommandObjectScript (*this, script_language));
393254721Semaste    m_command_dict["settings"]  = CommandObjectSP (new CommandObjectMultiwordSettings (*this));
394254721Semaste    m_command_dict["source"]    = CommandObjectSP (new CommandObjectMultiwordSource (*this));
395254721Semaste    m_command_dict["target"]    = CommandObjectSP (new CommandObjectMultiwordTarget (*this));
396254721Semaste    m_command_dict["thread"]    = CommandObjectSP (new CommandObjectMultiwordThread (*this));
397254721Semaste    m_command_dict["type"]      = CommandObjectSP (new CommandObjectType (*this));
398254721Semaste    m_command_dict["version"]   = CommandObjectSP (new CommandObjectVersion (*this));
399254721Semaste    m_command_dict["watchpoint"]= CommandObjectSP (new CommandObjectMultiwordWatchpoint (*this));
400254721Semaste
401254721Semaste    const char *break_regexes[][2] = {{"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2"},
402254721Semaste                                      {"^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1"},
403254721Semaste                                      {"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1"},
404254721Semaste                                      {"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"},
405254721Semaste                                      {"^(-.*)$", "breakpoint set %1"},
406254721Semaste                                      {"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%2' --shlib '%1'"},
407254721Semaste                                      {"^\\&(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1' --skip-prologue=0"},
408254721Semaste                                      {"^(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1'"}};
409254721Semaste
410254721Semaste    size_t num_regexes = sizeof break_regexes/sizeof(char *[2]);
411254721Semaste
412254721Semaste    std::unique_ptr<CommandObjectRegexCommand>
413254721Semaste    break_regex_cmd_ap(new CommandObjectRegexCommand (*this,
414254721Semaste                                                      "_regexp-break",
415254721Semaste                                                      "Set a breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.",
416254721Semaste                                                      "_regexp-break [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>",
417254721Semaste                                                      2,
418254721Semaste                                                      CommandCompletions::eSymbolCompletion |
419254721Semaste                                                      CommandCompletions::eSourceFileCompletion));
420254721Semaste
421254721Semaste    if (break_regex_cmd_ap.get())
422254721Semaste    {
423254721Semaste        bool success = true;
424254721Semaste        for (size_t i = 0; i < num_regexes; i++)
425254721Semaste        {
426254721Semaste            success = break_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], break_regexes[i][1]);
427254721Semaste            if (!success)
428254721Semaste                break;
429254721Semaste        }
430254721Semaste        success = break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full");
431254721Semaste
432254721Semaste        if (success)
433254721Semaste        {
434254721Semaste            CommandObjectSP break_regex_cmd_sp(break_regex_cmd_ap.release());
435254721Semaste            m_command_dict[break_regex_cmd_sp->GetCommandName ()] = break_regex_cmd_sp;
436254721Semaste        }
437254721Semaste    }
438254721Semaste
439254721Semaste    std::unique_ptr<CommandObjectRegexCommand>
440254721Semaste    tbreak_regex_cmd_ap(new CommandObjectRegexCommand (*this,
441254721Semaste                                                      "_regexp-tbreak",
442254721Semaste                                                      "Set a one shot breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.",
443254721Semaste                                                      "_regexp-tbreak [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>",
444254721Semaste                                                       2,
445254721Semaste                                                       CommandCompletions::eSymbolCompletion |
446254721Semaste                                                       CommandCompletions::eSourceFileCompletion));
447254721Semaste
448254721Semaste    if (tbreak_regex_cmd_ap.get())
449254721Semaste    {
450254721Semaste        bool success = true;
451254721Semaste        for (size_t i = 0; i < num_regexes; i++)
452254721Semaste        {
453254721Semaste            // If you add a resultant command string longer than 1024 characters be sure to increase the size of this buffer.
454254721Semaste            char buffer[1024];
455254721Semaste            int num_printed = snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o");
456254721Semaste            assert (num_printed < 1024);
457254721Semaste            success = tbreak_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], buffer);
458254721Semaste            if (!success)
459254721Semaste                break;
460254721Semaste        }
461254721Semaste        success = tbreak_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full");
462254721Semaste
463254721Semaste        if (success)
464254721Semaste        {
465254721Semaste            CommandObjectSP tbreak_regex_cmd_sp(tbreak_regex_cmd_ap.release());
466254721Semaste            m_command_dict[tbreak_regex_cmd_sp->GetCommandName ()] = tbreak_regex_cmd_sp;
467254721Semaste        }
468254721Semaste    }
469254721Semaste
470254721Semaste    std::unique_ptr<CommandObjectRegexCommand>
471254721Semaste    attach_regex_cmd_ap(new CommandObjectRegexCommand (*this,
472254721Semaste                                                       "_regexp-attach",
473254721Semaste                                                       "Attach to a process id if in decimal, otherwise treat the argument as a process name to attach to.",
474254721Semaste                                                       "_regexp-attach [<pid>]\n_regexp-attach [<process-name>]",
475254721Semaste                                                       2));
476254721Semaste    if (attach_regex_cmd_ap.get())
477254721Semaste    {
478254721Semaste        if (attach_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "process attach --pid %1") &&
479254721Semaste            attach_regex_cmd_ap->AddRegexCommand("^(-.*|.* -.*)$", "process attach %1") && // Any options that are specified get passed to 'process attach'
480254721Semaste            attach_regex_cmd_ap->AddRegexCommand("^(.+)$", "process attach --name '%1'") &&
481254721Semaste            attach_regex_cmd_ap->AddRegexCommand("^$", "process attach"))
482254721Semaste        {
483254721Semaste            CommandObjectSP attach_regex_cmd_sp(attach_regex_cmd_ap.release());
484254721Semaste            m_command_dict[attach_regex_cmd_sp->GetCommandName ()] = attach_regex_cmd_sp;
485254721Semaste        }
486254721Semaste    }
487254721Semaste
488254721Semaste    std::unique_ptr<CommandObjectRegexCommand>
489254721Semaste    down_regex_cmd_ap(new CommandObjectRegexCommand (*this,
490254721Semaste                                                     "_regexp-down",
491254721Semaste                                                     "Go down \"n\" frames in the stack (1 frame by default).",
492254721Semaste                                                     "_regexp-down [n]", 2));
493254721Semaste    if (down_regex_cmd_ap.get())
494254721Semaste    {
495254721Semaste        if (down_regex_cmd_ap->AddRegexCommand("^$", "frame select -r -1") &&
496254721Semaste            down_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r -%1"))
497254721Semaste        {
498254721Semaste            CommandObjectSP down_regex_cmd_sp(down_regex_cmd_ap.release());
499254721Semaste            m_command_dict[down_regex_cmd_sp->GetCommandName ()] = down_regex_cmd_sp;
500254721Semaste        }
501254721Semaste    }
502254721Semaste
503254721Semaste    std::unique_ptr<CommandObjectRegexCommand>
504254721Semaste    up_regex_cmd_ap(new CommandObjectRegexCommand (*this,
505254721Semaste                                                   "_regexp-up",
506254721Semaste                                                   "Go up \"n\" frames in the stack (1 frame by default).",
507254721Semaste                                                   "_regexp-up [n]", 2));
508254721Semaste    if (up_regex_cmd_ap.get())
509254721Semaste    {
510254721Semaste        if (up_regex_cmd_ap->AddRegexCommand("^$", "frame select -r 1") &&
511254721Semaste            up_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r %1"))
512254721Semaste        {
513254721Semaste            CommandObjectSP up_regex_cmd_sp(up_regex_cmd_ap.release());
514254721Semaste            m_command_dict[up_regex_cmd_sp->GetCommandName ()] = up_regex_cmd_sp;
515254721Semaste        }
516254721Semaste    }
517254721Semaste
518254721Semaste    std::unique_ptr<CommandObjectRegexCommand>
519254721Semaste    display_regex_cmd_ap(new CommandObjectRegexCommand (*this,
520254721Semaste                                                        "_regexp-display",
521254721Semaste                                                        "Add an expression evaluation stop-hook.",
522254721Semaste                                                        "_regexp-display expression", 2));
523254721Semaste    if (display_regex_cmd_ap.get())
524254721Semaste    {
525254721Semaste        if (display_regex_cmd_ap->AddRegexCommand("^(.+)$", "target stop-hook add -o \"expr -- %1\""))
526254721Semaste        {
527254721Semaste            CommandObjectSP display_regex_cmd_sp(display_regex_cmd_ap.release());
528254721Semaste            m_command_dict[display_regex_cmd_sp->GetCommandName ()] = display_regex_cmd_sp;
529254721Semaste        }
530254721Semaste    }
531254721Semaste
532254721Semaste    std::unique_ptr<CommandObjectRegexCommand>
533254721Semaste    undisplay_regex_cmd_ap(new CommandObjectRegexCommand (*this,
534254721Semaste                                                          "_regexp-undisplay",
535254721Semaste                                                          "Remove an expression evaluation stop-hook.",
536254721Semaste                                                          "_regexp-undisplay stop-hook-number", 2));
537254721Semaste    if (undisplay_regex_cmd_ap.get())
538254721Semaste    {
539254721Semaste        if (undisplay_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "target stop-hook delete %1"))
540254721Semaste        {
541254721Semaste            CommandObjectSP undisplay_regex_cmd_sp(undisplay_regex_cmd_ap.release());
542254721Semaste            m_command_dict[undisplay_regex_cmd_sp->GetCommandName ()] = undisplay_regex_cmd_sp;
543254721Semaste        }
544254721Semaste    }
545254721Semaste
546254721Semaste    std::unique_ptr<CommandObjectRegexCommand>
547254721Semaste    connect_gdb_remote_cmd_ap(new CommandObjectRegexCommand (*this,
548254721Semaste                                                             "gdb-remote",
549254721Semaste                                                             "Connect to a remote GDB server.  If no hostname is provided, localhost is assumed.",
550254721Semaste                                                             "gdb-remote [<hostname>:]<portnum>", 2));
551254721Semaste    if (connect_gdb_remote_cmd_ap.get())
552254721Semaste    {
553254721Semaste        if (connect_gdb_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin gdb-remote connect://%1") &&
554254721Semaste            connect_gdb_remote_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "process connect --plugin gdb-remote connect://localhost:%1"))
555254721Semaste        {
556254721Semaste            CommandObjectSP command_sp(connect_gdb_remote_cmd_ap.release());
557254721Semaste            m_command_dict[command_sp->GetCommandName ()] = command_sp;
558254721Semaste        }
559254721Semaste    }
560254721Semaste
561254721Semaste    std::unique_ptr<CommandObjectRegexCommand>
562254721Semaste    connect_kdp_remote_cmd_ap(new CommandObjectRegexCommand (*this,
563254721Semaste                                                             "kdp-remote",
564254721Semaste                                                             "Connect to a remote KDP server.  udp port 41139 is the default port number.",
565254721Semaste                                                             "kdp-remote <hostname>[:<portnum>]", 2));
566254721Semaste    if (connect_kdp_remote_cmd_ap.get())
567254721Semaste    {
568254721Semaste        if (connect_kdp_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin kdp-remote udp://%1") &&
569254721Semaste            connect_kdp_remote_cmd_ap->AddRegexCommand("^(.+)$", "process connect --plugin kdp-remote udp://%1:41139"))
570254721Semaste        {
571254721Semaste            CommandObjectSP command_sp(connect_kdp_remote_cmd_ap.release());
572254721Semaste            m_command_dict[command_sp->GetCommandName ()] = command_sp;
573254721Semaste        }
574254721Semaste    }
575254721Semaste
576254721Semaste    std::unique_ptr<CommandObjectRegexCommand>
577254721Semaste    bt_regex_cmd_ap(new CommandObjectRegexCommand (*this,
578254721Semaste                                                     "_regexp-bt",
579254721Semaste                                                     "Show a backtrace.  An optional argument is accepted; if that argument is a number, it specifies the number of frames to display.  If that argument is 'all', full backtraces of all threads are displayed.",
580254721Semaste                                                     "bt [<digit>|all]", 2));
581254721Semaste    if (bt_regex_cmd_ap.get())
582254721Semaste    {
583254721Semaste        // accept but don't document "bt -c <number>" -- before bt was a regex command if you wanted to backtrace
584254721Semaste        // three frames you would do "bt -c 3" but the intention is to have this emulate the gdb "bt" command and
585254721Semaste        // so now "bt 3" is the preferred form, in line with gdb.
586254721Semaste        if (bt_regex_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "thread backtrace -c %1") &&
587254721Semaste            bt_regex_cmd_ap->AddRegexCommand("^-c ([[:digit:]]+)$", "thread backtrace -c %1") &&
588254721Semaste            bt_regex_cmd_ap->AddRegexCommand("^all$", "thread backtrace all") &&
589254721Semaste            bt_regex_cmd_ap->AddRegexCommand("^$", "thread backtrace"))
590254721Semaste        {
591254721Semaste            CommandObjectSP command_sp(bt_regex_cmd_ap.release());
592254721Semaste            m_command_dict[command_sp->GetCommandName ()] = command_sp;
593254721Semaste        }
594254721Semaste    }
595254721Semaste
596254721Semaste    std::unique_ptr<CommandObjectRegexCommand>
597254721Semaste    list_regex_cmd_ap(new CommandObjectRegexCommand (*this,
598254721Semaste                                                     "_regexp-list",
599254721Semaste                                                     "Implements the GDB 'list' command in all of its forms except FILE:FUNCTION and maps them to the appropriate 'source list' commands.",
600263363Semaste                                                     "_regexp-list [<line>]\n_regexp-list [<file>:<line>]\n_regexp-list [<file>:<line>]",
601254721Semaste                                                     2,
602254721Semaste                                                     CommandCompletions::eSourceFileCompletion));
603254721Semaste    if (list_regex_cmd_ap.get())
604254721Semaste    {
605254721Semaste        if (list_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "source list --line %1") &&
606254721Semaste            list_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "source list --file '%1' --line %2") &&
607254721Semaste            list_regex_cmd_ap->AddRegexCommand("^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "source list --address %1") &&
608254721Semaste            list_regex_cmd_ap->AddRegexCommand("^-[[:space:]]*$", "source list --reverse") &&
609254721Semaste            list_regex_cmd_ap->AddRegexCommand("^-([[:digit:]]+)[[:space:]]*$", "source list --reverse --count %1") &&
610254721Semaste            list_regex_cmd_ap->AddRegexCommand("^(.+)$", "source list --name \"%1\"") &&
611254721Semaste            list_regex_cmd_ap->AddRegexCommand("^$", "source list"))
612254721Semaste        {
613254721Semaste            CommandObjectSP list_regex_cmd_sp(list_regex_cmd_ap.release());
614254721Semaste            m_command_dict[list_regex_cmd_sp->GetCommandName ()] = list_regex_cmd_sp;
615254721Semaste        }
616254721Semaste    }
617254721Semaste
618254721Semaste    std::unique_ptr<CommandObjectRegexCommand>
619254721Semaste    env_regex_cmd_ap(new CommandObjectRegexCommand (*this,
620254721Semaste                                                    "_regexp-env",
621254721Semaste                                                    "Implements a shortcut to viewing and setting environment variables.",
622254721Semaste                                                    "_regexp-env\n_regexp-env FOO=BAR", 2));
623254721Semaste    if (env_regex_cmd_ap.get())
624254721Semaste    {
625254721Semaste        if (env_regex_cmd_ap->AddRegexCommand("^$", "settings show target.env-vars") &&
626254721Semaste            env_regex_cmd_ap->AddRegexCommand("^([A-Za-z_][A-Za-z_0-9]*=.*)$", "settings set target.env-vars %1"))
627254721Semaste        {
628254721Semaste            CommandObjectSP env_regex_cmd_sp(env_regex_cmd_ap.release());
629254721Semaste            m_command_dict[env_regex_cmd_sp->GetCommandName ()] = env_regex_cmd_sp;
630254721Semaste        }
631254721Semaste    }
632254721Semaste
633263363Semaste    std::unique_ptr<CommandObjectRegexCommand>
634263363Semaste    jump_regex_cmd_ap(new CommandObjectRegexCommand (*this,
635263363Semaste                                                    "_regexp-jump",
636263363Semaste                                                    "Sets the program counter to a new address.",
637263363Semaste                                                    "_regexp-jump [<line>]\n"
638263363Semaste                                                    "_regexp-jump [<+-lineoffset>]\n"
639263363Semaste                                                    "_regexp-jump [<file>:<line>]\n"
640263363Semaste                                                    "_regexp-jump [*<addr>]\n", 2));
641263363Semaste    if (jump_regex_cmd_ap.get())
642263363Semaste    {
643263363Semaste        if (jump_regex_cmd_ap->AddRegexCommand("^\\*(.*)$", "thread jump --addr %1") &&
644263363Semaste            jump_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "thread jump --line %1") &&
645263363Semaste            jump_regex_cmd_ap->AddRegexCommand("^([^:]+):([0-9]+)$", "thread jump --file %1 --line %2") &&
646263363Semaste            jump_regex_cmd_ap->AddRegexCommand("^([+\\-][0-9]+)$", "thread jump --by %1"))
647263363Semaste        {
648263363Semaste            CommandObjectSP jump_regex_cmd_sp(jump_regex_cmd_ap.release());
649263363Semaste            m_command_dict[jump_regex_cmd_sp->GetCommandName ()] = jump_regex_cmd_sp;
650263363Semaste        }
651263363Semaste    }
652263363Semaste
653254721Semaste}
654254721Semaste
655254721Semasteint
656254721SemasteCommandInterpreter::GetCommandNamesMatchingPartialString (const char *cmd_str, bool include_aliases,
657254721Semaste                                                          StringList &matches)
658254721Semaste{
659254721Semaste    CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_str, matches);
660254721Semaste
661254721Semaste    if (include_aliases)
662254721Semaste    {
663254721Semaste        CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_str, matches);
664254721Semaste    }
665254721Semaste
666254721Semaste    return matches.GetSize();
667254721Semaste}
668254721Semaste
669254721SemasteCommandObjectSP
670254721SemasteCommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bool exact, StringList *matches)
671254721Semaste{
672254721Semaste    CommandObject::CommandMap::iterator pos;
673254721Semaste    CommandObjectSP command_sp;
674254721Semaste
675254721Semaste    std::string cmd(cmd_cstr);
676254721Semaste
677254721Semaste    if (HasCommands())
678254721Semaste    {
679254721Semaste        pos = m_command_dict.find(cmd);
680254721Semaste        if (pos != m_command_dict.end())
681254721Semaste            command_sp = pos->second;
682254721Semaste    }
683254721Semaste
684254721Semaste    if (include_aliases && HasAliases())
685254721Semaste    {
686254721Semaste        pos = m_alias_dict.find(cmd);
687254721Semaste        if (pos != m_alias_dict.end())
688254721Semaste            command_sp = pos->second;
689254721Semaste    }
690254721Semaste
691254721Semaste    if (HasUserCommands())
692254721Semaste    {
693254721Semaste        pos = m_user_dict.find(cmd);
694254721Semaste        if (pos != m_user_dict.end())
695254721Semaste            command_sp = pos->second;
696254721Semaste    }
697254721Semaste
698254721Semaste    if (!exact && !command_sp)
699254721Semaste    {
700254721Semaste        // We will only get into here if we didn't find any exact matches.
701254721Semaste
702254721Semaste        CommandObjectSP user_match_sp, alias_match_sp, real_match_sp;
703254721Semaste
704254721Semaste        StringList local_matches;
705254721Semaste        if (matches == NULL)
706254721Semaste            matches = &local_matches;
707254721Semaste
708254721Semaste        unsigned int num_cmd_matches = 0;
709254721Semaste        unsigned int num_alias_matches = 0;
710254721Semaste        unsigned int num_user_matches = 0;
711254721Semaste
712254721Semaste        // Look through the command dictionaries one by one, and if we get only one match from any of
713254721Semaste        // them in toto, then return that, otherwise return an empty CommandObjectSP and the list of matches.
714254721Semaste
715254721Semaste        if (HasCommands())
716254721Semaste        {
717254721Semaste            num_cmd_matches = CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_cstr, *matches);
718254721Semaste        }
719254721Semaste
720254721Semaste        if (num_cmd_matches == 1)
721254721Semaste        {
722254721Semaste            cmd.assign(matches->GetStringAtIndex(0));
723254721Semaste            pos = m_command_dict.find(cmd);
724254721Semaste            if (pos != m_command_dict.end())
725254721Semaste                real_match_sp = pos->second;
726254721Semaste        }
727254721Semaste
728254721Semaste        if (include_aliases && HasAliases())
729254721Semaste        {
730254721Semaste            num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_cstr, *matches);
731254721Semaste
732254721Semaste        }
733254721Semaste
734254721Semaste        if (num_alias_matches == 1)
735254721Semaste        {
736254721Semaste            cmd.assign(matches->GetStringAtIndex (num_cmd_matches));
737254721Semaste            pos = m_alias_dict.find(cmd);
738254721Semaste            if (pos != m_alias_dict.end())
739254721Semaste                alias_match_sp = pos->second;
740254721Semaste        }
741254721Semaste
742254721Semaste        if (HasUserCommands())
743254721Semaste        {
744254721Semaste            num_user_matches = CommandObject::AddNamesMatchingPartialString (m_user_dict, cmd_cstr, *matches);
745254721Semaste        }
746254721Semaste
747254721Semaste        if (num_user_matches == 1)
748254721Semaste        {
749254721Semaste            cmd.assign (matches->GetStringAtIndex (num_cmd_matches + num_alias_matches));
750254721Semaste
751254721Semaste            pos = m_user_dict.find (cmd);
752254721Semaste            if (pos != m_user_dict.end())
753254721Semaste                user_match_sp = pos->second;
754254721Semaste        }
755254721Semaste
756254721Semaste        // If we got exactly one match, return that, otherwise return the match list.
757254721Semaste
758254721Semaste        if (num_user_matches + num_cmd_matches + num_alias_matches == 1)
759254721Semaste        {
760254721Semaste            if (num_cmd_matches)
761254721Semaste                return real_match_sp;
762254721Semaste            else if (num_alias_matches)
763254721Semaste                return alias_match_sp;
764254721Semaste            else
765254721Semaste                return user_match_sp;
766254721Semaste        }
767254721Semaste    }
768254721Semaste    else if (matches && command_sp)
769254721Semaste    {
770254721Semaste        matches->AppendString (cmd_cstr);
771254721Semaste    }
772254721Semaste
773254721Semaste
774254721Semaste    return command_sp;
775254721Semaste}
776254721Semaste
777254721Semastebool
778254721SemasteCommandInterpreter::AddCommand (const char *name, const lldb::CommandObjectSP &cmd_sp, bool can_replace)
779254721Semaste{
780254721Semaste    if (name && name[0])
781254721Semaste    {
782254721Semaste        std::string name_sstr(name);
783254721Semaste        bool found = (m_command_dict.find (name_sstr) != m_command_dict.end());
784254721Semaste        if (found && !can_replace)
785254721Semaste            return false;
786254721Semaste        if (found && m_command_dict[name_sstr]->IsRemovable() == false)
787254721Semaste            return false;
788254721Semaste        m_command_dict[name_sstr] = cmd_sp;
789254721Semaste        return true;
790254721Semaste    }
791254721Semaste    return false;
792254721Semaste}
793254721Semaste
794254721Semastebool
795254721SemasteCommandInterpreter::AddUserCommand (std::string name,
796254721Semaste                                    const lldb::CommandObjectSP &cmd_sp,
797254721Semaste                                    bool can_replace)
798254721Semaste{
799254721Semaste    if (!name.empty())
800254721Semaste    {
801254721Semaste
802254721Semaste        const char* name_cstr = name.c_str();
803254721Semaste
804254721Semaste        // do not allow replacement of internal commands
805254721Semaste        if (CommandExists(name_cstr))
806254721Semaste        {
807254721Semaste            if (can_replace == false)
808254721Semaste                return false;
809254721Semaste            if (m_command_dict[name]->IsRemovable() == false)
810254721Semaste                return false;
811254721Semaste        }
812254721Semaste
813254721Semaste        if (UserCommandExists(name_cstr))
814254721Semaste        {
815254721Semaste            if (can_replace == false)
816254721Semaste                return false;
817254721Semaste            if (m_user_dict[name]->IsRemovable() == false)
818254721Semaste                return false;
819254721Semaste        }
820254721Semaste
821254721Semaste        m_user_dict[name] = cmd_sp;
822254721Semaste        return true;
823254721Semaste    }
824254721Semaste    return false;
825254721Semaste}
826254721Semaste
827254721SemasteCommandObjectSP
828254721SemasteCommandInterpreter::GetCommandSPExact (const char *cmd_cstr, bool include_aliases)
829254721Semaste{
830254721Semaste    Args cmd_words (cmd_cstr); // Break up the command string into words, in case it's a multi-word command.
831254721Semaste    CommandObjectSP ret_val;   // Possibly empty return value.
832254721Semaste
833254721Semaste    if (cmd_cstr == NULL)
834254721Semaste        return ret_val;
835254721Semaste
836254721Semaste    if (cmd_words.GetArgumentCount() == 1)
837254721Semaste        return GetCommandSP(cmd_cstr, include_aliases, true, NULL);
838254721Semaste    else
839254721Semaste    {
840254721Semaste        // We have a multi-word command (seemingly), so we need to do more work.
841254721Semaste        // First, get the cmd_obj_sp for the first word in the command.
842254721Semaste        CommandObjectSP cmd_obj_sp = GetCommandSP (cmd_words.GetArgumentAtIndex (0), include_aliases, true, NULL);
843254721Semaste        if (cmd_obj_sp.get() != NULL)
844254721Semaste        {
845254721Semaste            // Loop through the rest of the words in the command (everything passed in was supposed to be part of a
846254721Semaste            // command name), and find the appropriate sub-command SP for each command word....
847254721Semaste            size_t end = cmd_words.GetArgumentCount();
848254721Semaste            for (size_t j= 1; j < end; ++j)
849254721Semaste            {
850254721Semaste                if (cmd_obj_sp->IsMultiwordObject())
851254721Semaste                {
852254721Semaste                    cmd_obj_sp = cmd_obj_sp->GetSubcommandSP (cmd_words.GetArgumentAtIndex (j));
853254721Semaste                    if (cmd_obj_sp.get() == NULL)
854254721Semaste                        // The sub-command name was invalid.  Fail and return the empty 'ret_val'.
855254721Semaste                        return ret_val;
856254721Semaste                }
857254721Semaste                else
858254721Semaste                    // We have more words in the command name, but we don't have a multiword object. Fail and return
859254721Semaste                    // empty 'ret_val'.
860254721Semaste                    return ret_val;
861254721Semaste            }
862254721Semaste            // We successfully looped through all the command words and got valid command objects for them.  Assign the
863254721Semaste            // last object retrieved to 'ret_val'.
864254721Semaste            ret_val = cmd_obj_sp;
865254721Semaste        }
866254721Semaste    }
867254721Semaste    return ret_val;
868254721Semaste}
869254721Semaste
870254721SemasteCommandObject *
871254721SemasteCommandInterpreter::GetCommandObjectExact (const char *cmd_cstr, bool include_aliases)
872254721Semaste{
873254721Semaste    return GetCommandSPExact (cmd_cstr, include_aliases).get();
874254721Semaste}
875254721Semaste
876254721SemasteCommandObject *
877254721SemasteCommandInterpreter::GetCommandObject (const char *cmd_cstr, StringList *matches)
878254721Semaste{
879254721Semaste    CommandObject *command_obj = GetCommandSP (cmd_cstr, false, true, matches).get();
880254721Semaste
881254721Semaste    // If we didn't find an exact match to the command string in the commands, look in
882254721Semaste    // the aliases.
883254721Semaste
884254721Semaste    if (command_obj)
885254721Semaste        return command_obj;
886254721Semaste
887254721Semaste    command_obj = GetCommandSP (cmd_cstr, true, true, matches).get();
888254721Semaste
889254721Semaste    if (command_obj)
890254721Semaste        return command_obj;
891254721Semaste
892254721Semaste    // If there wasn't an exact match then look for an inexact one in just the commands
893254721Semaste    command_obj = GetCommandSP(cmd_cstr, false, false, NULL).get();
894254721Semaste
895254721Semaste    // Finally, if there wasn't an inexact match among the commands, look for an inexact
896254721Semaste    // match in both the commands and aliases.
897254721Semaste
898254721Semaste    if (command_obj)
899254721Semaste    {
900254721Semaste        if (matches)
901254721Semaste            matches->AppendString(command_obj->GetCommandName());
902254721Semaste        return command_obj;
903254721Semaste    }
904254721Semaste
905254721Semaste    return GetCommandSP(cmd_cstr, true, false, matches).get();
906254721Semaste}
907254721Semaste
908254721Semastebool
909254721SemasteCommandInterpreter::CommandExists (const char *cmd)
910254721Semaste{
911254721Semaste    return m_command_dict.find(cmd) != m_command_dict.end();
912254721Semaste}
913254721Semaste
914254721Semastebool
915254721SemasteCommandInterpreter::ProcessAliasOptionsArgs (lldb::CommandObjectSP &cmd_obj_sp,
916254721Semaste                                            const char *options_args,
917254721Semaste                                            OptionArgVectorSP &option_arg_vector_sp)
918254721Semaste{
919254721Semaste    bool success = true;
920254721Semaste    OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
921254721Semaste
922254721Semaste    if (!options_args || (strlen (options_args) < 1))
923254721Semaste        return true;
924254721Semaste
925254721Semaste    std::string options_string (options_args);
926254721Semaste    Args args (options_args);
927254721Semaste    CommandReturnObject result;
928254721Semaste    // Check to see if the command being aliased can take any command options.
929254721Semaste    Options *options = cmd_obj_sp->GetOptions ();
930254721Semaste    if (options)
931254721Semaste    {
932254721Semaste        // See if any options were specified as part of the alias;  if so, handle them appropriately.
933254721Semaste        options->NotifyOptionParsingStarting ();
934254721Semaste        args.Unshift ("dummy_arg");
935254721Semaste        args.ParseAliasOptions (*options, result, option_arg_vector, options_string);
936254721Semaste        args.Shift ();
937254721Semaste        if (result.Succeeded())
938254721Semaste            options->VerifyPartialOptions (result);
939254721Semaste        if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
940254721Semaste        {
941254721Semaste            result.AppendError ("Unable to create requested alias.\n");
942254721Semaste            return false;
943254721Semaste        }
944254721Semaste    }
945254721Semaste
946254721Semaste    if (!options_string.empty())
947254721Semaste    {
948254721Semaste        if (cmd_obj_sp->WantsRawCommandString ())
949254721Semaste            option_arg_vector->push_back (OptionArgPair ("<argument>",
950254721Semaste                                                          OptionArgValue (-1,
951254721Semaste                                                                          options_string)));
952254721Semaste        else
953254721Semaste        {
954254721Semaste            const size_t argc = args.GetArgumentCount();
955254721Semaste            for (size_t i = 0; i < argc; ++i)
956254721Semaste                if (strcmp (args.GetArgumentAtIndex (i), "") != 0)
957254721Semaste                    option_arg_vector->push_back
958254721Semaste                                (OptionArgPair ("<argument>",
959254721Semaste                                                OptionArgValue (-1,
960254721Semaste                                                                std::string (args.GetArgumentAtIndex (i)))));
961254721Semaste        }
962254721Semaste    }
963254721Semaste
964254721Semaste    return success;
965254721Semaste}
966254721Semaste
967254721Semastebool
968254721SemasteCommandInterpreter::GetAliasFullName (const char *cmd, std::string &full_name)
969254721Semaste{
970254721Semaste    bool exact_match  = (m_alias_dict.find(cmd) != m_alias_dict.end());
971254721Semaste    if (exact_match)
972254721Semaste    {
973254721Semaste        full_name.assign(cmd);
974254721Semaste        return exact_match;
975254721Semaste    }
976254721Semaste    else
977254721Semaste    {
978254721Semaste        StringList matches;
979254721Semaste        size_t num_alias_matches;
980254721Semaste        num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd, matches);
981254721Semaste        if (num_alias_matches == 1)
982254721Semaste        {
983254721Semaste            // Make sure this isn't shadowing a command in the regular command space:
984254721Semaste            StringList regular_matches;
985254721Semaste            const bool include_aliases = false;
986254721Semaste            const bool exact = false;
987254721Semaste            CommandObjectSP cmd_obj_sp(GetCommandSP (cmd, include_aliases, exact, &regular_matches));
988254721Semaste            if (cmd_obj_sp || regular_matches.GetSize() > 0)
989254721Semaste                return false;
990254721Semaste            else
991254721Semaste            {
992254721Semaste                full_name.assign (matches.GetStringAtIndex(0));
993254721Semaste                return true;
994254721Semaste            }
995254721Semaste        }
996254721Semaste        else
997254721Semaste            return false;
998254721Semaste    }
999254721Semaste}
1000254721Semaste
1001254721Semastebool
1002254721SemasteCommandInterpreter::AliasExists (const char *cmd)
1003254721Semaste{
1004254721Semaste    return m_alias_dict.find(cmd) != m_alias_dict.end();
1005254721Semaste}
1006254721Semaste
1007254721Semastebool
1008254721SemasteCommandInterpreter::UserCommandExists (const char *cmd)
1009254721Semaste{
1010254721Semaste    return m_user_dict.find(cmd) != m_user_dict.end();
1011254721Semaste}
1012254721Semaste
1013254721Semastevoid
1014254721SemasteCommandInterpreter::AddAlias (const char *alias_name, CommandObjectSP& command_obj_sp)
1015254721Semaste{
1016254721Semaste    command_obj_sp->SetIsAlias (true);
1017254721Semaste    m_alias_dict[alias_name] = command_obj_sp;
1018254721Semaste}
1019254721Semaste
1020254721Semastebool
1021254721SemasteCommandInterpreter::RemoveAlias (const char *alias_name)
1022254721Semaste{
1023254721Semaste    CommandObject::CommandMap::iterator pos = m_alias_dict.find(alias_name);
1024254721Semaste    if (pos != m_alias_dict.end())
1025254721Semaste    {
1026254721Semaste        m_alias_dict.erase(pos);
1027254721Semaste        return true;
1028254721Semaste    }
1029254721Semaste    return false;
1030254721Semaste}
1031254721Semastebool
1032254721SemasteCommandInterpreter::RemoveUser (const char *alias_name)
1033254721Semaste{
1034254721Semaste    CommandObject::CommandMap::iterator pos = m_user_dict.find(alias_name);
1035254721Semaste    if (pos != m_user_dict.end())
1036254721Semaste    {
1037254721Semaste        m_user_dict.erase(pos);
1038254721Semaste        return true;
1039254721Semaste    }
1040254721Semaste    return false;
1041254721Semaste}
1042254721Semaste
1043254721Semastevoid
1044254721SemasteCommandInterpreter::GetAliasHelp (const char *alias_name, const char *command_name, StreamString &help_string)
1045254721Semaste{
1046254721Semaste    help_string.Printf ("'%s", command_name);
1047254721Semaste    OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
1048254721Semaste
1049254721Semaste    if (option_arg_vector_sp)
1050254721Semaste    {
1051254721Semaste        OptionArgVector *options = option_arg_vector_sp.get();
1052254721Semaste        for (size_t i = 0; i < options->size(); ++i)
1053254721Semaste        {
1054254721Semaste            OptionArgPair cur_option = (*options)[i];
1055254721Semaste            std::string opt = cur_option.first;
1056254721Semaste            OptionArgValue value_pair = cur_option.second;
1057254721Semaste            std::string value = value_pair.second;
1058254721Semaste            if (opt.compare("<argument>") == 0)
1059254721Semaste            {
1060254721Semaste                help_string.Printf (" %s", value.c_str());
1061254721Semaste            }
1062254721Semaste            else
1063254721Semaste            {
1064254721Semaste                help_string.Printf (" %s", opt.c_str());
1065254721Semaste                if ((value.compare ("<no-argument>") != 0)
1066254721Semaste                    && (value.compare ("<need-argument") != 0))
1067254721Semaste                {
1068254721Semaste                    help_string.Printf (" %s", value.c_str());
1069254721Semaste                }
1070254721Semaste            }
1071254721Semaste        }
1072254721Semaste    }
1073254721Semaste
1074254721Semaste    help_string.Printf ("'");
1075254721Semaste}
1076254721Semaste
1077254721Semastesize_t
1078254721SemasteCommandInterpreter::FindLongestCommandWord (CommandObject::CommandMap &dict)
1079254721Semaste{
1080254721Semaste    CommandObject::CommandMap::const_iterator pos;
1081254721Semaste    CommandObject::CommandMap::const_iterator end = dict.end();
1082254721Semaste    size_t max_len = 0;
1083254721Semaste
1084254721Semaste    for (pos = dict.begin(); pos != end; ++pos)
1085254721Semaste    {
1086254721Semaste        size_t len = pos->first.size();
1087254721Semaste        if (max_len < len)
1088254721Semaste            max_len = len;
1089254721Semaste    }
1090254721Semaste    return max_len;
1091254721Semaste}
1092254721Semaste
1093254721Semastevoid
1094254721SemasteCommandInterpreter::GetHelp (CommandReturnObject &result,
1095254721Semaste                             uint32_t cmd_types)
1096254721Semaste{
1097254721Semaste    CommandObject::CommandMap::const_iterator pos;
1098254721Semaste    size_t max_len = FindLongestCommandWord (m_command_dict);
1099254721Semaste
1100254721Semaste    if ( (cmd_types & eCommandTypesBuiltin) == eCommandTypesBuiltin )
1101254721Semaste    {
1102254721Semaste
1103254721Semaste        result.AppendMessage("The following is a list of built-in, permanent debugger commands:");
1104254721Semaste        result.AppendMessage("");
1105254721Semaste
1106254721Semaste        for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
1107254721Semaste        {
1108254721Semaste            OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(),
1109254721Semaste                                     max_len);
1110254721Semaste        }
1111254721Semaste        result.AppendMessage("");
1112254721Semaste
1113254721Semaste    }
1114254721Semaste
1115254721Semaste    if (!m_alias_dict.empty() && ( (cmd_types & eCommandTypesAliases) == eCommandTypesAliases ))
1116254721Semaste    {
1117254721Semaste        result.AppendMessage("The following is a list of your current command abbreviations "
1118254721Semaste                             "(see 'help command alias' for more info):");
1119254721Semaste        result.AppendMessage("");
1120254721Semaste        max_len = FindLongestCommandWord (m_alias_dict);
1121254721Semaste
1122254721Semaste        for (pos = m_alias_dict.begin(); pos != m_alias_dict.end(); ++pos)
1123254721Semaste        {
1124254721Semaste            StreamString sstr;
1125254721Semaste            StreamString translation_and_help;
1126254721Semaste            std::string entry_name = pos->first;
1127254721Semaste            std::string second_entry = pos->second.get()->GetCommandName();
1128254721Semaste            GetAliasHelp (pos->first.c_str(), pos->second->GetCommandName(), sstr);
1129254721Semaste
1130254721Semaste            translation_and_help.Printf ("(%s)  %s", sstr.GetData(), pos->second->GetHelp());
1131254721Semaste            OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--",
1132254721Semaste                                     translation_and_help.GetData(), max_len);
1133254721Semaste        }
1134254721Semaste        result.AppendMessage("");
1135254721Semaste    }
1136254721Semaste
1137254721Semaste    if (!m_user_dict.empty() && ( (cmd_types & eCommandTypesUserDef) == eCommandTypesUserDef ))
1138254721Semaste    {
1139254721Semaste        result.AppendMessage ("The following is a list of your current user-defined commands:");
1140254721Semaste        result.AppendMessage("");
1141254721Semaste        max_len = FindLongestCommandWord (m_user_dict);
1142254721Semaste        for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos)
1143254721Semaste        {
1144254721Semaste            OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(),
1145254721Semaste                                     max_len);
1146254721Semaste        }
1147254721Semaste        result.AppendMessage("");
1148254721Semaste    }
1149254721Semaste
1150254721Semaste    result.AppendMessage("For more information on any particular command, try 'help <command-name>'.");
1151254721Semaste}
1152254721Semaste
1153254721SemasteCommandObject *
1154254721SemasteCommandInterpreter::GetCommandObjectForCommand (std::string &command_string)
1155254721Semaste{
1156254721Semaste    // This function finds the final, lowest-level, alias-resolved command object whose 'Execute' function will
1157254721Semaste    // eventually be invoked by the given command line.
1158254721Semaste
1159254721Semaste    CommandObject *cmd_obj = NULL;
1160254721Semaste    std::string white_space (" \t\v");
1161254721Semaste    size_t start = command_string.find_first_not_of (white_space);
1162254721Semaste    size_t end = 0;
1163254721Semaste    bool done = false;
1164254721Semaste    while (!done)
1165254721Semaste    {
1166254721Semaste        if (start != std::string::npos)
1167254721Semaste        {
1168254721Semaste            // Get the next word from command_string.
1169254721Semaste            end = command_string.find_first_of (white_space, start);
1170254721Semaste            if (end == std::string::npos)
1171254721Semaste                end = command_string.size();
1172254721Semaste            std::string cmd_word = command_string.substr (start, end - start);
1173254721Semaste
1174254721Semaste            if (cmd_obj == NULL)
1175254721Semaste                // Since cmd_obj is NULL we are on our first time through this loop. Check to see if cmd_word is a valid
1176254721Semaste                // command or alias.
1177254721Semaste                cmd_obj = GetCommandObject (cmd_word.c_str());
1178254721Semaste            else if (cmd_obj->IsMultiwordObject ())
1179254721Semaste            {
1180254721Semaste                // Our current object is a multi-word object; see if the cmd_word is a valid sub-command for our object.
1181254721Semaste                CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (cmd_word.c_str());
1182254721Semaste                if (sub_cmd_obj)
1183254721Semaste                    cmd_obj = sub_cmd_obj;
1184254721Semaste                else // cmd_word was not a valid sub-command word, so we are donee
1185254721Semaste                    done = true;
1186254721Semaste            }
1187254721Semaste            else
1188254721Semaste                // We have a cmd_obj and it is not a multi-word object, so we are done.
1189254721Semaste                done = true;
1190254721Semaste
1191254721Semaste            // If we didn't find a valid command object, or our command object is not a multi-word object, or
1192254721Semaste            // we are at the end of the command_string, then we are done.  Otherwise, find the start of the
1193254721Semaste            // next word.
1194254721Semaste
1195254721Semaste            if (!cmd_obj || !cmd_obj->IsMultiwordObject() || end >= command_string.size())
1196254721Semaste                done = true;
1197254721Semaste            else
1198254721Semaste                start = command_string.find_first_not_of (white_space, end);
1199254721Semaste        }
1200254721Semaste        else
1201254721Semaste            // Unable to find any more words.
1202254721Semaste            done = true;
1203254721Semaste    }
1204254721Semaste
1205254721Semaste    if (end == command_string.size())
1206254721Semaste        command_string.clear();
1207254721Semaste    else
1208254721Semaste        command_string = command_string.substr(end);
1209254721Semaste
1210254721Semaste    return cmd_obj;
1211254721Semaste}
1212254721Semaste
1213254721Semastestatic const char *k_white_space = " \t\v";
1214254721Semastestatic const char *k_valid_command_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
1215254721Semastestatic void
1216254721SemasteStripLeadingSpaces (std::string &s)
1217254721Semaste{
1218254721Semaste    if (!s.empty())
1219254721Semaste    {
1220254721Semaste        size_t pos = s.find_first_not_of (k_white_space);
1221254721Semaste        if (pos == std::string::npos)
1222254721Semaste            s.clear();
1223254721Semaste        else if (pos == 0)
1224254721Semaste            return;
1225254721Semaste        s.erase (0, pos);
1226254721Semaste    }
1227254721Semaste}
1228254721Semaste
1229254721Semastestatic size_t
1230254721SemasteFindArgumentTerminator (const std::string &s)
1231254721Semaste{
1232254721Semaste    const size_t s_len = s.size();
1233254721Semaste    size_t offset = 0;
1234254721Semaste    while (offset < s_len)
1235254721Semaste    {
1236254721Semaste        size_t pos = s.find ("--", offset);
1237254721Semaste        if (pos == std::string::npos)
1238254721Semaste            break;
1239254721Semaste        if (pos > 0)
1240254721Semaste        {
1241254721Semaste            if (isspace(s[pos-1]))
1242254721Semaste            {
1243254721Semaste                // Check if the string ends "\s--" (where \s is a space character)
1244254721Semaste                // or if we have "\s--\s".
1245254721Semaste                if ((pos + 2 >= s_len) || isspace(s[pos+2]))
1246254721Semaste                {
1247254721Semaste                    return pos;
1248254721Semaste                }
1249254721Semaste            }
1250254721Semaste        }
1251254721Semaste        offset = pos + 2;
1252254721Semaste    }
1253254721Semaste    return std::string::npos;
1254254721Semaste}
1255254721Semaste
1256254721Semastestatic bool
1257254721SemasteExtractCommand (std::string &command_string, std::string &command, std::string &suffix, char &quote_char)
1258254721Semaste{
1259254721Semaste    command.clear();
1260254721Semaste    suffix.clear();
1261254721Semaste    StripLeadingSpaces (command_string);
1262254721Semaste
1263254721Semaste    bool result = false;
1264254721Semaste    quote_char = '\0';
1265254721Semaste
1266254721Semaste    if (!command_string.empty())
1267254721Semaste    {
1268254721Semaste        const char first_char = command_string[0];
1269254721Semaste        if (first_char == '\'' || first_char == '"')
1270254721Semaste        {
1271254721Semaste            quote_char = first_char;
1272254721Semaste            const size_t end_quote_pos = command_string.find (quote_char, 1);
1273254721Semaste            if (end_quote_pos == std::string::npos)
1274254721Semaste            {
1275254721Semaste                command.swap (command_string);
1276254721Semaste                command_string.erase ();
1277254721Semaste            }
1278254721Semaste            else
1279254721Semaste            {
1280254721Semaste                command.assign (command_string, 1, end_quote_pos - 1);
1281254721Semaste                if (end_quote_pos + 1 < command_string.size())
1282254721Semaste                    command_string.erase (0, command_string.find_first_not_of (k_white_space, end_quote_pos + 1));
1283254721Semaste                else
1284254721Semaste                    command_string.erase ();
1285254721Semaste            }
1286254721Semaste        }
1287254721Semaste        else
1288254721Semaste        {
1289254721Semaste            const size_t first_space_pos = command_string.find_first_of (k_white_space);
1290254721Semaste            if (first_space_pos == std::string::npos)
1291254721Semaste            {
1292254721Semaste                command.swap (command_string);
1293254721Semaste                command_string.erase();
1294254721Semaste            }
1295254721Semaste            else
1296254721Semaste            {
1297254721Semaste                command.assign (command_string, 0, first_space_pos);
1298254721Semaste                command_string.erase(0, command_string.find_first_not_of (k_white_space, first_space_pos));
1299254721Semaste            }
1300254721Semaste        }
1301254721Semaste        result = true;
1302254721Semaste    }
1303254721Semaste
1304254721Semaste
1305254721Semaste    if (!command.empty())
1306254721Semaste    {
1307254721Semaste        // actual commands can't start with '-' or '_'
1308254721Semaste        if (command[0] != '-' && command[0] != '_')
1309254721Semaste        {
1310254721Semaste            size_t pos = command.find_first_not_of(k_valid_command_chars);
1311254721Semaste            if (pos > 0 && pos != std::string::npos)
1312254721Semaste            {
1313254721Semaste                suffix.assign (command.begin() + pos, command.end());
1314254721Semaste                command.erase (pos);
1315254721Semaste            }
1316254721Semaste        }
1317254721Semaste    }
1318254721Semaste
1319254721Semaste    return result;
1320254721Semaste}
1321254721Semaste
1322254721SemasteCommandObject *
1323254721SemasteCommandInterpreter::BuildAliasResult (const char *alias_name,
1324254721Semaste                                      std::string &raw_input_string,
1325254721Semaste                                      std::string &alias_result,
1326254721Semaste                                      CommandReturnObject &result)
1327254721Semaste{
1328254721Semaste    CommandObject *alias_cmd_obj = NULL;
1329254721Semaste    Args cmd_args (raw_input_string.c_str());
1330254721Semaste    alias_cmd_obj = GetCommandObject (alias_name);
1331254721Semaste    StreamString result_str;
1332254721Semaste
1333254721Semaste    if (alias_cmd_obj)
1334254721Semaste    {
1335254721Semaste        std::string alias_name_str = alias_name;
1336254721Semaste        if ((cmd_args.GetArgumentCount() == 0)
1337254721Semaste            || (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0))
1338254721Semaste            cmd_args.Unshift (alias_name);
1339254721Semaste
1340254721Semaste        result_str.Printf ("%s", alias_cmd_obj->GetCommandName ());
1341254721Semaste        OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
1342254721Semaste
1343254721Semaste        if (option_arg_vector_sp.get())
1344254721Semaste        {
1345254721Semaste            OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
1346254721Semaste
1347254721Semaste            for (size_t i = 0; i < option_arg_vector->size(); ++i)
1348254721Semaste            {
1349254721Semaste                OptionArgPair option_pair = (*option_arg_vector)[i];
1350254721Semaste                OptionArgValue value_pair = option_pair.second;
1351254721Semaste                int value_type = value_pair.first;
1352254721Semaste                std::string option = option_pair.first;
1353254721Semaste                std::string value = value_pair.second;
1354254721Semaste                if (option.compare ("<argument>") == 0)
1355254721Semaste                    result_str.Printf (" %s", value.c_str());
1356254721Semaste                else
1357254721Semaste                {
1358254721Semaste                    result_str.Printf (" %s", option.c_str());
1359263363Semaste                    if (value_type != OptionParser::eOptionalArgument)
1360254721Semaste                        result_str.Printf (" ");
1361263363Semaste                    if (value.compare ("<OptionParser::eNoArgument>") != 0)
1362254721Semaste                    {
1363254721Semaste                        int index = GetOptionArgumentPosition (value.c_str());
1364254721Semaste                        if (index == 0)
1365254721Semaste                            result_str.Printf ("%s", value.c_str());
1366254721Semaste                        else if (index >= cmd_args.GetArgumentCount())
1367254721Semaste                        {
1368254721Semaste
1369254721Semaste                            result.AppendErrorWithFormat
1370254721Semaste                            ("Not enough arguments provided; you need at least %d arguments to use this alias.\n",
1371254721Semaste                             index);
1372254721Semaste                            result.SetStatus (eReturnStatusFailed);
1373254721Semaste                            return alias_cmd_obj;
1374254721Semaste                        }
1375254721Semaste                        else
1376254721Semaste                        {
1377254721Semaste                            size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index));
1378254721Semaste                            if (strpos != std::string::npos)
1379254721Semaste                                raw_input_string = raw_input_string.erase (strpos,
1380254721Semaste                                                                          strlen (cmd_args.GetArgumentAtIndex (index)));
1381254721Semaste                            result_str.Printf ("%s", cmd_args.GetArgumentAtIndex (index));
1382254721Semaste                        }
1383254721Semaste                    }
1384254721Semaste                }
1385254721Semaste            }
1386254721Semaste        }
1387254721Semaste
1388254721Semaste        alias_result = result_str.GetData();
1389254721Semaste    }
1390254721Semaste    return alias_cmd_obj;
1391254721Semaste}
1392254721Semaste
1393254721SemasteError
1394254721SemasteCommandInterpreter::PreprocessCommand (std::string &command)
1395254721Semaste{
1396254721Semaste    // The command preprocessor needs to do things to the command
1397254721Semaste    // line before any parsing of arguments or anything else is done.
1398254721Semaste    // The only current stuff that gets proprocessed is anyting enclosed
1399254721Semaste    // in backtick ('`') characters is evaluated as an expression and
1400254721Semaste    // the result of the expression must be a scalar that can be substituted
1401254721Semaste    // into the command. An example would be:
1402254721Semaste    // (lldb) memory read `$rsp + 20`
1403254721Semaste    Error error; // Error for any expressions that might not evaluate
1404254721Semaste    size_t start_backtick;
1405254721Semaste    size_t pos = 0;
1406254721Semaste    while ((start_backtick = command.find ('`', pos)) != std::string::npos)
1407254721Semaste    {
1408254721Semaste        if (start_backtick > 0 && command[start_backtick-1] == '\\')
1409254721Semaste        {
1410254721Semaste            // The backtick was preceeded by a '\' character, remove the slash
1411254721Semaste            // and don't treat the backtick as the start of an expression
1412254721Semaste            command.erase(start_backtick-1, 1);
1413254721Semaste            // No need to add one to start_backtick since we just deleted a char
1414254721Semaste            pos = start_backtick;
1415254721Semaste        }
1416254721Semaste        else
1417254721Semaste        {
1418254721Semaste            const size_t expr_content_start = start_backtick + 1;
1419254721Semaste            const size_t end_backtick = command.find ('`', expr_content_start);
1420254721Semaste            if (end_backtick == std::string::npos)
1421254721Semaste                return error;
1422254721Semaste            else if (end_backtick == expr_content_start)
1423254721Semaste            {
1424254721Semaste                // Empty expression (two backticks in a row)
1425254721Semaste                command.erase (start_backtick, 2);
1426254721Semaste            }
1427254721Semaste            else
1428254721Semaste            {
1429254721Semaste                std::string expr_str (command, expr_content_start, end_backtick - expr_content_start);
1430254721Semaste
1431254721Semaste                ExecutionContext exe_ctx(GetExecutionContext());
1432254721Semaste                Target *target = exe_ctx.GetTargetPtr();
1433254721Semaste                // Get a dummy target to allow for calculator mode while processing backticks.
1434254721Semaste                // This also helps break the infinite loop caused when target is null.
1435254721Semaste                if (!target)
1436254721Semaste                    target = Host::GetDummyTarget(GetDebugger()).get();
1437254721Semaste                if (target)
1438254721Semaste                {
1439254721Semaste                    ValueObjectSP expr_result_valobj_sp;
1440254721Semaste
1441254721Semaste                    EvaluateExpressionOptions options;
1442263367Semaste                    options.SetCoerceToId(false);
1443263367Semaste                    options.SetUnwindOnError(true);
1444263367Semaste                    options.SetIgnoreBreakpoints(true);
1445263367Semaste                    options.SetKeepInMemory(false);
1446263367Semaste                    options.SetTryAllThreads(true);
1447263367Semaste                    options.SetTimeoutUsec(0);
1448254721Semaste
1449254721Semaste                    ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(),
1450254721Semaste                                                                               exe_ctx.GetFramePtr(),
1451254721Semaste                                                                               expr_result_valobj_sp,
1452254721Semaste                                                                               options);
1453254721Semaste
1454254721Semaste                    if (expr_result == eExecutionCompleted)
1455254721Semaste                    {
1456254721Semaste                        Scalar scalar;
1457254721Semaste                        if (expr_result_valobj_sp->ResolveValue (scalar))
1458254721Semaste                        {
1459254721Semaste                            command.erase (start_backtick, end_backtick - start_backtick + 1);
1460254721Semaste                            StreamString value_strm;
1461254721Semaste                            const bool show_type = false;
1462254721Semaste                            scalar.GetValue (&value_strm, show_type);
1463254721Semaste                            size_t value_string_size = value_strm.GetSize();
1464254721Semaste                            if (value_string_size)
1465254721Semaste                            {
1466254721Semaste                                command.insert (start_backtick, value_strm.GetData(), value_string_size);
1467254721Semaste                                pos = start_backtick + value_string_size;
1468254721Semaste                                continue;
1469254721Semaste                            }
1470254721Semaste                            else
1471254721Semaste                            {
1472254721Semaste                                error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str());
1473254721Semaste                            }
1474254721Semaste                        }
1475254721Semaste                        else
1476254721Semaste                        {
1477254721Semaste                            error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str());
1478254721Semaste                        }
1479254721Semaste                    }
1480254721Semaste                    else
1481254721Semaste                    {
1482254721Semaste                        if (expr_result_valobj_sp)
1483254721Semaste                            error = expr_result_valobj_sp->GetError();
1484254721Semaste                        if (error.Success())
1485254721Semaste                        {
1486254721Semaste
1487254721Semaste                            switch (expr_result)
1488254721Semaste                            {
1489254721Semaste                                case eExecutionSetupError:
1490254721Semaste                                    error.SetErrorStringWithFormat("expression setup error for the expression '%s'", expr_str.c_str());
1491254721Semaste                                    break;
1492254721Semaste                                case eExecutionCompleted:
1493254721Semaste                                    break;
1494254721Semaste                                case eExecutionDiscarded:
1495254721Semaste                                    error.SetErrorStringWithFormat("expression discarded for the expression '%s'", expr_str.c_str());
1496254721Semaste                                    break;
1497254721Semaste                                case eExecutionInterrupted:
1498254721Semaste                                    error.SetErrorStringWithFormat("expression interrupted for the expression '%s'", expr_str.c_str());
1499254721Semaste                                    break;
1500254721Semaste                                case eExecutionHitBreakpoint:
1501254721Semaste                                    error.SetErrorStringWithFormat("expression hit breakpoint for the expression '%s'", expr_str.c_str());
1502254721Semaste                                    break;
1503254721Semaste                                case eExecutionTimedOut:
1504254721Semaste                                    error.SetErrorStringWithFormat("expression timed out for the expression '%s'", expr_str.c_str());
1505254721Semaste                                    break;
1506263367Semaste                                case eExecutionStoppedForDebug:
1507263367Semaste                                    error.SetErrorStringWithFormat("expression stop at entry point for debugging for the expression '%s'", expr_str.c_str());
1508263367Semaste                                    break;
1509254721Semaste                            }
1510254721Semaste                        }
1511254721Semaste                    }
1512254721Semaste                }
1513254721Semaste            }
1514254721Semaste            if (error.Fail())
1515254721Semaste                break;
1516254721Semaste        }
1517254721Semaste    }
1518254721Semaste    return error;
1519254721Semaste}
1520254721Semaste
1521254721Semaste
1522254721Semastebool
1523254721SemasteCommandInterpreter::HandleCommand (const char *command_line,
1524254721Semaste                                   LazyBool lazy_add_to_history,
1525254721Semaste                                   CommandReturnObject &result,
1526254721Semaste                                   ExecutionContext *override_context,
1527254721Semaste                                   bool repeat_on_empty_command,
1528254721Semaste                                   bool no_context_switching)
1529254721Semaste
1530254721Semaste{
1531254721Semaste
1532254721Semaste    bool done = false;
1533254721Semaste    CommandObject *cmd_obj = NULL;
1534254721Semaste    bool wants_raw_input = false;
1535254721Semaste    std::string command_string (command_line);
1536254721Semaste    std::string original_command_string (command_line);
1537254721Semaste
1538254721Semaste    Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMANDS));
1539254721Semaste    Host::SetCrashDescriptionWithFormat ("HandleCommand(command = \"%s\")", command_line);
1540254721Semaste
1541254721Semaste    // Make a scoped cleanup object that will clear the crash description string
1542254721Semaste    // on exit of this function.
1543254721Semaste    lldb_utility::CleanUp <const char *> crash_description_cleanup(NULL, Host::SetCrashDescription);
1544254721Semaste
1545254721Semaste    if (log)
1546254721Semaste        log->Printf ("Processing command: %s", command_line);
1547254721Semaste
1548254721Semaste    Timer scoped_timer (__PRETTY_FUNCTION__, "Handling command: %s.", command_line);
1549254721Semaste
1550254721Semaste    if (!no_context_switching)
1551254721Semaste        UpdateExecutionContext (override_context);
1552254721Semaste
1553254721Semaste    bool add_to_history;
1554254721Semaste    if (lazy_add_to_history == eLazyBoolCalculate)
1555254721Semaste        add_to_history = (m_command_source_depth == 0);
1556254721Semaste    else
1557254721Semaste        add_to_history = (lazy_add_to_history == eLazyBoolYes);
1558254721Semaste
1559254721Semaste    bool empty_command = false;
1560254721Semaste    bool comment_command = false;
1561254721Semaste    if (command_string.empty())
1562254721Semaste        empty_command = true;
1563254721Semaste    else
1564254721Semaste    {
1565254721Semaste        const char *k_space_characters = "\t\n\v\f\r ";
1566254721Semaste
1567254721Semaste        size_t non_space = command_string.find_first_not_of (k_space_characters);
1568254721Semaste        // Check for empty line or comment line (lines whose first
1569254721Semaste        // non-space character is the comment character for this interpreter)
1570254721Semaste        if (non_space == std::string::npos)
1571254721Semaste            empty_command = true;
1572254721Semaste        else if (command_string[non_space] == m_comment_char)
1573254721Semaste             comment_command = true;
1574254721Semaste        else if (command_string[non_space] == CommandHistory::g_repeat_char)
1575254721Semaste        {
1576254721Semaste            const char *history_string = m_command_history.FindString(command_string.c_str() + non_space);
1577254721Semaste            if (history_string == NULL)
1578254721Semaste            {
1579254721Semaste                result.AppendErrorWithFormat ("Could not find entry: %s in history", command_string.c_str());
1580254721Semaste                result.SetStatus(eReturnStatusFailed);
1581254721Semaste                return false;
1582254721Semaste            }
1583254721Semaste            add_to_history = false;
1584254721Semaste            command_string = history_string;
1585254721Semaste            original_command_string = history_string;
1586254721Semaste        }
1587254721Semaste    }
1588254721Semaste
1589254721Semaste    if (empty_command)
1590254721Semaste    {
1591254721Semaste        if (repeat_on_empty_command)
1592254721Semaste        {
1593254721Semaste            if (m_command_history.IsEmpty())
1594254721Semaste            {
1595254721Semaste                result.AppendError ("empty command");
1596254721Semaste                result.SetStatus(eReturnStatusFailed);
1597254721Semaste                return false;
1598254721Semaste            }
1599254721Semaste            else
1600254721Semaste            {
1601254721Semaste                command_line = m_repeat_command.c_str();
1602254721Semaste                command_string = command_line;
1603254721Semaste                original_command_string = command_line;
1604254721Semaste                if (m_repeat_command.empty())
1605254721Semaste                {
1606254721Semaste                    result.AppendErrorWithFormat("No auto repeat.\n");
1607254721Semaste                    result.SetStatus (eReturnStatusFailed);
1608254721Semaste                    return false;
1609254721Semaste                }
1610254721Semaste            }
1611254721Semaste            add_to_history = false;
1612254721Semaste        }
1613254721Semaste        else
1614254721Semaste        {
1615254721Semaste            result.SetStatus (eReturnStatusSuccessFinishNoResult);
1616254721Semaste            return true;
1617254721Semaste        }
1618254721Semaste    }
1619254721Semaste    else if (comment_command)
1620254721Semaste    {
1621254721Semaste        result.SetStatus (eReturnStatusSuccessFinishNoResult);
1622254721Semaste        return true;
1623254721Semaste    }
1624254721Semaste
1625254721Semaste
1626254721Semaste    Error error (PreprocessCommand (command_string));
1627254721Semaste
1628254721Semaste    if (error.Fail())
1629254721Semaste    {
1630254721Semaste        result.AppendError (error.AsCString());
1631254721Semaste        result.SetStatus(eReturnStatusFailed);
1632254721Semaste        return false;
1633254721Semaste    }
1634254721Semaste    // Phase 1.
1635254721Semaste
1636254721Semaste    // Before we do ANY kind of argument processing, etc. we need to figure out what the real/final command object
1637254721Semaste    // is for the specified command, and whether or not it wants raw input.  This gets complicated by the fact that
1638254721Semaste    // the user could have specified an alias, and in translating the alias there may also be command options and/or
1639254721Semaste    // even data (including raw text strings) that need to be found and inserted into the command line as part of
1640254721Semaste    // the translation.  So this first step is plain look-up & replacement, resulting in three things:  1). the command
1641254721Semaste    // object whose Execute method will actually be called; 2). a revised command string, with all substitutions &
1642254721Semaste    // replacements taken care of; 3). whether or not the Execute function wants raw input or not.
1643254721Semaste
1644254721Semaste    StreamString revised_command_line;
1645254721Semaste    size_t actual_cmd_name_len = 0;
1646254721Semaste    std::string next_word;
1647254721Semaste    StringList matches;
1648254721Semaste    while (!done)
1649254721Semaste    {
1650254721Semaste        char quote_char = '\0';
1651254721Semaste        std::string suffix;
1652254721Semaste        ExtractCommand (command_string, next_word, suffix, quote_char);
1653254721Semaste        if (cmd_obj == NULL)
1654254721Semaste        {
1655254721Semaste            std::string full_name;
1656254721Semaste            if (GetAliasFullName(next_word.c_str(), full_name))
1657254721Semaste            {
1658254721Semaste                std::string alias_result;
1659254721Semaste                cmd_obj = BuildAliasResult (full_name.c_str(), command_string, alias_result, result);
1660254721Semaste                revised_command_line.Printf ("%s", alias_result.c_str());
1661254721Semaste                if (cmd_obj)
1662254721Semaste                {
1663254721Semaste                    wants_raw_input = cmd_obj->WantsRawCommandString ();
1664254721Semaste                    actual_cmd_name_len = strlen (cmd_obj->GetCommandName());
1665254721Semaste                }
1666254721Semaste            }
1667254721Semaste            else
1668254721Semaste            {
1669254721Semaste                cmd_obj = GetCommandObject (next_word.c_str(), &matches);
1670254721Semaste                if (cmd_obj)
1671254721Semaste                {
1672254721Semaste                    actual_cmd_name_len += next_word.length();
1673254721Semaste                    revised_command_line.Printf ("%s", next_word.c_str());
1674254721Semaste                    wants_raw_input = cmd_obj->WantsRawCommandString ();
1675254721Semaste                }
1676254721Semaste                else
1677254721Semaste                {
1678254721Semaste                    revised_command_line.Printf ("%s", next_word.c_str());
1679254721Semaste                }
1680254721Semaste            }
1681254721Semaste        }
1682254721Semaste        else
1683254721Semaste        {
1684254721Semaste            if (cmd_obj->IsMultiwordObject ())
1685254721Semaste            {
1686254721Semaste                CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (next_word.c_str());
1687254721Semaste                if (sub_cmd_obj)
1688254721Semaste                {
1689254721Semaste                    actual_cmd_name_len += next_word.length() + 1;
1690254721Semaste                    revised_command_line.Printf (" %s", next_word.c_str());
1691254721Semaste                    cmd_obj = sub_cmd_obj;
1692254721Semaste                    wants_raw_input = cmd_obj->WantsRawCommandString ();
1693254721Semaste                }
1694254721Semaste                else
1695254721Semaste                {
1696254721Semaste                    if (quote_char)
1697254721Semaste                        revised_command_line.Printf (" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char);
1698254721Semaste                    else
1699254721Semaste                        revised_command_line.Printf (" %s%s", next_word.c_str(), suffix.c_str());
1700254721Semaste                    done = true;
1701254721Semaste                }
1702254721Semaste            }
1703254721Semaste            else
1704254721Semaste            {
1705254721Semaste                if (quote_char)
1706254721Semaste                    revised_command_line.Printf (" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char);
1707254721Semaste                else
1708254721Semaste                    revised_command_line.Printf (" %s%s", next_word.c_str(), suffix.c_str());
1709254721Semaste                done = true;
1710254721Semaste            }
1711254721Semaste        }
1712254721Semaste
1713254721Semaste        if (cmd_obj == NULL)
1714254721Semaste        {
1715254721Semaste            const size_t num_matches = matches.GetSize();
1716254721Semaste            if (matches.GetSize() > 1) {
1717254721Semaste                StreamString error_msg;
1718254721Semaste                error_msg.Printf ("Ambiguous command '%s'. Possible matches:\n", next_word.c_str());
1719254721Semaste
1720254721Semaste                for (uint32_t i = 0; i < num_matches; ++i) {
1721254721Semaste                    error_msg.Printf ("\t%s\n", matches.GetStringAtIndex(i));
1722254721Semaste                }
1723254721Semaste                result.AppendRawError (error_msg.GetString().c_str());
1724254721Semaste            } else {
1725254721Semaste                // We didn't have only one match, otherwise we wouldn't get here.
1726254721Semaste                assert(num_matches == 0);
1727254721Semaste                result.AppendErrorWithFormat ("'%s' is not a valid command.\n", next_word.c_str());
1728254721Semaste            }
1729254721Semaste            result.SetStatus (eReturnStatusFailed);
1730254721Semaste            return false;
1731254721Semaste        }
1732254721Semaste
1733254721Semaste        if (cmd_obj->IsMultiwordObject ())
1734254721Semaste        {
1735254721Semaste            if (!suffix.empty())
1736254721Semaste            {
1737254721Semaste
1738254721Semaste                result.AppendErrorWithFormat ("command '%s' did not recognize '%s%s%s' as valid (subcommand might be invalid).\n",
1739254721Semaste                                              cmd_obj->GetCommandName(),
1740254721Semaste                                              next_word.empty() ? "" : next_word.c_str(),
1741254721Semaste                                              next_word.empty() ? " -- " : " ",
1742254721Semaste                                              suffix.c_str());
1743254721Semaste                result.SetStatus (eReturnStatusFailed);
1744254721Semaste                return false;
1745254721Semaste            }
1746254721Semaste        }
1747254721Semaste        else
1748254721Semaste        {
1749254721Semaste            // If we found a normal command, we are done
1750254721Semaste            done = true;
1751254721Semaste            if (!suffix.empty())
1752254721Semaste            {
1753254721Semaste                switch (suffix[0])
1754254721Semaste                {
1755254721Semaste                case '/':
1756254721Semaste                    // GDB format suffixes
1757254721Semaste                    {
1758254721Semaste                        Options *command_options = cmd_obj->GetOptions();
1759254721Semaste                        if (command_options && command_options->SupportsLongOption("gdb-format"))
1760254721Semaste                        {
1761254721Semaste                            std::string gdb_format_option ("--gdb-format=");
1762254721Semaste                            gdb_format_option += (suffix.c_str() + 1);
1763254721Semaste
1764254721Semaste                            bool inserted = false;
1765254721Semaste                            std::string &cmd = revised_command_line.GetString();
1766254721Semaste                            size_t arg_terminator_idx = FindArgumentTerminator (cmd);
1767254721Semaste                            if (arg_terminator_idx != std::string::npos)
1768254721Semaste                            {
1769254721Semaste                                // Insert the gdb format option before the "--" that terminates options
1770254721Semaste                                gdb_format_option.append(1,' ');
1771254721Semaste                                cmd.insert(arg_terminator_idx, gdb_format_option);
1772254721Semaste                                inserted = true;
1773254721Semaste                            }
1774254721Semaste
1775254721Semaste                            if (!inserted)
1776254721Semaste                                revised_command_line.Printf (" %s", gdb_format_option.c_str());
1777254721Semaste
1778254721Semaste                            if (wants_raw_input && FindArgumentTerminator(cmd) == std::string::npos)
1779254721Semaste                                revised_command_line.PutCString (" --");
1780254721Semaste                        }
1781254721Semaste                        else
1782254721Semaste                        {
1783254721Semaste                            result.AppendErrorWithFormat ("the '%s' command doesn't support the --gdb-format option\n",
1784254721Semaste                                                          cmd_obj->GetCommandName());
1785254721Semaste                            result.SetStatus (eReturnStatusFailed);
1786254721Semaste                            return false;
1787254721Semaste                        }
1788254721Semaste                    }
1789254721Semaste                    break;
1790254721Semaste
1791254721Semaste                default:
1792254721Semaste                    result.AppendErrorWithFormat ("unknown command shorthand suffix: '%s'\n",
1793254721Semaste                                                  suffix.c_str());
1794254721Semaste                    result.SetStatus (eReturnStatusFailed);
1795254721Semaste                    return false;
1796254721Semaste
1797254721Semaste                }
1798254721Semaste            }
1799254721Semaste        }
1800254721Semaste        if (command_string.length() == 0)
1801254721Semaste            done = true;
1802254721Semaste
1803254721Semaste    }
1804254721Semaste
1805254721Semaste    if (!command_string.empty())
1806254721Semaste        revised_command_line.Printf (" %s", command_string.c_str());
1807254721Semaste
1808254721Semaste    // End of Phase 1.
1809254721Semaste    // At this point cmd_obj should contain the CommandObject whose Execute method will be called, if the command
1810254721Semaste    // specified was valid; revised_command_line contains the complete command line (including command name(s)),
1811254721Semaste    // fully translated with all substitutions & translations taken care of (still in raw text format); and
1812254721Semaste    // wants_raw_input specifies whether the Execute method expects raw input or not.
1813254721Semaste
1814254721Semaste
1815254721Semaste    if (log)
1816254721Semaste    {
1817254721Semaste        log->Printf ("HandleCommand, cmd_obj : '%s'", cmd_obj ? cmd_obj->GetCommandName() : "<not found>");
1818254721Semaste        log->Printf ("HandleCommand, revised_command_line: '%s'", revised_command_line.GetData());
1819254721Semaste        log->Printf ("HandleCommand, wants_raw_input:'%s'", wants_raw_input ? "True" : "False");
1820254721Semaste    }
1821254721Semaste
1822254721Semaste    // Phase 2.
1823254721Semaste    // Take care of things like setting up the history command & calling the appropriate Execute method on the
1824254721Semaste    // CommandObject, with the appropriate arguments.
1825254721Semaste
1826254721Semaste    if (cmd_obj != NULL)
1827254721Semaste    {
1828254721Semaste        if (add_to_history)
1829254721Semaste        {
1830254721Semaste            Args command_args (revised_command_line.GetData());
1831254721Semaste            const char *repeat_command = cmd_obj->GetRepeatCommand(command_args, 0);
1832254721Semaste            if (repeat_command != NULL)
1833254721Semaste                m_repeat_command.assign(repeat_command);
1834254721Semaste            else
1835254721Semaste                m_repeat_command.assign(original_command_string.c_str());
1836254721Semaste
1837254721Semaste            m_command_history.AppendString (original_command_string);
1838254721Semaste        }
1839254721Semaste
1840254721Semaste        command_string = revised_command_line.GetData();
1841254721Semaste        std::string command_name (cmd_obj->GetCommandName());
1842254721Semaste        std::string remainder;
1843254721Semaste        if (actual_cmd_name_len < command_string.length())
1844254721Semaste            remainder = command_string.substr (actual_cmd_name_len);  // Note: 'actual_cmd_name_len' may be considerably shorter
1845254721Semaste                                                           // than cmd_obj->GetCommandName(), because name completion
1846254721Semaste                                                           // allows users to enter short versions of the names,
1847254721Semaste                                                           // e.g. 'br s' for 'breakpoint set'.
1848254721Semaste
1849254721Semaste        // Remove any initial spaces
1850254721Semaste        std::string white_space (" \t\v");
1851254721Semaste        size_t pos = remainder.find_first_not_of (white_space);
1852254721Semaste        if (pos != 0 && pos != std::string::npos)
1853254721Semaste            remainder.erase(0, pos);
1854254721Semaste
1855254721Semaste        if (log)
1856254721Semaste            log->Printf ("HandleCommand, command line after removing command name(s): '%s'", remainder.c_str());
1857254721Semaste
1858254721Semaste        cmd_obj->Execute (remainder.c_str(), result);
1859254721Semaste    }
1860254721Semaste    else
1861254721Semaste    {
1862254721Semaste        // We didn't find the first command object, so complete the first argument.
1863254721Semaste        Args command_args (revised_command_line.GetData());
1864254721Semaste        StringList matches;
1865254721Semaste        int num_matches;
1866254721Semaste        int cursor_index = 0;
1867254721Semaste        int cursor_char_position = strlen (command_args.GetArgumentAtIndex(0));
1868254721Semaste        bool word_complete;
1869254721Semaste        num_matches = HandleCompletionMatches (command_args,
1870254721Semaste                                               cursor_index,
1871254721Semaste                                               cursor_char_position,
1872254721Semaste                                               0,
1873254721Semaste                                               -1,
1874254721Semaste                                               word_complete,
1875254721Semaste                                               matches);
1876254721Semaste
1877254721Semaste        if (num_matches > 0)
1878254721Semaste        {
1879254721Semaste            std::string error_msg;
1880254721Semaste            error_msg.assign ("ambiguous command '");
1881254721Semaste            error_msg.append(command_args.GetArgumentAtIndex(0));
1882254721Semaste            error_msg.append ("'.");
1883254721Semaste
1884254721Semaste            error_msg.append (" Possible completions:");
1885254721Semaste            for (int i = 0; i < num_matches; i++)
1886254721Semaste            {
1887254721Semaste                error_msg.append ("\n\t");
1888254721Semaste                error_msg.append (matches.GetStringAtIndex (i));
1889254721Semaste            }
1890254721Semaste            error_msg.append ("\n");
1891254721Semaste            result.AppendRawError (error_msg.c_str());
1892254721Semaste        }
1893254721Semaste        else
1894254721Semaste            result.AppendErrorWithFormat ("Unrecognized command '%s'.\n", command_args.GetArgumentAtIndex (0));
1895254721Semaste
1896254721Semaste        result.SetStatus (eReturnStatusFailed);
1897254721Semaste    }
1898254721Semaste
1899254721Semaste    if (log)
1900254721Semaste      log->Printf ("HandleCommand, command %s", (result.Succeeded() ? "succeeded" : "did not succeed"));
1901254721Semaste
1902254721Semaste    return result.Succeeded();
1903254721Semaste}
1904254721Semaste
1905254721Semasteint
1906254721SemasteCommandInterpreter::HandleCompletionMatches (Args &parsed_line,
1907254721Semaste                                             int &cursor_index,
1908254721Semaste                                             int &cursor_char_position,
1909254721Semaste                                             int match_start_point,
1910254721Semaste                                             int max_return_elements,
1911254721Semaste                                             bool &word_complete,
1912254721Semaste                                             StringList &matches)
1913254721Semaste{
1914254721Semaste    int num_command_matches = 0;
1915254721Semaste    bool look_for_subcommand = false;
1916254721Semaste
1917254721Semaste    // For any of the command completions a unique match will be a complete word.
1918254721Semaste    word_complete = true;
1919254721Semaste
1920254721Semaste    if (cursor_index == -1)
1921254721Semaste    {
1922254721Semaste        // We got nothing on the command line, so return the list of commands
1923254721Semaste        bool include_aliases = true;
1924254721Semaste        num_command_matches = GetCommandNamesMatchingPartialString ("", include_aliases, matches);
1925254721Semaste    }
1926254721Semaste    else if (cursor_index == 0)
1927254721Semaste    {
1928254721Semaste        // The cursor is in the first argument, so just do a lookup in the dictionary.
1929254721Semaste        CommandObject *cmd_obj = GetCommandObject (parsed_line.GetArgumentAtIndex(0), &matches);
1930254721Semaste        num_command_matches = matches.GetSize();
1931254721Semaste
1932254721Semaste        if (num_command_matches == 1
1933254721Semaste            && cmd_obj && cmd_obj->IsMultiwordObject()
1934254721Semaste            && matches.GetStringAtIndex(0) != NULL
1935254721Semaste            && strcmp (parsed_line.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
1936254721Semaste        {
1937269024Semaste            if (parsed_line.GetArgumentCount() == 1)
1938269024Semaste            {
1939269024Semaste                word_complete = true;
1940269024Semaste            }
1941269024Semaste            else
1942269024Semaste            {
1943269024Semaste                look_for_subcommand = true;
1944269024Semaste                num_command_matches = 0;
1945269024Semaste                matches.DeleteStringAtIndex(0);
1946269024Semaste                parsed_line.AppendArgument ("");
1947269024Semaste                cursor_index++;
1948269024Semaste                cursor_char_position = 0;
1949269024Semaste            }
1950254721Semaste        }
1951254721Semaste    }
1952254721Semaste
1953254721Semaste    if (cursor_index > 0 || look_for_subcommand)
1954254721Semaste    {
1955254721Semaste        // We are completing further on into a commands arguments, so find the command and tell it
1956254721Semaste        // to complete the command.
1957254721Semaste        // First see if there is a matching initial command:
1958254721Semaste        CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0));
1959254721Semaste        if (command_object == NULL)
1960254721Semaste        {
1961254721Semaste            return 0;
1962254721Semaste        }
1963254721Semaste        else
1964254721Semaste        {
1965254721Semaste            parsed_line.Shift();
1966254721Semaste            cursor_index--;
1967254721Semaste            num_command_matches = command_object->HandleCompletion (parsed_line,
1968254721Semaste                                                                    cursor_index,
1969254721Semaste                                                                    cursor_char_position,
1970254721Semaste                                                                    match_start_point,
1971254721Semaste                                                                    max_return_elements,
1972254721Semaste                                                                    word_complete,
1973254721Semaste                                                                    matches);
1974254721Semaste        }
1975254721Semaste    }
1976254721Semaste
1977254721Semaste    return num_command_matches;
1978254721Semaste
1979254721Semaste}
1980254721Semaste
1981254721Semasteint
1982254721SemasteCommandInterpreter::HandleCompletion (const char *current_line,
1983254721Semaste                                      const char *cursor,
1984254721Semaste                                      const char *last_char,
1985254721Semaste                                      int match_start_point,
1986254721Semaste                                      int max_return_elements,
1987254721Semaste                                      StringList &matches)
1988254721Semaste{
1989254721Semaste    // We parse the argument up to the cursor, so the last argument in parsed_line is
1990254721Semaste    // the one containing the cursor, and the cursor is after the last character.
1991254721Semaste
1992254721Semaste    Args parsed_line(current_line, last_char - current_line);
1993254721Semaste    Args partial_parsed_line(current_line, cursor - current_line);
1994254721Semaste
1995254721Semaste    // Don't complete comments, and if the line we are completing is just the history repeat character,
1996254721Semaste    // substitute the appropriate history line.
1997254721Semaste    const char *first_arg = parsed_line.GetArgumentAtIndex(0);
1998254721Semaste    if (first_arg)
1999254721Semaste    {
2000254721Semaste        if (first_arg[0] == m_comment_char)
2001254721Semaste            return 0;
2002254721Semaste        else if (first_arg[0] == CommandHistory::g_repeat_char)
2003254721Semaste        {
2004254721Semaste            const char *history_string = m_command_history.FindString (first_arg);
2005254721Semaste            if (history_string != NULL)
2006254721Semaste            {
2007254721Semaste                matches.Clear();
2008254721Semaste                matches.InsertStringAtIndex(0, history_string);
2009254721Semaste                return -2;
2010254721Semaste            }
2011254721Semaste            else
2012254721Semaste                return 0;
2013254721Semaste
2014254721Semaste        }
2015254721Semaste    }
2016254721Semaste
2017254721Semaste
2018254721Semaste    int num_args = partial_parsed_line.GetArgumentCount();
2019254721Semaste    int cursor_index = partial_parsed_line.GetArgumentCount() - 1;
2020254721Semaste    int cursor_char_position;
2021254721Semaste
2022254721Semaste    if (cursor_index == -1)
2023254721Semaste        cursor_char_position = 0;
2024254721Semaste    else
2025254721Semaste        cursor_char_position = strlen (partial_parsed_line.GetArgumentAtIndex(cursor_index));
2026254721Semaste
2027254721Semaste    if (cursor > current_line && cursor[-1] == ' ')
2028254721Semaste    {
2029254721Semaste        // We are just after a space.  If we are in an argument, then we will continue
2030254721Semaste        // parsing, but if we are between arguments, then we have to complete whatever the next
2031254721Semaste        // element would be.
2032254721Semaste        // We can distinguish the two cases because if we are in an argument (e.g. because the space is
2033254721Semaste        // protected by a quote) then the space will also be in the parsed argument...
2034254721Semaste
2035254721Semaste        const char *current_elem = partial_parsed_line.GetArgumentAtIndex(cursor_index);
2036254721Semaste        if (cursor_char_position == 0 || current_elem[cursor_char_position - 1] != ' ')
2037254721Semaste        {
2038269024Semaste            parsed_line.InsertArgumentAtIndex(cursor_index + 1, "", '\0');
2039254721Semaste            cursor_index++;
2040254721Semaste            cursor_char_position = 0;
2041254721Semaste        }
2042254721Semaste    }
2043254721Semaste
2044254721Semaste    int num_command_matches;
2045254721Semaste
2046254721Semaste    matches.Clear();
2047254721Semaste
2048254721Semaste    // Only max_return_elements == -1 is supported at present:
2049254721Semaste    assert (max_return_elements == -1);
2050254721Semaste    bool word_complete;
2051254721Semaste    num_command_matches = HandleCompletionMatches (parsed_line,
2052254721Semaste                                                   cursor_index,
2053254721Semaste                                                   cursor_char_position,
2054254721Semaste                                                   match_start_point,
2055254721Semaste                                                   max_return_elements,
2056254721Semaste                                                   word_complete,
2057254721Semaste                                                   matches);
2058254721Semaste
2059254721Semaste    if (num_command_matches <= 0)
2060254721Semaste            return num_command_matches;
2061254721Semaste
2062254721Semaste    if (num_args == 0)
2063254721Semaste    {
2064254721Semaste        // If we got an empty string, insert nothing.
2065254721Semaste        matches.InsertStringAtIndex(0, "");
2066254721Semaste    }
2067254721Semaste    else
2068254721Semaste    {
2069254721Semaste        // Now figure out if there is a common substring, and if so put that in element 0, otherwise
2070254721Semaste        // put an empty string in element 0.
2071254721Semaste        std::string command_partial_str;
2072254721Semaste        if (cursor_index >= 0)
2073254721Semaste            command_partial_str.assign(parsed_line.GetArgumentAtIndex(cursor_index),
2074254721Semaste                                       parsed_line.GetArgumentAtIndex(cursor_index) + cursor_char_position);
2075254721Semaste
2076254721Semaste        std::string common_prefix;
2077254721Semaste        matches.LongestCommonPrefix (common_prefix);
2078254721Semaste        const size_t partial_name_len = command_partial_str.size();
2079254721Semaste
2080254721Semaste        // If we matched a unique single command, add a space...
2081254721Semaste        // Only do this if the completer told us this was a complete word, however...
2082254721Semaste        if (num_command_matches == 1 && word_complete)
2083254721Semaste        {
2084254721Semaste            char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index);
2085254721Semaste            if (quote_char != '\0')
2086254721Semaste                common_prefix.push_back(quote_char);
2087254721Semaste
2088254721Semaste            common_prefix.push_back(' ');
2089254721Semaste        }
2090254721Semaste        common_prefix.erase (0, partial_name_len);
2091254721Semaste        matches.InsertStringAtIndex(0, common_prefix.c_str());
2092254721Semaste    }
2093254721Semaste    return num_command_matches;
2094254721Semaste}
2095254721Semaste
2096254721Semaste
2097254721SemasteCommandInterpreter::~CommandInterpreter ()
2098254721Semaste{
2099254721Semaste}
2100254721Semaste
2101254721Semastevoid
2102269024SemasteCommandInterpreter::UpdatePrompt (const char *new_prompt)
2103254721Semaste{
2104269024Semaste    EventSP prompt_change_event_sp (new Event(eBroadcastBitResetPrompt, new EventDataBytes (new_prompt)));;
2105269024Semaste    BroadcastEvent (prompt_change_event_sp);
2106269024Semaste    if (m_command_io_handler_sp)
2107269024Semaste        m_command_io_handler_sp->SetPrompt(new_prompt);
2108254721Semaste}
2109254721Semaste
2110254721Semaste
2111254721Semastebool
2112254721SemasteCommandInterpreter::Confirm (const char *message, bool default_answer)
2113254721Semaste{
2114254721Semaste    // Check AutoConfirm first:
2115254721Semaste    if (m_debugger.GetAutoConfirm())
2116254721Semaste        return default_answer;
2117269024Semaste
2118269024Semaste    IOHandlerConfirm *confirm = new IOHandlerConfirm(m_debugger,
2119269024Semaste                                                     message,
2120269024Semaste                                                     default_answer);
2121269024Semaste    IOHandlerSP io_handler_sp (confirm);
2122269024Semaste    m_debugger.RunIOHandler (io_handler_sp);
2123269024Semaste    return confirm->GetResponse();
2124254721Semaste}
2125254721Semaste
2126254721SemasteOptionArgVectorSP
2127254721SemasteCommandInterpreter::GetAliasOptions (const char *alias_name)
2128254721Semaste{
2129254721Semaste    OptionArgMap::iterator pos;
2130254721Semaste    OptionArgVectorSP ret_val;
2131254721Semaste
2132254721Semaste    std::string alias (alias_name);
2133254721Semaste
2134254721Semaste    if (HasAliasOptions())
2135254721Semaste    {
2136254721Semaste        pos = m_alias_options.find (alias);
2137254721Semaste        if (pos != m_alias_options.end())
2138254721Semaste          ret_val = pos->second;
2139254721Semaste    }
2140254721Semaste
2141254721Semaste    return ret_val;
2142254721Semaste}
2143254721Semaste
2144254721Semastevoid
2145254721SemasteCommandInterpreter::RemoveAliasOptions (const char *alias_name)
2146254721Semaste{
2147254721Semaste    OptionArgMap::iterator pos = m_alias_options.find(alias_name);
2148254721Semaste    if (pos != m_alias_options.end())
2149254721Semaste    {
2150254721Semaste        m_alias_options.erase (pos);
2151254721Semaste    }
2152254721Semaste}
2153254721Semaste
2154254721Semastevoid
2155254721SemasteCommandInterpreter::AddOrReplaceAliasOptions (const char *alias_name, OptionArgVectorSP &option_arg_vector_sp)
2156254721Semaste{
2157254721Semaste    m_alias_options[alias_name] = option_arg_vector_sp;
2158254721Semaste}
2159254721Semaste
2160254721Semastebool
2161254721SemasteCommandInterpreter::HasCommands ()
2162254721Semaste{
2163254721Semaste    return (!m_command_dict.empty());
2164254721Semaste}
2165254721Semaste
2166254721Semastebool
2167254721SemasteCommandInterpreter::HasAliases ()
2168254721Semaste{
2169254721Semaste    return (!m_alias_dict.empty());
2170254721Semaste}
2171254721Semaste
2172254721Semastebool
2173254721SemasteCommandInterpreter::HasUserCommands ()
2174254721Semaste{
2175254721Semaste    return (!m_user_dict.empty());
2176254721Semaste}
2177254721Semaste
2178254721Semastebool
2179254721SemasteCommandInterpreter::HasAliasOptions ()
2180254721Semaste{
2181254721Semaste    return (!m_alias_options.empty());
2182254721Semaste}
2183254721Semaste
2184254721Semastevoid
2185254721SemasteCommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj,
2186254721Semaste                                           const char *alias_name,
2187254721Semaste                                           Args &cmd_args,
2188254721Semaste                                           std::string &raw_input_string,
2189254721Semaste                                           CommandReturnObject &result)
2190254721Semaste{
2191254721Semaste    OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name);
2192254721Semaste
2193254721Semaste    bool wants_raw_input = alias_cmd_obj->WantsRawCommandString();
2194254721Semaste
2195254721Semaste    // Make sure that the alias name is the 0th element in cmd_args
2196254721Semaste    std::string alias_name_str = alias_name;
2197254721Semaste    if (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0)
2198254721Semaste        cmd_args.Unshift (alias_name);
2199254721Semaste
2200254721Semaste    Args new_args (alias_cmd_obj->GetCommandName());
2201254721Semaste    if (new_args.GetArgumentCount() == 2)
2202254721Semaste        new_args.Shift();
2203254721Semaste
2204254721Semaste    if (option_arg_vector_sp.get())
2205254721Semaste    {
2206254721Semaste        if (wants_raw_input)
2207254721Semaste        {
2208254721Semaste            // We have a command that both has command options and takes raw input.  Make *sure* it has a
2209254721Semaste            // " -- " in the right place in the raw_input_string.
2210254721Semaste            size_t pos = raw_input_string.find(" -- ");
2211254721Semaste            if (pos == std::string::npos)
2212254721Semaste            {
2213254721Semaste                // None found; assume it goes at the beginning of the raw input string
2214254721Semaste                raw_input_string.insert (0, " -- ");
2215254721Semaste            }
2216254721Semaste        }
2217254721Semaste
2218254721Semaste        OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
2219254721Semaste        const size_t old_size = cmd_args.GetArgumentCount();
2220254721Semaste        std::vector<bool> used (old_size + 1, false);
2221254721Semaste
2222254721Semaste        used[0] = true;
2223254721Semaste
2224254721Semaste        for (size_t i = 0; i < option_arg_vector->size(); ++i)
2225254721Semaste        {
2226254721Semaste            OptionArgPair option_pair = (*option_arg_vector)[i];
2227254721Semaste            OptionArgValue value_pair = option_pair.second;
2228254721Semaste            int value_type = value_pair.first;
2229254721Semaste            std::string option = option_pair.first;
2230254721Semaste            std::string value = value_pair.second;
2231254721Semaste            if (option.compare ("<argument>") == 0)
2232254721Semaste            {
2233254721Semaste                if (!wants_raw_input
2234254721Semaste                    || (value.compare("--") != 0)) // Since we inserted this above, make sure we don't insert it twice
2235254721Semaste                    new_args.AppendArgument (value.c_str());
2236254721Semaste            }
2237254721Semaste            else
2238254721Semaste            {
2239263363Semaste                if (value_type != OptionParser::eOptionalArgument)
2240254721Semaste                    new_args.AppendArgument (option.c_str());
2241254721Semaste                if (value.compare ("<no-argument>") != 0)
2242254721Semaste                {
2243254721Semaste                    int index = GetOptionArgumentPosition (value.c_str());
2244254721Semaste                    if (index == 0)
2245254721Semaste                    {
2246254721Semaste                        // value was NOT a positional argument; must be a real value
2247263363Semaste                        if (value_type != OptionParser::eOptionalArgument)
2248254721Semaste                            new_args.AppendArgument (value.c_str());
2249254721Semaste                        else
2250254721Semaste                        {
2251254721Semaste                            char buffer[255];
2252254721Semaste                            ::snprintf (buffer, sizeof (buffer), "%s%s", option.c_str(), value.c_str());
2253254721Semaste                            new_args.AppendArgument (buffer);
2254254721Semaste                        }
2255254721Semaste
2256254721Semaste                    }
2257254721Semaste                    else if (index >= cmd_args.GetArgumentCount())
2258254721Semaste                    {
2259254721Semaste                        result.AppendErrorWithFormat
2260254721Semaste                                    ("Not enough arguments provided; you need at least %d arguments to use this alias.\n",
2261254721Semaste                                     index);
2262254721Semaste                        result.SetStatus (eReturnStatusFailed);
2263254721Semaste                        return;
2264254721Semaste                    }
2265254721Semaste                    else
2266254721Semaste                    {
2267254721Semaste                        // Find and remove cmd_args.GetArgumentAtIndex(i) from raw_input_string
2268254721Semaste                        size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index));
2269254721Semaste                        if (strpos != std::string::npos)
2270254721Semaste                        {
2271254721Semaste                            raw_input_string = raw_input_string.erase (strpos, strlen (cmd_args.GetArgumentAtIndex (index)));
2272254721Semaste                        }
2273254721Semaste
2274263363Semaste                        if (value_type != OptionParser::eOptionalArgument)
2275254721Semaste                            new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index));
2276254721Semaste                        else
2277254721Semaste                        {
2278254721Semaste                            char buffer[255];
2279254721Semaste                            ::snprintf (buffer, sizeof(buffer), "%s%s", option.c_str(),
2280254721Semaste                                        cmd_args.GetArgumentAtIndex (index));
2281254721Semaste                            new_args.AppendArgument (buffer);
2282254721Semaste                        }
2283254721Semaste                        used[index] = true;
2284254721Semaste                    }
2285254721Semaste                }
2286254721Semaste            }
2287254721Semaste        }
2288254721Semaste
2289254721Semaste        for (size_t j = 0; j < cmd_args.GetArgumentCount(); ++j)
2290254721Semaste        {
2291254721Semaste            if (!used[j] && !wants_raw_input)
2292254721Semaste                new_args.AppendArgument (cmd_args.GetArgumentAtIndex (j));
2293254721Semaste        }
2294254721Semaste
2295254721Semaste        cmd_args.Clear();
2296254721Semaste        cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector());
2297254721Semaste    }
2298254721Semaste    else
2299254721Semaste    {
2300254721Semaste        result.SetStatus (eReturnStatusSuccessFinishNoResult);
2301254721Semaste        // This alias was not created with any options; nothing further needs to be done, unless it is a command that
2302254721Semaste        // wants raw input, in which case we need to clear the rest of the data from cmd_args, since its in the raw
2303254721Semaste        // input string.
2304254721Semaste        if (wants_raw_input)
2305254721Semaste        {
2306254721Semaste            cmd_args.Clear();
2307254721Semaste            cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector());
2308254721Semaste        }
2309254721Semaste        return;
2310254721Semaste    }
2311254721Semaste
2312254721Semaste    result.SetStatus (eReturnStatusSuccessFinishNoResult);
2313254721Semaste    return;
2314254721Semaste}
2315254721Semaste
2316254721Semaste
2317254721Semasteint
2318254721SemasteCommandInterpreter::GetOptionArgumentPosition (const char *in_string)
2319254721Semaste{
2320254721Semaste    int position = 0;   // Any string that isn't an argument position, i.e. '%' followed by an integer, gets a position
2321254721Semaste                        // of zero.
2322254721Semaste
2323254721Semaste    char *cptr = (char *) in_string;
2324254721Semaste
2325254721Semaste    // Does it start with '%'
2326254721Semaste    if (cptr[0] == '%')
2327254721Semaste    {
2328254721Semaste        ++cptr;
2329254721Semaste
2330254721Semaste        // Is the rest of it entirely digits?
2331254721Semaste        if (isdigit (cptr[0]))
2332254721Semaste        {
2333254721Semaste            const char *start = cptr;
2334254721Semaste            while (isdigit (cptr[0]))
2335254721Semaste                ++cptr;
2336254721Semaste
2337254721Semaste            // We've gotten to the end of the digits; are we at the end of the string?
2338254721Semaste            if (cptr[0] == '\0')
2339254721Semaste                position = atoi (start);
2340254721Semaste        }
2341254721Semaste    }
2342254721Semaste
2343254721Semaste    return position;
2344254721Semaste}
2345254721Semaste
2346254721Semastevoid
2347254721SemasteCommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result)
2348254721Semaste{
2349254721Semaste    FileSpec init_file;
2350254721Semaste    if (in_cwd)
2351254721Semaste    {
2352254721Semaste        // In the current working directory we don't load any program specific
2353254721Semaste        // .lldbinit files, we only look for a "./.lldbinit" file.
2354254721Semaste        if (m_skip_lldbinit_files)
2355254721Semaste            return;
2356254721Semaste
2357254721Semaste        init_file.SetFile ("./.lldbinit", true);
2358254721Semaste    }
2359254721Semaste    else
2360254721Semaste    {
2361254721Semaste        // If we aren't looking in the current working directory we are looking
2362254721Semaste        // in the home directory. We will first see if there is an application
2363254721Semaste        // specific ".lldbinit" file whose name is "~/.lldbinit" followed by a
2364254721Semaste        // "-" and the name of the program. If this file doesn't exist, we fall
2365254721Semaste        // back to just the "~/.lldbinit" file. We also obey any requests to not
2366254721Semaste        // load the init files.
2367254721Semaste        const char *init_file_path = "~/.lldbinit";
2368254721Semaste
2369254721Semaste        if (m_skip_app_init_files == false)
2370254721Semaste        {
2371254721Semaste            FileSpec program_file_spec (Host::GetProgramFileSpec());
2372254721Semaste            const char *program_name = program_file_spec.GetFilename().AsCString();
2373254721Semaste
2374254721Semaste            if (program_name)
2375254721Semaste            {
2376254721Semaste                char program_init_file_name[PATH_MAX];
2377254721Semaste                ::snprintf (program_init_file_name, sizeof(program_init_file_name), "%s-%s", init_file_path, program_name);
2378254721Semaste                init_file.SetFile (program_init_file_name, true);
2379254721Semaste                if (!init_file.Exists())
2380254721Semaste                    init_file.Clear();
2381254721Semaste            }
2382254721Semaste        }
2383254721Semaste
2384254721Semaste        if (!init_file && !m_skip_lldbinit_files)
2385254721Semaste			init_file.SetFile (init_file_path, true);
2386254721Semaste    }
2387254721Semaste
2388254721Semaste    // If the file exists, tell HandleCommand to 'source' it; this will do the actual broadcasting
2389254721Semaste    // of the commands back to any appropriate listener (see CommandObjectSource::Execute for more details).
2390254721Semaste
2391254721Semaste    if (init_file.Exists())
2392254721Semaste    {
2393269024Semaste        const bool saved_batch = SetBatchCommandMode (true);
2394269024Semaste        HandleCommandsFromFile (init_file,
2395269024Semaste                                NULL,           // Execution context
2396269024Semaste                                eLazyBoolYes,   // Stop on continue
2397269024Semaste                                eLazyBoolNo,    // Stop on error
2398269024Semaste                                eLazyBoolNo,    // Don't echo commands
2399269024Semaste                                eLazyBoolNo,    // Don't print command output
2400269024Semaste                                eLazyBoolNo,    // Don't add the commands that are sourced into the history buffer
2401269024Semaste                                result);
2402269024Semaste        SetBatchCommandMode (saved_batch);
2403254721Semaste    }
2404254721Semaste    else
2405254721Semaste    {
2406254721Semaste        // nothing to be done if the file doesn't exist
2407254721Semaste        result.SetStatus(eReturnStatusSuccessFinishNoResult);
2408254721Semaste    }
2409254721Semaste}
2410254721Semaste
2411254721SemastePlatformSP
2412254721SemasteCommandInterpreter::GetPlatform (bool prefer_target_platform)
2413254721Semaste{
2414254721Semaste    PlatformSP platform_sp;
2415254721Semaste    if (prefer_target_platform)
2416254721Semaste    {
2417254721Semaste        ExecutionContext exe_ctx(GetExecutionContext());
2418254721Semaste        Target *target = exe_ctx.GetTargetPtr();
2419254721Semaste        if (target)
2420254721Semaste            platform_sp = target->GetPlatform();
2421254721Semaste    }
2422254721Semaste
2423254721Semaste    if (!platform_sp)
2424254721Semaste        platform_sp = m_debugger.GetPlatformList().GetSelectedPlatform();
2425254721Semaste    return platform_sp;
2426254721Semaste}
2427254721Semaste
2428254721Semastevoid
2429254721SemasteCommandInterpreter::HandleCommands (const StringList &commands,
2430254721Semaste                                    ExecutionContext *override_context,
2431254721Semaste                                    bool stop_on_continue,
2432254721Semaste                                    bool stop_on_error,
2433254721Semaste                                    bool echo_commands,
2434254721Semaste                                    bool print_results,
2435254721Semaste                                    LazyBool add_to_history,
2436254721Semaste                                    CommandReturnObject &result)
2437254721Semaste{
2438254721Semaste    size_t num_lines = commands.GetSize();
2439254721Semaste
2440254721Semaste    // If we are going to continue past a "continue" then we need to run the commands synchronously.
2441254721Semaste    // Make sure you reset this value anywhere you return from the function.
2442254721Semaste
2443254721Semaste    bool old_async_execution = m_debugger.GetAsyncExecution();
2444254721Semaste
2445254721Semaste    // If we've been given an execution context, set it at the start, but don't keep resetting it or we will
2446254721Semaste    // cause series of commands that change the context, then do an operation that relies on that context to fail.
2447254721Semaste
2448254721Semaste    if (override_context != NULL)
2449254721Semaste        UpdateExecutionContext (override_context);
2450254721Semaste
2451254721Semaste    if (!stop_on_continue)
2452254721Semaste    {
2453254721Semaste        m_debugger.SetAsyncExecution (false);
2454254721Semaste    }
2455254721Semaste
2456254721Semaste    for (size_t idx = 0; idx < num_lines; idx++)
2457254721Semaste    {
2458254721Semaste        const char *cmd = commands.GetStringAtIndex(idx);
2459254721Semaste        if (cmd[0] == '\0')
2460254721Semaste            continue;
2461254721Semaste
2462254721Semaste        if (echo_commands)
2463254721Semaste        {
2464254721Semaste            result.AppendMessageWithFormat ("%s %s\n",
2465269024Semaste                                            m_debugger.GetPrompt(),
2466269024Semaste                                            cmd);
2467254721Semaste        }
2468254721Semaste
2469254721Semaste        CommandReturnObject tmp_result;
2470254721Semaste        // If override_context is not NULL, pass no_context_switching = true for
2471254721Semaste        // HandleCommand() since we updated our context already.
2472254721Semaste
2473254721Semaste        // We might call into a regex or alias command, in which case the add_to_history will get lost.  This
2474254721Semaste        // m_command_source_depth dingus is the way we turn off adding to the history in that case, so set it up here.
2475254721Semaste        if (!add_to_history)
2476254721Semaste            m_command_source_depth++;
2477254721Semaste        bool success = HandleCommand(cmd, add_to_history, tmp_result,
2478254721Semaste                                     NULL, /* override_context */
2479254721Semaste                                     true, /* repeat_on_empty_command */
2480254721Semaste                                     override_context != NULL /* no_context_switching */);
2481254721Semaste        if (!add_to_history)
2482254721Semaste            m_command_source_depth--;
2483254721Semaste
2484254721Semaste        if (print_results)
2485254721Semaste        {
2486254721Semaste            if (tmp_result.Succeeded())
2487254721Semaste              result.AppendMessageWithFormat("%s", tmp_result.GetOutputData());
2488254721Semaste        }
2489254721Semaste
2490254721Semaste        if (!success || !tmp_result.Succeeded())
2491254721Semaste        {
2492254721Semaste            const char *error_msg = tmp_result.GetErrorData();
2493254721Semaste            if (error_msg == NULL || error_msg[0] == '\0')
2494254721Semaste                error_msg = "<unknown error>.\n";
2495254721Semaste            if (stop_on_error)
2496254721Semaste            {
2497254721Semaste                result.AppendErrorWithFormat("Aborting reading of commands after command #%zu: '%s' failed with %s",
2498254721Semaste                                         idx, cmd, error_msg);
2499254721Semaste                result.SetStatus (eReturnStatusFailed);
2500254721Semaste                m_debugger.SetAsyncExecution (old_async_execution);
2501254721Semaste                return;
2502254721Semaste            }
2503254721Semaste            else if (print_results)
2504254721Semaste            {
2505254721Semaste                result.AppendMessageWithFormat ("Command #%zu '%s' failed with %s",
2506254721Semaste                                                idx + 1,
2507254721Semaste                                                cmd,
2508254721Semaste                                                error_msg);
2509254721Semaste            }
2510254721Semaste        }
2511254721Semaste
2512254721Semaste        if (result.GetImmediateOutputStream())
2513254721Semaste            result.GetImmediateOutputStream()->Flush();
2514254721Semaste
2515254721Semaste        if (result.GetImmediateErrorStream())
2516254721Semaste            result.GetImmediateErrorStream()->Flush();
2517254721Semaste
2518254721Semaste        // N.B. Can't depend on DidChangeProcessState, because the state coming into the command execution
2519254721Semaste        // could be running (for instance in Breakpoint Commands.
2520254721Semaste        // So we check the return value to see if it is has running in it.
2521254721Semaste        if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult)
2522254721Semaste                || (tmp_result.GetStatus() == eReturnStatusSuccessContinuingResult))
2523254721Semaste        {
2524254721Semaste            if (stop_on_continue)
2525254721Semaste            {
2526254721Semaste                // If we caused the target to proceed, and we're going to stop in that case, set the
2527254721Semaste                // status in our real result before returning.  This is an error if the continue was not the
2528254721Semaste                // last command in the set of commands to be run.
2529254721Semaste                if (idx != num_lines - 1)
2530254721Semaste                    result.AppendErrorWithFormat("Aborting reading of commands after command #%zu: '%s' continued the target.\n",
2531254721Semaste                                                 idx + 1, cmd);
2532254721Semaste                else
2533254721Semaste                    result.AppendMessageWithFormat ("Command #%zu '%s' continued the target.\n", idx + 1, cmd);
2534254721Semaste
2535254721Semaste                result.SetStatus(tmp_result.GetStatus());
2536254721Semaste                m_debugger.SetAsyncExecution (old_async_execution);
2537254721Semaste
2538254721Semaste                return;
2539254721Semaste            }
2540254721Semaste        }
2541254721Semaste
2542254721Semaste    }
2543254721Semaste
2544254721Semaste    result.SetStatus (eReturnStatusSuccessFinishResult);
2545254721Semaste    m_debugger.SetAsyncExecution (old_async_execution);
2546254721Semaste
2547254721Semaste    return;
2548254721Semaste}
2549254721Semaste
2550269024Semaste// Make flags that we can pass into the IOHandler so our delegates can do the right thing
2551269024Semasteenum {
2552269024Semaste    eHandleCommandFlagStopOnContinue = (1u << 0),
2553269024Semaste    eHandleCommandFlagStopOnError    = (1u << 1),
2554269024Semaste    eHandleCommandFlagEchoCommand    = (1u << 2),
2555269024Semaste    eHandleCommandFlagPrintResult    = (1u << 3)
2556269024Semaste};
2557269024Semaste
2558254721Semastevoid
2559254721SemasteCommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file,
2560254721Semaste                                            ExecutionContext *context,
2561269024Semaste                                            LazyBool stop_on_continue,
2562269024Semaste                                            LazyBool stop_on_error,
2563269024Semaste                                            LazyBool echo_command,
2564269024Semaste                                            LazyBool print_result,
2565254721Semaste                                            LazyBool add_to_history,
2566254721Semaste                                            CommandReturnObject &result)
2567254721Semaste{
2568254721Semaste    if (cmd_file.Exists())
2569254721Semaste    {
2570269024Semaste        StreamFileSP input_file_sp (new StreamFile());
2571269024Semaste
2572269024Semaste        std::string cmd_file_path = cmd_file.GetPath();
2573269024Semaste        Error error = input_file_sp->GetFile().Open(cmd_file_path.c_str(), File::eOpenOptionRead);
2574269024Semaste
2575269024Semaste        if (error.Success())
2576254721Semaste        {
2577269024Semaste            Debugger &debugger = GetDebugger();
2578269024Semaste
2579269024Semaste            uint32_t flags = 0;
2580269024Semaste
2581269024Semaste            if (stop_on_continue == eLazyBoolCalculate)
2582269024Semaste            {
2583269024Semaste                if (m_command_source_flags.empty())
2584269024Semaste                {
2585269024Semaste                    // Stop on continue by default
2586269024Semaste                    flags |= eHandleCommandFlagStopOnContinue;
2587269024Semaste                }
2588269024Semaste                else if (m_command_source_flags.back() & eHandleCommandFlagStopOnContinue)
2589269024Semaste                {
2590269024Semaste                    flags |= eHandleCommandFlagStopOnContinue;
2591269024Semaste                }
2592269024Semaste            }
2593269024Semaste            else if (stop_on_continue == eLazyBoolYes)
2594269024Semaste            {
2595269024Semaste                flags |= eHandleCommandFlagStopOnContinue;
2596269024Semaste            }
2597269024Semaste
2598269024Semaste            if (stop_on_error == eLazyBoolCalculate)
2599269024Semaste            {
2600269024Semaste                if (m_command_source_flags.empty())
2601269024Semaste                {
2602269024Semaste                    if (GetStopCmdSourceOnError())
2603269024Semaste                        flags |= eHandleCommandFlagStopOnError;
2604269024Semaste                }
2605269024Semaste                else if (m_command_source_flags.back() & eHandleCommandFlagStopOnError)
2606269024Semaste                {
2607269024Semaste                    flags |= eHandleCommandFlagStopOnError;
2608269024Semaste                }
2609269024Semaste            }
2610269024Semaste            else if (stop_on_error == eLazyBoolYes)
2611269024Semaste            {
2612269024Semaste                flags |= eHandleCommandFlagStopOnError;
2613269024Semaste            }
2614269024Semaste
2615269024Semaste            if (echo_command == eLazyBoolCalculate)
2616269024Semaste            {
2617269024Semaste                if (m_command_source_flags.empty())
2618269024Semaste                {
2619269024Semaste                    // Echo command by default
2620269024Semaste                    flags |= eHandleCommandFlagEchoCommand;
2621269024Semaste                }
2622269024Semaste                else if (m_command_source_flags.back() & eHandleCommandFlagEchoCommand)
2623269024Semaste                {
2624269024Semaste                    flags |= eHandleCommandFlagEchoCommand;
2625269024Semaste                }
2626269024Semaste            }
2627269024Semaste            else if (echo_command == eLazyBoolYes)
2628269024Semaste            {
2629269024Semaste                flags |= eHandleCommandFlagEchoCommand;
2630269024Semaste            }
2631269024Semaste
2632269024Semaste            if (print_result == eLazyBoolCalculate)
2633269024Semaste            {
2634269024Semaste                if (m_command_source_flags.empty())
2635269024Semaste                {
2636269024Semaste                    // Print output by default
2637269024Semaste                    flags |= eHandleCommandFlagPrintResult;
2638269024Semaste                }
2639269024Semaste                else if (m_command_source_flags.back() & eHandleCommandFlagPrintResult)
2640269024Semaste                {
2641269024Semaste                    flags |= eHandleCommandFlagPrintResult;
2642269024Semaste                }
2643269024Semaste            }
2644269024Semaste            else if (print_result == eLazyBoolYes)
2645269024Semaste            {
2646269024Semaste                flags |= eHandleCommandFlagPrintResult;
2647269024Semaste            }
2648269024Semaste
2649269024Semaste            if (flags & eHandleCommandFlagPrintResult)
2650269024Semaste            {
2651269024Semaste                debugger.GetOutputFile()->Printf("Executing commands in '%s'.\n", cmd_file_path.c_str());
2652269024Semaste            }
2653269024Semaste
2654269024Semaste            // Used for inheriting the right settings when "command source" might have
2655269024Semaste            // nested "command source" commands
2656269024Semaste            lldb::StreamFileSP empty_stream_sp;
2657269024Semaste            m_command_source_flags.push_back(flags);
2658269024Semaste            IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
2659269024Semaste                                                              input_file_sp,
2660269024Semaste                                                              empty_stream_sp, // Pass in an empty stream so we inherit the top input reader output stream
2661269024Semaste                                                              empty_stream_sp, // Pass in an empty stream so we inherit the top input reader error stream
2662269024Semaste                                                              flags,
2663269024Semaste                                                              NULL, // Pass in NULL for "editline_name" so no history is saved, or written
2664269024Semaste                                                              debugger.GetPrompt(),
2665269024Semaste                                                              false, // Not multi-line
2666269024Semaste                                                              *this));
2667269024Semaste            const bool old_async_execution = debugger.GetAsyncExecution();
2668269024Semaste
2669269024Semaste            // Set synchronous execution if we not stopping when we continue
2670269024Semaste            if ((flags & eHandleCommandFlagStopOnContinue) == 0)
2671269024Semaste                debugger.SetAsyncExecution (false);
2672269024Semaste
2673269024Semaste            m_command_source_depth++;
2674269024Semaste
2675269024Semaste            debugger.RunIOHandler(io_handler_sp);
2676269024Semaste            if (!m_command_source_flags.empty())
2677269024Semaste                m_command_source_flags.pop_back();
2678269024Semaste            m_command_source_depth--;
2679269024Semaste            result.SetStatus (eReturnStatusSuccessFinishNoResult);
2680269024Semaste            debugger.SetAsyncExecution (old_async_execution);
2681269024Semaste        }
2682269024Semaste        else
2683269024Semaste        {
2684269024Semaste            result.AppendErrorWithFormat ("error: an error occurred read file '%s': %s\n", cmd_file_path.c_str(), error.AsCString());
2685254721Semaste            result.SetStatus (eReturnStatusFailed);
2686254721Semaste        }
2687269024Semaste
2688269024Semaste
2689254721Semaste    }
2690254721Semaste    else
2691254721Semaste    {
2692254721Semaste        result.AppendErrorWithFormat ("Error reading commands from file %s - file not found.\n",
2693254721Semaste                                      cmd_file.GetFilename().AsCString());
2694254721Semaste        result.SetStatus (eReturnStatusFailed);
2695254721Semaste        return;
2696254721Semaste    }
2697254721Semaste}
2698254721Semaste
2699254721SemasteScriptInterpreter *
2700254721SemasteCommandInterpreter::GetScriptInterpreter (bool can_create)
2701254721Semaste{
2702254721Semaste    if (m_script_interpreter_ap.get() != NULL)
2703254721Semaste        return m_script_interpreter_ap.get();
2704254721Semaste
2705254721Semaste    if (!can_create)
2706254721Semaste        return NULL;
2707254721Semaste
2708254721Semaste    // <rdar://problem/11751427>
2709254721Semaste    // we need to protect the initialization of the script interpreter
2710254721Semaste    // otherwise we could end up with two threads both trying to create
2711254721Semaste    // their instance of it, and for some languages (e.g. Python)
2712254721Semaste    // this is a bulletproof recipe for disaster!
2713254721Semaste    // this needs to be a function-level static because multiple Debugger instances living in the same process
2714254721Semaste    // still need to be isolated and not try to initialize Python concurrently
2715254721Semaste    static Mutex g_interpreter_mutex(Mutex::eMutexTypeRecursive);
2716254721Semaste    Mutex::Locker interpreter_lock(g_interpreter_mutex);
2717254721Semaste
2718254721Semaste    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
2719254721Semaste    if (log)
2720254721Semaste        log->Printf("Initializing the ScriptInterpreter now\n");
2721254721Semaste
2722254721Semaste    lldb::ScriptLanguage script_lang = GetDebugger().GetScriptLanguage();
2723254721Semaste    switch (script_lang)
2724254721Semaste    {
2725254721Semaste        case eScriptLanguagePython:
2726254721Semaste#ifndef LLDB_DISABLE_PYTHON
2727254721Semaste            m_script_interpreter_ap.reset (new ScriptInterpreterPython (*this));
2728254721Semaste            break;
2729254721Semaste#else
2730254721Semaste            // Fall through to the None case when python is disabled
2731254721Semaste#endif
2732254721Semaste        case eScriptLanguageNone:
2733254721Semaste            m_script_interpreter_ap.reset (new ScriptInterpreterNone (*this));
2734254721Semaste            break;
2735254721Semaste    };
2736254721Semaste
2737254721Semaste    return m_script_interpreter_ap.get();
2738254721Semaste}
2739254721Semaste
2740254721Semaste
2741254721Semaste
2742254721Semastebool
2743254721SemasteCommandInterpreter::GetSynchronous ()
2744254721Semaste{
2745254721Semaste    return m_synchronous_execution;
2746254721Semaste}
2747254721Semaste
2748254721Semastevoid
2749254721SemasteCommandInterpreter::SetSynchronous (bool value)
2750254721Semaste{
2751254721Semaste    m_synchronous_execution  = value;
2752254721Semaste}
2753254721Semaste
2754254721Semastevoid
2755254721SemasteCommandInterpreter::OutputFormattedHelpText (Stream &strm,
2756254721Semaste                                             const char *word_text,
2757254721Semaste                                             const char *separator,
2758254721Semaste                                             const char *help_text,
2759254721Semaste                                             size_t max_word_len)
2760254721Semaste{
2761254721Semaste    const uint32_t max_columns = m_debugger.GetTerminalWidth();
2762254721Semaste
2763254721Semaste    int indent_size = max_word_len + strlen (separator) + 2;
2764254721Semaste
2765254721Semaste    strm.IndentMore (indent_size);
2766254721Semaste
2767254721Semaste    StreamString text_strm;
2768254721Semaste    text_strm.Printf ("%-*s %s %s",  (int)max_word_len, word_text, separator, help_text);
2769254721Semaste
2770254721Semaste    size_t len = text_strm.GetSize();
2771254721Semaste    const char *text = text_strm.GetData();
2772254721Semaste    if (text[len - 1] == '\n')
2773254721Semaste    {
2774254721Semaste        text_strm.EOL();
2775254721Semaste        len = text_strm.GetSize();
2776254721Semaste    }
2777254721Semaste
2778254721Semaste    if (len  < max_columns)
2779254721Semaste    {
2780254721Semaste        // Output it as a single line.
2781254721Semaste        strm.Printf ("%s", text);
2782254721Semaste    }
2783254721Semaste    else
2784254721Semaste    {
2785254721Semaste        // We need to break it up into multiple lines.
2786254721Semaste        bool first_line = true;
2787254721Semaste        int text_width;
2788254721Semaste        size_t start = 0;
2789254721Semaste        size_t end = start;
2790254721Semaste        const size_t final_end = strlen (text);
2791254721Semaste
2792254721Semaste        while (end < final_end)
2793254721Semaste        {
2794254721Semaste            if (first_line)
2795254721Semaste                text_width = max_columns - 1;
2796254721Semaste            else
2797254721Semaste                text_width = max_columns - indent_size - 1;
2798254721Semaste
2799254721Semaste            // Don't start the 'text' on a space, since we're already outputting the indentation.
2800254721Semaste            if (!first_line)
2801254721Semaste            {
2802254721Semaste                while ((start < final_end) && (text[start] == ' '))
2803254721Semaste                  start++;
2804254721Semaste            }
2805254721Semaste
2806254721Semaste            end = start + text_width;
2807254721Semaste            if (end > final_end)
2808254721Semaste                end = final_end;
2809254721Semaste            else
2810254721Semaste            {
2811254721Semaste                // If we're not at the end of the text, make sure we break the line on white space.
2812254721Semaste                while (end > start
2813254721Semaste                       && text[end] != ' ' && text[end] != '\t' && text[end] != '\n')
2814254721Semaste                    end--;
2815254721Semaste                assert (end > 0);
2816254721Semaste            }
2817254721Semaste
2818254721Semaste            const size_t sub_len = end - start;
2819254721Semaste            if (start != 0)
2820254721Semaste              strm.EOL();
2821254721Semaste            if (!first_line)
2822254721Semaste                strm.Indent();
2823254721Semaste            else
2824254721Semaste                first_line = false;
2825254721Semaste            assert (start <= final_end);
2826254721Semaste            assert (start + sub_len <= final_end);
2827254721Semaste            if (sub_len > 0)
2828254721Semaste                strm.Write (text + start, sub_len);
2829254721Semaste            start = end + 1;
2830254721Semaste        }
2831254721Semaste    }
2832254721Semaste    strm.EOL();
2833254721Semaste    strm.IndentLess(indent_size);
2834254721Semaste}
2835254721Semaste
2836254721Semastevoid
2837254721SemasteCommandInterpreter::OutputHelpText (Stream &strm,
2838254721Semaste                                    const char *word_text,
2839254721Semaste                                    const char *separator,
2840254721Semaste                                    const char *help_text,
2841254721Semaste                                    uint32_t max_word_len)
2842254721Semaste{
2843254721Semaste    int indent_size = max_word_len + strlen (separator) + 2;
2844254721Semaste
2845254721Semaste    strm.IndentMore (indent_size);
2846254721Semaste
2847254721Semaste    StreamString text_strm;
2848254721Semaste    text_strm.Printf ("%-*s %s %s",  max_word_len, word_text, separator, help_text);
2849254721Semaste
2850254721Semaste    const uint32_t max_columns = m_debugger.GetTerminalWidth();
2851254721Semaste
2852254721Semaste    size_t len = text_strm.GetSize();
2853254721Semaste    const char *text = text_strm.GetData();
2854254721Semaste
2855254721Semaste    uint32_t chars_left = max_columns;
2856254721Semaste
2857254721Semaste    for (uint32_t i = 0; i < len; i++)
2858254721Semaste    {
2859254721Semaste        if ((text[i] == ' ' && ::strchr((text+i+1), ' ') && chars_left < ::strchr((text+i+1), ' ')-(text+i)) || text[i] == '\n')
2860254721Semaste        {
2861254721Semaste            chars_left = max_columns - indent_size;
2862254721Semaste            strm.EOL();
2863254721Semaste            strm.Indent();
2864254721Semaste        }
2865254721Semaste        else
2866254721Semaste        {
2867254721Semaste            strm.PutChar(text[i]);
2868254721Semaste            chars_left--;
2869254721Semaste        }
2870254721Semaste
2871254721Semaste    }
2872254721Semaste
2873254721Semaste    strm.EOL();
2874254721Semaste    strm.IndentLess(indent_size);
2875254721Semaste}
2876254721Semaste
2877254721Semastevoid
2878254721SemasteCommandInterpreter::FindCommandsForApropos (const char *search_word, StringList &commands_found,
2879254721Semaste                                            StringList &commands_help, bool search_builtin_commands, bool search_user_commands)
2880254721Semaste{
2881254721Semaste    CommandObject::CommandMap::const_iterator pos;
2882254721Semaste
2883254721Semaste    if (search_builtin_commands)
2884254721Semaste    {
2885254721Semaste        for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
2886254721Semaste        {
2887254721Semaste            const char *command_name = pos->first.c_str();
2888254721Semaste            CommandObject *cmd_obj = pos->second.get();
2889254721Semaste
2890254721Semaste            if (cmd_obj->HelpTextContainsWord (search_word))
2891254721Semaste            {
2892254721Semaste                commands_found.AppendString (command_name);
2893254721Semaste                commands_help.AppendString (cmd_obj->GetHelp());
2894254721Semaste            }
2895254721Semaste
2896254721Semaste            if (cmd_obj->IsMultiwordObject())
2897254721Semaste                cmd_obj->AproposAllSubCommands (command_name,
2898254721Semaste                                                search_word,
2899254721Semaste                                                commands_found,
2900254721Semaste                                                commands_help);
2901254721Semaste
2902254721Semaste        }
2903254721Semaste    }
2904254721Semaste
2905254721Semaste    if (search_user_commands)
2906254721Semaste    {
2907254721Semaste        for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos)
2908254721Semaste        {
2909254721Semaste            const char *command_name = pos->first.c_str();
2910254721Semaste            CommandObject *cmd_obj = pos->second.get();
2911254721Semaste
2912254721Semaste            if (cmd_obj->HelpTextContainsWord (search_word))
2913254721Semaste            {
2914254721Semaste                commands_found.AppendString (command_name);
2915254721Semaste                commands_help.AppendString (cmd_obj->GetHelp());
2916254721Semaste            }
2917254721Semaste
2918254721Semaste            if (cmd_obj->IsMultiwordObject())
2919254721Semaste                cmd_obj->AproposAllSubCommands (command_name,
2920254721Semaste                                                search_word,
2921254721Semaste                                                commands_found,
2922254721Semaste                                                commands_help);
2923254721Semaste
2924254721Semaste        }
2925254721Semaste    }
2926254721Semaste}
2927254721Semaste
2928254721Semastevoid
2929254721SemasteCommandInterpreter::UpdateExecutionContext (ExecutionContext *override_context)
2930254721Semaste{
2931254721Semaste    if (override_context != NULL)
2932254721Semaste    {
2933254721Semaste        m_exe_ctx_ref = *override_context;
2934254721Semaste    }
2935254721Semaste    else
2936254721Semaste    {
2937254721Semaste        const bool adopt_selected = true;
2938254721Semaste        m_exe_ctx_ref.SetTargetPtr (m_debugger.GetSelectedTarget().get(), adopt_selected);
2939254721Semaste    }
2940254721Semaste}
2941269024Semaste
2942269024Semaste
2943269024Semastesize_t
2944269024SemasteCommandInterpreter::GetProcessOutput ()
2945269024Semaste{
2946269024Semaste    //  The process has stuff waiting for stderr; get it and write it out to the appropriate place.
2947269024Semaste    char stdio_buffer[1024];
2948269024Semaste    size_t len;
2949269024Semaste    size_t total_bytes = 0;
2950269024Semaste    Error error;
2951269024Semaste    TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget());
2952269024Semaste    if (target_sp)
2953269024Semaste    {
2954269024Semaste        ProcessSP process_sp (target_sp->GetProcessSP());
2955269024Semaste        if (process_sp)
2956269024Semaste        {
2957269024Semaste            while ((len = process_sp->GetSTDOUT (stdio_buffer, sizeof (stdio_buffer), error)) > 0)
2958269024Semaste            {
2959269024Semaste                size_t bytes_written = len;
2960269024Semaste                m_debugger.GetOutputFile()->Write (stdio_buffer, bytes_written);
2961269024Semaste                total_bytes += len;
2962269024Semaste            }
2963269024Semaste            while ((len = process_sp->GetSTDERR (stdio_buffer, sizeof (stdio_buffer), error)) > 0)
2964269024Semaste            {
2965269024Semaste                size_t bytes_written = len;
2966269024Semaste                m_debugger.GetErrorFile()->Write (stdio_buffer, bytes_written);
2967269024Semaste                total_bytes += len;
2968269024Semaste            }
2969269024Semaste        }
2970269024Semaste    }
2971269024Semaste    return total_bytes;
2972269024Semaste}
2973269024Semaste
2974269024Semastevoid
2975269024SemasteCommandInterpreter::IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
2976269024Semaste{
2977269024Semaste    const bool is_interactive = io_handler.GetIsInteractive();
2978269024Semaste    if (is_interactive == false)
2979269024Semaste    {
2980269024Semaste        // When we are not interactive, don't execute blank lines. This will happen
2981269024Semaste        // sourcing a commands file. We don't want blank lines to repeat the previous
2982269024Semaste        // command and cause any errors to occur (like redefining an alias, get an error
2983269024Semaste        // and stop parsing the commands file).
2984269024Semaste        if (line.empty())
2985269024Semaste            return;
2986269024Semaste
2987269024Semaste        // When using a non-interactive file handle (like when sourcing commands from a file)
2988269024Semaste        // we need to echo the command out so we don't just see the command output and no
2989269024Semaste        // command...
2990269024Semaste        if (io_handler.GetFlags().Test(eHandleCommandFlagEchoCommand))
2991269024Semaste            io_handler.GetOutputStreamFile()->Printf("%s%s\n", io_handler.GetPrompt(), line.c_str());
2992269024Semaste    }
2993269024Semaste
2994269024Semaste    lldb_private::CommandReturnObject result;
2995269024Semaste    HandleCommand(line.c_str(), eLazyBoolCalculate, result);
2996269024Semaste
2997269024Semaste    // Now emit the command output text from the command we just executed
2998269024Semaste    if (io_handler.GetFlags().Test(eHandleCommandFlagPrintResult))
2999269024Semaste    {
3000269024Semaste        // Display any STDOUT/STDERR _prior_ to emitting the command result text
3001269024Semaste        GetProcessOutput ();
3002269024Semaste
3003269024Semaste        if (!result.GetImmediateOutputStream())
3004269024Semaste        {
3005269024Semaste            const char *output = result.GetOutputData();
3006269024Semaste            if (output && output[0])
3007269024Semaste                io_handler.GetOutputStreamFile()->PutCString(output);
3008269024Semaste        }
3009269024Semaste
3010269024Semaste        // Now emit the command error text from the command we just executed
3011269024Semaste        if (!result.GetImmediateErrorStream())
3012269024Semaste        {
3013269024Semaste            const char *error = result.GetErrorData();
3014269024Semaste            if (error && error[0])
3015269024Semaste                io_handler.GetErrorStreamFile()->PutCString(error);
3016269024Semaste        }
3017269024Semaste    }
3018269024Semaste
3019269024Semaste    switch (result.GetStatus())
3020269024Semaste    {
3021269024Semaste        case eReturnStatusInvalid:
3022269024Semaste        case eReturnStatusSuccessFinishNoResult:
3023269024Semaste        case eReturnStatusSuccessFinishResult:
3024269024Semaste        case eReturnStatusStarted:
3025269024Semaste            break;
3026269024Semaste
3027269024Semaste        case eReturnStatusSuccessContinuingNoResult:
3028269024Semaste        case eReturnStatusSuccessContinuingResult:
3029269024Semaste            if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnContinue))
3030269024Semaste                io_handler.SetIsDone(true);
3031269024Semaste            break;
3032269024Semaste
3033269024Semaste        case eReturnStatusFailed:
3034269024Semaste            if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnError))
3035269024Semaste                io_handler.SetIsDone(true);
3036269024Semaste            break;
3037269024Semaste
3038269024Semaste        case eReturnStatusQuit:
3039269024Semaste            io_handler.SetIsDone(true);
3040269024Semaste            break;
3041269024Semaste    }
3042269024Semaste}
3043269024Semaste
3044269024Semastevoid
3045269024SemasteCommandInterpreter::GetLLDBCommandsFromIOHandler (const char *prompt,
3046269024Semaste                                                  IOHandlerDelegate &delegate,
3047269024Semaste                                                  bool asynchronously,
3048269024Semaste                                                  void *baton)
3049269024Semaste{
3050269024Semaste    Debugger &debugger = GetDebugger();
3051269024Semaste    IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
3052269024Semaste                                                      "lldb",       // Name of input reader for history
3053269024Semaste                                                      prompt,       // Prompt
3054269024Semaste                                                      true,         // Get multiple lines
3055269024Semaste                                                      delegate));   // IOHandlerDelegate
3056269024Semaste
3057269024Semaste    if (io_handler_sp)
3058269024Semaste    {
3059269024Semaste        io_handler_sp->SetUserData (baton);
3060269024Semaste        if (asynchronously)
3061269024Semaste            debugger.PushIOHandler(io_handler_sp);
3062269024Semaste        else
3063269024Semaste            debugger.RunIOHandler(io_handler_sp);
3064269024Semaste    }
3065269024Semaste
3066269024Semaste}
3067269024Semaste
3068269024Semaste
3069269024Semastevoid
3070269024SemasteCommandInterpreter::GetPythonCommandsFromIOHandler (const char *prompt,
3071269024Semaste                                                    IOHandlerDelegate &delegate,
3072269024Semaste                                                    bool asynchronously,
3073269024Semaste                                                    void *baton)
3074269024Semaste{
3075269024Semaste    Debugger &debugger = GetDebugger();
3076269024Semaste    IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
3077269024Semaste                                                      "lldb-python",    // Name of input reader for history
3078269024Semaste                                                      prompt,           // Prompt
3079269024Semaste                                                      true,             // Get multiple lines
3080269024Semaste                                                      delegate));       // IOHandlerDelegate
3081269024Semaste
3082269024Semaste    if (io_handler_sp)
3083269024Semaste    {
3084269024Semaste        io_handler_sp->SetUserData (baton);
3085269024Semaste        if (asynchronously)
3086269024Semaste            debugger.PushIOHandler(io_handler_sp);
3087269024Semaste        else
3088269024Semaste            debugger.RunIOHandler(io_handler_sp);
3089269024Semaste    }
3090269024Semaste
3091269024Semaste}
3092269024Semaste
3093269024Semastebool
3094269024SemasteCommandInterpreter::IsActive ()
3095269024Semaste{
3096269024Semaste    return m_debugger.IsTopIOHandler (m_command_io_handler_sp);
3097269024Semaste}
3098269024Semaste
3099269024Semastevoid
3100269024SemasteCommandInterpreter::RunCommandInterpreter(bool auto_handle_events,
3101269024Semaste                                          bool spawn_thread)
3102269024Semaste{
3103269024Semaste    const bool multiple_lines = false; // Only get one line at a time
3104269024Semaste    if (!m_command_io_handler_sp)
3105269024Semaste        m_command_io_handler_sp.reset(new IOHandlerEditline (m_debugger,
3106269024Semaste                                                             m_debugger.GetInputFile(),
3107269024Semaste                                                             m_debugger.GetOutputFile(),
3108269024Semaste                                                             m_debugger.GetErrorFile(),
3109269024Semaste                                                             eHandleCommandFlagEchoCommand | eHandleCommandFlagPrintResult,
3110269024Semaste                                                             "lldb",
3111269024Semaste                                                             m_debugger.GetPrompt(),
3112269024Semaste                                                             multiple_lines,
3113269024Semaste                                                             *this));
3114269024Semaste    m_debugger.PushIOHandler(m_command_io_handler_sp);
3115269024Semaste
3116269024Semaste    if (auto_handle_events)
3117269024Semaste        m_debugger.StartEventHandlerThread();
3118269024Semaste
3119269024Semaste    if (spawn_thread)
3120269024Semaste    {
3121269024Semaste        m_debugger.StartIOHandlerThread();
3122269024Semaste    }
3123269024Semaste    else
3124269024Semaste    {
3125269024Semaste        m_debugger.ExecuteIOHanders();
3126269024Semaste
3127269024Semaste        if (auto_handle_events)
3128269024Semaste            m_debugger.StopEventHandlerThread();
3129269024Semaste    }
3130269024Semaste
3131269024Semaste}
3132269024Semaste
3133