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