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