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