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