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