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