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