1 //===-- CommandInterpreter.cpp ----------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include <string>
11 #include <vector>
12 #include <stdlib.h>
13 
14 #include "CommandObjectScript.h"
15 #include "lldb/Interpreter/CommandObjectRegexCommand.h"
16 
17 #include "../Commands/CommandObjectApropos.h"
18 #include "../Commands/CommandObjectArgs.h"
19 #include "../Commands/CommandObjectBreakpoint.h"
20 #include "../Commands/CommandObjectBugreport.h"
21 #include "../Commands/CommandObjectDisassemble.h"
22 #include "../Commands/CommandObjectExpression.h"
23 #include "../Commands/CommandObjectFrame.h"
24 #include "../Commands/CommandObjectGUI.h"
25 #include "../Commands/CommandObjectHelp.h"
26 #include "../Commands/CommandObjectLog.h"
27 #include "../Commands/CommandObjectMemory.h"
28 #include "../Commands/CommandObjectPlatform.h"
29 #include "../Commands/CommandObjectPlugin.h"
30 #include "../Commands/CommandObjectProcess.h"
31 #include "../Commands/CommandObjectQuit.h"
32 #include "../Commands/CommandObjectRegister.h"
33 #include "../Commands/CommandObjectSettings.h"
34 #include "../Commands/CommandObjectSource.h"
35 #include "../Commands/CommandObjectCommands.h"
36 #include "../Commands/CommandObjectSyntax.h"
37 #include "../Commands/CommandObjectTarget.h"
38 #include "../Commands/CommandObjectThread.h"
39 #include "../Commands/CommandObjectType.h"
40 #include "../Commands/CommandObjectVersion.h"
41 #include "../Commands/CommandObjectWatchpoint.h"
42 #include "../Commands/CommandObjectLanguage.h"
43 
44 #include "lldb/Core/Debugger.h"
45 #include "lldb/Core/Log.h"
46 #include "lldb/Core/PluginManager.h"
47 #include "lldb/Core/State.h"
48 #include "lldb/Core/Stream.h"
49 #include "lldb/Core/StreamFile.h"
50 #include "lldb/Core/Timer.h"
51 
52 #ifndef LLDB_DISABLE_LIBEDIT
53 #include "lldb/Host/Editline.h"
54 #endif
55 #include "lldb/Host/Host.h"
56 #include "lldb/Host/HostInfo.h"
57 
58 #include "lldb/Interpreter/Args.h"
59 #include "lldb/Interpreter/CommandCompletions.h"
60 #include "lldb/Interpreter/CommandInterpreter.h"
61 #include "lldb/Interpreter/CommandReturnObject.h"
62 #include "lldb/Interpreter/Options.h"
63 #include "lldb/Interpreter/OptionValueProperties.h"
64 #include "lldb/Interpreter/Property.h"
65 
66 
67 #include "lldb/Target/Process.h"
68 #include "lldb/Target/Thread.h"
69 #include "lldb/Target/TargetList.h"
70 
71 #include "lldb/Utility/CleanUp.h"
72 
73 #include "llvm/ADT/SmallString.h"
74 #include "llvm/ADT/STLExtras.h"
75 #include "llvm/Support/Path.h"
76 
77 using namespace lldb;
78 using namespace lldb_private;
79 
80 static const char *k_white_space = " \t\v";
81 
82 static PropertyDefinition
83 g_properties[] =
84 {
85     { "expand-regex-aliases", OptionValue::eTypeBoolean, true, false, nullptr, nullptr, "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." },
86     { "prompt-on-quit", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "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." },
87     { "stop-command-source-on-error", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "If true, LLDB will stop running a 'command source' script upon encountering an error." },
88     { "space-repl-prompts", OptionValue::eTypeBoolean, true, false, nullptr, nullptr, "If true, blank lines will be printed between between REPL submissions." },
89     { nullptr                  , OptionValue::eTypeInvalid, true, 0    , nullptr, nullptr, nullptr }
90 };
91 
92 enum
93 {
94     ePropertyExpandRegexAliases = 0,
95     ePropertyPromptOnQuit = 1,
96     ePropertyStopCmdSourceOnError = 2,
97     eSpaceReplPrompts = 3
98 };
99 
100 ConstString &
101 CommandInterpreter::GetStaticBroadcasterClass ()
102 {
103     static ConstString class_name ("lldb.commandInterpreter");
104     return class_name;
105 }
106 
107 CommandInterpreter::CommandInterpreter(Debugger &debugger, ScriptLanguage script_language, bool synchronous_execution)
108     : Broadcaster(debugger.GetBroadcasterManager(), CommandInterpreter::GetStaticBroadcasterClass().AsCString()),
109       Properties(OptionValuePropertiesSP(new OptionValueProperties(ConstString("interpreter")))),
110       IOHandlerDelegate(IOHandlerDelegate::Completion::LLDBCommand),
111       m_debugger(debugger),
112       m_synchronous_execution(synchronous_execution),
113       m_skip_lldbinit_files(false),
114       m_skip_app_init_files(false),
115       m_script_interpreter_sp(),
116       m_command_io_handler_sp(),
117       m_comment_char('#'),
118       m_batch_command_mode(false),
119       m_truncation_warning(eNoTruncation),
120       m_command_source_depth(0),
121       m_num_errors(0),
122       m_quit_requested(false),
123       m_stopped_for_crash(false)
124 {
125     debugger.SetScriptLanguage (script_language);
126     SetEventName (eBroadcastBitThreadShouldExit, "thread-should-exit");
127     SetEventName (eBroadcastBitResetPrompt, "reset-prompt");
128     SetEventName (eBroadcastBitQuitCommandReceived, "quit");
129     CheckInWithManager ();
130     m_collection_sp->Initialize (g_properties);
131 }
132 
133 bool
134 CommandInterpreter::GetExpandRegexAliases () const
135 {
136     const uint32_t idx = ePropertyExpandRegexAliases;
137     return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0);
138 }
139 
140 bool
141 CommandInterpreter::GetPromptOnQuit () const
142 {
143     const uint32_t idx = ePropertyPromptOnQuit;
144     return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0);
145 }
146 
147 void
148 CommandInterpreter::SetPromptOnQuit (bool b)
149 {
150     const uint32_t idx = ePropertyPromptOnQuit;
151     m_collection_sp->SetPropertyAtIndexAsBoolean (nullptr, idx, b);
152 }
153 
154 void
155 CommandInterpreter::ResolveCommand(const char *command_line, CommandReturnObject &result)
156 {
157     std::string command = command_line;
158     if (ResolveCommandImpl(command, result) != nullptr) {
159         result.AppendMessageWithFormat("%s", command.c_str());
160         result.SetStatus(eReturnStatusSuccessFinishResult);
161     }
162 }
163 
164 
165 bool
166 CommandInterpreter::GetStopCmdSourceOnError () const
167 {
168     const uint32_t idx = ePropertyStopCmdSourceOnError;
169     return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0);
170 }
171 
172 bool
173 CommandInterpreter::GetSpaceReplPrompts () const
174 {
175     const uint32_t idx = eSpaceReplPrompts;
176     return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0);
177 }
178 
179 void
180 CommandInterpreter::Initialize ()
181 {
182     Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
183 
184     CommandReturnObject result;
185 
186     LoadCommandDictionary ();
187 
188     // An alias arguments vector to reuse - reset it before use...
189     OptionArgVectorSP alias_arguments_vector_sp (new OptionArgVector);
190 
191     // Set up some initial aliases.
192     CommandObjectSP cmd_obj_sp = GetCommandSPExact ("quit", false);
193     if (cmd_obj_sp)
194     {
195         AddAlias ("q", cmd_obj_sp);
196         AddAlias ("exit", cmd_obj_sp);
197     }
198 
199     cmd_obj_sp = GetCommandSPExact ("_regexp-attach",false);
200     if (cmd_obj_sp)
201         AddAlias ("attach", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
202 
203     cmd_obj_sp = GetCommandSPExact ("process detach",false);
204     if (cmd_obj_sp)
205     {
206         AddAlias ("detach", cmd_obj_sp);
207     }
208 
209     cmd_obj_sp = GetCommandSPExact ("process continue", false);
210     if (cmd_obj_sp)
211     {
212         AddAlias ("c", cmd_obj_sp);
213         AddAlias ("continue", cmd_obj_sp);
214     }
215 
216     cmd_obj_sp = GetCommandSPExact ("_regexp-break",false);
217     if (cmd_obj_sp)
218         AddAlias ("b", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
219 
220     cmd_obj_sp = GetCommandSPExact ("_regexp-tbreak",false);
221     if (cmd_obj_sp)
222         AddAlias ("tbreak", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
223 
224     cmd_obj_sp = GetCommandSPExact ("thread step-inst", false);
225     if (cmd_obj_sp)
226     {
227         AddAlias ("stepi", cmd_obj_sp);
228         AddAlias ("si", cmd_obj_sp);
229     }
230 
231     cmd_obj_sp = GetCommandSPExact ("thread step-inst-over", false);
232     if (cmd_obj_sp)
233     {
234         AddAlias ("nexti", cmd_obj_sp);
235         AddAlias ("ni", cmd_obj_sp);
236     }
237 
238     cmd_obj_sp = GetCommandSPExact ("thread step-in", false);
239     if (cmd_obj_sp)
240     {
241         AddAlias ("s", cmd_obj_sp);
242         AddAlias ("step", cmd_obj_sp);
243         CommandAlias *sif_alias = AddAlias ("sif", cmd_obj_sp, "--end-linenumber block --step-in-target %1");
244         if (sif_alias)
245         {
246             sif_alias->SetHelp("Step through the current block, stopping if you step "
247                                "directly into a function whose name matches the TargetFunctionName.");
248             sif_alias->SetSyntax("sif <TargetFunctionName>");
249         }
250     }
251 
252     cmd_obj_sp = GetCommandSPExact ("thread step-over", false);
253     if (cmd_obj_sp)
254     {
255         AddAlias ("n", cmd_obj_sp);
256         AddAlias ("next", cmd_obj_sp);
257     }
258 
259     cmd_obj_sp = GetCommandSPExact ("thread step-out", false);
260     if (cmd_obj_sp)
261     {
262         AddAlias ("finish", cmd_obj_sp);
263     }
264 
265     cmd_obj_sp = GetCommandSPExact ("frame select", false);
266     if (cmd_obj_sp)
267     {
268         AddAlias ("f", cmd_obj_sp);
269     }
270 
271     cmd_obj_sp = GetCommandSPExact ("thread select", false);
272     if (cmd_obj_sp)
273     {
274         AddAlias ("t", cmd_obj_sp);
275     }
276 
277     cmd_obj_sp = GetCommandSPExact ("_regexp-jump",false);
278     if (cmd_obj_sp)
279     {
280         AddAlias ("j", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
281         AddAlias ("jump", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
282     }
283 
284     cmd_obj_sp = GetCommandSPExact ("_regexp-list", false);
285     if (cmd_obj_sp)
286     {
287         AddAlias ("l", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
288         AddAlias ("list", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
289     }
290 
291     cmd_obj_sp = GetCommandSPExact ("_regexp-env", false);
292     if (cmd_obj_sp)
293         AddAlias ("env", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
294 
295     cmd_obj_sp = GetCommandSPExact ("memory read", false);
296     if (cmd_obj_sp)
297         AddAlias ("x", cmd_obj_sp);
298 
299     cmd_obj_sp = GetCommandSPExact ("_regexp-up", false);
300     if (cmd_obj_sp)
301         AddAlias ("up", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
302 
303     cmd_obj_sp = GetCommandSPExact ("_regexp-down", false);
304     if (cmd_obj_sp)
305         AddAlias ("down", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
306 
307     cmd_obj_sp = GetCommandSPExact ("_regexp-display", false);
308     if (cmd_obj_sp)
309         AddAlias ("display", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
310 
311     cmd_obj_sp = GetCommandSPExact ("disassemble", false);
312     if (cmd_obj_sp)
313         AddAlias ("dis", cmd_obj_sp);
314 
315     cmd_obj_sp = GetCommandSPExact ("disassemble", false);
316     if (cmd_obj_sp)
317         AddAlias ("di", cmd_obj_sp);
318 
319 
320 
321     cmd_obj_sp = GetCommandSPExact ("_regexp-undisplay", false);
322     if (cmd_obj_sp)
323         AddAlias ("undisplay", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
324 
325     cmd_obj_sp = GetCommandSPExact ("_regexp-bt", false);
326     if (cmd_obj_sp)
327         AddAlias ("bt", cmd_obj_sp)->SetSyntax(cmd_obj_sp->GetSyntax());
328 
329     cmd_obj_sp = GetCommandSPExact ("target create", false);
330     if (cmd_obj_sp)
331         AddAlias ("file", cmd_obj_sp);
332 
333     cmd_obj_sp = GetCommandSPExact ("target modules", false);
334     if (cmd_obj_sp)
335         AddAlias ("image", cmd_obj_sp);
336 
337 
338     alias_arguments_vector_sp.reset(new OptionArgVector);
339 
340     cmd_obj_sp = GetCommandSPExact ("expression", false);
341     if (cmd_obj_sp)
342     {
343         AddAlias ("p", cmd_obj_sp, "--")->SetHelpLong("");
344         AddAlias ("print", cmd_obj_sp, "--")->SetHelpLong("");
345         AddAlias ("call", cmd_obj_sp, "--")->SetHelpLong("");
346         if (auto po = AddAlias ("po", cmd_obj_sp, "-O --"))
347         {
348             po->SetHelp("Evaluate an expression in the current program context, using user defined variables and variables currently in scope, and display the result of evaluation in a language-specific manner.");
349             po->SetHelpLong("");
350         }
351         AddAlias("parray", cmd_obj_sp, "--element-count %1 --")->SetHelpLong("");
352         AddAlias("poarray", cmd_obj_sp, "--object-description --element-count %1 --")->SetHelpLong("");
353     }
354 
355     cmd_obj_sp = GetCommandSPExact ("process kill", false);
356     if (cmd_obj_sp)
357     {
358         AddAlias ("kill", cmd_obj_sp);
359     }
360 
361     cmd_obj_sp = GetCommandSPExact ("process launch", false);
362     if (cmd_obj_sp)
363     {
364         alias_arguments_vector_sp.reset (new OptionArgVector);
365 #if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
366         AddAlias ("r", cmd_obj_sp, "--");
367         AddAlias ("run", cmd_obj_sp, "--");
368 #else
369     #if defined(__APPLE__)
370         std::string shell_option;
371         shell_option.append("--shell-expand-args");
372         shell_option.append(" true");
373         shell_option.append(" --");
374         AddAlias ("r", cmd_obj_sp, "--shell-expand-args true --");
375         AddAlias ("run", cmd_obj_sp, "--shell-expand-args true --");
376     #else
377         StreamString defaultshell;
378         defaultshell.Printf("--shell=%s --", HostInfo::GetDefaultShell().GetPath().c_str());
379         AddAlias ("r", cmd_obj_sp, defaultshell.GetData());
380         AddAlias ("run", cmd_obj_sp, defaultshell.GetData());
381     #endif
382 #endif
383     }
384 
385     cmd_obj_sp = GetCommandSPExact ("target symbols add", false);
386     if (cmd_obj_sp)
387     {
388         AddAlias ("add-dsym", cmd_obj_sp);
389     }
390 
391     cmd_obj_sp = GetCommandSPExact ("breakpoint set", false);
392     if (cmd_obj_sp)
393     {
394         AddAlias ("rbreak", cmd_obj_sp, "--func-regex %1");
395     }
396 }
397 
398 void
399 CommandInterpreter::Clear()
400 {
401     m_command_io_handler_sp.reset();
402 
403     if (m_script_interpreter_sp)
404         m_script_interpreter_sp->Clear();
405 }
406 
407 const char *
408 CommandInterpreter::ProcessEmbeddedScriptCommands (const char *arg)
409 {
410     // This function has not yet been implemented.
411 
412     // Look for any embedded script command
413     // If found,
414     //    get interpreter object from the command dictionary,
415     //    call execute_one_command on it,
416     //    get the results as a string,
417     //    substitute that string for current stuff.
418 
419     return arg;
420 }
421 
422 
423 void
424 CommandInterpreter::LoadCommandDictionary ()
425 {
426     Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
427 
428     lldb::ScriptLanguage script_language = m_debugger.GetScriptLanguage();
429 
430     m_command_dict["apropos"]   = CommandObjectSP (new CommandObjectApropos (*this));
431     m_command_dict["breakpoint"]= CommandObjectSP (new CommandObjectMultiwordBreakpoint (*this));
432     m_command_dict["bugreport"] = CommandObjectSP (new CommandObjectMultiwordBugreport (*this));
433     m_command_dict["command"]   = CommandObjectSP (new CommandObjectMultiwordCommands (*this));
434     m_command_dict["disassemble"] = CommandObjectSP (new CommandObjectDisassemble (*this));
435     m_command_dict["expression"]= CommandObjectSP (new CommandObjectExpression (*this));
436     m_command_dict["frame"]     = CommandObjectSP (new CommandObjectMultiwordFrame (*this));
437     m_command_dict["gui"]       = CommandObjectSP (new CommandObjectGUI (*this));
438     m_command_dict["help"]      = CommandObjectSP (new CommandObjectHelp (*this));
439     m_command_dict["log"]       = CommandObjectSP (new CommandObjectLog (*this));
440     m_command_dict["memory"]    = CommandObjectSP (new CommandObjectMemory (*this));
441     m_command_dict["platform"]  = CommandObjectSP (new CommandObjectPlatform (*this));
442     m_command_dict["plugin"]    = CommandObjectSP (new CommandObjectPlugin (*this));
443     m_command_dict["process"]   = CommandObjectSP (new CommandObjectMultiwordProcess (*this));
444     m_command_dict["quit"]      = CommandObjectSP (new CommandObjectQuit (*this));
445     m_command_dict["register"]  = CommandObjectSP (new CommandObjectRegister (*this));
446     m_command_dict["script"]    = CommandObjectSP (new CommandObjectScript (*this, script_language));
447     m_command_dict["settings"]  = CommandObjectSP (new CommandObjectMultiwordSettings (*this));
448     m_command_dict["source"]    = CommandObjectSP (new CommandObjectMultiwordSource (*this));
449     m_command_dict["target"]    = CommandObjectSP (new CommandObjectMultiwordTarget (*this));
450     m_command_dict["thread"]    = CommandObjectSP (new CommandObjectMultiwordThread (*this));
451     m_command_dict["type"]      = CommandObjectSP (new CommandObjectType (*this));
452     m_command_dict["version"]   = CommandObjectSP (new CommandObjectVersion (*this));
453     m_command_dict["watchpoint"]= CommandObjectSP (new CommandObjectMultiwordWatchpoint (*this));
454     m_command_dict["language"]  = CommandObjectSP (new CommandObjectLanguage(*this));
455 
456     const char *break_regexes[][2] = {{"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2"},
457                                       {"^/([^/]+)/$", "breakpoint set --source-pattern-regexp '%1'"},
458                                       {"^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1"},
459                                       {"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1"},
460                                       {"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"},
461                                       {"^(-.*)$", "breakpoint set %1"},
462                                       {"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%2' --shlib '%1'"},
463                                       {"^\\&(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1' --skip-prologue=0"},
464                                       {"^[\"']?(.*[^[:space:]\"'])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"}};
465 
466     size_t num_regexes = llvm::array_lengthof(break_regexes);
467 
468     std::unique_ptr<CommandObjectRegexCommand>
469     break_regex_cmd_ap(new CommandObjectRegexCommand (*this,
470                                                       "_regexp-break",
471                                                       "Set a breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.\n",
472                                                       "\n_regexp-break <filename>:<linenum> # _regexp-break main.c:12      // Break on line 12 of main.c\n"
473                                                       "_regexp-break <linenum>            # _regexp-break 12             // Break on line 12 of current file\n"
474                                                       "_regexp-break <address>            # _regexp-break 0x1234000      // Break on address 0x1234000\n"
475                                                       "_regexp-break <name>               # _regexp-break main           // Break in 'main' after the prologue\n"
476                                                       "_regexp-break &<name>              # _regexp-break &main          // Break on the first instruction in 'main'\n"
477                                                       "_regexp-break <module>`<name>      # _regexp-break libc.so`malloc // Break in 'malloc' only in the 'libc.so' shared library\n"
478                                                       "_regexp-break /<source-regex>/     # _regexp-break /break here/   // Break on all lines that match the regular expression 'break here' in the current file.\n",
479                                                       2,
480                                                       CommandCompletions::eSymbolCompletion |
481                                                       CommandCompletions::eSourceFileCompletion,
482                                                       false));
483 
484     if (break_regex_cmd_ap.get())
485     {
486         bool success = true;
487         for (size_t i = 0; i < num_regexes; i++)
488         {
489             success = break_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], break_regexes[i][1]);
490             if (!success)
491                 break;
492         }
493         success = break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full");
494 
495         if (success)
496         {
497             CommandObjectSP break_regex_cmd_sp(break_regex_cmd_ap.release());
498             m_command_dict[break_regex_cmd_sp->GetCommandName ()] = break_regex_cmd_sp;
499         }
500     }
501 
502     std::unique_ptr<CommandObjectRegexCommand>
503     tbreak_regex_cmd_ap(new CommandObjectRegexCommand (*this,
504                                                       "_regexp-tbreak",
505                                                       "Set a one shot breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.",
506                                                       "_regexp-tbreak [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>",
507                                                        2,
508                                                        CommandCompletions::eSymbolCompletion |
509                                                        CommandCompletions::eSourceFileCompletion,
510                                                        false));
511 
512     if (tbreak_regex_cmd_ap.get())
513     {
514         bool success = true;
515         for (size_t i = 0; i < num_regexes; i++)
516         {
517             // If you add a resultant command string longer than 1024 characters be sure to increase the size of this buffer.
518             char buffer[1024];
519             int num_printed = snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o");
520             assert (num_printed < 1024);
521             UNUSED_IF_ASSERT_DISABLED(num_printed);
522             success = tbreak_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], buffer);
523             if (!success)
524                 break;
525         }
526         success = tbreak_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full");
527 
528         if (success)
529         {
530             CommandObjectSP tbreak_regex_cmd_sp(tbreak_regex_cmd_ap.release());
531             m_command_dict[tbreak_regex_cmd_sp->GetCommandName ()] = tbreak_regex_cmd_sp;
532         }
533     }
534 
535     std::unique_ptr<CommandObjectRegexCommand>
536     attach_regex_cmd_ap(new CommandObjectRegexCommand (*this,
537                                                        "_regexp-attach",
538                                                        "Attach to a process id if in decimal, otherwise treat the argument as a process name to attach to.",
539                                                        "_regexp-attach [<pid>]\n_regexp-attach [<process-name>]",
540                                                        2,
541                                                        0,
542                                                        false));
543     if (attach_regex_cmd_ap.get())
544     {
545         if (attach_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "process attach --pid %1") &&
546             attach_regex_cmd_ap->AddRegexCommand("^(-.*|.* -.*)$", "process attach %1") && // Any options that are specified get passed to 'process attach'
547             attach_regex_cmd_ap->AddRegexCommand("^(.+)$", "process attach --name '%1'") &&
548             attach_regex_cmd_ap->AddRegexCommand("^$", "process attach"))
549         {
550             CommandObjectSP attach_regex_cmd_sp(attach_regex_cmd_ap.release());
551             m_command_dict[attach_regex_cmd_sp->GetCommandName ()] = attach_regex_cmd_sp;
552         }
553     }
554 
555     std::unique_ptr<CommandObjectRegexCommand>
556     down_regex_cmd_ap(new CommandObjectRegexCommand (*this,
557                                                      "_regexp-down",
558                                                      "Go down \"n\" frames in the stack (1 frame by default).",
559                                                      "_regexp-down [n]",
560                                                      2,
561                                                      0,
562                                                      false));
563     if (down_regex_cmd_ap.get())
564     {
565         if (down_regex_cmd_ap->AddRegexCommand("^$", "frame select -r -1") &&
566             down_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r -%1"))
567         {
568             CommandObjectSP down_regex_cmd_sp(down_regex_cmd_ap.release());
569             m_command_dict[down_regex_cmd_sp->GetCommandName ()] = down_regex_cmd_sp;
570         }
571     }
572 
573     std::unique_ptr<CommandObjectRegexCommand>
574     up_regex_cmd_ap(new CommandObjectRegexCommand (*this,
575                                                    "_regexp-up",
576                                                    "Go up \"n\" frames in the stack (1 frame by default).",
577                                                    "_regexp-up [n]",
578                                                    2,
579                                                    0,
580                                                    false));
581     if (up_regex_cmd_ap.get())
582     {
583         if (up_regex_cmd_ap->AddRegexCommand("^$", "frame select -r 1") &&
584             up_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r %1"))
585         {
586             CommandObjectSP up_regex_cmd_sp(up_regex_cmd_ap.release());
587             m_command_dict[up_regex_cmd_sp->GetCommandName ()] = up_regex_cmd_sp;
588         }
589     }
590 
591     std::unique_ptr<CommandObjectRegexCommand>
592     display_regex_cmd_ap(new CommandObjectRegexCommand (*this,
593                                                         "_regexp-display",
594                                                         "Add an expression evaluation stop-hook.",
595                                                         "_regexp-display expression",
596                                                         2,
597                                                         0,
598                                                         false));
599     if (display_regex_cmd_ap.get())
600     {
601         if (display_regex_cmd_ap->AddRegexCommand("^(.+)$", "target stop-hook add -o \"expr -- %1\""))
602         {
603             CommandObjectSP display_regex_cmd_sp(display_regex_cmd_ap.release());
604             m_command_dict[display_regex_cmd_sp->GetCommandName ()] = display_regex_cmd_sp;
605         }
606     }
607 
608     std::unique_ptr<CommandObjectRegexCommand>
609     undisplay_regex_cmd_ap(new CommandObjectRegexCommand (*this,
610                                                           "_regexp-undisplay",
611                                                           "Remove an expression evaluation stop-hook.",
612                                                           "_regexp-undisplay stop-hook-number",
613                                                           2,
614                                                           0,
615                                                           false));
616     if (undisplay_regex_cmd_ap.get())
617     {
618         if (undisplay_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "target stop-hook delete %1"))
619         {
620             CommandObjectSP undisplay_regex_cmd_sp(undisplay_regex_cmd_ap.release());
621             m_command_dict[undisplay_regex_cmd_sp->GetCommandName ()] = undisplay_regex_cmd_sp;
622         }
623     }
624 
625     std::unique_ptr<CommandObjectRegexCommand>
626     connect_gdb_remote_cmd_ap(new CommandObjectRegexCommand (*this,
627                                                              "gdb-remote",
628                                                              "Connect to a remote GDB server.  If no hostname is provided, localhost is assumed.",
629                                                              "gdb-remote [<hostname>:]<portnum>",
630                                                              2,
631                                                              0,
632                                                              false));
633     if (connect_gdb_remote_cmd_ap.get())
634     {
635         if (connect_gdb_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin gdb-remote connect://%1") &&
636             connect_gdb_remote_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "process connect --plugin gdb-remote connect://localhost:%1"))
637         {
638             CommandObjectSP command_sp(connect_gdb_remote_cmd_ap.release());
639             m_command_dict[command_sp->GetCommandName ()] = command_sp;
640         }
641     }
642 
643     std::unique_ptr<CommandObjectRegexCommand>
644     connect_kdp_remote_cmd_ap(new CommandObjectRegexCommand (*this,
645                                                              "kdp-remote",
646                                                              "Connect to a remote KDP server.  udp port 41139 is the default port number.",
647                                                              "kdp-remote <hostname>[:<portnum>]",
648                                                              2,
649                                                              0,
650                                                              false));
651     if (connect_kdp_remote_cmd_ap.get())
652     {
653         if (connect_kdp_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin kdp-remote udp://%1") &&
654             connect_kdp_remote_cmd_ap->AddRegexCommand("^(.+)$", "process connect --plugin kdp-remote udp://%1:41139"))
655         {
656             CommandObjectSP command_sp(connect_kdp_remote_cmd_ap.release());
657             m_command_dict[command_sp->GetCommandName ()] = command_sp;
658         }
659     }
660 
661     std::unique_ptr<CommandObjectRegexCommand>
662     bt_regex_cmd_ap(new CommandObjectRegexCommand (*this,
663                                                    "_regexp-bt",
664                                                    "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.",
665                                                    "bt [<digit>|all]",
666                                                    2,
667                                                    0,
668                                                    false));
669     if (bt_regex_cmd_ap.get())
670     {
671         // accept but don't document "bt -c <number>" -- before bt was a regex command if you wanted to backtrace
672         // three frames you would do "bt -c 3" but the intention is to have this emulate the gdb "bt" command and
673         // so now "bt 3" is the preferred form, in line with gdb.
674         if (bt_regex_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "thread backtrace -c %1") &&
675             bt_regex_cmd_ap->AddRegexCommand("^-c ([[:digit:]]+)$", "thread backtrace -c %1") &&
676             bt_regex_cmd_ap->AddRegexCommand("^all$", "thread backtrace all") &&
677             bt_regex_cmd_ap->AddRegexCommand("^$", "thread backtrace"))
678         {
679             CommandObjectSP command_sp(bt_regex_cmd_ap.release());
680             m_command_dict[command_sp->GetCommandName ()] = command_sp;
681         }
682     }
683 
684     std::unique_ptr<CommandObjectRegexCommand>
685     list_regex_cmd_ap(new CommandObjectRegexCommand (*this,
686                                                      "_regexp-list",
687                                                      "Implements the GDB 'list' command in all of its forms except FILE:FUNCTION and maps them to the appropriate 'source list' commands.",
688                                                      "_regexp-list [<line>]\n_regexp-list [<file>:<line>]\n_regexp-list [<file>:<line>]",
689                                                      2,
690                                                      CommandCompletions::eSourceFileCompletion,
691                                                      false));
692     if (list_regex_cmd_ap.get())
693     {
694         if (list_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "source list --line %1") &&
695             list_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "source list --file '%1' --line %2") &&
696             list_regex_cmd_ap->AddRegexCommand("^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "source list --address %1") &&
697             list_regex_cmd_ap->AddRegexCommand("^-[[:space:]]*$", "source list --reverse") &&
698             list_regex_cmd_ap->AddRegexCommand("^-([[:digit:]]+)[[:space:]]*$", "source list --reverse --count %1") &&
699             list_regex_cmd_ap->AddRegexCommand("^(.+)$", "source list --name \"%1\"") &&
700             list_regex_cmd_ap->AddRegexCommand("^$", "source list"))
701         {
702             CommandObjectSP list_regex_cmd_sp(list_regex_cmd_ap.release());
703             m_command_dict[list_regex_cmd_sp->GetCommandName ()] = list_regex_cmd_sp;
704         }
705     }
706 
707     std::unique_ptr<CommandObjectRegexCommand>
708     env_regex_cmd_ap(new CommandObjectRegexCommand (*this,
709                                                     "_regexp-env",
710                                                     "Implements a shortcut to viewing and setting environment variables.",
711                                                     "_regexp-env\n_regexp-env FOO=BAR",
712                                                     2,
713                                                     0,
714                                                     false));
715     if (env_regex_cmd_ap.get())
716     {
717         if (env_regex_cmd_ap->AddRegexCommand("^$", "settings show target.env-vars") &&
718             env_regex_cmd_ap->AddRegexCommand("^([A-Za-z_][A-Za-z_0-9]*=.*)$", "settings set target.env-vars %1"))
719         {
720             CommandObjectSP env_regex_cmd_sp(env_regex_cmd_ap.release());
721             m_command_dict[env_regex_cmd_sp->GetCommandName ()] = env_regex_cmd_sp;
722         }
723     }
724 
725     std::unique_ptr<CommandObjectRegexCommand>
726     jump_regex_cmd_ap(new CommandObjectRegexCommand (*this,
727                                                     "_regexp-jump",
728                                                     "Sets the program counter to a new address.",
729                                                     "_regexp-jump [<line>]\n"
730                                                     "_regexp-jump [<+-lineoffset>]\n"
731                                                     "_regexp-jump [<file>:<line>]\n"
732                                                     "_regexp-jump [*<addr>]\n",
733                                                      2,
734                                                      0,
735                                                      false));
736     if (jump_regex_cmd_ap.get())
737     {
738         if (jump_regex_cmd_ap->AddRegexCommand("^\\*(.*)$", "thread jump --addr %1") &&
739             jump_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "thread jump --line %1") &&
740             jump_regex_cmd_ap->AddRegexCommand("^([^:]+):([0-9]+)$", "thread jump --file %1 --line %2") &&
741             jump_regex_cmd_ap->AddRegexCommand("^([+\\-][0-9]+)$", "thread jump --by %1"))
742         {
743             CommandObjectSP jump_regex_cmd_sp(jump_regex_cmd_ap.release());
744             m_command_dict[jump_regex_cmd_sp->GetCommandName ()] = jump_regex_cmd_sp;
745         }
746     }
747 
748 }
749 
750 int
751 CommandInterpreter::GetCommandNamesMatchingPartialString (const char *cmd_str, bool include_aliases,
752                                                           StringList &matches)
753 {
754     AddNamesMatchingPartialString (m_command_dict, cmd_str, matches);
755 
756     if (include_aliases)
757     {
758         AddNamesMatchingPartialString (m_alias_dict, cmd_str, matches);
759     }
760 
761     return matches.GetSize();
762 }
763 
764 CommandObjectSP
765 CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bool exact, StringList *matches)
766 {
767     CommandObject::CommandMap::iterator pos;
768     CommandObjectSP command_sp;
769 
770     std::string cmd(cmd_cstr);
771 
772     if (HasCommands())
773     {
774         pos = m_command_dict.find(cmd);
775         if (pos != m_command_dict.end())
776             command_sp = pos->second;
777     }
778 
779     if (include_aliases && HasAliases())
780     {
781         auto alias_pos = m_alias_dict.find(cmd);
782         if (alias_pos != m_alias_dict.end())
783             command_sp = alias_pos->second;
784     }
785 
786     if (HasUserCommands())
787     {
788         pos = m_user_dict.find(cmd);
789         if (pos != m_user_dict.end())
790             command_sp = pos->second;
791     }
792 
793     if (!exact && !command_sp)
794     {
795         // We will only get into here if we didn't find any exact matches.
796 
797         CommandObjectSP user_match_sp, alias_match_sp, real_match_sp;
798 
799         StringList local_matches;
800         if (matches == nullptr)
801             matches = &local_matches;
802 
803         unsigned int num_cmd_matches = 0;
804         unsigned int num_alias_matches = 0;
805         unsigned int num_user_matches = 0;
806 
807         // Look through the command dictionaries one by one, and if we get only one match from any of
808         // them in toto, then return that, otherwise return an empty CommandObjectSP and the list of matches.
809 
810         if (HasCommands())
811         {
812             num_cmd_matches = AddNamesMatchingPartialString (m_command_dict, cmd_cstr, *matches);
813         }
814 
815         if (num_cmd_matches == 1)
816         {
817             cmd.assign(matches->GetStringAtIndex(0));
818             pos = m_command_dict.find(cmd);
819             if (pos != m_command_dict.end())
820                 real_match_sp = pos->second;
821         }
822 
823         if (include_aliases && HasAliases())
824         {
825             num_alias_matches = AddNamesMatchingPartialString (m_alias_dict, cmd_cstr, *matches);
826 
827         }
828 
829         if (num_alias_matches == 1)
830         {
831             cmd.assign(matches->GetStringAtIndex (num_cmd_matches));
832             auto alias_pos = m_alias_dict.find(cmd);
833             if (alias_pos != m_alias_dict.end())
834                 alias_match_sp = alias_pos->second;
835         }
836 
837         if (HasUserCommands())
838         {
839             num_user_matches = AddNamesMatchingPartialString (m_user_dict, cmd_cstr, *matches);
840         }
841 
842         if (num_user_matches == 1)
843         {
844             cmd.assign (matches->GetStringAtIndex (num_cmd_matches + num_alias_matches));
845 
846             pos = m_user_dict.find (cmd);
847             if (pos != m_user_dict.end())
848                 user_match_sp = pos->second;
849         }
850 
851         // If we got exactly one match, return that, otherwise return the match list.
852 
853         if (num_user_matches + num_cmd_matches + num_alias_matches == 1)
854         {
855             if (num_cmd_matches)
856                 return real_match_sp;
857             else if (num_alias_matches)
858                 return alias_match_sp;
859             else
860                 return user_match_sp;
861         }
862     }
863     else if (matches && command_sp)
864     {
865         matches->AppendString (cmd_cstr);
866     }
867 
868 
869     return command_sp;
870 }
871 
872 bool
873 CommandInterpreter::AddCommand (const char *name, const lldb::CommandObjectSP &cmd_sp, bool can_replace)
874 {
875     if (cmd_sp.get())
876         assert((this == &cmd_sp->GetCommandInterpreter()) && "tried to add a CommandObject from a different interpreter");
877 
878     if (name && name[0])
879     {
880         std::string name_sstr(name);
881         bool found = (m_command_dict.find (name_sstr) != m_command_dict.end());
882         if (found && !can_replace)
883             return false;
884         if (found && m_command_dict[name_sstr]->IsRemovable() == false)
885             return false;
886         m_command_dict[name_sstr] = cmd_sp;
887         return true;
888     }
889     return false;
890 }
891 
892 bool
893 CommandInterpreter::AddUserCommand (std::string name,
894                                     const lldb::CommandObjectSP &cmd_sp,
895                                     bool can_replace)
896 {
897     if (cmd_sp.get())
898         assert((this == &cmd_sp->GetCommandInterpreter()) && "tried to add a CommandObject from a different interpreter");
899 
900     if (!name.empty())
901     {
902         const char* name_cstr = name.c_str();
903 
904         // do not allow replacement of internal commands
905         if (CommandExists(name_cstr))
906         {
907             if (can_replace == false)
908                 return false;
909             if (m_command_dict[name]->IsRemovable() == false)
910                 return false;
911         }
912 
913         if (UserCommandExists(name_cstr))
914         {
915             if (can_replace == false)
916                 return false;
917             if (m_user_dict[name]->IsRemovable() == false)
918                 return false;
919         }
920 
921         m_user_dict[name] = cmd_sp;
922         return true;
923     }
924     return false;
925 }
926 
927 CommandObjectSP
928 CommandInterpreter::GetCommandSPExact (const char *cmd_cstr, bool include_aliases)
929 {
930     Args cmd_words (cmd_cstr); // Break up the command string into words, in case it's a multi-word command.
931     CommandObjectSP ret_val;   // Possibly empty return value.
932 
933     if (cmd_cstr == nullptr)
934         return ret_val;
935 
936     if (cmd_words.GetArgumentCount() == 1)
937         return GetCommandSP(cmd_cstr, include_aliases, true, nullptr);
938     else
939     {
940         // We have a multi-word command (seemingly), so we need to do more work.
941         // First, get the cmd_obj_sp for the first word in the command.
942         CommandObjectSP cmd_obj_sp = GetCommandSP (cmd_words.GetArgumentAtIndex (0), include_aliases, true, nullptr);
943         if (cmd_obj_sp.get() != nullptr)
944         {
945             // Loop through the rest of the words in the command (everything passed in was supposed to be part of a
946             // command name), and find the appropriate sub-command SP for each command word....
947             size_t end = cmd_words.GetArgumentCount();
948             for (size_t j= 1; j < end; ++j)
949             {
950                 if (cmd_obj_sp->IsMultiwordObject())
951                 {
952                     cmd_obj_sp = cmd_obj_sp->GetSubcommandSP (cmd_words.GetArgumentAtIndex (j));
953                     if (cmd_obj_sp.get() == nullptr)
954                         // The sub-command name was invalid.  Fail and return the empty 'ret_val'.
955                         return ret_val;
956                 }
957                 else
958                     // We have more words in the command name, but we don't have a multiword object. Fail and return
959                     // empty 'ret_val'.
960                     return ret_val;
961             }
962             // We successfully looped through all the command words and got valid command objects for them.  Assign the
963             // last object retrieved to 'ret_val'.
964             ret_val = cmd_obj_sp;
965         }
966     }
967     return ret_val;
968 }
969 
970 CommandObject *
971 CommandInterpreter::GetCommandObjectExact (const char *cmd_cstr, bool include_aliases)
972 {
973     return GetCommandSPExact (cmd_cstr, include_aliases).get();
974 }
975 
976 CommandObject *
977 CommandInterpreter::GetCommandObject (const char *cmd_cstr, StringList *matches)
978 {
979     CommandObject *command_obj = GetCommandSP (cmd_cstr, false, true, matches).get();
980 
981     // If we didn't find an exact match to the command string in the commands, look in
982     // the aliases.
983 
984     if (command_obj)
985         return command_obj;
986 
987     command_obj = GetCommandSP (cmd_cstr, true, true, matches).get();
988 
989     if (command_obj)
990         return command_obj;
991 
992     // If there wasn't an exact match then look for an inexact one in just the commands
993     command_obj = GetCommandSP(cmd_cstr, false, false, nullptr).get();
994 
995     // Finally, if there wasn't an inexact match among the commands, look for an inexact
996     // match in both the commands and aliases.
997 
998     if (command_obj)
999     {
1000         if (matches)
1001             matches->AppendString(command_obj->GetCommandName());
1002         return command_obj;
1003     }
1004 
1005     return GetCommandSP(cmd_cstr, true, false, matches).get();
1006 }
1007 
1008 bool
1009 CommandInterpreter::CommandExists (const char *cmd)
1010 {
1011     return m_command_dict.find(cmd) != m_command_dict.end();
1012 }
1013 
1014 bool
1015 CommandInterpreter::GetAliasFullName (const char *cmd, std::string &full_name)
1016 {
1017     bool exact_match  = (m_alias_dict.find(cmd) != m_alias_dict.end());
1018     if (exact_match)
1019     {
1020         full_name.assign(cmd);
1021         return exact_match;
1022     }
1023     else
1024     {
1025         StringList matches;
1026         size_t num_alias_matches;
1027         num_alias_matches = AddNamesMatchingPartialString (m_alias_dict, cmd, matches);
1028         if (num_alias_matches == 1)
1029         {
1030             // Make sure this isn't shadowing a command in the regular command space:
1031             StringList regular_matches;
1032             const bool include_aliases = false;
1033             const bool exact = false;
1034             CommandObjectSP cmd_obj_sp(GetCommandSP (cmd, include_aliases, exact, &regular_matches));
1035             if (cmd_obj_sp || regular_matches.GetSize() > 0)
1036                 return false;
1037             else
1038             {
1039                 full_name.assign (matches.GetStringAtIndex(0));
1040                 return true;
1041             }
1042         }
1043         else
1044             return false;
1045     }
1046 }
1047 
1048 bool
1049 CommandInterpreter::AliasExists (const char *cmd)
1050 {
1051     return m_alias_dict.find(cmd) != m_alias_dict.end();
1052 }
1053 
1054 bool
1055 CommandInterpreter::UserCommandExists (const char *cmd)
1056 {
1057     return m_user_dict.find(cmd) != m_user_dict.end();
1058 }
1059 
1060 CommandAlias*
1061 CommandInterpreter::AddAlias (const char *alias_name,
1062                               lldb::CommandObjectSP& command_obj_sp,
1063                               const char *args_string)
1064 {
1065     if (command_obj_sp.get())
1066         assert((this == &command_obj_sp->GetCommandInterpreter()) && "tried to add a CommandObject from a different interpreter");
1067 
1068     std::unique_ptr<CommandAlias> command_alias_up(new CommandAlias(*this,
1069                                                                     command_obj_sp,
1070                                                                     args_string,
1071                                                                     alias_name));
1072 
1073     if (command_alias_up && command_alias_up->IsValid())
1074     {
1075         m_alias_dict[alias_name] = CommandObjectSP(command_alias_up.get());
1076         return command_alias_up.release();
1077     }
1078 
1079     return nullptr;
1080 }
1081 
1082 bool
1083 CommandInterpreter::RemoveAlias (const char *alias_name)
1084 {
1085     auto pos = m_alias_dict.find(alias_name);
1086     if (pos != m_alias_dict.end())
1087     {
1088         m_alias_dict.erase(pos);
1089         return true;
1090     }
1091     return false;
1092 }
1093 
1094 bool
1095 CommandInterpreter::RemoveCommand (const char *cmd)
1096 {
1097     auto pos = m_command_dict.find(cmd);
1098     if (pos != m_command_dict.end())
1099     {
1100         if (pos->second->IsRemovable())
1101         {
1102             // Only regular expression objects or python commands are removable
1103             m_command_dict.erase(pos);
1104             return true;
1105         }
1106     }
1107     return false;
1108 }
1109 bool
1110 CommandInterpreter::RemoveUser (const char *alias_name)
1111 {
1112     CommandObject::CommandMap::iterator pos = m_user_dict.find(alias_name);
1113     if (pos != m_user_dict.end())
1114     {
1115         m_user_dict.erase(pos);
1116         return true;
1117     }
1118     return false;
1119 }
1120 
1121 void
1122 CommandInterpreter::GetHelp (CommandReturnObject &result,
1123                              uint32_t cmd_types)
1124 {
1125     const char * help_prologue = GetDebugger().GetIOHandlerHelpPrologue();
1126     if (help_prologue != NULL)
1127     {
1128         OutputFormattedHelpText(result.GetOutputStream(), NULL, help_prologue);
1129     }
1130 
1131     CommandObject::CommandMap::const_iterator pos;
1132     size_t max_len = FindLongestCommandWord (m_command_dict);
1133 
1134     if ( (cmd_types & eCommandTypesBuiltin) == eCommandTypesBuiltin )
1135     {
1136         result.AppendMessage("Debugger commands:");
1137         result.AppendMessage("");
1138 
1139         for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
1140         {
1141             if (!(cmd_types & eCommandTypesHidden) && (pos->first.compare(0, 1, "_") == 0))
1142                 continue;
1143 
1144             OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(),
1145                                      max_len);
1146         }
1147         result.AppendMessage("");
1148 
1149     }
1150 
1151     if (!m_alias_dict.empty() && ( (cmd_types & eCommandTypesAliases) == eCommandTypesAliases ))
1152     {
1153         result.AppendMessageWithFormat("Current command abbreviations "
1154                                        "(type '%shelp command alias' for more info):\n",
1155                                        GetCommandPrefix());
1156         result.AppendMessage("");
1157         max_len = FindLongestCommandWord (m_alias_dict);
1158 
1159         for (auto alias_pos = m_alias_dict.begin(); alias_pos != m_alias_dict.end(); ++alias_pos)
1160         {
1161             OutputFormattedHelpText (result.GetOutputStream(), alias_pos->first.c_str(), "--", alias_pos->second->GetHelp(),
1162                                      max_len);
1163         }
1164         result.AppendMessage("");
1165     }
1166 
1167     if (!m_user_dict.empty() && ( (cmd_types & eCommandTypesUserDef) == eCommandTypesUserDef ))
1168     {
1169         result.AppendMessage ("Current user-defined commands:");
1170         result.AppendMessage("");
1171         max_len = FindLongestCommandWord (m_user_dict);
1172         for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos)
1173         {
1174             OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(),
1175                                      max_len);
1176         }
1177         result.AppendMessage("");
1178     }
1179 
1180     result.AppendMessageWithFormat("For more information on any command, type '%shelp <command-name>'.\n",
1181                                    GetCommandPrefix());
1182 }
1183 
1184 CommandObject *
1185 CommandInterpreter::GetCommandObjectForCommand (std::string &command_string)
1186 {
1187     // This function finds the final, lowest-level, alias-resolved command object whose 'Execute' function will
1188     // eventually be invoked by the given command line.
1189 
1190     CommandObject *cmd_obj = nullptr;
1191     size_t start = command_string.find_first_not_of (k_white_space);
1192     size_t end = 0;
1193     bool done = false;
1194     while (!done)
1195     {
1196         if (start != std::string::npos)
1197         {
1198             // Get the next word from command_string.
1199             end = command_string.find_first_of (k_white_space, start);
1200             if (end == std::string::npos)
1201                 end = command_string.size();
1202             std::string cmd_word = command_string.substr (start, end - start);
1203 
1204             if (cmd_obj == nullptr)
1205                 // Since cmd_obj is NULL we are on our first time through this loop. Check to see if cmd_word is a valid
1206                 // command or alias.
1207                 cmd_obj = GetCommandObject (cmd_word.c_str());
1208             else if (cmd_obj->IsMultiwordObject ())
1209             {
1210                 // Our current object is a multi-word object; see if the cmd_word is a valid sub-command for our object.
1211                 CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (cmd_word.c_str());
1212                 if (sub_cmd_obj)
1213                     cmd_obj = sub_cmd_obj;
1214                 else // cmd_word was not a valid sub-command word, so we are done
1215                     done = true;
1216             }
1217             else
1218                 // We have a cmd_obj and it is not a multi-word object, so we are done.
1219                 done = true;
1220 
1221             // If we didn't find a valid command object, or our command object is not a multi-word object, or
1222             // we are at the end of the command_string, then we are done.  Otherwise, find the start of the
1223             // next word.
1224 
1225             if (!cmd_obj || !cmd_obj->IsMultiwordObject() || end >= command_string.size())
1226                 done = true;
1227             else
1228                 start = command_string.find_first_not_of (k_white_space, end);
1229         }
1230         else
1231             // Unable to find any more words.
1232             done = true;
1233     }
1234 
1235     if (end == command_string.size())
1236         command_string.clear();
1237     else
1238         command_string = command_string.substr(end);
1239 
1240     return cmd_obj;
1241 }
1242 
1243 static const char *k_valid_command_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
1244 static void
1245 StripLeadingSpaces (std::string &s)
1246 {
1247     if (!s.empty())
1248     {
1249         size_t pos = s.find_first_not_of (k_white_space);
1250         if (pos == std::string::npos)
1251             s.clear();
1252         else if (pos == 0)
1253             return;
1254         s.erase (0, pos);
1255     }
1256 }
1257 
1258 static size_t
1259 FindArgumentTerminator (const std::string &s)
1260 {
1261     const size_t s_len = s.size();
1262     size_t offset = 0;
1263     while (offset < s_len)
1264     {
1265         size_t pos = s.find ("--", offset);
1266         if (pos == std::string::npos)
1267             break;
1268         if (pos > 0)
1269         {
1270             if (isspace(s[pos-1]))
1271             {
1272                 // Check if the string ends "\s--" (where \s is a space character)
1273                 // or if we have "\s--\s".
1274                 if ((pos + 2 >= s_len) || isspace(s[pos+2]))
1275                 {
1276                     return pos;
1277                 }
1278             }
1279         }
1280         offset = pos + 2;
1281     }
1282     return std::string::npos;
1283 }
1284 
1285 static bool
1286 ExtractCommand (std::string &command_string, std::string &command, std::string &suffix, char &quote_char)
1287 {
1288     command.clear();
1289     suffix.clear();
1290     StripLeadingSpaces (command_string);
1291 
1292     bool result = false;
1293     quote_char = '\0';
1294 
1295     if (!command_string.empty())
1296     {
1297         const char first_char = command_string[0];
1298         if (first_char == '\'' || first_char == '"')
1299         {
1300             quote_char = first_char;
1301             const size_t end_quote_pos = command_string.find (quote_char, 1);
1302             if (end_quote_pos == std::string::npos)
1303             {
1304                 command.swap (command_string);
1305                 command_string.erase ();
1306             }
1307             else
1308             {
1309                 command.assign (command_string, 1, end_quote_pos - 1);
1310                 if (end_quote_pos + 1 < command_string.size())
1311                     command_string.erase (0, command_string.find_first_not_of (k_white_space, end_quote_pos + 1));
1312                 else
1313                     command_string.erase ();
1314             }
1315         }
1316         else
1317         {
1318             const size_t first_space_pos = command_string.find_first_of (k_white_space);
1319             if (first_space_pos == std::string::npos)
1320             {
1321                 command.swap (command_string);
1322                 command_string.erase();
1323             }
1324             else
1325             {
1326                 command.assign (command_string, 0, first_space_pos);
1327                 command_string.erase(0, command_string.find_first_not_of (k_white_space, first_space_pos));
1328             }
1329         }
1330         result = true;
1331     }
1332 
1333 
1334     if (!command.empty())
1335     {
1336         // actual commands can't start with '-' or '_'
1337         if (command[0] != '-' && command[0] != '_')
1338         {
1339             size_t pos = command.find_first_not_of(k_valid_command_chars);
1340             if (pos > 0 && pos != std::string::npos)
1341             {
1342                 suffix.assign (command.begin() + pos, command.end());
1343                 command.erase (pos);
1344             }
1345         }
1346     }
1347 
1348     return result;
1349 }
1350 
1351 CommandObject *
1352 CommandInterpreter::BuildAliasResult (const char *alias_name,
1353                                       std::string &raw_input_string,
1354                                       std::string &alias_result,
1355                                       CommandReturnObject &result)
1356 {
1357     CommandObject *alias_cmd_obj = nullptr;
1358     Args cmd_args (raw_input_string);
1359     alias_cmd_obj = GetCommandObject (alias_name);
1360     StreamString result_str;
1361 
1362     if (alias_cmd_obj && alias_cmd_obj->IsAlias())
1363     {
1364         std::pair<CommandObjectSP, OptionArgVectorSP> desugared = ((CommandAlias*)alias_cmd_obj)->Desugar();
1365         OptionArgVectorSP option_arg_vector_sp =  desugared.second;
1366         alias_cmd_obj = desugared.first.get();
1367         std::string alias_name_str = alias_name;
1368         if ((cmd_args.GetArgumentCount() == 0)
1369             || (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0))
1370             cmd_args.Unshift (alias_name);
1371 
1372         result_str.Printf ("%s", alias_cmd_obj->GetCommandName ());
1373 
1374         if (option_arg_vector_sp.get())
1375         {
1376             OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
1377 
1378             for (size_t i = 0; i < option_arg_vector->size(); ++i)
1379             {
1380                 OptionArgPair option_pair = (*option_arg_vector)[i];
1381                 OptionArgValue value_pair = option_pair.second;
1382                 int value_type = value_pair.first;
1383                 std::string option = option_pair.first;
1384                 std::string value = value_pair.second;
1385                 if (option.compare ("<argument>") == 0)
1386                     result_str.Printf (" %s", value.c_str());
1387                 else
1388                 {
1389                     result_str.Printf (" %s", option.c_str());
1390                     if (value_type != OptionParser::eNoArgument)
1391                     {
1392                         if (value_type != OptionParser::eOptionalArgument)
1393                             result_str.Printf (" ");
1394                         int index = GetOptionArgumentPosition (value.c_str());
1395                         if (index == 0)
1396                             result_str.Printf ("%s", value.c_str());
1397                         else if (static_cast<size_t>(index) >= cmd_args.GetArgumentCount())
1398                         {
1399 
1400                             result.AppendErrorWithFormat
1401                             ("Not enough arguments provided; you need at least %d arguments to use this alias.\n",
1402                              index);
1403                             result.SetStatus (eReturnStatusFailed);
1404                             return nullptr;
1405                         }
1406                         else
1407                         {
1408                             size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index));
1409                             if (strpos != std::string::npos)
1410                                 raw_input_string = raw_input_string.erase (strpos,
1411                                                                           strlen (cmd_args.GetArgumentAtIndex (index)));
1412                             result_str.Printf ("%s", cmd_args.GetArgumentAtIndex (index));
1413                         }
1414                     }
1415                 }
1416             }
1417         }
1418 
1419         alias_result = result_str.GetData();
1420     }
1421     return alias_cmd_obj;
1422 }
1423 
1424 Error
1425 CommandInterpreter::PreprocessCommand (std::string &command)
1426 {
1427     // The command preprocessor needs to do things to the command
1428     // line before any parsing of arguments or anything else is done.
1429     // The only current stuff that gets preprocessed is anything enclosed
1430     // in backtick ('`') characters is evaluated as an expression and
1431     // the result of the expression must be a scalar that can be substituted
1432     // into the command. An example would be:
1433     // (lldb) memory read `$rsp + 20`
1434     Error error; // Error for any expressions that might not evaluate
1435     size_t start_backtick;
1436     size_t pos = 0;
1437     while ((start_backtick = command.find ('`', pos)) != std::string::npos)
1438     {
1439         if (start_backtick > 0 && command[start_backtick-1] == '\\')
1440         {
1441             // The backtick was preceded by a '\' character, remove the slash
1442             // and don't treat the backtick as the start of an expression
1443             command.erase(start_backtick-1, 1);
1444             // No need to add one to start_backtick since we just deleted a char
1445             pos = start_backtick;
1446         }
1447         else
1448         {
1449             const size_t expr_content_start = start_backtick + 1;
1450             const size_t end_backtick = command.find ('`', expr_content_start);
1451             if (end_backtick == std::string::npos)
1452                 return error;
1453             else if (end_backtick == expr_content_start)
1454             {
1455                 // Empty expression (two backticks in a row)
1456                 command.erase (start_backtick, 2);
1457             }
1458             else
1459             {
1460                 std::string expr_str (command, expr_content_start, end_backtick - expr_content_start);
1461 
1462                 ExecutionContext exe_ctx(GetExecutionContext());
1463                 Target *target = exe_ctx.GetTargetPtr();
1464                 // Get a dummy target to allow for calculator mode while processing backticks.
1465                 // This also helps break the infinite loop caused when target is null.
1466                 if (!target)
1467                     target = m_debugger.GetDummyTarget();
1468                 if (target)
1469                 {
1470                     ValueObjectSP expr_result_valobj_sp;
1471 
1472                     EvaluateExpressionOptions options;
1473                     options.SetCoerceToId(false);
1474                     options.SetUnwindOnError(true);
1475                     options.SetIgnoreBreakpoints(true);
1476                     options.SetKeepInMemory(false);
1477                     options.SetTryAllThreads(true);
1478                     options.SetTimeoutUsec(0);
1479 
1480                     ExpressionResults expr_result = target->EvaluateExpression (expr_str.c_str(),
1481                                                                                 exe_ctx.GetFramePtr(),
1482                                                                                 expr_result_valobj_sp,
1483                                                                                 options);
1484 
1485                     if (expr_result == eExpressionCompleted)
1486                     {
1487                         Scalar scalar;
1488                         if (expr_result_valobj_sp)
1489                             expr_result_valobj_sp = expr_result_valobj_sp->GetQualifiedRepresentationIfAvailable(expr_result_valobj_sp->GetDynamicValueType(), true);
1490                         if (expr_result_valobj_sp->ResolveValue (scalar))
1491                         {
1492                             command.erase (start_backtick, end_backtick - start_backtick + 1);
1493                             StreamString value_strm;
1494                             const bool show_type = false;
1495                             scalar.GetValue (&value_strm, show_type);
1496                             size_t value_string_size = value_strm.GetSize();
1497                             if (value_string_size)
1498                             {
1499                                 command.insert (start_backtick, value_strm.GetData(), value_string_size);
1500                                 pos = start_backtick + value_string_size;
1501                                 continue;
1502                             }
1503                             else
1504                             {
1505                                 error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str());
1506                             }
1507                         }
1508                         else
1509                         {
1510                             error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str());
1511                         }
1512                     }
1513                     else
1514                     {
1515                         if (expr_result_valobj_sp)
1516                             error = expr_result_valobj_sp->GetError();
1517                         if (error.Success())
1518                         {
1519 
1520                             switch (expr_result)
1521                             {
1522                                 case eExpressionSetupError:
1523                                     error.SetErrorStringWithFormat("expression setup error for the expression '%s'", expr_str.c_str());
1524                                     break;
1525                                 case eExpressionParseError:
1526                                     error.SetErrorStringWithFormat ("expression parse error for the expression '%s'", expr_str.c_str());
1527                                     break;
1528                                 case eExpressionResultUnavailable:
1529                                     error.SetErrorStringWithFormat ("expression error fetching result for the expression '%s'", expr_str.c_str());
1530                                     break;
1531                                 case eExpressionCompleted:
1532                                     break;
1533                                 case eExpressionDiscarded:
1534                                     error.SetErrorStringWithFormat("expression discarded for the expression '%s'", expr_str.c_str());
1535                                     break;
1536                                 case eExpressionInterrupted:
1537                                     error.SetErrorStringWithFormat("expression interrupted for the expression '%s'", expr_str.c_str());
1538                                     break;
1539                                 case eExpressionHitBreakpoint:
1540                                     error.SetErrorStringWithFormat("expression hit breakpoint for the expression '%s'", expr_str.c_str());
1541                                     break;
1542                                 case eExpressionTimedOut:
1543                                     error.SetErrorStringWithFormat("expression timed out for the expression '%s'", expr_str.c_str());
1544                                     break;
1545                                 case eExpressionStoppedForDebug:
1546                                     error.SetErrorStringWithFormat("expression stop at entry point for debugging for the expression '%s'", expr_str.c_str());
1547                                     break;
1548                             }
1549                         }
1550                     }
1551                 }
1552             }
1553             if (error.Fail())
1554                 break;
1555         }
1556     }
1557     return error;
1558 }
1559 
1560 
1561 bool
1562 CommandInterpreter::HandleCommand (const char *command_line,
1563                                    LazyBool lazy_add_to_history,
1564                                    CommandReturnObject &result,
1565                                    ExecutionContext *override_context,
1566                                    bool repeat_on_empty_command,
1567                                    bool no_context_switching)
1568 
1569 {
1570 
1571     std::string command_string (command_line);
1572     std::string original_command_string (command_line);
1573 
1574     Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMANDS));
1575     Host::SetCrashDescriptionWithFormat ("HandleCommand(command = \"%s\")", command_line);
1576 
1577     // Make a scoped cleanup object that will clear the crash description string
1578     // on exit of this function.
1579     lldb_utility::CleanUp <const char *> crash_description_cleanup(nullptr, Host::SetCrashDescription);
1580 
1581     if (log)
1582         log->Printf ("Processing command: %s", command_line);
1583 
1584     Timer scoped_timer (__PRETTY_FUNCTION__, "Handling command: %s.", command_line);
1585 
1586     if (!no_context_switching)
1587         UpdateExecutionContext (override_context);
1588 
1589     bool add_to_history;
1590     if (lazy_add_to_history == eLazyBoolCalculate)
1591         add_to_history = (m_command_source_depth == 0);
1592     else
1593         add_to_history = (lazy_add_to_history == eLazyBoolYes);
1594 
1595     bool empty_command = false;
1596     bool comment_command = false;
1597     if (command_string.empty())
1598         empty_command = true;
1599     else
1600     {
1601         const char *k_space_characters = "\t\n\v\f\r ";
1602 
1603         size_t non_space = command_string.find_first_not_of (k_space_characters);
1604         // Check for empty line or comment line (lines whose first
1605         // non-space character is the comment character for this interpreter)
1606         if (non_space == std::string::npos)
1607             empty_command = true;
1608         else if (command_string[non_space] == m_comment_char)
1609              comment_command = true;
1610         else if (command_string[non_space] == CommandHistory::g_repeat_char)
1611         {
1612             const char *history_string = m_command_history.FindString(command_string.c_str() + non_space);
1613             if (history_string == nullptr)
1614             {
1615                 result.AppendErrorWithFormat ("Could not find entry: %s in history", command_string.c_str());
1616                 result.SetStatus(eReturnStatusFailed);
1617                 return false;
1618             }
1619             add_to_history = false;
1620             command_string = history_string;
1621             original_command_string = history_string;
1622         }
1623     }
1624 
1625     if (empty_command)
1626     {
1627         if (repeat_on_empty_command)
1628         {
1629             if (m_command_history.IsEmpty())
1630             {
1631                 result.AppendError ("empty command");
1632                 result.SetStatus(eReturnStatusFailed);
1633                 return false;
1634             }
1635             else
1636             {
1637                 command_line = m_repeat_command.c_str();
1638                 command_string = command_line;
1639                 original_command_string = command_line;
1640                 if (m_repeat_command.empty())
1641                 {
1642                     result.AppendErrorWithFormat("No auto repeat.\n");
1643                     result.SetStatus (eReturnStatusFailed);
1644                     return false;
1645                 }
1646             }
1647             add_to_history = false;
1648         }
1649         else
1650         {
1651             result.SetStatus (eReturnStatusSuccessFinishNoResult);
1652             return true;
1653         }
1654     }
1655     else if (comment_command)
1656     {
1657         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1658         return true;
1659     }
1660 
1661 
1662     Error error (PreprocessCommand (command_string));
1663 
1664     if (error.Fail())
1665     {
1666         result.AppendError (error.AsCString());
1667         result.SetStatus(eReturnStatusFailed);
1668         return false;
1669     }
1670 
1671     // Phase 1.
1672 
1673     // Before we do ANY kind of argument processing, we need to figure out what
1674     // the real/final command object is for the specified command.  This gets
1675     // complicated by the fact that the user could have specified an alias, and,
1676     // in translating the alias, there may also be command options and/or even
1677     // data (including raw text strings) that need to be found and inserted into
1678     // the command line as part of the translation.  So this first step is plain
1679     // look-up and replacement, resulting in:
1680     //    1. the command object whose Execute method will actually be called
1681     //    2. a revised command string, with all substitutions and replacements
1682     //       taken care of
1683     // From 1 above, we can determine whether the Execute function wants raw
1684     // input or not.
1685 
1686     CommandObject *cmd_obj = ResolveCommandImpl(command_string, result);
1687 
1688     // Although the user may have abbreviated the command, the command_string now
1689     // has the command expanded to the full name.  For example, if the input
1690     // was "br s -n main", command_string is now "breakpoint set -n main".
1691 
1692     if (log)
1693     {
1694         log->Printf("HandleCommand, cmd_obj : '%s'", cmd_obj ? cmd_obj->GetCommandName() : "<not found>");
1695         log->Printf("HandleCommand, (revised) command_string: '%s'", command_string.c_str());
1696         const bool wants_raw_input = (cmd_obj != NULL) ? cmd_obj->WantsRawCommandString() : false;
1697         log->Printf("HandleCommand, wants_raw_input:'%s'", wants_raw_input ? "True" : "False");
1698     }
1699 
1700     // Phase 2.
1701     // Take care of things like setting up the history command & calling the appropriate Execute method on the
1702     // CommandObject, with the appropriate arguments.
1703 
1704     if (cmd_obj != nullptr)
1705     {
1706         if (add_to_history)
1707         {
1708             Args command_args (command_string);
1709             const char *repeat_command = cmd_obj->GetRepeatCommand(command_args, 0);
1710             if (repeat_command != nullptr)
1711                 m_repeat_command.assign(repeat_command);
1712             else
1713                 m_repeat_command.assign(original_command_string.c_str());
1714 
1715             m_command_history.AppendString (original_command_string);
1716         }
1717 
1718         std::string remainder;
1719         const std::size_t actual_cmd_name_len = strlen (cmd_obj->GetCommandName());
1720         if (actual_cmd_name_len < command_string.length())
1721             remainder = command_string.substr (actual_cmd_name_len);
1722 
1723         // Remove any initial spaces
1724         size_t pos = remainder.find_first_not_of (k_white_space);
1725         if (pos != 0 && pos != std::string::npos)
1726             remainder.erase(0, pos);
1727 
1728         if (log)
1729             log->Printf ("HandleCommand, command line after removing command name(s): '%s'", remainder.c_str());
1730 
1731         cmd_obj->Execute (remainder.c_str(), result);
1732     }
1733     else
1734     {
1735         // We didn't find the first command object, so complete the first argument.
1736         Args command_args (command_string);
1737         StringList matches;
1738         int num_matches;
1739         int cursor_index = 0;
1740         int cursor_char_position = strlen (command_args.GetArgumentAtIndex(0));
1741         bool word_complete;
1742         num_matches = HandleCompletionMatches (command_args,
1743                                                cursor_index,
1744                                                cursor_char_position,
1745                                                0,
1746                                                -1,
1747                                                word_complete,
1748                                                matches);
1749 
1750         if (num_matches > 0)
1751         {
1752             std::string error_msg;
1753             error_msg.assign ("ambiguous command '");
1754             error_msg.append(command_args.GetArgumentAtIndex(0));
1755             error_msg.append ("'.");
1756 
1757             error_msg.append (" Possible completions:");
1758             for (int i = 0; i < num_matches; i++)
1759             {
1760                 error_msg.append ("\n\t");
1761                 error_msg.append (matches.GetStringAtIndex (i));
1762             }
1763             error_msg.append ("\n");
1764             result.AppendRawError (error_msg.c_str());
1765         }
1766         else
1767             result.AppendErrorWithFormat ("Unrecognized command '%s'.\n", command_args.GetArgumentAtIndex (0));
1768 
1769         result.SetStatus (eReturnStatusFailed);
1770     }
1771 
1772     if (log)
1773       log->Printf ("HandleCommand, command %s", (result.Succeeded() ? "succeeded" : "did not succeed"));
1774 
1775     return result.Succeeded();
1776 }
1777 
1778 int
1779 CommandInterpreter::HandleCompletionMatches (Args &parsed_line,
1780                                              int &cursor_index,
1781                                              int &cursor_char_position,
1782                                              int match_start_point,
1783                                              int max_return_elements,
1784                                              bool &word_complete,
1785                                              StringList &matches)
1786 {
1787     int num_command_matches = 0;
1788     bool look_for_subcommand = false;
1789 
1790     // For any of the command completions a unique match will be a complete word.
1791     word_complete = true;
1792 
1793     if (cursor_index == -1)
1794     {
1795         // We got nothing on the command line, so return the list of commands
1796         bool include_aliases = true;
1797         num_command_matches = GetCommandNamesMatchingPartialString ("", include_aliases, matches);
1798     }
1799     else if (cursor_index == 0)
1800     {
1801         // The cursor is in the first argument, so just do a lookup in the dictionary.
1802         CommandObject *cmd_obj = GetCommandObject (parsed_line.GetArgumentAtIndex(0), &matches);
1803         num_command_matches = matches.GetSize();
1804 
1805         if (num_command_matches == 1
1806             && cmd_obj && cmd_obj->IsMultiwordObject()
1807             && matches.GetStringAtIndex(0) != nullptr
1808             && strcmp (parsed_line.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
1809         {
1810             if (parsed_line.GetArgumentCount() == 1)
1811             {
1812                 word_complete = true;
1813             }
1814             else
1815             {
1816                 look_for_subcommand = true;
1817                 num_command_matches = 0;
1818                 matches.DeleteStringAtIndex(0);
1819                 parsed_line.AppendArgument ("");
1820                 cursor_index++;
1821                 cursor_char_position = 0;
1822             }
1823         }
1824     }
1825 
1826     if (cursor_index > 0 || look_for_subcommand)
1827     {
1828         // We are completing further on into a commands arguments, so find the command and tell it
1829         // to complete the command.
1830         // First see if there is a matching initial command:
1831         CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0));
1832         if (command_object == nullptr)
1833         {
1834             return 0;
1835         }
1836         else
1837         {
1838             parsed_line.Shift();
1839             cursor_index--;
1840             num_command_matches = command_object->HandleCompletion (parsed_line,
1841                                                                     cursor_index,
1842                                                                     cursor_char_position,
1843                                                                     match_start_point,
1844                                                                     max_return_elements,
1845                                                                     word_complete,
1846                                                                     matches);
1847         }
1848     }
1849 
1850     return num_command_matches;
1851 
1852 }
1853 
1854 int
1855 CommandInterpreter::HandleCompletion (const char *current_line,
1856                                       const char *cursor,
1857                                       const char *last_char,
1858                                       int match_start_point,
1859                                       int max_return_elements,
1860                                       StringList &matches)
1861 {
1862     // We parse the argument up to the cursor, so the last argument in parsed_line is
1863     // the one containing the cursor, and the cursor is after the last character.
1864 
1865     Args parsed_line(llvm::StringRef(current_line, last_char - current_line));
1866     Args partial_parsed_line(llvm::StringRef(current_line, cursor - current_line));
1867 
1868     // Don't complete comments, and if the line we are completing is just the history repeat character,
1869     // substitute the appropriate history line.
1870     const char *first_arg = parsed_line.GetArgumentAtIndex(0);
1871     if (first_arg)
1872     {
1873         if (first_arg[0] == m_comment_char)
1874             return 0;
1875         else if (first_arg[0] == CommandHistory::g_repeat_char)
1876         {
1877             const char *history_string = m_command_history.FindString (first_arg);
1878             if (history_string != nullptr)
1879             {
1880                 matches.Clear();
1881                 matches.InsertStringAtIndex(0, history_string);
1882                 return -2;
1883             }
1884             else
1885                 return 0;
1886 
1887         }
1888     }
1889 
1890 
1891     int num_args = partial_parsed_line.GetArgumentCount();
1892     int cursor_index = partial_parsed_line.GetArgumentCount() - 1;
1893     int cursor_char_position;
1894 
1895     if (cursor_index == -1)
1896         cursor_char_position = 0;
1897     else
1898         cursor_char_position = strlen (partial_parsed_line.GetArgumentAtIndex(cursor_index));
1899 
1900     if (cursor > current_line && cursor[-1] == ' ')
1901     {
1902         // We are just after a space.  If we are in an argument, then we will continue
1903         // parsing, but if we are between arguments, then we have to complete whatever the next
1904         // element would be.
1905         // We can distinguish the two cases because if we are in an argument (e.g. because the space is
1906         // protected by a quote) then the space will also be in the parsed argument...
1907 
1908         const char *current_elem = partial_parsed_line.GetArgumentAtIndex(cursor_index);
1909         if (cursor_char_position == 0 || current_elem[cursor_char_position - 1] != ' ')
1910         {
1911             parsed_line.InsertArgumentAtIndex(cursor_index + 1, "", '\0');
1912             cursor_index++;
1913             cursor_char_position = 0;
1914         }
1915     }
1916 
1917     int num_command_matches;
1918 
1919     matches.Clear();
1920 
1921     // Only max_return_elements == -1 is supported at present:
1922     assert (max_return_elements == -1);
1923     bool word_complete;
1924     num_command_matches = HandleCompletionMatches (parsed_line,
1925                                                    cursor_index,
1926                                                    cursor_char_position,
1927                                                    match_start_point,
1928                                                    max_return_elements,
1929                                                    word_complete,
1930                                                    matches);
1931 
1932     if (num_command_matches <= 0)
1933         return num_command_matches;
1934 
1935     if (num_args == 0)
1936     {
1937         // If we got an empty string, insert nothing.
1938         matches.InsertStringAtIndex(0, "");
1939     }
1940     else
1941     {
1942         // Now figure out if there is a common substring, and if so put that in element 0, otherwise
1943         // put an empty string in element 0.
1944         std::string command_partial_str;
1945         if (cursor_index >= 0)
1946             command_partial_str.assign(parsed_line.GetArgumentAtIndex(cursor_index),
1947                                        parsed_line.GetArgumentAtIndex(cursor_index) + cursor_char_position);
1948 
1949         std::string common_prefix;
1950         matches.LongestCommonPrefix (common_prefix);
1951         const size_t partial_name_len = command_partial_str.size();
1952         common_prefix.erase (0, partial_name_len);
1953 
1954         // If we matched a unique single command, add a space...
1955         // Only do this if the completer told us this was a complete word, however...
1956         if (num_command_matches == 1 && word_complete)
1957         {
1958             char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index);
1959             common_prefix = Args::EscapeLLDBCommandArgument(common_prefix, quote_char);
1960             if (quote_char != '\0')
1961                 common_prefix.push_back(quote_char);
1962             common_prefix.push_back(' ');
1963         }
1964         matches.InsertStringAtIndex(0, common_prefix.c_str());
1965     }
1966     return num_command_matches;
1967 }
1968 
1969 
1970 CommandInterpreter::~CommandInterpreter ()
1971 {
1972 }
1973 
1974 void
1975 CommandInterpreter::UpdatePrompt (const char *new_prompt)
1976 {
1977     EventSP prompt_change_event_sp (new Event(eBroadcastBitResetPrompt, new EventDataBytes (new_prompt)));;
1978     BroadcastEvent (prompt_change_event_sp);
1979     if (m_command_io_handler_sp)
1980         m_command_io_handler_sp->SetPrompt(new_prompt);
1981 }
1982 
1983 
1984 bool
1985 CommandInterpreter::Confirm (const char *message, bool default_answer)
1986 {
1987     // Check AutoConfirm first:
1988     if (m_debugger.GetAutoConfirm())
1989         return default_answer;
1990 
1991     IOHandlerConfirm *confirm = new IOHandlerConfirm(m_debugger,
1992                                                      message,
1993                                                      default_answer);
1994     IOHandlerSP io_handler_sp (confirm);
1995     m_debugger.RunIOHandler (io_handler_sp);
1996     return confirm->GetResponse();
1997 }
1998 
1999 CommandAlias*
2000 CommandInterpreter::GetAlias (const char *alias_name)
2001 {
2002     OptionArgVectorSP ret_val;
2003 
2004     std::string alias (alias_name);
2005 
2006     auto pos = m_alias_dict.find(alias);
2007     if (pos != m_alias_dict.end())
2008         return (CommandAlias*)pos->second.get();
2009 
2010     return nullptr;
2011 }
2012 
2013 bool
2014 CommandInterpreter::HasCommands ()
2015 {
2016     return (!m_command_dict.empty());
2017 }
2018 
2019 bool
2020 CommandInterpreter::HasAliases ()
2021 {
2022     return (!m_alias_dict.empty());
2023 }
2024 
2025 bool
2026 CommandInterpreter::HasUserCommands ()
2027 {
2028     return (!m_user_dict.empty());
2029 }
2030 
2031 bool
2032 CommandInterpreter::HasAliasOptions ()
2033 {
2034     return HasAliases();
2035 }
2036 
2037 void
2038 CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj,
2039                                            const char *alias_name,
2040                                            Args &cmd_args,
2041                                            std::string &raw_input_string,
2042                                            CommandReturnObject &result)
2043 {
2044     OptionArgVectorSP option_arg_vector_sp = GetAlias(alias_name)->GetOptionArguments();
2045 
2046     bool wants_raw_input = alias_cmd_obj->WantsRawCommandString();
2047 
2048     // Make sure that the alias name is the 0th element in cmd_args
2049     std::string alias_name_str = alias_name;
2050     if (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0)
2051         cmd_args.Unshift (alias_name);
2052 
2053     Args new_args (alias_cmd_obj->GetCommandName());
2054     if (new_args.GetArgumentCount() == 2)
2055         new_args.Shift();
2056 
2057     if (option_arg_vector_sp.get())
2058     {
2059         if (wants_raw_input)
2060         {
2061             // We have a command that both has command options and takes raw input.  Make *sure* it has a
2062             // " -- " in the right place in the raw_input_string.
2063             size_t pos = raw_input_string.find(" -- ");
2064             if (pos == std::string::npos)
2065             {
2066                 // None found; assume it goes at the beginning of the raw input string
2067                 raw_input_string.insert (0, " -- ");
2068             }
2069         }
2070 
2071         OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
2072         const size_t old_size = cmd_args.GetArgumentCount();
2073         std::vector<bool> used (old_size + 1, false);
2074 
2075         used[0] = true;
2076 
2077         for (size_t i = 0; i < option_arg_vector->size(); ++i)
2078         {
2079             OptionArgPair option_pair = (*option_arg_vector)[i];
2080             OptionArgValue value_pair = option_pair.second;
2081             int value_type = value_pair.first;
2082             std::string option = option_pair.first;
2083             std::string value = value_pair.second;
2084             if (option.compare ("<argument>") == 0)
2085             {
2086                 if (!wants_raw_input
2087                     || (value.compare("--") != 0)) // Since we inserted this above, make sure we don't insert it twice
2088                     new_args.AppendArgument (value.c_str());
2089             }
2090             else
2091             {
2092                 if (value_type != OptionParser::eOptionalArgument)
2093                     new_args.AppendArgument (option.c_str());
2094                 if (value.compare ("<no-argument>") != 0)
2095                 {
2096                     int index = GetOptionArgumentPosition (value.c_str());
2097                     if (index == 0)
2098                     {
2099                         // value was NOT a positional argument; must be a real value
2100                         if (value_type != OptionParser::eOptionalArgument)
2101                             new_args.AppendArgument (value.c_str());
2102                         else
2103                         {
2104                             char buffer[255];
2105                             ::snprintf (buffer, sizeof (buffer), "%s%s", option.c_str(), value.c_str());
2106                             new_args.AppendArgument (buffer);
2107                         }
2108 
2109                     }
2110                     else if (static_cast<size_t>(index) >= cmd_args.GetArgumentCount())
2111                     {
2112                         result.AppendErrorWithFormat
2113                                     ("Not enough arguments provided; you need at least %d arguments to use this alias.\n",
2114                                      index);
2115                         result.SetStatus (eReturnStatusFailed);
2116                         return;
2117                     }
2118                     else
2119                     {
2120                         // Find and remove cmd_args.GetArgumentAtIndex(i) from raw_input_string
2121                         size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index));
2122                         if (strpos != std::string::npos)
2123                         {
2124                             raw_input_string = raw_input_string.erase (strpos, strlen (cmd_args.GetArgumentAtIndex (index)));
2125                         }
2126 
2127                         if (value_type != OptionParser::eOptionalArgument)
2128                             new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index));
2129                         else
2130                         {
2131                             char buffer[255];
2132                             ::snprintf (buffer, sizeof(buffer), "%s%s", option.c_str(),
2133                                         cmd_args.GetArgumentAtIndex (index));
2134                             new_args.AppendArgument (buffer);
2135                         }
2136                         used[index] = true;
2137                     }
2138                 }
2139             }
2140         }
2141 
2142         for (size_t j = 0; j < cmd_args.GetArgumentCount(); ++j)
2143         {
2144             if (!used[j] && !wants_raw_input)
2145                 new_args.AppendArgument (cmd_args.GetArgumentAtIndex (j));
2146         }
2147 
2148         cmd_args.Clear();
2149         cmd_args.SetArguments (new_args.GetArgumentCount(), new_args.GetConstArgumentVector());
2150     }
2151     else
2152     {
2153         result.SetStatus (eReturnStatusSuccessFinishNoResult);
2154         // This alias was not created with any options; nothing further needs to be done, unless it is a command that
2155         // wants raw input, in which case we need to clear the rest of the data from cmd_args, since its in the raw
2156         // input string.
2157         if (wants_raw_input)
2158         {
2159             cmd_args.Clear();
2160             cmd_args.SetArguments (new_args.GetArgumentCount(), new_args.GetConstArgumentVector());
2161         }
2162         return;
2163     }
2164 
2165     result.SetStatus (eReturnStatusSuccessFinishNoResult);
2166     return;
2167 }
2168 
2169 
2170 int
2171 CommandInterpreter::GetOptionArgumentPosition (const char *in_string)
2172 {
2173     int position = 0;   // Any string that isn't an argument position, i.e. '%' followed by an integer, gets a position
2174                         // of zero.
2175 
2176     const char *cptr = in_string;
2177 
2178     // Does it start with '%'
2179     if (cptr[0] == '%')
2180     {
2181         ++cptr;
2182 
2183         // Is the rest of it entirely digits?
2184         if (isdigit (cptr[0]))
2185         {
2186             const char *start = cptr;
2187             while (isdigit (cptr[0]))
2188                 ++cptr;
2189 
2190             // We've gotten to the end of the digits; are we at the end of the string?
2191             if (cptr[0] == '\0')
2192                 position = atoi (start);
2193         }
2194     }
2195 
2196     return position;
2197 }
2198 
2199 void
2200 CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result)
2201 {
2202     FileSpec init_file;
2203     if (in_cwd)
2204     {
2205         ExecutionContext exe_ctx(GetExecutionContext());
2206         Target *target = exe_ctx.GetTargetPtr();
2207         if (target)
2208         {
2209             // In the current working directory we don't load any program specific
2210             // .lldbinit files, we only look for a ".lldbinit" file.
2211             if (m_skip_lldbinit_files)
2212                 return;
2213 
2214             LoadCWDlldbinitFile should_load = target->TargetProperties::GetLoadCWDlldbinitFile ();
2215             if (should_load == eLoadCWDlldbinitWarn)
2216             {
2217                 FileSpec dot_lldb (".lldbinit", true);
2218                 llvm::SmallString<64> home_dir_path;
2219                 llvm::sys::path::home_directory (home_dir_path);
2220                 FileSpec homedir_dot_lldb (home_dir_path.c_str(), false);
2221                 homedir_dot_lldb.AppendPathComponent (".lldbinit");
2222                 homedir_dot_lldb.ResolvePath ();
2223                 if (dot_lldb.Exists ()
2224                     && dot_lldb.GetDirectory() != homedir_dot_lldb.GetDirectory())
2225                 {
2226                     result.AppendErrorWithFormat (
2227                             "There is a .lldbinit file in the current directory which is not being read.\n"
2228                             "To silence this warning without sourcing in the local .lldbinit,\n"
2229                             "add the following to the lldbinit file in your home directory:\n"
2230                             "    settings set target.load-cwd-lldbinit false\n"
2231                             "To allow lldb to source .lldbinit files in the current working directory,\n"
2232                             "set the value of this variable to true.  Only do so if you understand and\n"
2233                             "accept the security risk.");
2234                     result.SetStatus (eReturnStatusFailed);
2235                     return;
2236                 }
2237             }
2238             else if (should_load == eLoadCWDlldbinitTrue)
2239             {
2240                 init_file.SetFile ("./.lldbinit", true);
2241             }
2242         }
2243     }
2244     else
2245     {
2246         // If we aren't looking in the current working directory we are looking
2247         // in the home directory. We will first see if there is an application
2248         // specific ".lldbinit" file whose name is "~/.lldbinit" followed by a
2249         // "-" and the name of the program. If this file doesn't exist, we fall
2250         // back to just the "~/.lldbinit" file. We also obey any requests to not
2251         // load the init files.
2252         llvm::SmallString<64> home_dir_path;
2253         llvm::sys::path::home_directory(home_dir_path);
2254         FileSpec profilePath(home_dir_path.c_str(), false);
2255         profilePath.AppendPathComponent(".lldbinit");
2256         std::string init_file_path = profilePath.GetPath();
2257 
2258         if (m_skip_app_init_files == false)
2259         {
2260             FileSpec program_file_spec(HostInfo::GetProgramFileSpec());
2261             const char *program_name = program_file_spec.GetFilename().AsCString();
2262 
2263             if (program_name)
2264             {
2265                 char program_init_file_name[PATH_MAX];
2266                 ::snprintf (program_init_file_name, sizeof(program_init_file_name), "%s-%s", init_file_path.c_str(), program_name);
2267                 init_file.SetFile (program_init_file_name, true);
2268                 if (!init_file.Exists())
2269                     init_file.Clear();
2270             }
2271         }
2272 
2273         if (!init_file && !m_skip_lldbinit_files)
2274 			init_file.SetFile (init_file_path.c_str(), false);
2275     }
2276 
2277     // If the file exists, tell HandleCommand to 'source' it; this will do the actual broadcasting
2278     // of the commands back to any appropriate listener (see CommandObjectSource::Execute for more details).
2279 
2280     if (init_file.Exists())
2281     {
2282         const bool saved_batch = SetBatchCommandMode (true);
2283         CommandInterpreterRunOptions options;
2284         options.SetSilent (true);
2285         options.SetStopOnError (false);
2286         options.SetStopOnContinue (true);
2287 
2288         HandleCommandsFromFile (init_file,
2289                                 nullptr,           // Execution context
2290                                 options,
2291                                 result);
2292         SetBatchCommandMode (saved_batch);
2293     }
2294     else
2295     {
2296         // nothing to be done if the file doesn't exist
2297         result.SetStatus(eReturnStatusSuccessFinishNoResult);
2298     }
2299 }
2300 
2301 const char *
2302 CommandInterpreter::GetCommandPrefix()
2303 {
2304     const char * prefix = GetDebugger().GetIOHandlerCommandPrefix();
2305     return prefix == NULL ? "" : prefix;
2306 }
2307 
2308 PlatformSP
2309 CommandInterpreter::GetPlatform (bool prefer_target_platform)
2310 {
2311     PlatformSP platform_sp;
2312     if (prefer_target_platform)
2313     {
2314         ExecutionContext exe_ctx(GetExecutionContext());
2315         Target *target = exe_ctx.GetTargetPtr();
2316         if (target)
2317             platform_sp = target->GetPlatform();
2318     }
2319 
2320     if (!platform_sp)
2321         platform_sp = m_debugger.GetPlatformList().GetSelectedPlatform();
2322     return platform_sp;
2323 }
2324 
2325 void
2326 CommandInterpreter::HandleCommands (const StringList &commands,
2327                                     ExecutionContext *override_context,
2328                                     CommandInterpreterRunOptions &options,
2329                                     CommandReturnObject &result)
2330 {
2331     size_t num_lines = commands.GetSize();
2332 
2333     // If we are going to continue past a "continue" then we need to run the commands synchronously.
2334     // Make sure you reset this value anywhere you return from the function.
2335 
2336     bool old_async_execution = m_debugger.GetAsyncExecution();
2337 
2338     // If we've been given an execution context, set it at the start, but don't keep resetting it or we will
2339     // cause series of commands that change the context, then do an operation that relies on that context to fail.
2340 
2341     if (override_context != nullptr)
2342         UpdateExecutionContext (override_context);
2343 
2344     if (!options.GetStopOnContinue())
2345     {
2346         m_debugger.SetAsyncExecution (false);
2347     }
2348 
2349     for (size_t idx = 0; idx < num_lines; idx++)
2350     {
2351         const char *cmd = commands.GetStringAtIndex(idx);
2352         if (cmd[0] == '\0')
2353             continue;
2354 
2355         if (options.GetEchoCommands())
2356         {
2357             result.AppendMessageWithFormat ("%s %s\n",
2358                                             m_debugger.GetPrompt(),
2359                                             cmd);
2360         }
2361 
2362         CommandReturnObject tmp_result;
2363         // If override_context is not NULL, pass no_context_switching = true for
2364         // HandleCommand() since we updated our context already.
2365 
2366         // We might call into a regex or alias command, in which case the add_to_history will get lost.  This
2367         // m_command_source_depth dingus is the way we turn off adding to the history in that case, so set it up here.
2368         if (!options.GetAddToHistory())
2369             m_command_source_depth++;
2370         bool success = HandleCommand(cmd, options.m_add_to_history, tmp_result,
2371                                      nullptr, /* override_context */
2372                                      true, /* repeat_on_empty_command */
2373                                      override_context != nullptr /* no_context_switching */);
2374         if (!options.GetAddToHistory())
2375             m_command_source_depth--;
2376 
2377         if (options.GetPrintResults())
2378         {
2379             if (tmp_result.Succeeded())
2380               result.AppendMessageWithFormat("%s", tmp_result.GetOutputData());
2381         }
2382 
2383         if (!success || !tmp_result.Succeeded())
2384         {
2385             const char *error_msg = tmp_result.GetErrorData();
2386             if (error_msg == nullptr || error_msg[0] == '\0')
2387                 error_msg = "<unknown error>.\n";
2388             if (options.GetStopOnError())
2389             {
2390                 result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' failed with %s",
2391                                                 (uint64_t)idx, cmd, error_msg);
2392                 result.SetStatus (eReturnStatusFailed);
2393                 m_debugger.SetAsyncExecution (old_async_execution);
2394                 return;
2395             }
2396             else if (options.GetPrintResults())
2397             {
2398                 result.AppendMessageWithFormat ("Command #%" PRIu64 " '%s' failed with %s",
2399                                                 (uint64_t)idx + 1,
2400                                                 cmd,
2401                                                 error_msg);
2402             }
2403         }
2404 
2405         if (result.GetImmediateOutputStream())
2406             result.GetImmediateOutputStream()->Flush();
2407 
2408         if (result.GetImmediateErrorStream())
2409             result.GetImmediateErrorStream()->Flush();
2410 
2411         // N.B. Can't depend on DidChangeProcessState, because the state coming into the command execution
2412         // could be running (for instance in Breakpoint Commands.
2413         // So we check the return value to see if it is has running in it.
2414         if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult)
2415                 || (tmp_result.GetStatus() == eReturnStatusSuccessContinuingResult))
2416         {
2417             if (options.GetStopOnContinue())
2418             {
2419                 // If we caused the target to proceed, and we're going to stop in that case, set the
2420                 // status in our real result before returning.  This is an error if the continue was not the
2421                 // last command in the set of commands to be run.
2422                 if (idx != num_lines - 1)
2423                     result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' continued the target.\n",
2424                                                  (uint64_t)idx + 1, cmd);
2425                 else
2426                     result.AppendMessageWithFormat("Command #%" PRIu64 " '%s' continued the target.\n", (uint64_t)idx + 1, cmd);
2427 
2428                 result.SetStatus(tmp_result.GetStatus());
2429                 m_debugger.SetAsyncExecution (old_async_execution);
2430 
2431                 return;
2432             }
2433         }
2434 
2435         // Also check for "stop on crash here:
2436         bool should_stop = false;
2437         if (tmp_result.GetDidChangeProcessState() && options.GetStopOnCrash())
2438         {
2439             TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget());
2440             if (target_sp)
2441             {
2442                 ProcessSP process_sp (target_sp->GetProcessSP());
2443                 if (process_sp)
2444                 {
2445                     for (ThreadSP thread_sp : process_sp->GetThreadList().Threads())
2446                     {
2447                         StopReason reason = thread_sp->GetStopReason();
2448                         if (reason == eStopReasonSignal || reason == eStopReasonException || reason == eStopReasonInstrumentation)
2449                         {
2450                             should_stop = true;
2451                             break;
2452                         }
2453                     }
2454                 }
2455             }
2456             if (should_stop)
2457             {
2458                 if (idx != num_lines - 1)
2459                     result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' stopped with a signal or exception.\n",
2460                                                  (uint64_t)idx + 1, cmd);
2461                 else
2462                     result.AppendMessageWithFormat("Command #%" PRIu64 " '%s' stopped with a signal or exception.\n", (uint64_t)idx + 1, cmd);
2463 
2464                 result.SetStatus(tmp_result.GetStatus());
2465                 m_debugger.SetAsyncExecution (old_async_execution);
2466 
2467                 return;
2468             }
2469         }
2470 
2471     }
2472 
2473     result.SetStatus (eReturnStatusSuccessFinishResult);
2474     m_debugger.SetAsyncExecution (old_async_execution);
2475 
2476     return;
2477 }
2478 
2479 // Make flags that we can pass into the IOHandler so our delegates can do the right thing
2480 enum {
2481     eHandleCommandFlagStopOnContinue = (1u << 0),
2482     eHandleCommandFlagStopOnError    = (1u << 1),
2483     eHandleCommandFlagEchoCommand    = (1u << 2),
2484     eHandleCommandFlagPrintResult    = (1u << 3),
2485     eHandleCommandFlagStopOnCrash    = (1u << 4)
2486 };
2487 
2488 void
2489 CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file,
2490                                             ExecutionContext *context,
2491                                             CommandInterpreterRunOptions &options,
2492                                             CommandReturnObject &result)
2493 {
2494     if (cmd_file.Exists())
2495     {
2496         StreamFileSP input_file_sp (new StreamFile());
2497 
2498         std::string cmd_file_path = cmd_file.GetPath();
2499         Error error = input_file_sp->GetFile().Open(cmd_file_path.c_str(), File::eOpenOptionRead);
2500 
2501         if (error.Success())
2502         {
2503             Debugger &debugger = GetDebugger();
2504 
2505             uint32_t flags = 0;
2506 
2507             if (options.m_stop_on_continue == eLazyBoolCalculate)
2508             {
2509                 if (m_command_source_flags.empty())
2510                 {
2511                     // Stop on continue by default
2512                     flags |= eHandleCommandFlagStopOnContinue;
2513                 }
2514                 else if (m_command_source_flags.back() & eHandleCommandFlagStopOnContinue)
2515                 {
2516                     flags |= eHandleCommandFlagStopOnContinue;
2517                 }
2518             }
2519             else if (options.m_stop_on_continue == eLazyBoolYes)
2520             {
2521                 flags |= eHandleCommandFlagStopOnContinue;
2522             }
2523 
2524             if (options.m_stop_on_error == eLazyBoolCalculate)
2525             {
2526                 if (m_command_source_flags.empty())
2527                 {
2528                     if (GetStopCmdSourceOnError())
2529                         flags |= eHandleCommandFlagStopOnError;
2530                 }
2531                 else if (m_command_source_flags.back() & eHandleCommandFlagStopOnError)
2532                 {
2533                     flags |= eHandleCommandFlagStopOnError;
2534                 }
2535             }
2536             else if (options.m_stop_on_error == eLazyBoolYes)
2537             {
2538                 flags |= eHandleCommandFlagStopOnError;
2539             }
2540 
2541             if (options.GetStopOnCrash())
2542             {
2543                 if (m_command_source_flags.empty())
2544                 {
2545                     // Echo command by default
2546                     flags |= eHandleCommandFlagStopOnCrash;
2547                 }
2548                 else if (m_command_source_flags.back() & eHandleCommandFlagStopOnCrash)
2549                 {
2550                     flags |= eHandleCommandFlagStopOnCrash;
2551                 }
2552             }
2553 
2554             if (options.m_echo_commands == eLazyBoolCalculate)
2555             {
2556                 if (m_command_source_flags.empty())
2557                 {
2558                     // Echo command by default
2559                     flags |= eHandleCommandFlagEchoCommand;
2560                 }
2561                 else if (m_command_source_flags.back() & eHandleCommandFlagEchoCommand)
2562                 {
2563                     flags |= eHandleCommandFlagEchoCommand;
2564                 }
2565             }
2566             else if (options.m_echo_commands == eLazyBoolYes)
2567             {
2568                 flags |= eHandleCommandFlagEchoCommand;
2569             }
2570 
2571             if (options.m_print_results == eLazyBoolCalculate)
2572             {
2573                 if (m_command_source_flags.empty())
2574                 {
2575                     // Print output by default
2576                     flags |= eHandleCommandFlagPrintResult;
2577                 }
2578                 else if (m_command_source_flags.back() & eHandleCommandFlagPrintResult)
2579                 {
2580                     flags |= eHandleCommandFlagPrintResult;
2581                 }
2582             }
2583             else if (options.m_print_results == eLazyBoolYes)
2584             {
2585                 flags |= eHandleCommandFlagPrintResult;
2586             }
2587 
2588             if (flags & eHandleCommandFlagPrintResult)
2589             {
2590                 debugger.GetOutputFile()->Printf("Executing commands in '%s'.\n", cmd_file_path.c_str());
2591             }
2592 
2593             // Used for inheriting the right settings when "command source" might have
2594             // nested "command source" commands
2595             lldb::StreamFileSP empty_stream_sp;
2596             m_command_source_flags.push_back(flags);
2597             IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
2598                                                               IOHandler::Type::CommandInterpreter,
2599                                                               input_file_sp,
2600                                                               empty_stream_sp, // Pass in an empty stream so we inherit the top input reader output stream
2601                                                               empty_stream_sp, // Pass in an empty stream so we inherit the top input reader error stream
2602                                                               flags,
2603                                                               nullptr, // Pass in NULL for "editline_name" so no history is saved, or written
2604                                                               debugger.GetPrompt(),
2605                                                               NULL,
2606                                                               false, // Not multi-line
2607                                                               debugger.GetUseColor(),
2608                                                               0,
2609                                                               *this));
2610             const bool old_async_execution = debugger.GetAsyncExecution();
2611 
2612             // Set synchronous execution if we are not stopping on continue
2613             if ((flags & eHandleCommandFlagStopOnContinue) == 0)
2614                 debugger.SetAsyncExecution (false);
2615 
2616             m_command_source_depth++;
2617 
2618             debugger.RunIOHandler(io_handler_sp);
2619             if (!m_command_source_flags.empty())
2620                 m_command_source_flags.pop_back();
2621             m_command_source_depth--;
2622             result.SetStatus (eReturnStatusSuccessFinishNoResult);
2623             debugger.SetAsyncExecution (old_async_execution);
2624         }
2625         else
2626         {
2627             result.AppendErrorWithFormat ("error: an error occurred read file '%s': %s\n", cmd_file_path.c_str(), error.AsCString());
2628             result.SetStatus (eReturnStatusFailed);
2629         }
2630 
2631 
2632     }
2633     else
2634     {
2635         result.AppendErrorWithFormat ("Error reading commands from file %s - file not found.\n",
2636                                       cmd_file.GetFilename().AsCString("<Unknown>"));
2637         result.SetStatus (eReturnStatusFailed);
2638         return;
2639     }
2640 }
2641 
2642 ScriptInterpreter *
2643 CommandInterpreter::GetScriptInterpreter(bool can_create)
2644 {
2645     if (m_script_interpreter_sp)
2646         return m_script_interpreter_sp.get();
2647 
2648     if (!can_create)
2649         return nullptr;
2650 
2651     lldb::ScriptLanguage script_lang = GetDebugger().GetScriptLanguage();
2652     m_script_interpreter_sp = PluginManager::GetScriptInterpreterForLanguage(script_lang, *this);
2653     return m_script_interpreter_sp.get();
2654 }
2655 
2656 bool
2657 CommandInterpreter::GetSynchronous ()
2658 {
2659     return m_synchronous_execution;
2660 }
2661 
2662 void
2663 CommandInterpreter::SetSynchronous (bool value)
2664 {
2665     m_synchronous_execution  = value;
2666 }
2667 
2668 void
2669 CommandInterpreter::OutputFormattedHelpText (Stream &strm,
2670                                              const char *prefix,
2671                                              const char *help_text)
2672 {
2673     const uint32_t max_columns = m_debugger.GetTerminalWidth();
2674     if (prefix == NULL)
2675         prefix = "";
2676 
2677     size_t prefix_width = strlen(prefix);
2678     size_t line_width_max = max_columns - prefix_width;
2679     const char *help_text_end = help_text + strlen(help_text);
2680     const char *line_start = help_text;
2681     if (line_width_max < 16)
2682         line_width_max = help_text_end - help_text + prefix_width;
2683 
2684     strm.IndentMore (prefix_width);
2685     while (line_start < help_text_end)
2686     {
2687         // Break each line at the first newline or last space/tab before
2688         // the maximum number of characters that fit on a line.  Lines with no
2689         // natural break are left unbroken to wrap.
2690         const char *line_end = help_text_end;
2691         const char *line_scan = line_start;
2692         const char *line_scan_end = help_text_end;
2693         while (line_scan < line_scan_end)
2694         {
2695             char next = *line_scan;
2696             if (next == '\t' || next == ' ')
2697             {
2698                 line_end = line_scan;
2699                 line_scan_end = line_start + line_width_max;
2700             }
2701             else if (next == '\n' || next == '\0')
2702             {
2703                 line_end = line_scan;
2704                 break;
2705             }
2706             ++line_scan;
2707         }
2708 
2709         // Prefix the first line, indent subsequent lines to line up
2710         if (line_start == help_text)
2711             strm.Write (prefix, prefix_width);
2712         else
2713             strm.Indent();
2714         strm.Write (line_start, line_end - line_start);
2715         strm.EOL();
2716 
2717         // When a line breaks at whitespace consume it before continuing
2718         line_start = line_end;
2719         char next = *line_start;
2720         if (next == '\n')
2721             ++line_start;
2722         else while (next == ' ' || next == '\t')
2723             next = *(++line_start);
2724     }
2725     strm.IndentLess (prefix_width);
2726 }
2727 
2728 void
2729 CommandInterpreter::OutputFormattedHelpText (Stream &strm,
2730                                              const char *word_text,
2731                                              const char *separator,
2732                                              const char *help_text,
2733                                              size_t max_word_len)
2734 {
2735     StreamString prefix_stream;
2736     prefix_stream.Printf ("  %-*s %s ",  (int)max_word_len, word_text, separator);
2737     OutputFormattedHelpText (strm, prefix_stream.GetData(), help_text);
2738 }
2739 
2740 void
2741 CommandInterpreter::OutputHelpText (Stream &strm,
2742                                     const char *word_text,
2743                                     const char *separator,
2744                                     const char *help_text,
2745                                     uint32_t max_word_len)
2746 {
2747     int indent_size = max_word_len + strlen (separator) + 2;
2748 
2749     strm.IndentMore (indent_size);
2750 
2751     StreamString text_strm;
2752     text_strm.Printf ("%-*s %s %s",  max_word_len, word_text, separator, help_text);
2753 
2754     const uint32_t max_columns = m_debugger.GetTerminalWidth();
2755 
2756     size_t len = text_strm.GetSize();
2757     const char *text = text_strm.GetData();
2758 
2759     uint32_t chars_left = max_columns;
2760 
2761     for (uint32_t i = 0; i < len; i++)
2762     {
2763         if ((text[i] == ' ' && ::strchr((text+i+1), ' ') && chars_left < ::strchr((text+i+1), ' ')-(text+i)) || text[i] == '\n')
2764         {
2765             chars_left = max_columns - indent_size;
2766             strm.EOL();
2767             strm.Indent();
2768         }
2769         else
2770         {
2771             strm.PutChar(text[i]);
2772             chars_left--;
2773         }
2774 
2775     }
2776 
2777     strm.EOL();
2778     strm.IndentLess(indent_size);
2779 }
2780 
2781 void
2782 CommandInterpreter::FindCommandsForApropos (const char *search_word,
2783                                             StringList &commands_found,
2784                                             StringList &commands_help,
2785                                             CommandObject::CommandMap &command_map)
2786 {
2787     CommandObject::CommandMap::const_iterator pos;
2788 
2789     for (pos = command_map.begin(); pos != command_map.end(); ++pos)
2790     {
2791         const char *command_name = pos->first.c_str();
2792         CommandObject *cmd_obj = pos->second.get();
2793 
2794         const bool search_short_help = true;
2795         const bool search_long_help = false;
2796         const bool search_syntax = false;
2797         const bool search_options = false;
2798         if (strcasestr(command_name, search_word) ||
2799             cmd_obj->HelpTextContainsWord (search_word,
2800                                            search_short_help,
2801                                            search_long_help,
2802                                            search_syntax,
2803                                            search_options))
2804         {
2805             commands_found.AppendString (cmd_obj->GetCommandName());
2806             commands_help.AppendString (cmd_obj->GetHelp());
2807         }
2808 
2809         if (cmd_obj->IsMultiwordObject())
2810         {
2811             CommandObjectMultiword *cmd_multiword = cmd_obj->GetAsMultiwordCommand();
2812             FindCommandsForApropos(search_word,
2813                                    commands_found,
2814                                    commands_help,
2815                                    cmd_multiword->GetSubcommandDictionary());
2816         }
2817     }
2818 }
2819 
2820 
2821 void
2822 CommandInterpreter::FindCommandsForApropos (const char *search_word,
2823                                             StringList &commands_found,
2824                                             StringList &commands_help,
2825                                             bool search_builtin_commands,
2826                                             bool search_user_commands,
2827                                             bool search_alias_commands)
2828 {
2829     CommandObject::CommandMap::const_iterator pos;
2830 
2831     if (search_builtin_commands)
2832         FindCommandsForApropos(search_word, commands_found, commands_help, m_command_dict);
2833 
2834     if (search_user_commands)
2835         FindCommandsForApropos(search_word, commands_found, commands_help, m_user_dict);
2836 
2837     if (search_alias_commands)
2838         FindCommandsForApropos(search_word, commands_found, commands_help, m_alias_dict);
2839 }
2840 
2841 void
2842 CommandInterpreter::UpdateExecutionContext (ExecutionContext *override_context)
2843 {
2844     if (override_context != nullptr)
2845     {
2846         m_exe_ctx_ref = *override_context;
2847     }
2848     else
2849     {
2850         const bool adopt_selected = true;
2851         m_exe_ctx_ref.SetTargetPtr (m_debugger.GetSelectedTarget().get(), adopt_selected);
2852     }
2853 }
2854 
2855 
2856 size_t
2857 CommandInterpreter::GetProcessOutput ()
2858 {
2859     //  The process has stuff waiting for stderr; get it and write it out to the appropriate place.
2860     char stdio_buffer[1024];
2861     size_t len;
2862     size_t total_bytes = 0;
2863     Error error;
2864     TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget());
2865     if (target_sp)
2866     {
2867         ProcessSP process_sp (target_sp->GetProcessSP());
2868         if (process_sp)
2869         {
2870             while ((len = process_sp->GetSTDOUT (stdio_buffer, sizeof (stdio_buffer), error)) > 0)
2871             {
2872                 size_t bytes_written = len;
2873                 m_debugger.GetOutputFile()->Write (stdio_buffer, bytes_written);
2874                 total_bytes += len;
2875             }
2876             while ((len = process_sp->GetSTDERR (stdio_buffer, sizeof (stdio_buffer), error)) > 0)
2877             {
2878                 size_t bytes_written = len;
2879                 m_debugger.GetErrorFile()->Write (stdio_buffer, bytes_written);
2880                 total_bytes += len;
2881             }
2882         }
2883     }
2884     return total_bytes;
2885 }
2886 
2887 void
2888 CommandInterpreter::IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
2889 {
2890     const bool is_interactive = io_handler.GetIsInteractive();
2891     if (is_interactive == false)
2892     {
2893         // When we are not interactive, don't execute blank lines. This will happen
2894         // sourcing a commands file. We don't want blank lines to repeat the previous
2895         // command and cause any errors to occur (like redefining an alias, get an error
2896         // and stop parsing the commands file).
2897         if (line.empty())
2898             return;
2899 
2900         // When using a non-interactive file handle (like when sourcing commands from a file)
2901         // we need to echo the command out so we don't just see the command output and no
2902         // command...
2903         if (io_handler.GetFlags().Test(eHandleCommandFlagEchoCommand))
2904             io_handler.GetOutputStreamFile()->Printf("%s%s\n", io_handler.GetPrompt(), line.c_str());
2905     }
2906 
2907     lldb_private::CommandReturnObject result;
2908     HandleCommand(line.c_str(), eLazyBoolCalculate, result);
2909 
2910     // Now emit the command output text from the command we just executed
2911     if (io_handler.GetFlags().Test(eHandleCommandFlagPrintResult))
2912     {
2913         // Display any STDOUT/STDERR _prior_ to emitting the command result text
2914         GetProcessOutput ();
2915 
2916         if (!result.GetImmediateOutputStream())
2917         {
2918             const char *output = result.GetOutputData();
2919             if (output && output[0])
2920                 io_handler.GetOutputStreamFile()->PutCString(output);
2921         }
2922 
2923         // Now emit the command error text from the command we just executed
2924         if (!result.GetImmediateErrorStream())
2925         {
2926             const char *error = result.GetErrorData();
2927             if (error && error[0])
2928                 io_handler.GetErrorStreamFile()->PutCString(error);
2929         }
2930     }
2931 
2932     switch (result.GetStatus())
2933     {
2934         case eReturnStatusInvalid:
2935         case eReturnStatusSuccessFinishNoResult:
2936         case eReturnStatusSuccessFinishResult:
2937         case eReturnStatusStarted:
2938             break;
2939 
2940         case eReturnStatusSuccessContinuingNoResult:
2941         case eReturnStatusSuccessContinuingResult:
2942             if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnContinue))
2943                 io_handler.SetIsDone(true);
2944             break;
2945 
2946         case eReturnStatusFailed:
2947             m_num_errors++;
2948             if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnError))
2949                 io_handler.SetIsDone(true);
2950             break;
2951 
2952         case eReturnStatusQuit:
2953             m_quit_requested = true;
2954             io_handler.SetIsDone(true);
2955             break;
2956     }
2957 
2958     // Finally, if we're going to stop on crash, check that here:
2959     if (!m_quit_requested
2960         && result.GetDidChangeProcessState()
2961         && io_handler.GetFlags().Test(eHandleCommandFlagStopOnCrash))
2962     {
2963         bool should_stop = false;
2964         TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget());
2965         if (target_sp)
2966         {
2967             ProcessSP process_sp (target_sp->GetProcessSP());
2968             if (process_sp)
2969             {
2970                 for (ThreadSP thread_sp : process_sp->GetThreadList().Threads())
2971                 {
2972                     StopReason reason = thread_sp->GetStopReason();
2973                     if ((reason == eStopReasonSignal
2974                         || reason == eStopReasonException
2975                         || reason == eStopReasonInstrumentation)
2976                         && !result.GetAbnormalStopWasExpected())
2977                     {
2978                         should_stop = true;
2979                         break;
2980                     }
2981                 }
2982             }
2983         }
2984         if (should_stop)
2985         {
2986             io_handler.SetIsDone(true);
2987             m_stopped_for_crash = true;
2988         }
2989     }
2990 }
2991 
2992 bool
2993 CommandInterpreter::IOHandlerInterrupt (IOHandler &io_handler)
2994 {
2995     ExecutionContext exe_ctx (GetExecutionContext());
2996     Process *process = exe_ctx.GetProcessPtr();
2997 
2998     if (process)
2999     {
3000         StateType state = process->GetState();
3001         if (StateIsRunningState(state))
3002         {
3003             process->Halt();
3004             return true; // Don't do any updating when we are running
3005         }
3006     }
3007 
3008     ScriptInterpreter *script_interpreter = GetScriptInterpreter (false);
3009     if (script_interpreter)
3010     {
3011         if (script_interpreter->Interrupt())
3012             return true;
3013     }
3014     return false;
3015 }
3016 
3017 void
3018 CommandInterpreter::GetLLDBCommandsFromIOHandler (const char *prompt,
3019                                                   IOHandlerDelegate &delegate,
3020                                                   bool asynchronously,
3021                                                   void *baton)
3022 {
3023     Debugger &debugger = GetDebugger();
3024     IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
3025                                                       IOHandler::Type::CommandList,
3026                                                       "lldb",       // Name of input reader for history
3027                                                       prompt,       // Prompt
3028                                                       NULL,         // Continuation prompt
3029                                                       true,         // Get multiple lines
3030                                                       debugger.GetUseColor(),
3031                                                       0,            // Don't show line numbers
3032                                                       delegate));   // IOHandlerDelegate
3033 
3034     if (io_handler_sp)
3035     {
3036         io_handler_sp->SetUserData (baton);
3037         if (asynchronously)
3038             debugger.PushIOHandler(io_handler_sp);
3039         else
3040             debugger.RunIOHandler(io_handler_sp);
3041     }
3042 
3043 }
3044 
3045 
3046 void
3047 CommandInterpreter::GetPythonCommandsFromIOHandler (const char *prompt,
3048                                                     IOHandlerDelegate &delegate,
3049                                                     bool asynchronously,
3050                                                     void *baton)
3051 {
3052     Debugger &debugger = GetDebugger();
3053     IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
3054                                                       IOHandler::Type::PythonCode,
3055                                                       "lldb-python",    // Name of input reader for history
3056                                                       prompt,           // Prompt
3057                                                       NULL,             // Continuation prompt
3058                                                       true,             // Get multiple lines
3059                                                       debugger.GetUseColor(),
3060                                                       0,                // Don't show line numbers
3061                                                       delegate));       // IOHandlerDelegate
3062 
3063     if (io_handler_sp)
3064     {
3065         io_handler_sp->SetUserData (baton);
3066         if (asynchronously)
3067             debugger.PushIOHandler(io_handler_sp);
3068         else
3069             debugger.RunIOHandler(io_handler_sp);
3070     }
3071 
3072 }
3073 
3074 bool
3075 CommandInterpreter::IsActive ()
3076 {
3077     return m_debugger.IsTopIOHandler (m_command_io_handler_sp);
3078 }
3079 
3080 lldb::IOHandlerSP
3081 CommandInterpreter::GetIOHandler(bool force_create, CommandInterpreterRunOptions *options)
3082 {
3083     // Always re-create the IOHandlerEditline in case the input
3084     // changed. The old instance might have had a non-interactive
3085     // input and now it does or vice versa.
3086     if (force_create || !m_command_io_handler_sp)
3087     {
3088         // Always re-create the IOHandlerEditline in case the input
3089         // changed. The old instance might have had a non-interactive
3090         // input and now it does or vice versa.
3091         uint32_t flags = 0;
3092 
3093         if (options)
3094         {
3095             if (options->m_stop_on_continue == eLazyBoolYes)
3096                 flags |= eHandleCommandFlagStopOnContinue;
3097             if (options->m_stop_on_error == eLazyBoolYes)
3098                 flags |= eHandleCommandFlagStopOnError;
3099             if (options->m_stop_on_crash == eLazyBoolYes)
3100                 flags |= eHandleCommandFlagStopOnCrash;
3101             if (options->m_echo_commands != eLazyBoolNo)
3102                 flags |= eHandleCommandFlagEchoCommand;
3103             if (options->m_print_results != eLazyBoolNo)
3104                 flags |= eHandleCommandFlagPrintResult;
3105         }
3106         else
3107         {
3108             flags = eHandleCommandFlagEchoCommand | eHandleCommandFlagPrintResult;
3109         }
3110 
3111         m_command_io_handler_sp.reset(new IOHandlerEditline (m_debugger,
3112                                                              IOHandler::Type::CommandInterpreter,
3113                                                              m_debugger.GetInputFile(),
3114                                                              m_debugger.GetOutputFile(),
3115                                                              m_debugger.GetErrorFile(),
3116                                                              flags,
3117                                                              "lldb",
3118                                                              m_debugger.GetPrompt(),
3119                                                              NULL,                      // Continuation prompt
3120                                                              false,                     // Don't enable multiple line input, just single line commands
3121                                                              m_debugger.GetUseColor(),
3122                                                              0,            // Don't show line numbers
3123                                                              *this));
3124     }
3125     return m_command_io_handler_sp;
3126 }
3127 
3128 void
3129 CommandInterpreter::RunCommandInterpreter(bool auto_handle_events,
3130                                           bool spawn_thread,
3131                                           CommandInterpreterRunOptions &options)
3132 {
3133     // Always re-create the command interpreter when we run it in case
3134     // any file handles have changed.
3135     bool force_create = true;
3136     m_debugger.PushIOHandler(GetIOHandler(force_create, &options));
3137     m_stopped_for_crash = false;
3138 
3139     if (auto_handle_events)
3140         m_debugger.StartEventHandlerThread();
3141 
3142     if (spawn_thread)
3143     {
3144         m_debugger.StartIOHandlerThread();
3145     }
3146     else
3147     {
3148         m_debugger.ExecuteIOHandlers();
3149 
3150         if (auto_handle_events)
3151             m_debugger.StopEventHandlerThread();
3152     }
3153 
3154 }
3155 
3156 CommandObject *
3157 CommandInterpreter::ResolveCommandImpl(std::string &command_line, CommandReturnObject &result)
3158 {
3159     std::string scratch_command(command_line);  // working copy so we don't modify command_line unless we succeed
3160     CommandObject *cmd_obj = nullptr;
3161     StreamString revised_command_line;
3162     bool wants_raw_input = false;
3163     size_t actual_cmd_name_len = 0;
3164     std::string next_word;
3165     StringList matches;
3166     bool done = false;
3167     while (!done)
3168     {
3169         char quote_char = '\0';
3170         std::string suffix;
3171         ExtractCommand(scratch_command, next_word, suffix, quote_char);
3172         if (cmd_obj == nullptr)
3173         {
3174             std::string full_name;
3175             if (GetAliasFullName(next_word.c_str(), full_name))
3176             {
3177                 std::string alias_result;
3178                 cmd_obj = BuildAliasResult(full_name.c_str(), scratch_command, alias_result, result);
3179                 revised_command_line.Printf("%s", alias_result.c_str());
3180                 if (cmd_obj)
3181                 {
3182                     wants_raw_input = cmd_obj->WantsRawCommandString();
3183                     actual_cmd_name_len = strlen(cmd_obj->GetCommandName());
3184                 }
3185             }
3186             else
3187             {
3188                 cmd_obj = GetCommandObject(next_word.c_str(), &matches);
3189                 if (cmd_obj)
3190                 {
3191                     actual_cmd_name_len += strlen(cmd_obj->GetCommandName());
3192                     revised_command_line.Printf("%s", cmd_obj->GetCommandName());
3193                     wants_raw_input = cmd_obj->WantsRawCommandString();
3194                 }
3195                 else
3196                 {
3197                     revised_command_line.Printf ("%s", next_word.c_str());
3198                 }
3199             }
3200         }
3201         else
3202         {
3203             if (cmd_obj->IsMultiwordObject ())
3204             {
3205                 CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject(next_word.c_str());
3206                 if (sub_cmd_obj)
3207                 {
3208                     // The subcommand's name includes the parent command's name,
3209                     // so restart rather than append to the revised_command_line.
3210                     actual_cmd_name_len = strlen(sub_cmd_obj->GetCommandName()) + 1;
3211                     revised_command_line.Clear();
3212                     revised_command_line.Printf("%s", sub_cmd_obj->GetCommandName());
3213                     cmd_obj = sub_cmd_obj;
3214                     wants_raw_input = cmd_obj->WantsRawCommandString();
3215                 }
3216                 else
3217                 {
3218                     if (quote_char)
3219                         revised_command_line.Printf(" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char);
3220                     else
3221                         revised_command_line.Printf(" %s%s", next_word.c_str(), suffix.c_str());
3222                     done = true;
3223                 }
3224             }
3225             else
3226             {
3227                 if (quote_char)
3228                     revised_command_line.Printf(" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char);
3229                 else
3230                     revised_command_line.Printf(" %s%s", next_word.c_str(), suffix.c_str());
3231                 done = true;
3232             }
3233         }
3234 
3235         if (cmd_obj == nullptr)
3236         {
3237             const size_t num_matches = matches.GetSize();
3238             if (matches.GetSize() > 1) {
3239                 StreamString error_msg;
3240                 error_msg.Printf("Ambiguous command '%s'. Possible matches:\n", next_word.c_str());
3241 
3242                 for (uint32_t i = 0; i < num_matches; ++i) {
3243                     error_msg.Printf("\t%s\n", matches.GetStringAtIndex(i));
3244                 }
3245                 result.AppendRawError(error_msg.GetString().c_str());
3246             } else {
3247                 // We didn't have only one match, otherwise we wouldn't get here.
3248                 assert(num_matches == 0);
3249                 result.AppendErrorWithFormat("'%s' is not a valid command.\n", next_word.c_str());
3250             }
3251             result.SetStatus(eReturnStatusFailed);
3252             return nullptr;
3253         }
3254 
3255         if (cmd_obj->IsMultiwordObject())
3256         {
3257             if (!suffix.empty())
3258             {
3259                 result.AppendErrorWithFormat("command '%s' did not recognize '%s%s%s' as valid (subcommand might be invalid).\n",
3260                                              cmd_obj->GetCommandName(),
3261                                              next_word.empty() ? "" : next_word.c_str(),
3262                                              next_word.empty() ? " -- " : " ",
3263                                              suffix.c_str());
3264                 result.SetStatus(eReturnStatusFailed);
3265                 return nullptr;
3266             }
3267         }
3268         else
3269         {
3270             // If we found a normal command, we are done
3271             done = true;
3272             if (!suffix.empty())
3273             {
3274                 switch (suffix[0])
3275                 {
3276                 case '/':
3277                     // GDB format suffixes
3278                     {
3279                         Options *command_options = cmd_obj->GetOptions();
3280                         if (command_options && command_options->SupportsLongOption("gdb-format"))
3281                         {
3282                             std::string gdb_format_option("--gdb-format=");
3283                             gdb_format_option += (suffix.c_str() + 1);
3284 
3285                             bool inserted = false;
3286                             std::string &cmd = revised_command_line.GetString();
3287                             size_t arg_terminator_idx = FindArgumentTerminator(cmd);
3288                             if (arg_terminator_idx != std::string::npos)
3289                             {
3290                                 // Insert the gdb format option before the "--" that terminates options
3291                                 gdb_format_option.append(1,' ');
3292                                 cmd.insert(arg_terminator_idx, gdb_format_option);
3293                                 inserted = true;
3294                             }
3295 
3296                             if (!inserted)
3297                                 revised_command_line.Printf(" %s", gdb_format_option.c_str());
3298 
3299                             if (wants_raw_input && FindArgumentTerminator(cmd) == std::string::npos)
3300                                 revised_command_line.PutCString(" --");
3301                         }
3302                         else
3303                         {
3304                             result.AppendErrorWithFormat("the '%s' command doesn't support the --gdb-format option\n",
3305                                                          cmd_obj->GetCommandName());
3306                             result.SetStatus(eReturnStatusFailed);
3307                             return nullptr;
3308                         }
3309                     }
3310                     break;
3311 
3312                 default:
3313                     result.AppendErrorWithFormat("unknown command shorthand suffix: '%s'\n",
3314                                                  suffix.c_str());
3315                     result.SetStatus(eReturnStatusFailed);
3316                     return nullptr;
3317                 }
3318             }
3319         }
3320         if (scratch_command.empty())
3321             done = true;
3322     }
3323 
3324     if (!scratch_command.empty())
3325         revised_command_line.Printf(" %s", scratch_command.c_str());
3326 
3327     if (cmd_obj != NULL)
3328         command_line = revised_command_line.GetData();
3329 
3330     return cmd_obj;
3331 }
3332